编译器细节:动态链接与静态链接行为分析

news/2025/10/2 12:51:58/文章来源:https://www.cnblogs.com/Whitejoce/p/19123479

gccld.so (以 Alpine Linux为例)

  • 背景:Alpine Linux 是一个基于 musl libc 和 busybox 构建的轻量级 Linux 发行版,专注于安全性、资源效率和简洁性。它被广泛用于 Docker 容器、嵌入式系统和云计算环境。

gccld.so 分别是什么?

ld.sodynamic linker/loader)是程序运行时的动态链接器。gcc 在编译期决定程序如何被加载,而 ld.so 在运行时执行加载。

1. gcc(GNU Compiler Collection)

  • 功能:将 C/C++ 源代码编译成目标文件(.o),并调用链接器(ld)生成可执行文件。
  • 它本身不直接做动态链接,但它会:
    • 调用汇编器(as
    • 调用链接器(ld,来自 binutils)
    • 在链接时指定使用哪个 动态链接器(dynamic linker)
示例:当你运行 `gcc main.c -o app`,gcc 实际上做了:
源码 .c↓
预处理 (cpp)        → #include, #define 展开↓
编译 (cc1)          → 生成汇编代码(.s)↓
汇编 (as)           → 生成目标文件(.o)↓
链接 (ld)           → 合并所有 .o 和库,生成可执行文件

2. ld.so / ld-musl-*(动态链接器,Dynamic Linker/Loader)

  • 功能
    • 程序启动时由内核加载
    • 负责加载程序依赖的共享库(如 libc.so, libpthread.so 等)
    • 进行符号解析、重定位
    • 然后跳转到程序入口 _startmain

⚠️ 注意:ld.so 是 GNU glibc 中对动态链接器的称呼,在 musl 中它叫 ld-musl-*,但作用相同。


一、动态链接:编译期 vs 运行时

gcc 默认进行动态链接

阶段 参与者 职责
编译/链接期 gcc + ld(链接器) 将源码编译为可执行文件,并在其中嵌入一个名为 .interp 的段,用于指定运行时的动态链接器路径。
运行期 内核 + ld.so 内核加载程序,读取 .interp 段,然后加载并执行指定的动态链接器(如 ld-musl-*ld-linux-*)。动态链接器负责加载所有依赖的共享库,并启动程序。

它们通过 动态链接 建立联系:

gcc hello.c -o hello
  1. 预处理 + 编译
    gcc 把 hello.c 编译成目标文件 hello.o

  2. 链接(Linking)
    gcc 调用 ld(GNU linker,属于 binutils)进行链接

  3. 关键一步:嵌入“解释器”路径(INTERP segment)

    • 链接器会在最终的 ELF 可执行文件中写入一个特殊的段:.interp
    • 内容是动态链接器的路径,例如:
      /lib/ld-musl-x86_64.so.1
      
    • 这个路径是在链接时由 gcc 使用的 "specs" 文件或 crt 对象文件决定的
  4. 运行时:内核发现 .interp 后,先加载 ld-musl,再由它加载程序和 libc

    execve("hello", ...) → 内核读取 ELF 的 .interp: "/lib/ld-musl-x86_64.so.1"→ 先加载 ld-musl→ ld-musl 加载 libmusl.so(即 libc 实现)→ 解析符号,完成重定位→ 跳转到 _start → main()
    

所以:

gcc 编译时,将 ld.so 的路径写入.interp 段,告诉内核在运行时使用哪个动态链接器。


二、静态链接:无运行时依赖

静态链接通过 -static 标志实现,它将所有依赖库的代码直接复制到最终的可执行文件中。

$ gcc --verbose -static hello.c -o hello
#include "..." search starts here:
#include <...> search starts here:/usr/include
End of search list.
...
COLLECT_GCC_OPTIONS='--verbose' '-static' '-mtune=generic' .../usr/lib/gcc/x86_64-linux-gnu/11/cc1 -quiet -imultiarch x86_64-linux-gnu ...as ... -o /tmp/ccXXXXXX.o.../usr/bin/ld --hash-style=gnu --build-id --eh-frame-hdr -m elf_x86_64 \-static [... lots of .a files...] \-o hello-static
# 只是 ld 多了一个 -static 参数,表示要静态链接
# 链接器加载了 libc.a, libgcc.a, crt*.o 等静态对象

意味着:

  • 所有需要的库代码(包括 libc 中的 printf, malloc 等)都被直接复制进最终的二进制文件中
  • 不再依赖外部 .so 文件
  • 没有 .interp
  • 不需要动态链接器参与启动过程

此时程序结构更简单:

用户执行 ./hello→ 内核直接加载整个程序映像(包含所有代码)→ 直接跳转到入口点 _start → main()

你可以通过以下命令验证一个程序是否为静态链接:

# 输出类似 "statically linked" 的信息
file ./hello
# 如果输出 "not a dynamic executable",则是静态链接
ldd ./hello
# 如果没有输出,则表示没有 .interp 段
readelf -l ./hello | grep 'INTERP'

三、Alpine (musl) vs. 主流发行版 (glibc)

Alpine 的 gcc 是为 musl C特别配置的,这与 Ubuntu/CentOS 等使用 glibc 的系统有本质区别。

项目 Alpine Linux (musl) Ubuntu/CentOS (glibc)
C 标准库 musl libc glibc
动态链接器 /lib/ld-musl-*.so.1 /lib/ld-linux-*.so.2
target triplet *-alpine-linux-musl *-pc-linux-gnu
可移植性 musl 静态链接的程序通常具有更好的跨发行版可移植性。 glibc 静态链接的程序可能因依赖 NSS 等机制而无法在 Alpine 上运行。

target triplet:*-vendor-os-libc,* 代表架构,如 x86_64

具体差异在哪里?

1. GCC 的 “target triplet” 和 “specs”

spec file: /lib/gcc/x86_64-alpine-linux-musl/11.2.1/specs

# Alpine 的 GCC 被编译为:
x86_64-alpine-linux-musl
# 而不是常见的:
x86_64-pc-linux-gnu

这意味着:

  • 默认包含头文件路径指向 Alpine 特有的位置
  • 默认使用 musl-gcc 行为(即使命令叫 gcc
  • 自动设置 .interp/lib/ld-musl-x86_64.so.1

2. CRT(C Runtime Startup)对象不同

  • 使用 crt1.o, crti.o, crtn.o 来自 musl,而非 glibc
  • 这些对象定义了 _start 符号和初始化流程

3. 链接脚本和默认库不同

  • 默认链接 -lc 时,链接的是 libc.alibc.so 来自 musl,不是 glibc
  • 不支持某些 glibc 特有的 symbol(如 __stack_chk_fail_guard

四、如何验证

1. 查看可执行文件使用的动态链接器

$ readelf -l main | grep -A 2 'INTERP'INTERP         0x0000000000000318 0x0000000000000318 0x00000000000003180x000000000000001c 0x000000000000001c  R      0x1[Requesting program interpreter: /lib/ld-musl-x86_64.so.1]

2. 查看 gcc 默认链接了什么

$ gcc -Wl,--verbose | grep 'SEARCH_DIR\|libc\.'
# 你会看到它搜索 musl 的库路径,比如:
SEARCH_DIR("/usr/x86_64-alpine-linux-musl/lib")
# wsl2 (Ubuntu) 下的对比
$ gcc -Wl,--verbose | grep 'SEARCH_DIR\|libc\.'
SEARCH_DIR("=/usr/local/lib/x86_64-linux-gnu"); SEARCH_DIR("=/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu"); SEARCH_DIR("=/usr/lib/x86_64-linux-gnu64"); SEARCH_DIR("=/usr/local/lib64"); SEARCH_DIR("=/lib64"); SEARCH_DIR("=/usr/lib64"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib64"); SEARCH_DIR("=/usr/x86_64-linux-gnu/lib");
attempt to open /usr/lib/gcc/x86_64-linux-gnu/11/libc.so failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/11/libc.a failed
attempt to open /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libc.so succeeded
opened script file /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libc.so
/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libc.so
opened script file /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/libc.so
attempt to open /lib/x86_64-linux-gnu/libc.so.6 succeeded
/lib/x86_64-linux-gnu/libc.so.6
/usr/bin/ld: ld-linux-x86-64.so.2 needed by /lib/x86_64-linux-gnu/libc.so.6
/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o: in function `_start':
(.text+0x1b): undefined reference to `main'
/usr/bin/ld: link errors found, deleting executable `a.out'
collect2: error: ld returned 1 exit status

3. 检查 gcc 目标架构

$ gcc -v
# 输出中会有类似:
Target: x86_64-alpine-linux-musl
Configured with: /path/to/configure --target=x86_64-alpine-linux-musl ...

  • 如果你想进一步探索:
    • 了解什么是 abi
    • 使用 crossnone 工具链
    • 了解 newlibuClibc 等其他 C 库

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/924912.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网站图片特效源码品牌建设工作经验

前言&#xff1a;关于MVC和SSM基本内容的梳理&#xff0c;以及两者之间的关系。 文章目录 1. 三层架构2. MVC3. SSM 1. 三层架构 三层架构是指&#xff1a; 视图层view&#xff08;表现层&#xff09;: 用于显示数据和接收用户输入的数据&#xff0c;为用户提供一种交互式操作…

.net做网站用什么框架长春是几线城市2021

0. cas服务搭建参考:CAS 5.3服务器搭建_cas-overlay-CSDN博客 1. 参照springsecurity适配cas的方式, 一直失败, 无奈关闭springssecurity认证 2. 后端服务适配cas: 参考前后端分离项目(springbootvue)接入单点登录cas_前后端分离做cas单点登录-CSDN博客 1) 引入maven依赖 …

使用虚幻引擎(UE5)制作开箱爆金币功能 - 详解

使用虚幻引擎(UE5)制作开箱爆金币功能 - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &…

网站空间内存公司建设网站带来什么

目录 前言&#xff1a; 题单&#xff1a; P3386 【模板】二分图最大匹配 P1525 [NOIP2010 提高组] 关押罪犯 P3385 【模板】负环 P3371 【模板】单源最短路径&#xff08;弱化版&#xff09; SPFA写法 Dij写法&#xff1a; P3385 【模板】负环 P5960 【模板】差分约束…

网站空间稳定性centos wordpress 搭建

1、什么是混流&#xff1f; 混流就是把多路音视频流合成单流。准确的说&#xff0c;混流应该叫做混音&#xff08;音频流&#xff09;混画面&#xff08;视频流&#xff09; 混流的过程包括解码、混流、编码和推流四个部分。混流这个环节包括做抖动缓冲&#xff0c;目的是把多…

2025 年自动喷砂机厂家 TOP 企业品牌推荐排行榜,从生产规模到技术创新,自动喷砂机推荐这十家公司!

在工业生产领域,自动喷砂机作为关键的表面处理设备,其重要性不言而喻。从汽车制造、工程机械,到航空航天、金属结构等众多行业,都依赖自动喷砂机对工件进行除锈、清洁、强化等处理,以提升产品质量和使用寿命。然而…

有哪些网站可以做电子邀请函家电维修怎么自己做网站

程序遍历MySQL然后插入Redis&#xff0c;效率极低。利用redis-cli命令行工具有一个批量插入模式&#xff0c;是专门为批量执行命令设计的。可以把Mysql查询的内容格式化成redis-cli可用数据格式。1&#xff0c; 根据表创建一个sql&#xff0c;将数据转换为redis可用的格式(1) 表…

深入解析:《考研408数据结构》第三章(3.1 栈)复习笔记

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025年光亮剂源头厂家最新推荐榜单:聚焦实力厂商,为电镀企业精选高口碑品牌

当前电镀行业对光亮剂的需求日益增长,但市场乱象却给企业采购带来诸多困扰。一方面,大量小型厂家涌入市场,产品质量缺乏保障,部分产品稳定性差,易导致电镀工件报废,增加企业成本;另一方面,多数厂家技术能力有限…

React前端框架有哪些? - 指南

React前端框架有哪些? - 指南2025-10-02 12:33 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !importan…

微信公众号搭建微网站长沙水业网站是哪家公司做的

django实现图片瀑布流布局 我们在一些图片网站上经常会看到&#xff0c;满屏都是图片&#xff0c;而且图片都大小不一&#xff0c;却可以按空间排列。默认一个div是占用一行&#xff0c;当想把div里的图片并排显示的时候&#xff0c;只能使用float属性&#xff0c;但是&#xf…

七宝做网站公司word做网站框架

视频&#xff1a;黑马程序员SpringBoot3Vue3全套视频教程&#xff0c;springbootvue企业级全栈开发从基础、实战到面试一套通关_哔哩哔哩_bilibili 图示&#xff1a;

公司让我做网站负责人电子商务网站建设需要什么

[ICPC2021 Nanjing R] Klee in Solitary Confinement 题面翻译 给定 n , k n,k n,k 和一个长为 n n n 的序列&#xff0c;你可以选择对区间 [ l , r ] [l, r] [l,r] 的数整体加上 k k k&#xff0c;也可以不加。最大化众数出现次数并输出。 题目描述 Since the travele…

物品“复活”软件开发过程(第一版)

物品“复活”软件开发过程(第一版)| 环节 | 完成时间(h) | | 计划 | 0.5 | | 分析需求 | 0.5 | | 设计文档 | 1 | | 代码规范 | 0.5 | | 具体设计 | 0.5 …

怎样做展会推广网站pc端购物网站建站

我正在努力构建将应用程序的* .csv文件与理想的保管箱帐户同步的机会.我到目前为止做了什么>清单中的权限和com.dropbox.client2.android.AuthActivity>使用我的发行商店签署了我的应用程序>执行一些代码来检查保管箱服务问题是我不明白我在哪里可以得到APP_KEY和SECR…

卖表网站源码长沙住建

问题&#xff1a; 给定一个二叉树的根节点 root &#xff0c;返回它的 中序 遍历。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&…

docker 安装 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

详细介绍:机器学习+数字孪生:从诊断到自主决策的跨越

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

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

深入解析:[linux仓库]深入解析Linux动态链接与动态库加载:理解背后的原理与技巧pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font…