隐藏链接到 .so 文件的第 3 方 .a 文件中的符号

2024-01-20

我正在构建一个共享 (.so) 库,该库由多个 .a 文件和调用它们的瘦 API 层组成。我只希望我的 API 和外部依赖项可见,因此我使用 GCC 提供的“隐藏”可见性构建代码(-fvisibility=hidden).

然而,其中一个库是专有的第三方 .a 文件(我们已付费使用),我只能访问其二进制文件。当我将其静态链接到我的 .so 文件中时,它的符号在我的 .so 的动态符号表中可见。我猜测这是因为该库不是使用隐藏的可见性选项构建的。我宁愿将这些功能隐藏起来,因为它们管理我们软件的敏感部分,并且我不希望第三方链接到这些符号。

有什么方法可以在事后将这些符号标记为“隐藏”,以便它们不会出现在我的 .so 文件的符号列表中?我看过objdump and objcopy但我很难理解这些术语。

我尝试过的其他事情:

  • 从 .a 中提取 .o 并尝试按照此处所述重新编译:如何将预构建的目标文件添加到 cmake 中的可执行文件中 https://stackoverflow.com/questions/38609303/how-to-add-prebuilt-object-files-to-executable-in-cmake

这是如何解决您的问题的一个有效示例。

这是您无法重新编译的专有静态库的源代码:

$ cat tpa.c
int tpa(void)
{
    return 2;
}
$ cat tpb.c
int tpb(void)
{
    return 3;
}

The library, libtp.a, must have been built essentially like this1:

$ gcc -fPIC -c -O1 tpa.c tpb.c
$ ar rcs libtp.a tpa.o tpb.o

的符号表tpa.o and tpb.o are:-

$ readelf -s libtp.a

File: libtp.a(tpa.o)

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS tpa.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     9: 0000000000000000    10 FUNC    GLOBAL DEFAULT    1 tpa

File: libtp.a(tpb.o)

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS tpb.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     9: 0000000000000000    10 FUNC    GLOBAL DEFAULT    1 tpb

您可以看到两个功能符号tpa and tpb are GLOBAL( = 可用于链接) 并且有DEFAULT动态可见性,不HIDDEN.

现在这是您自己的静态库的源代码,libus.a

$ cat usa.c
int usa(void)
{
    return 5;
}
$ cat usb.c
int usb(void)
{
    return 7;
}

你像这样构建:

$ gcc -fPIC -c -O1 -fvisibility=hidden usa.c usb.c
$ ar rcs libus.a usa.o usb.o

中的函数符号libus.a也都是GLOBAL但他们的动态 能见度是HIDDEN:-

$ readelf -s libus.a

File: libus.a(usa.o)

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS usa.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     9: 0000000000000000    10 FUNC    GLOBAL HIDDEN     1 usa

File: libus.a(usb.o)

Symbol table '.symtab' contains 10 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 FILE    LOCAL  DEFAULT  ABS usb.c
     2: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     3: 0000000000000000     0 SECTION LOCAL  DEFAULT    2 
     4: 0000000000000000     0 SECTION LOCAL  DEFAULT    3 
     5: 0000000000000000     0 SECTION LOCAL  DEFAULT    5 
     6: 0000000000000000     0 SECTION LOCAL  DEFAULT    6 
     7: 0000000000000000     0 SECTION LOCAL  DEFAULT    7 
     8: 0000000000000000     0 SECTION LOCAL  DEFAULT    4 
     9: 0000000000000000    10 FUNC    GLOBAL HIDDEN     1 usb

这是共享库的源代码:

$ cat usc.c
extern int tpa(void);
extern int tpb(void);
extern int usa(void);
extern int usb(void);

int usc(void)
{
    return tpa() * tpb() * usa() * usb();
}

你编译的:-

$ gcc -fPIC -c -O1 usc.c

现在你想要链接usc.o, libtp.a and libus.a在您的共享库中libsus.so。如果你 用普通方法做:

$ gcc -shared -o libsus.so usc.o -L. -ltp -lus

然后你会发现:

$ readelf --dyn-syms libsus.so

Symbol table '.dynsym' contains 8 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __cxa_finalize
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 0000000000001139    38 FUNC    GLOBAL DEFAULT   12 usc
     6: 000000000000115f    10 FUNC    GLOBAL DEFAULT   12 tpa
     7: 0000000000001169    10 FUNC    GLOBAL DEFAULT   12 tpb

认为HIDDEN可见性符号来自libus.a动态中不存在 符号表,但是DEFAULT可见性符号来自libtp.a被包含在内, 你不想要的。

要排除后者,请按如下方式链接您的共享库:

$ gcc -shared -o libsus.so usc.o -L. -ltp -lus -Wl,--exclude-libs=libtp.a

那么动态符号表就变成:

$ readelf --dyn-syms libsus.so

Symbol table '.dynsym' contains 6 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __cxa_finalize
     2: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_registerTMCloneTable
     3: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND _ITM_deregisterTMCloneTab
     4: 0000000000000000     0 NOTYPE  WEAK   DEFAULT  UND __gmon_start__
     5: 00000000000010f9    38 FUNC    GLOBAL DEFAULT   10 usc

如你所愿。

链接器选项--exclude-libs is 有记录的 https://sourceware.org/binutils/docs/ld/Options.html#Options:

--排除库 lib,lib,...

指定不应自动导出符号的存档库列表。 库名称可以用逗号或冒号分隔。指定 --exclude-libs ALL 会从自动导出中排除所有存档库中的符号。 ... 对于 ELF 目标端口,受此选项影响的符号将被视为隐藏。

为了确保tp*符号定义have已链接,你 仍然可以在共享库的完整符号表中看到它们:

$ readelf -s libsus.so | egrep 'FUNC.*(us|tp)(a|b|c)' 
     5: 00000000000010f9    38 FUNC    GLOBAL DEFAULT   10 usc
    41: 0000000000001133    10 FUNC    LOCAL  DEFAULT   10 usa
    44: 000000000000111f    10 FUNC    LOCAL  DEFAULT   10 tpa
    46: 000000000000113d    10 FUNC    LOCAL  DEFAULT   10 usb
    48: 0000000000001129    10 FUNC    LOCAL  DEFAULT   10 tpb
    50: 00000000000010f9    38 FUNC    GLOBAL DEFAULT   10 usc

就像显式隐藏一样us*符号,它们成为LOCAL,不可用于进一步链接。 (你看usc两次在grep因为它被列为全局符号和动态符号)。

正如你可以从中推断出的那样,我们不需要费力去编译我们的 自己的us*代码与-fvisibility=hidden,只要我们要存档 它在libus.a以便进一步联动。我们可以像这样链接共享库:

$ gcc -shared -o libsus.so usc.o -L. -ltp -lus -Wl,--exclude-libs=libtp.a,libus.a

具有相同的效果。


[1] I specify -fPIC explicitly to be sure of generating position-independent object code that I can link in a DSO, but this has been the GCC default since GCC 6.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

隐藏链接到 .so 文件的第 3 方 .a 文件中的符号 的相关文章

  • 检测到 NuGet 包的版本冲突

    我正在开发 ASP Net core 2 1 Web 应用程序项目 我的解决方案中有 1 个项目和 3 个其他库 它是高级架构 数据访问层 DAL 业务层 BL 公共层 CL 所以我需要添加引用来连接一些库和项目 我已经添加了CL参考我的项
  • Tensorflow 中的自定义资源

    由于某些原因 我需要为 Tensorflow 实现自定义资源 我试图从查找表实现中获得灵感 如果我理解得好的话 我需要实现3个TF操作 创建我的资源 资源的初始化 例如 在查找表的情况下填充哈希表 执行查找 查找 查询步骤 为了促进实施 我
  • C++ 中的软(不是:弱)引用 - 这可能吗?有实施吗?

    在 C 中我正在使用boost shared ptr and boost weak ptr自动删除不再需要的对象 我知道这些与引用计数一起工作 在 Java 中 内存由垃圾收集器管理 它将内置对象引用视为strong WeakReferen
  • 为什么基类必须有一个带有 0 个参数的构造函数?

    这不会编译 namespace Constructor0Args class Base public Base int x class Derived Base class Program static void Main string a
  • 通信对象 System.ServiceModel.Channels.ServiceChannel 不能用于通信

    通信对象System ServiceModel Channels ServiceChannel 无法用于通信 因为它处于故障状态 这个错误到底是什么意思 我该如何解决它 您收到此错误是因为您让服务器端发生 NET 异常 并且您没有捕获并处理
  • Guid 应包含 32 位数字和 4 个破折号

    我有一个包含 createuserwizard 控件的网站 创建帐户后 验证电子邮件及其验证 URL 将发送到用户的电子邮件地址 但是 当我进行测试运行时 单击电子邮件中的 URL 时 会出现以下错误 Guid should contain
  • 在 Xcode4 中使用 Boost

    有人设置 C Xcode4 项目来使用 Boost 吗 对于一个简单的 C 控制台应用程序 我需要在 Xcode 中设置哪些设置 Thanks 用这个来管理它 和这个
  • TextBox 焦点的 WinForms 事件?

    我想添加一个偶数TextBox当它有焦点时 我知道我可以用一个简单的方法来做到这一点textbox1 Focus并检查布尔值 但我不想那样做 我想这样做 this tGID Focus new System EventHandler thi
  • VS30063:您无权访问 https://dev.azure.com

    我正在尝试在 asp net core 2 1 mvc 应用程序中使用以下代码连接 Azure DevOps Uri orgUrl new Uri https dev azure com xxxxx String personalAcces
  • 禁用 LINQ 上下文的所有延迟加载或强制预先加载

    我有一个文档生成器 目前包含约 200 个项目的查询 但完成后可能会超过 500 个 我最近注意到一些映射表示延迟加载 这给文档生成器带来了一个问题 因为它需要根据生成的文档来访问所有这些属性 虽然我知道DataLoadOptions可以指
  • 事件日志写入错误

    很简单 我想向事件日志写入一些内容 protected override void OnStop TODO Add code here to perform any tear down necessary to stop your serv
  • 用于从字符串安全转换的辅助函数

    回到 VB6 我编写了一些函数 让我在编码时无需关心字符串的 null 和 数字的 null 和 0 等之间的区别 编码时 没有什么比添加特殊情况更能降低我的工作效率了用于处理可能导致一些不相关错误的数据的代码 9999 10000 如果我
  • C# using 语句、SQL 和 SqlConnection

    使用 using 语句 C SQL 可以吗 private static void CreateCommand string queryString string connectionString using SqlConnection c
  • 如何排列表格中的项目 - MVC3 视图 (Index.cshtml)

    我想使用 ASP NET MVC3 显示特定类型食品样本中存在的不同类型维生素的含量 如何在我的视图 Index cshtml 中显示它 an example 这些是我的代码 table tr th th foreach var m in
  • 在 C 中复制两个相邻字节的最快方法是什么?

    好吧 让我们从最明显的解决方案开始 memcpy Ptr const char a b 2 调用库函数的开销相当大 编译器有时不会优化它 我不会依赖编译器优化 但即使 GCC 很聪明 如果我将程序移植到带有垃圾编译器的更奇特的平台上 我也不
  • UWP 无法在两个应用程序之间创建本地主机连接

    我正在尝试在两个 UWP 应用程序之间设置 TCP 连接 当服务器和客户端在同一个应用程序中运行时 它可以正常工作 但是 当我将服务器部分移动到一个应用程序并将客户端部分移动到另一个应用程序时 ConnectAsync 会引发异常 服务器未
  • Qt - 设置不可编辑的QComboBox的显示文本

    我想将 QComboBox 的文本设置为某些自定义文本 不在 QComboBox 的列表中 而不将此文本添加为 QComboBox 的项目 此行为可以在可编辑的 QComboBox 上实现QComboBox setEditText cons
  • 是否有一个 C++ 库可以从 PDF 文件中提取文本,例如 PDFBox for Java? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 去年 我使用 PDFBox 在 Java 中创建了一个应用程序来获取某些 PDF 文件中的原始文本 现在
  • 内核开发和 C++ [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 从我know https stackoverflow com questions 580292 what languages are windo
  • Azure函数版本2.0-应用程序blobTrigger不工作

    我有一个工作功能应用程序 它有一个 blob 输入和一个事件中心输出 在测试版中工作 随着最新的更改 我的功能不再起作用 我尝试根据发行说明更新 host json 文件 但它没有引用 blob 触发器 version 2 0 extens

随机推荐

  • 如何使用任何库在Python中将RTF字符串转换为纯文本[重复]

    这个问题在这里已经有答案了 我想在不使用正则表达式的情况下将 rtf 字符串转换为纯文本 rtfstring rtf1 ansi ansicpg1252 deff0 deflang1033 fonttbl f0 Arial colortbl
  • 如何使用curl 通过代理模拟来自Firefox 的请求?

    特别是 当我将 Firefox 设置为使用 https 流量代理时 我尝试复制 Firefox 的行为 根据我的测试 Firefox 似乎向代理发送 CONNECT 请求 而以下curl 命令直接向代理发送 GET curl proxy b
  • 将列表框的选定值显示为标签 - 多个值

    我有一个名为 lstPTLNameDHOD 的列表框 其中有多个 PTL 名称 可以使用 Ctrl 键选择这些名称 我想在标签中显示选定的姓名 或者以某种方式显示提交表单的人可以看到他们提交表单的确切对象 我的问题是我只能在标签上显示一个名
  • Python:使用另一个大字典更新一个大字典

    我正在尝试使用另一个字典中的值来更新大型字典的某些值 其中它们具有相似的键 相同的日期但格式不同 我当前使用的流程太慢 我想减少瓶颈 这是我当前的解决方案 它将更新的字典写入文件 from dateutil import parser Fi
  • 在 Node.js 中共享对象并避免全局变量

    在下面的代码片段中共享数据库连接的最合适的方式是什么 db变量 与我的路由器 控制器 无需转动db变量变成全局变量 var mongo require mongoskin db mongo db config db adress app u
  • 使用 Akka 以编程方式获取临时端口

    如果我在 Akka 中将 ActorSystem 配置为使用临时 tcp 端口 更具体地说 我将 http 端口配置为 0 有没有办法在 ActorSystem 启动后以编程方式获取此端口 任何使用 actorOf 创建 Actor 的尝试
  • 如何找到 3 个数组的交集,同时忽略空数组?

    我必须找到 3 个整数数组的交集元素 有条件地说a b c 如果数组中的任何一个为 null 只需忽略该数组并找到剩余数组的交集 如果三个都为 null 则返回 提前致谢 ps 红宝石1 9 3 一种方法是这样的 a b c tap a a
  • Docker 编写安装requirements.txt

    在我的 docker 镜像中 我正在克隆 git master 分支来检索代码 我使用 docker compose 作为开发环境 并使用卷运行容器 我在从 python requests txt 文件安装新项目需求时遇到了问题 在开发环境
  • 如何在 IntelliJ 中调试 Clojure 文件?

    第5行不能设置断点 其中包含 x IntelliJ 不会让我这样做 我使用了不同的插件 例如拉克洛胡尔 https github com JetBrains la clojure and Cursive https cursivecloju
  • RMarkdown 可折叠面板

    当我正在为学生准备教程时 我需要一种方法来隐藏可折叠面板中的内容 这些内容可以通过单击按钮来显示 我已经使用下面的代码让它工作了 RMarkdown 文件如下所示 title Collapsible Panel output html do
  • 显示文本区域的当前行号和列号

    我正在我的网络应用程序中制作一个文件编辑界面 我有一个包含文件内容的文本区域 当文本区域聚焦时 我想输出光标的位置 即行号和列 这很有用 因为错误消息通常会产生行号 问题是 如何确定文本区域中光标的位置 我正在使用原型库 也许已经有解决方案
  • 使用 Gold Parser 解析项目和包文件 --“IdList”需要帮助

    我正在涉足对象帕斯卡引擎 http goldparser org engine 1 pascal index htm 作者 Rob van den Brink 并且看起来 除了一些小的且容易纠正的错误 它适用于 Delphi 单元文件 但是
  • 验证驾驶执照号码?

    我正在开发 ACH 支付处理器 想知道是否可以根据某些规则来确定驾驶执照领域的范围 对此有什么想法吗 我可以只假设数字还是其他更像 SSN 的数字 Thanks 我为我正在从事的一个项目想出了这个 function utilities fu
  • SQL 查询从列中提取文本并将其存储到同一记录中的不同列

    我需要一些有关 SQL 查询的帮助 我有一个 SQL 表 其中包含已提交表单的列详细信息 我需要获取存储在该列中的部分文本 并将其放入同一行的不同列中 我需要复制的文本位始终位于列中的相同位置 任何帮助将不胜感激 伙计们 我的脑子一片空白
  • Symfony 中的 Doctrine 实体中的 @var 注释是什么?

    也许是一个愚蠢的问题 但我不知道这让我烦恼 当我创建一个实体时app console doctrine generate entity它添加了一个 var每个属性的注释 什么是 var用于 它显然表明了数据类型 但我没有看到任何文档中提到它
  • 无法使用微软编译器编译Qt

    我想使用 VS2010 编译器构建 Qt 4 7 3 但在配置时遇到问题 我正在使用 VS command shell 我的配置命令如下所示 configure exe platform win32 msvc2010 no webkit n
  • 有没有办法在 iOS 中以编程方式打开和关闭蓝牙和/或 WiFi?

    我正在寻找一种简单的方法来在 iOS 4 x 设备 iPhone 和 iPad 上切换蓝牙和 WiFi 的打开和关闭状态 当我在不同的位置和使用场景之间移动时 我会不断切换这些功能 现在需要多次点击并访问 设置 应用程序 我希望创建一个简单
  • 如何使用Python找到any()中匹配的内容?

    我正在用Python工作 使用any https docs python org 2 library functions html any像这样寻找 a 之间的匹配String 数组和从 Reddit API 中提取的评论 目前 我正在这样
  • 保持 GH 主页与 README.md 同步

    在为我的项目创建 GitHub Pages 时 建议我导入现有的README md作为项目的主页 后来我合并了gh pages with master并最终得到了两者index html and README md 问题 是更新README
  • 隐藏链接到 .so 文件的第 3 方 .a 文件中的符号

    我正在构建一个共享 so 库 该库由多个 a 文件和调用它们的瘦 API 层组成 我只希望我的 API 和外部依赖项可见 因此我使用 GCC 提供的 隐藏 可见性构建代码 fvisibility hidden 然而 其中一个库是专有的第三方