惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
H
Hacker News: Front Page
P
Palo Alto Networks Blog
T
ThreatConnect
Apple Machine Learning Research
Apple Machine Learning Research
博客园_首页
T
True Tiger Recordings
P
Privacy & Cybersecurity Law Blog
B
Blog
IT之家
IT之家
Last Week in AI
Last Week in AI
F
Full Disclosure
Hacker News: Ask HN
Hacker News: Ask HN
C
Comments on: Blog
Microsoft Azure Blog
Microsoft Azure Blog
C
Cybersecurity and Infrastructure Security Agency CISA
Microsoft Security Blog
Microsoft Security Blog
博客园 - 【当耐特】
N
News and Events Feed by Topic
NISL@THU
NISL@THU
腾讯CDC
雷峰网
雷峰网
Security Latest
Security Latest
李成银的技术随笔
M
Microsoft Research Blog - Microsoft Research
L
LangChain Blog
L
Lohrmann on Cybersecurity
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
C
Check Point Blog
Y
Y Combinator Blog
Recent Announcements
Recent Announcements
博客园 - Franky
N
News | PayPal Newsroom
V
V2EX
A
About on SuperTechFans
The Register - Security
The Register - Security
月光博客
月光博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Google Online Security Blog
Google Online Security Blog
MyScale Blog
MyScale Blog
Cisco Talos Blog
Cisco Talos Blog
Vercel News
Vercel News
WordPress大学
WordPress大学
C
Cyber Attacks, Cyber Crime and Cyber Security
The Hacker News
The Hacker News
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
IntelliJ IDEA : IntelliJ IDEA – the Leading IDE for Professional Development in Java and Kotlin | The JetBrains Blog
爱范儿
爱范儿
A
Arctic Wolf
L
LINUX DO - 最新话题
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More

博客园 - chaoguo1234

Plist 二进制格式 UIImageView 设置图片不生效的原因排查 Any metadata 的内存布局 - chaoguo1234 Mach-O 文件结构 Block Copy 的内存布局详解 __block 变量内存布局详解 Block 内存布局详解 XNU Inside: iOS 模拟器 WebKit Insie: WebKit 调试(二) NSMutableDictionary 的内存布局 NSDictionary 内存布局 WebKit Inside: GPU 进程调试 WebKit Inside: 渲染树 WebKit Inside: px 与 pt WebKit Inside: CSS 的匹配原理 一文搞懂 ARM 64 系列: ADD(立即数版) 一文搞懂 ARM 64: AUTIBSP 一文搞懂 ARM 64 系列: PACISB XCode 编译 PAG 源码 一文搞懂 ARM 64 系列: 一文搞懂 ARM 64 系列: 函数调用传参与返回值 一文搞懂 ARM 64 系列: 寄存器
dyld: 神秘的 __dso_handle
chaoguo1234 · 2024-11-19 · via 博客园 - chaoguo1234

iOS动态链接器dyld中有一个神秘的变量__dso_handle:

// dyld/dyldMain.cpp
static const MachOAnalyzer* getDyldMH()
{
#if __LP64__
    // 声明 __dso_handle
    extern const MachOAnalyzer __dso_handle;
    return &__dso_handle;
#else
    ...
#endif // __LP64__
}

这个函数内部声明了一个变量__dso_handle,其类型是struct MachOAnalyzer

查看struct MachOAnalyzer的定义,它继承自struct mach_header:

image

struct mach_header正是XNU内核里面,定义的Mach-O文件头:

// EXTENERL_HEADERS/mach-o/loader.h
struct mach_header {
	uint32_t	magic;		/* mach magic number identifier */
	cpu_type_t	cputype;	/* cpu specifier */
	cpu_subtype_t	cpusubtype;	/* machine specifier */
	uint32_t	filetype;	/* type of file */
	uint32_t	ncmds;		/* number of load commands */
	uint32_t	sizeofcmds;	/* the size of all the load commands */
	uint32_t	flags;		/* flags */
};

从上面函数getDyldMH的名字来看,它返回dyld这个Mach-O文件的文件头,而这确实也符合变量__dso_handle的类型定义。

但是奇怪的事情发生了,搜遍整个dyld源码库,都无法找到变量__dso_handle的定义。所有能搜到的地方,都只是对这个变量__dso_handle的声明。

众所周知,动态连接器dyld本身是静态链接的。

也就是说,动态连接器dyld本身是不依赖任何其他动态库的。

因此,这个变量__dso_handle不可能定义在其他动态库。

既然这样,动态链接器dyld本身是如何静态链接通过的呢?

答案只可能是静态链接器ld在链接过程中做了手脚。

查看静态链接器ld的源码,也就是llvm的源码,可以找到如下代码:

// lld/MachO/SyntheticSections.cpp
void macho::createSyntheticSymbols() {
  // addHeaderSymbol 的 lamba 表达式
  auto addHeaderSymbol = [](const char *name) {
    symtab->addSynthetic(name, in.header->isec, /*value=*/0,
                         /*isPrivateExtern=*/true, /*includeInSymtab=*/false,
                         /*referencedDynamically=*/false);
  };

  ...

  // The Itanium C++ ABI requires dylibs to pass a pointer to __cxa_atexit
  // which does e.g. cleanup of static global variables. The ABI document
  // says that the pointer can point to any address in one of the dylib's
  // segments, but in practice ld64 seems to set it to point to the header,
  // so that's what's implemented here.
  addHeaderSymbol("___dso_handle");
}

上面代码定义了一个addHeaderSymbollamda表达式,然后使用它添加了一个符号,这个符号正是__dso_handle

调用addHeaderSymbol上方的注释使用chatGPT翻译过来如下:

Itanium C++ ABI 要求动态库传递一个指向 __cxa_atexit 的指针,该函数负责例如静态全局变量的清理。ABI 文档指出,指针可以指向动态库的某个段中的任意地址,但实际上,ld64(苹果的链接器)似乎将其设置为指向头部,所以这里实现了这种做法。

注释中提到的Itanium C++ ABI最初是为英特尔和惠普联合开发的Itanium处理器架构设计的。

但其影响已经超过了最初设计的架构范围,并被广泛用于其他架构,比如x86x86-64上的多种编译器,包括GCCClang

而且,注释中还提到,__dso_handle在苹果的实现里,是指向了Mach-O的头部。

至此,谜底解开~。