当前位置: 首页 > news >正文

TIPS 二进制程序暴露符号给动态链接库使用

背景

在支持插件/扩展的C/C++系统中,通常会支持在程序运行时加载动态链接库。这时二进制程序会提供一些函数/接口让动态链接库调用,但是这些函数在二进制程序中又不会使用,导致在编译时编译器直接把这些符号删除了,加载链接库就会由于找不到符号而失败。
本文将描述一种将仅在动态链接库中使用的符号如何暴露出来的方法。

方法描述

目标:将要导出的符号放到 .dynsym 区。

dlopen的动态链接库会去解析 .dynysm 区中的符号。

  1. 保留所有要导出的符号,以防被inline 或者被链接器删除掉
  2. 将符号都导出到 .dynsym

-rdynamic 编译选项也能解决这个问题,但是会导出一些不相关的符号,也会影响程序的优化。

假设需要保留的符号放在某一个静态链接库中,在编译二进制文件时,使用 -Wl,--whole-archive 可以将符号都保留下来,再使用 -Wl,--export-dynamic-symbol 命令导出相关符号,比如:

target_link_libraries(observerPUBLIClibalibb-Wl,--whole-archivelibkeep_symbols-Wl,--no-whole-archive-Wl,--export-dynamic-symbol=export_*)

链接器将会保留 -Wl,--whole-archive-Wl,--no-whole-archive 之间所有链接库的所有符号(注意要导出的符号不要让它inline 掉),使用 -Wl,--export-dynamic-symbol=export_* 命令导出所有 export_ 开头的符号(你可以编写其它的正则表达式)。

参考资料

  • 将符号放到.dynsym区中
  • 保留未使用的符号
  • WASM中关于符号导出的讨论
  • 可执行符号导出的问题讨论
  • lld 手册
  • cmake的enable_exports
  • lld 增加 --export-dynamic-symbol-list
  • Linux kernel export_symbol 解析

一些其它参考信息

Postgres中的做法

链接postgres的命令

gcc -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Werror=vla -Wendif-labels -Wmissing-format-attribute -Wimplicit-fallthrough=3 -Wcast-function-type -Wshadow=compatible-local -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -Wno-format-truncation -Wno-stringop-truncation -g -O0 access/brin/brin.o access/brin/brin_bloom.o access/brin/brin_inclusion.o ....... ../../src/timezone/strftime.o jit/jit.o ../../src/common/libpgcommon_srv.a ../../src/port/libpgport_srv.a -L../../src/port -L../../src/common   
-Wl,--as-needed -Wl,-rpath,'/root/github/postgres/debug/lib',
--enable-new-dtags
-Wl,--export-dynamic
-lm -o postgres

PostgreSQL使用 -Wl,--export-dynamic 解决了将符号放到 .dynsym 的问题(也可以参考 -rdynamic 编译选项)。但是这种方法会把所有相关的符号都放过去,因为PG是一个大部分模块都支持扩展的应用,符号都导出去没啥问题。

将符号保留在 .symtab

尝试过其它方法,比如将符号保留在 .symtab 区中,符号保留成功但是动态库引用不到。
当前的符号在.symtab区中:
在这里插入图片描述
在这里插入图片描述

使用 version-script 指定过符号是global但是dlopen依然由于找不到符号而打开失败, 这时obp_charset_ctype 符号已经在.symtab区域中
写脚本的方法是在编译 observer的时候增加选项:-Wl,--version-script=/data/project/src/observer/plugin_export.lds
在这里插入图片描述

ld链接器的一些参数

ld 有一些参数可能会用:

--dynamic-list-data         Add data symbols to dynamic list
--dynamic-list-cpp-new      Use C++ operator new/delete dynamic list
--dynamic-list-cpp-typeinfo Use C++ typeinfo dynamic list
--dynamic-list FILE         Read dynamic list

ld.lld 参数会有一些区别
(ld.lld 是LLVM针对gnu ld的替代品,速度更快)

链接选项增加:-Wl,--export-dynamic-symbol=obp_*
这时候这些符号都去了dynamic区了
在这里插入图片描述

相关文章:

TIPS 二进制程序暴露符号给动态链接库使用

背景 在支持插件/扩展的C/C系统中,通常会支持在程序运行时加载动态链接库。这时二进制程序会提供一些函数/接口让动态链接库调用,但是这些函数在二进制程序中又不会使用,导致在编译时编译器直接把这些符号删除了,加载链接库就会由…...

【分布式微服务云原生】8分钟掌握微服务通信的艺术:Dubbo与OpenFeign全面解析

摘要: 在构建微服务架构时,服务间的通信机制是核心要素之一。Dubbo和OpenFeign是两个非常流行的服务调用框架,它们各有千秋,适用于不同的场景。本文将深入探讨Dubbo和OpenFeign的主要特点、使用场景以及它们之间的差异&#xff0c…...

sicp每日一题[2.33]

Exercise 2.33 Fill in the missing expressions to complete the following definitions of some basic list-manipulation operations as accumulations: ; p 表示一个函数,sequence 表示一个列表 ; 这个函数将对列表中每一个元素进行 p 操作 (define (map p sequ…...

【Mybatis】常见面试题汇总 共56题

文章目录 1. 介绍下MyBatis?2. MyBatis 框架的应用场景?3. MyBatis 有哪些优点?4. MyBatis 有哪些缺点?5. MyBatis 用到了哪些设计模式?6. MyBatis常用注解有哪些?7. MyBatis 有哪些核心组件?8. MyBatis编程步骤是什么样的?9. MyBatis 和…...

每天一道面试题(17):服务网格学习笔记

什么是服务网格? 服务网格(Service Mesh)是处理微服务间通信的一种基础设施层。它主要用于解耦服务间的通信与业务逻辑,使开发者可以专注于业务实现。服务网格在微服务架构的演进中扮演了重要角色,特别是在解决服务间…...

【nrm】npm 注册表管理器

nrm是什么 nrm(NPM Registry Manager)是一个用于管理 Node.js 包管理器(如 npm 和 Yarn)的注册表工具。它可以帮助用户快速切换不同的 npm 源,以便于提高包安装的速度和效率,特别是在中国大陆地区&#xf…...

解压短视频素材资源网站推荐

如果你正在寻找解压短视频素材,那么这篇文章正是为你而写!以下是一些热门的网站,帮助你轻松找到所需的素材,快来看看吧! 蛙学网 蛙学网是国内领先的视频素材网站,提供丰富的解压视频素材。无论是放松心情的…...

Qemu开发ARM篇-6、emmc/SD卡AB分区镜像制作并通过uboot进行挂载启动

文章目录 1、AB分区镜像制作2、uboot修改3、镜像启动 在上一篇 Qemu开发ARM篇-5、buildroot制作根文件系统并挂载启动中,我们通过buildroot制作了根文件系统,并通过 SD卡的形式将其挂载到设备并成功进行了启动,但上一章中,我们的…...

Spring Boot中使用ThreadPoolTaskScheduler实现轻量级多线程定时任务

引言 在Java开发中,Spring Boot提供了多种方式来执行定时任务,如Scheduled注解和TaskScheduler。当需要执行多线程定时任务时,ThreadPoolTaskScheduler是一个轻量级的解决方案。本文将通过一个具体的业务场景,介绍如何使用Thread…...

完全二叉树的节点个数 C++ 简单问题

完全二叉树 的定义如下:在完全二叉树中,除了最底层节点可能没填满外,其余每层节点数都达到最大值,并且最下面一层的节点都集中在该层最左边的若干位置。若最底层为第 h 层,则该层包含 1~ 2h 个节点。 示例 1&#xff…...

每日一题学习笔记

给你两个字符串:ransomNote 和 magazine ,判断 ransomNote 能不能由 magazine 里面的字符构成。 如果可以,返回 true ;否则返回 false 。 magazine 中的每个字符只能在 ransomNote 中使用一次。 示例 1: 输入&#…...

从事人工智能学习Python还是学习C++?

人工智能(Artificial Intelligence,简称AI)是当今科技领域最热门的研究方向之一。AI 涉及多个学科和技术,特别是机器学习、神经网络、深度学习等技术的应用。在AI的开发过程中,编程语言的选择对于开发效率和项目实现至…...

博客摘录「 CNN中的感受野和有效感受野会对模型产生怎样的影响?」2024年9月29日

,中心像素受影响较大,离中心越远梯度信号越弱。梯度信号的衰减是指数级的,这意味着应用于感受野的大多数像素的梯度将是可忽略的(如果有的话)。 有效感受野的定义...

AURIX单片机示例:开发入门与点亮LED

文章目录 目的模板工程Blinky_LED示例链接总结 目的 这个例程比较简单,主要通过这个例程来介绍 AURIX™ Development Studio(ADS) 和 iLLD 库来开发 AURIX 系列单片机一些入门的内容。一些更为基础的资料等内容可以参考下面文章: 《英飞凌 AURIX TriCo…...

MySQL字符串函数与操作

在编程领域中,字符串操作是数据处理中至关重要的一部分。无论是文本分析、日志处理,还是格式化输出,字符串的操作技能都能极大提高工作效率。在 Python 中,字符串相关的函数和方法为开发者提供了强大的工具,帮助完成各种任务。了解如何灵活运用这些工具,能够有效提升编程…...

HTML+CSS 水滴登录页

文章目录 一、效果演示二、Code1.HTML2.CSS 三、实现思路拆分 一、效果演示 实现了一个水滴登录页的效果。页面包含一个水滴形状的登录框和两个按钮,登录框包括用户名、密码和登录按钮,按钮分别为忘记密码和注册。整个页面的设计非常有创意,采…...

基于Next.js和TailwindCss的TailwindCss

最近在研究 Next.js 和 TailwindCss ,这两天没事的时候就搞了一个 c。 目前工具部署在 Vercel ,欢迎各位体验(能提出意见更好嘿嘿) 体验地址: https://icon.999872.xyz/ 图片预览 👇...

若依开源系统多数据源整合clickhouse数据库详细步骤

1.添加依赖【pom.xml文件】 <!-- clickhouse数据源依赖--><dependency><groupId>ru.yandex.clickhouse</groupId>...

Subdominator:一款针对漏洞奖励计划的子域名安全枚举工具

关于Subdominator Subdominator是一款针对漏洞奖励计划的子域名安全枚举工具&#xff0c;可用于在漏洞搜寻和侦察过程中进行被动子域名枚举。它旨在通过高效枚举子域名和各种免费被动资源来帮助研究人员和网络安全专业人员发现潜在的安全漏洞。 Subdominator 与各种免费和付费…...

[leetcode]516_最长回文子序列

给你一个字符串 s &#xff0c;找出其中最长的回文子序列&#xff0c;并返回该序列的长度。 子序列定义为&#xff1a;不改变剩余字符顺序的情况下&#xff0c;删除某些字符或者不删除任何字符形成的一个序列。示例 1&#xff1a; 输入&#xff1a;s "bbbab" 输出&a…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

在rocky linux 9.5上在线安装 docker

前面是指南&#xff0c;后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

【网络安全产品大调研系列】2. 体验漏洞扫描

前言 2023 年漏洞扫描服务市场规模预计为 3.06&#xff08;十亿美元&#xff09;。漏洞扫描服务市场行业预计将从 2024 年的 3.48&#xff08;十亿美元&#xff09;增长到 2032 年的 9.54&#xff08;十亿美元&#xff09;。预测期内漏洞扫描服务市场 CAGR&#xff08;增长率&…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Cinnamon修改面板小工具图标

Cinnamon开始菜单-CSDN博客 设置模块都是做好的&#xff0c;比GNOME简单得多&#xff01; 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...

《C++ 模板》

目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板&#xff0c;就像一个模具&#xff0c;里面可以将不同类型的材料做成一个形状&#xff0c;其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式&#xff1a;templa…...

push [特殊字符] present

push &#x1f19a; present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中&#xff0c;push 和 present 是两种不同的视图控制器切换方式&#xff0c;它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...