动态库运行时符号解析

C/C++动态加载So编程 dladdr、dlclose、dlerror、dlopen、dlsym等动态链接加载器的编程接口和示例。 阅读详情

现在有如下代码:

main.c:

#include<stdio.h>
void print() {
    printf("print in main.c \n");
}

int main() {
    func();
    return 0;
}

temp.c:

#include<stdio.h>
void print() {
    printf("print in temp.c \n");
}

void func() {
    print();
}

将temp.c编译成动态库:gcc -fPIC -shared -o libtemp.so temp.c
然后构建可运行程序:gcc -o main main.c libtemp.so


运行之后发现输出:

printf("print in main.c \n");


这是因为:

如果一个全局符号在多个库中进行了定义,那么多该符号的引用会被绑定到扫描库时找到的第一个定义,其中扫描顺序是按照这些库在静态链接命令行中列出时从左到右的顺序。


我们可以通过readelf  -r libtemp.so 查看动态relocation section的内容:

Relocation section '.rela.plt' at offset 0x480 contains 3 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000201018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000201020  000800000007 R_X86_64_JUMP_SLO 00000000000005ec print + 0
000000201028  000500000007 R_X86_64_JUMP_SLO 0000000000000000 __cxa_finalize + 0

这说明print并没有绑定到当前库中的print符号上。那么,如果要想库中的全局符号绑定到该符号在库中的定义上,方法如下:

gcc -fPIC -shared -Wl,Bsymbolic -o libtemp.so temp.c


加上Bsymbolic之后,再次采取readelf  -r 查看动态库:

Relocation section '.rela.plt' at offset 0x480 contains 2 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000201018  000200000007 R_X86_64_JUMP_SLO 0000000000000000 puts + 0
000000201020  000500000007 R_X86_64_JUMP_SLO 0000000000000000 __cxa_finalize + 0

这个时候说明print已经不采用动态解析了,因为已经绑定到当前库中的定义上了。为了确实这一点,objdump -d libtemp.so输出如下:

00000000000005cc <print>:
 5cc:   55                      push   %rbp
 5cd:   48 89 e5                mov    %rsp,%rbp
 5d0:   48 8d 3d 5f 00 00 00    lea    0x5f(%rip),%rdi        # 636 <_fini+0xe>
 5d7:   e8 04 ff ff ff          callq  4e0 <puts@plt>
 5dc:   c9                      leaveq 
 5dd:   c3                      retq   

00000000000005de <func>:
 5de:   55                      push   %rbp
 5df:   48 89 e5                mov    %rsp,%rbp
 5e2:   b8 00 00 00 00          mov    $0x0,%eax
 5e7:   e8 e0 ff ff ff          <span style="color:#FF0000;">callq  5cc <print></span>
 5ec:   c9                      leaveq 
 5ed:   c3                      retq   
 5ee:   66 90                   xchg   %ax,%ax

最后,如果一个库中的函数不对外公开,只是内部使用,那么最好是在函数的定义前面加上static。

MinGW与MSVC动态库(.dll/.a/.lib)的链接机制深度解析:从编译链接到运行时加载 本文深度解析了MinGW与MSVC编译器在Windows平台下处理动态库(.dll/.a/.lib)的链接机制差异。核心在于MSVC链接时必须依赖导入库(.lib),而MinGW链接器可直接读取.dll或使用.a引导文件。文章从编译链接原理、二进制文件结构到运行时加载,系统阐述了两者的工作流程,并提供了跨编译器互操作及Qt项目中的实战指南。 阅读详情

相关推荐

C++静态库与动态库:原理、创建、使用与工程实践指南

在软件工程中,库是代码复用和模块化设计的核心概念,它将通用功能封装为可复用的二进制组件。从原理上看,库分为静态库和动态库两种主要形式,其根本差异在于链接时机和代码合并方式。静态库在编译链接期将代码直接复制到最终可执行文件中,生成独立、自包含的程序,但会导致磁盘空间浪费和更新困难;动态库则在运行时被加载和映射到进程内存空间,支持多进程共享同一份代码,显著节省内存并便于模块化更新,但带来了依赖管理和版本兼容性等挑战。这两种技术方案在性能、部署、维护等方面各有优劣,其选择直接影响程序的体积、启动速度、内存占用和部

weixin_34319374的博客 349

解析C++库文件(.a/.so)的生成方法以及与源文件(.cpp)、头文件(.h)的关系

解析C++库文件(.a/.so)的生成方法以及与源文件(.cpp)、头文件(.h)的关系 在一个C++工程中,并非所有的代码都会被编译为可执行文件。只有带有main函数的文件才会生成可执行文件。而对于其他代码,我们只想将其大包围一个东西,供其他程序调用,这个东西就叫做库。生成库文件的过程如下。 1.库文件生成方法 首先,我们自己编写一个简单的代码libHello.cpp //这是一个库文件 #include <iostream> using namespace std; void prin

CH_monsy的博客 4340

千兆以太网的接收和crc校验

解析该以太网帧,包括统计该以太网帧长度+过滤功能(端口号对不对,是否为udp协议)+CRC校验,将解析结果存入状态fifo,一旦状态fifo开始有数,就开始开启读过程,读过程开始时,首先读状态fifo,根据从状态fifo里面读出的以太网帧长度,来读数据fifo(这样能够防止跨帧读),然后在根据状态fifo里面读出的crc校验正确标志和过滤标志,来确定是否将数据fifo读出来的数据送给下一个模块。改掉之后在抓一下,可以看到抓出来的数据完全正确,从最后开始看,除去4个crc校验的尾巴,数据是到255结束的。

weixin_45284871的博客 2739

Linux so剖析

Linux so剖析 此处so指Shared Object,即动态链接库,本文将从so文件格式开始讲述,在了解完so文件格式的必要知识后,接下来最简概述so的生成,即编译器的静态链接,然后便是so的加载与动态链接,以及动态链接库的依赖动态链接库。 so的文件格式为ELF(Executable and Linkable Format),ELF由Unix System Laboratories开发,已经成为标准。常见的动态链接库(so), 静态库(a), 编译目标文件(o), 可执行文件, CoreDump文件

胡超的学习日志 3986

硬核拆解华为/大疆/小米硬件面试真题:手撕电路+考点思维导图(附答案)

设计一个增益为20dB、带宽≥100kHz的同相放大器,电源电压±5V,要求输出摆幅≥8V。12位ADC的参考电压2.5V,输入信号1kHz正弦波,峰峰值2V。输入24V转5V/10A的同步降压电路,开关频率500kHz,计算MOSFET的损耗并选择型号(需提供TI官网截图)。设计无人机图传系统,要求1080P@30fps,传输距离2km。FPGA设计中,100MHz时钟域到50MHz时钟域传输32位数据,给出同步方案并画时序图。“设计一个输入12V、输出5V/3A的同步降压电路,给出关键参数计算”

qq_63103361的博客 3538

洛谷P5707 【深基2.例12】上学迟到(c语言)

第一篇题解 题目描述 yyy 的学校要求早上 8 点前到达。学校到 yyy 的家一共有 s(s\le 10000)s(s≤10000) 米,而 yyy 可以以 v(v<10000)v(v<10000) 米每分钟的速度匀速走到学校。此外在上学路上它还要额外花 10 分钟时间进行垃圾分类。请问为了避免迟到 yyy 最晚什么时候出门?输出 HH:MM 的时间格式,不足两位时补零。由于路途遥远, yyy 可能不得不提前一天出发,不过不可能提前超过一天。 输入格式 两个正整数 s,v,意思已经在题目中给定

cc_love_program的博客 1万+

[Linux][C/C++]运行时遍历ELF程序头(Program Header)获取符号表和符号版本信息

Linux 采用 ELF 作为其可链接可执行文件的格式,并提供诸如 nm 之类的工具进行 ELF 符号表的解析。比如,一个简单的 Hello World 程序: #include <iostream> using namespace std; int main() { cout << "Hello World!" << endl; return 0; } 我们可以利用 nm 命令查看 Hello World 程序依赖的动态链接符号,以及各个符号所对应的

modisir的博客 1265

MicroLogix1400编程(使用RSLogix 500 + RSLinx Classic Lite)

MicroLogix1400编程

noscallion的博客 1万+

[Linux][C/C++]通过ELF读取当前进程的符号表并获取符号的版本信息

Linux 采用 ELF 作为其可链接可执行文件的格式,并提供诸如 nm 之类的工具进行 ELF 符号表的解析。如下例程: #include <pthread.h> int main() { pthread_cond_t cond; pthread_cond_init(&cond, NULL); pthread_cond_destroy(&cond); return 0; } ...

modisir的博客 3736

数字IC设计(8)之AHB-Lite总线(持续更新)

AHB总线全称Advanced High-performance Bus,意为先进高性能总线。推出该总线的目的是补充APB总线在性能上的不足,APB总线适合挂载低速外设,所以AHB总线用来挂载高性能的外设,这样子可以分工合作,节约资源。AHB总线可以实现多主多从的连接,此时需要设计仲裁机和matrix(矩阵),AHB-Lite一般用于一主多从,此时则不需要仲裁机和matrix,但是也可以用AHB-Lite来实现多主多从,就是设计多个layer,每个layer是一主多从,再把各个layer连起来;

qq_69440734的博客 2256

Android 面试题 Handler篇

1.Handler的实现原理。

ViewHandKownHealth的博客 955

Cling动态库管理:如何实现运行时动态加载与符号解析

Cling作为一款强大的交互式C++解释器,其动态库管理功能让开发者能够在运行时灵活加载和卸载共享库,实现真正的动态编程体验。本文将详细介绍Cling动态库管理的核心机制,教你如何利用这一功能提升C++开发效率。 ## 🔍 什么是Cling动态库管理? Cling的动态库管理系统允许你在不重新编译程序的情况下,实时加载、卸载和调用共享库中的函数。这对于快速原型开发、插件系统和交互式数据分析至

gitblog_00538的博客 248

Android NDK/JNI面试题大全及参考答案(3万字长文)

是一套工具集合,它允许开发者为Android平台编写原生应用程序或者应用程序的部分模块。NDK 主要用于开发那些需要高性能计算的应用程序,例如游戏引擎、图像处理软件或音频/视频编码解码器等。通过使用 C 或 C++ 编写代码,开发者可以利用硬件加速功能,提高应用性能。NDK 提供了一系列工具来帮助开发者完成从源代码到可执行文件的整个过程,包括编译、链接、调试等功能。

大模型大数据攻城狮的专栏 1257

TBOOX/TBOX动态库加载:运行时动态链接与符号解析

在现代软件开发中,动态库(Dynamic Library)技术是实现模块化、插件化架构的核心技术之一。TBOX作为一款跨平台的C语言基础库,提供了统一、简洁的动态库加载接口,让开发者能够在不同操作系统上实现一致的运行时动态链接体验。 本文将深入探讨TBOX动态库加载机制,涵盖运行时动态链接原理、符号解析机制、跨平台实现细节,并通过实际代码示例展示如何高效使用这一功能。 ## 动态库加载基础概念...

gitblog_00695的博客 572

SAP-MM-供应商对账平台(功能集合)

(1)集成OA审批,线上核销,结果写入SAP; (2)集成SRM,线上与供应商对账确认,写入SAP; (3)集成财务付款结果确认写入,OA回传结果,定时同步SRM供应商平台。 欢迎留言交流,功能完善,如需要页面设计,请订阅专栏

qq_32198063的博客 748

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

dlopen_dlsym:运行时加载动态库

本文介绍了动态库运行时加载技术dlopen/dlsym的核心概念与应用。通过动态加载库,开发者可以实现插件架构、延迟加载和条件加载等功能。文章详细解析了dlopen和dlsym的函数原型、参数及返回值,并提供了完整的代码示例演示如何加载动态库并调用其中的函数。此外,还探讨了错误处理、符号版本管理、跨平台适配等高级主题,以及性能优化和安全注意事项。这种技术为软件提供了更高的灵活性和扩展性,特别适合需要动态功能加载的场景,如插件系统和模块化应用程序开发。

always_TT的博客 883

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

C/C++动态库依赖全解析:从编译链接到运行时加载的完整指南

动态链接库(DLL/SO)是现代软件开发中实现代码复用和模块化的核心技术。其核心原理在于符号解析与动态绑定机制:编译时链接器记录所需符号的声明信息,运行时加载器则负责在内存中定位并绑定这些符号的真实地址。这一分离机制带来了模块化更新和资源节省的优势,但也引入了编译期与运行期依赖不一致的经典问题。在工程实践中,通过RPATH/RUNPATH、符号可见性控制(如-fvisibility=hidden)等技术手段,可以有效管理库文件的查找路径和符号冲突。这些技术对于构建稳定可移植的C/C++应用程序至关重要,尤其

dflkg8956的专栏 393

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深入解析 Linux 中动静态库的加载机制:从原理到实践

静态库适用于独立部署和嵌入式环境。动态库优化资源利用,支持热更新和模块化设计。掌握两者的加载原理和技术细节,开发者能够:✅ 设计高性能、易维护的软件架构✅ 快速诊断依赖和兼容性问题✅ 实现安全可靠的库管理策略。

2301_76794365的博客 1571

你真的懂动态库符号版本吗?:一个老程序员的血泪实践分享

掌握C语言动态库的版本兼容符号管理,解决升级兼容难题。本文分享符号版本控制在实际项目中的应用技巧与避坑经验,提升库的稳定性与可维护性,老程序员实战总结,值得收藏。

QuickDebug的博客 992

动态库链接顺序如何影响符号冲突?一个GCC实战案例解析

本文通过一个GCC实战案例,深入解析了动态库链接顺序如何影响符号冲突的解决。当多个动态库存在同名符号时,链接器会依据优先级规则进行选择,而命令行中动态库的出现顺序往往是决定性因素。理解这一机制对于排查C/C++项目中因符号冲突引发的隐蔽运行时错误至关重要。

ik67890123的博客 395

C语言动态库更新后程序崩溃?一文搞懂符号版本控制与兼容策略

解决C语言动态库更新兼容难题,本文深入解析符号版本控制与兼容策略,涵盖实际应用场景及GNU符号版本机制。掌握动态库升级不崩溃的关键方法,提升系统稳定性,C语言动态库的版本兼容处理实用指南值得收藏。

VarChat的博客 1077

为什么编译二进制时也要链接动态库,只需要头文件可以吗

当两个动态库(.so)包含同名函数时,编译链接阶段不会报 “重定义(multiple definition)” 错误(这和静态库 / 源码重定义完全不同),但运行时会触发 “符号遮蔽(Symbol Hiding)” 问题—— 动态链接器会优先绑定 “先加载的那个库中的函数”,后加载的库中的同名函数永远不会被调用,最终导致逻辑错误(或崩溃,若函数签名不一致)。动态库同名函数 → 编译链接 “无感知”,运行时 “选第一个”,无重定义错误,但有隐性逻辑问题;

he_wen_jie的博客 891

c++动态库静态库

动态库编译程序只加载连接符号,运行程序时通过符号加载对应库文件函数。 静态库编译程序连接符号和函数体同时打包到一起,运行程序时也是通过符号进行加载函数体。 共同点:内存启动原理是现用现开辟;并且跟随类创建自己独立运行内存空间;类似多个子类同时创建对象,那么基类内存空间都是独立的一样。重点静态库不代表静态(static);动态库和静态库只是程序部署的一种解决方案。 不同点:动态库是把整体进行分...

一个草根敲键盘的故事 301

C/C++程序编译与链接(三) 动态库的概念

对一些核心动态库(比如libc.so,libstd++.so等),这些都不是问题,因为这些库的位置,都已经被预先内置到系统中。但是对我们自己依赖动态库的程序,要想运行必须有两点:1. 操作系统中有程序需要的动态库。构建动态库生成的二进制文件本质上与可执行文件是相同的,唯一的区别在与动态库缺少了让其独立执行的启动程例程。运行时需要将可执行程序的符号正确解析到正确的地址上,这个地址是动态库所映射到进程内存映射中的地址。与路径一样,对操作系统自身的功能动态库,版本都是适配于操作系统的最合适的版本。

mo4776的博客 594

linux仓库深入解析Linux动态链接与动态库加载:理解背后的原理与技巧 - App

https://blog.youkuaiyun.com/egoist2023/article/details/152362060?sharetype=blogdetail&shareId=152362060&sharerefer=APP&sharesource=2401_85812043&sharefrom=link

2401_85812043的博客 131

备战2020校招日记----4.17

文章目录0.目标完成情况1. 知识复盘1.1 符号解析1.2 静态库1.3 重定位1.4 生成可执行文件1.5 共享库(动态链接库)1.6 共享库的运行时链接回答自己的问题明日目标 0.目标完成情况 LeetCode两道 ---- 没做,实在不想做啊,这东西一旦不做就不想做了。 侯捷的视频---- 没看。 csapp第7章看完符号解析----- 超额完成,前11节都看完了,后面不打算看了。...

ustc_sse_shenzhang的博客 225
上一篇: How to compile/build QEMU 1.4.0 on Ubuntu 12.04
下一篇: Android Audio Policy小记
Sailingthink
博客等级 码龄14年 31粉丝 26原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值