ELF 链接加载与 System V AMD64 ABI

共 79 题
#

1. ELF header(ELF64_Ehdr)中 e_type、e_machine、e_entry、e_phoff、e_shoff 等字段的含义

A e_entry 是程序入口的虚拟地址,而 e_phoff 指向程序头表偏移 ✓ 正确答案
B e_type 用于标识 ELF 文件的目标机器架构
C e_shoff 指向程序头表的偏移
D e_machine 表示 ELF 文件的类型
#

2. ELF(Executable and Linkable Format)的 relocatable(.o)、executable、shared object、core dump 四类文件

A core dump 是共享库
B executable 文件包含重定位信息供链接器合并
C relocatable 文件包含未解析符号与重定位信息,供链接器使用 ✓ 正确答案
D shared object 是进程崩溃时的内存快照
#

3. Program header(Elf64_Phdr)的 PT_LOAD、PT_INTERP、PT_DYNAMIC 段类型

A PT_DYNAMIC 携带动态链接所需信息,如 DT_NEEDED 等 ✓ 正确答案
B PT_LOAD 指定动态链接器路径
C PT_INTERP 描述需要映射到内存的段权限
D PT_LOAD 指向解释器路径
#

4. Section header(Elf64_Shdr)的 .text、.data、.bss、.rodata 段

A .bss 段在文件中不占空间,加载时清零 ✓ 正确答案
B .text 段存放可读写的全局变量
C .rodata 段存放可写的初始化数据
D .data 段存放机器指令
#

5. ld.so 的动态链接流程,从 DT_NEEDED 解析、符号查找到重定位的完整链路

A 重定位发生在依赖解析之前
B DT_NEEDED 只记录主程序自身符号
C 符号查找在重定位完成之后进行
D ld.so 先解析 DT_NEEDED 依赖,再查找符号,最后执行重定位 ✓ 正确答案
#

6. ELF 调试信息(DWARF)的 .debug_info、.debug_line、.debug_frame

A .debug_line 记录类型与变量描述
B .debug_frame 记录源代码行号到地址的映射
C .debug_info 以 DIE 描述类型、变量、函数等结构 ✓ 正确答案
D .debug_frame 存储符号表
#

7. readelf、objdump、nm、ldd、file 工具的实战

A readelf 用于反汇编机器码
B ldd 用于显示动态库依赖 ✓ 正确答案
C objdump 用于列出动态库依赖
D nm 用于解析 ELF 段头
#

8. 位置无关代码(PIC)与 PIE(Position Independent Executable)

A PIC 和 PIE 是同一种概念,无区别
B PIE 是位置无关的可执行文件,配合 ASLR 提升安全性 ✓ 正确答案
C PIC 只能用于可执行文件
D PIE 不能加载到任意地址
#

9. ELF TLS(Thread Local Storage)的 .tdata 与 .tbss 段

A .tdata 存放未初始化的线程局部变量
B 线程通过 TP 寄存器基址寻址各自独立的 TLS 副本 ✓ 正确答案
C .tbss 存放已初始化的线程局部变量
D TLS 变量在所有线程间共享同一份存储
#

10. ELF note 段(.note.gnu.property、.note.gnu.build-id)的元数据

A .note.gnu.build-id 用于记录程序依赖的处理器安全特性
B .note.gnu.property 保存唯一哈希标识便于调试匹配
C note 段参与程序运行逻辑
D .note.gnu.property 记录 CET、IBT 等处理器特性声明 ✓ 正确答案
#

11. ELF 版本脚本(version script)的符号可见性控制

A version script 的 local 符号会进入动态符号表
B version script 只能增加符号,不能隐藏符号
C version script 通过 global/local 控制符号导出,并支持符号版本化 ✓ 正确答案
D version script 与符号可见性无关
#

12. binutils、lld、mold 三种链接器的性能差异

A GNU ld 采用多线程并行设计,速度最快
B mold 相比 lld 在速度上没有任何优势
C lld 是 LLVM 生态的链接器,采用多线程并行 ✓ 正确答案
D 三种链接器的 ELF 输出语义完全不同
#

13. x86-64 与 AArch64 的 ABI 差异对比

A x86-64 用 x0-x7 传整数参数
B x86-64 用 d0-d7 传浮点参数
C AArch64 用 x0-x7 传前 8 个整数参数 ✓ 正确答案
D AArch64 用 rdi-r9 传整数参数
#

14. 栈对齐(16 字节对齐)的 ABI 强制与崩溃边界

A SSE 指令(如 movaps)要求 16 字节对齐,栈未对齐会触发通用保护异常 ✓ 正确答案
B 16 字节对齐只是为了美观,与指令无关
C 栈对齐只在 32 位系统要求
D 违反栈对齐不会导致任何崩溃
#

15. 红区(red zone,128 字节)的工程语义

A 红区只允许叶函数使用,用于免去栈帧调整 ✓ 正确答案
B 红区位于 rsp 上方 128 字节
C 非叶函数也可随意使用红区
D 红区与信号处理器无关
#

16. 结构体返回的"内存参数"(sret)约定与寄存器返回的分界

A sret 返回方式将结果放入寄存器
B sret 不使用调用方分配的内存
C 所有结构体都必须用 sret 返回
D 超过 16 字节的结构体通常用 sret 隐藏指针返回 ✓ 正确答案
#

17. System V i386 ABI(32 位)的 cdecl ABI 传参规则

A cdecl 由调用者清栈,支持可变参数 ✓ 正确答案
B cdecl 使用寄存器传递参数
C cdecl 由被调函数清栈
D cdecl 返回值总是存放在 edx
#

18. x86-64 栈帧的 rbp 帧指针省略(-fomit-frame-pointer)

A -fomit-frame-pointer 会保留 rbp 帧指针链
B 该选项与调试回溯无关
C 省略 rbp 会损失一个通用寄存器
D 省略 rbp 后,函数用 rsp 相对偏移访问局部变量 ✓ 正确答案
#

19. Itanium C++ ABI(itanium-cxx-abi)的 name mangling 规则

A 命名空间在 mangling 中不参与编码
B mangling 只用于普通函数,不处理模板
C C++ mangling 以 _Z 开头编码名称与类型 ✓ 正确答案
D mangling 使重载函数产生相同符号
#

20. x86-64 SysV 的 EH frame 与 DWARF CFI 异常处理

A .eh_frame 存储源代码行号
B 异常展开与普通 unwind 使用不同的机制
C 异常展开沿 CFI 逐帧回退并调用析构函数 ✓ 正确答案
D .eh_frame 只与信号处理有关
#

21. COFF(Common Object File Format)的 section table 与 symbol table

A COFF 的 section table 记录符号名称
B COFF 的 symbol table 逐项描述各节
C COFF 与 ELF 的节组织结构完全相同
D COFF 的重定位表与 section 关联 ✓ 正确答案
#

22. Mach-O 与 ELF 在段(segment)vs 节(section)层次上的差异

A Mach-O 中 section 包含 segment
B Mach-O 与 ELF 的层次结构完全相同
C ELF 的 program header 与 section 是强绑定关系
D Mach-O 采用 segment 包含 section 的两层结构 ✓ 正确答案
#

23. Mach-O 中 __objc_methlist、__objc_classlist 等 Objective-C 元数据

A __objc_methlist 保存类对象列表
B __objc_selrefs 保存方法实现
C __objc_classlist 列出所有类对象 ✓ 正确答案
D ObjC 元数据不参与运行时
#

24. Mach-O 的 __TEXT、__DATA 段的"两段式"模型

A __TEXT 与 __DATA 分离支持 W^X 与代码共享 ✓ 正确答案
B __DATA 段是可执行代码段
C __TEXT 段是可读写数据段
D 两段式模型无法实现代码共享
#

25. Mach-O 的 load commands,包括 LC_SEGMENT_64、LC_DYLD_INFO、LC_SYMTAB

A LC_SEGMENT_64 提供符号表信息
B LC_DYLD_INFO 提供动态链接所需的绑定信息 ✓ 正确答案
C LC_SYMTAB 描述段的映射位置
D load commands 与加载过程无关
#

26. Mach-O 的 magic number,即 MH_MAGIC_64 与 MH_CIGAM_64(小端序)的区别

A MH_CIGAM_64 是字节交换后的魔数,用于识别字节序 ✓ 正确答案
B MH_MAGIC_64 与 MH_CIGAM_64 是同一值
C 魔数只用于识别文件大小
D CIGAM 表示文件已损坏
#

27. dyld 的 Mach-O 动态链接流程与 dyld_shared_cache

A dyld 只加载主程序,不处理依赖库
B dyld_shared_cache 把系统库合并为单一映射以加快启动 ✓ 正确答案
C dyld_shared_cache 会增加内存占用与启动时间
D dyld 不做符号绑定
#

28. COFF 与 ELF 的 ABI 兼容性挑战

A COFF 与 ELF 的重定位类型完全一致
B COFF 与 ELF 使用相同的调试格式
C 同一二进制可在 Windows 与 Unix 直接复用
D COFF 与 ELF 在节组织、重定位与调用约定上存在多项差异 ✓ 正确答案
#

29. Mach-O 的 LC_CODE_SIGNATURE 签名与 LC_DYLD_INFO_ONLY 重定位

A LC_CODE_SIGNATURE 用于提供重定位信息
B LC_DYLD_INFO_ONLY 用于验证代码签名
C LC_CODE_SIGNATURE 用于验证二进制完整性,防止篡改 ✓ 正确答案
D 两者都与动态链接无关
#

30. --as-needed、--no-undefined、-z now 的链接器标志语义

A --as-needed 会强制链接所有库
B --no-undefined 允许未定义符号存在
C -z now 禁用 lazy binding,使 GOT 加载时全部解析 ✓ 正确答案
D -z now 会启用延迟绑定
#

31. 动态加载 dlopen/dlsym/dlclose 的运行时链接

A dlsym 用于加载共享库
B dlopen 返回库句柄,dlsym 通过句柄查找符号 ✓ 正确答案
C dlclose 增加库的引用计数
D dlopen 只能加载编译期已链接的库
#

32. 动态链接的"延迟绑定"(lazy binding)vs"立即绑定"(now binding)的取舍

A lazy binding 在加载时解析全部符号
B now binding 会加快启动速度
C lazy binding 会消除首次调用延迟
D now binding 配合 Full RELRO 使 GOT 只读,提升安全性 ✓ 正确答案
#

33. GCC 的 -fvisibility=hidden 与符号可见性控制

A -fvisibility=hidden 让所有符号默认可见
B 该选项会增加符号表体积
C 显式标注的符号才进入动态符号表,可规范共享库 ABI ✓ 正确答案
D 可见性控制与优化无关
#

34. 链接器"幽灵符号"(linker script symbol)与 VDSO

A linker script 无法定义符号地址
B VDSO 只能在内核态使用
C VDSO 由内核映射到进程空间,用于用户态实现部分系统调用 ✓ 正确答案
D VDSO 会显著增加系统调用开销
#

35. 动态库的"按需加载"vs"预加载"的工程取舍

A 预加载适合符号覆盖,如拦截 malloc ✓ 正确答案
B 按需加载会在启动时加载全部库
C 按需加载无法用于插件
D 预加载会减少启动时间
#

36. 动态链接的 GOT/PLT 攻击(return-to-PLT)

A return-to-PLT 是直接覆盖 GOT 的堆溢出攻击
B PLT 跳板无法被攻击者利用
C Full RELRO 使 GOT 只读,可提升对 GOT/PLT 攻击的防御 ✓ 正确答案
D ASLR 对 return-to-PLT 攻击无效
#

37. Itanium C++ ABI 的"COMDAT"折叠与"弱符号"边界

A COMDAT 节在链接时保留多个同名副本
B COMDAT 与弱符号无关
C 模板实例化会产生符号冲突
D 弱符号允许多个定义,链接器选择其一不报错 ✓ 正确答案
#

38. Java 的 JNI ABI 与 native 库的边界

A JNI 函数按 Java_包名_类名_方法名 规则命名 ✓ 正确答案
B JNIEnv 是普通结构体,不包含函数表
C JNI 不处理引用管理
D JNI 函数名与 Java 方法无关
#

39. Rust ABI 的"显式"(extern "C")与"自定义"(Rust ABI 不稳定)差异

A Rust 默认 ABI 是稳定的 C 调用约定
B extern "C" 采用稳定的 C 调用约定,适合 FFI ✓ 正确答案
C Rust ABI 保证跨语言兼容
D extern "C" 与 Rust ABI 完全相同
#

40. Go 的 ABI 在 1.17 之后的 register-based 改造

A Go 一直用栈传递参数
B Go 1.17+ 使用寄存器传递函数参数与返回值 ✓ 正确答案
C register-based ABI 会增加调用开销
D Go ABI 是对外暴露的稳定接口
#

41. WASM(WebAssembly)的线性内存与 ABI 模型

A WASM 有多个相互隔离的地址空间
B WASM 线性内存是唯一的连续地址空间 ✓ 正确答案
C WASM 调用约定依赖未定义行为
D WASM 无内存管理机制
#

42. 静态链接与动态链接在可执行体积、启动速度、内存共享与升级成本上如何取舍?

A 静态链接可共享内存,内存占用更小
B 动态链接升级库只需替换文件,且可共享内存 ✓ 正确答案
C 静态链接启动速度更慢
D 动态链接体积更大
#

43. LTO(Link Time Optimization)在链接期做跨模块内联与死代码删除的原理是什么,构建开销从何而来?

A LTO 无法进行常量传播
B LTO 只做单文件优化
C LTO 会降低链接时间
D LTO 在链接期合并 IR 进行跨模块内联与死代码删除 ✓ 正确答案
#

44. -ffunction-sections 配合 --gc-sections 如何剔除未引用函数,为何需结合 -fdata-sections?

A 数据回收无需分节
B -ffunction-sections 让数据独立成节
C --gc-sections 回收所有节,包括被引用的
D -fdata-sections 让每个全局变量独立成节,配合 --gc-sections 回收未引用数据 ✓ 正确答案
#

45. 强符号与弱符号的解析规则是什么,多个目标文件定义同名弱符号时链接器如何选择?

A 强符号优先于弱符号,多个弱符号时链接器选择一个 ✓ 正确答案
B 多个强符号同名时链接器选择任意一个
C 弱符号总是覆盖强符号
D 多个弱符号必然报错
#

46. 链接器如何确定输出文件中各段的加载地址(LMA)与虚拟地址(VMA),嵌入式场景为何要分离二者?

A VMA 是段在文件中的加载地址
B VMA 与 LMA 总是不同
C 嵌入式场景中代码常存于 Flash(LMA)而运行于 RAM(VMA) ✓ 正确答案
D 链接脚本无法指定地址
#

47. 静态链接 glibc 为何会带来 NSS、TLS 等运行期功能的兼容问题?

A 静态链接 glibc 后 NSS 模块仍可动态加载
B TLS 与静态链接无关
C 静态链接完全不影响 glibc 运行期功能
D NSS 需要动态加载模块,静态链接会破坏名字解析等功能 ✓ 正确答案
#

48. 链接器如何处理未定义符号与公共符号(common symbol),-fno-common 改变了什么行为?

A -fno-common 会把多个 common 定义合并为公共符号
B -fno-common 会取消符号解析
C 未定义符号在链接时总是被忽略
D 默认 -fcommon 允许多个 TU 的未初始化变量合并为 common symbol ✓ 正确答案
#

49. Mach-O 的"通用二进制"(Universal/Fat binary)的多架构支持

A Fat binary 只能包含一个架构
B Fat binary 用 fat header 封装多架构切片,加载时按架构选择 ✓ 正确答案
C Universal binary 会减小体积
D Fat binary 与架构无关
#

50. 源码、ABI、API、行为兼容性构成的 ABI 兼容性"层"

A ABI 兼容意味着已编译二进制无需重新编译即可运行 ✓ 正确答案
B 源码兼容保证二进制兼容
C API 兼容与行为兼容完全相同
D ABI 兼容不要求 API 兼容
#

51. ABI 稳定性的边界,新增函数 vs 修改函数签名 vs 修改 struct 布局如何取舍

A 修改函数签名不破坏 ABI 兼容性
B 修改 struct 布局不影响 ABI
C 新增函数通常不破坏 ABI 兼容性 ✓ 正确答案
D 所有修改都破坏 ABI
#

52. Node.js 的 N-API 与 NAN 的 ABI 稳定性

A NAN 与 N-API 的稳定性相同
B NAN 提供稳定 ABI 无需重编译
C N-API 依赖 V8 内部头文件
D N-API 提供稳定 ABI,模块可在不同 Node 版本复用 ✓ 正确答案
#

53. Python 的 C API(CPython)的稳定 vs 不稳定边界

A 完整 C API 依赖内部数据结构,跨版本无需重编译
B 使用稳定 ABI(Py_LIMITED_API)的扩展可在多个 Python 版本复用 ✓ 正确答案
C PyObject 布局是稳定 ABI 的一部分
D 所有扩展都无需重编译
#

54. PLT(Procedure Linkage Table)与 GOT(Global Offset Table)的 lazy binding 机制

A lazy binding 下每次调用都重新解析
B lazy binding 下首次调用会解析并回填 GOT 槽位 ✓ 正确答案
C GOT 槽位在 lazy binding 下从不回填
D PLT 与 GOT 无关
#

55. 动态段的 DT_NEEDED、DT_SYMTAB、DT_STRTAB、DT_RELA 等动态表项

A DT_RELA 指向动态符号表
B DT_SYMTAB 指向字符串表
C DT_NEEDED 列出依赖库名 ✓ 正确答案
D DT_STRTAB 列出依赖库
#

56. 符号表(.symtab)与动态符号表(.dynsym)的差异

A .symtab 用于动态链接解析
B .symtab 是运行必需的
C strip 会移除 .dynsym 使程序无法运行
D .dynsym 只含动态链接所需符号,运行时实际使用 ✓ 正确答案
#

57. 重定位表(.rela.dyn、.rela.plt)的 RELA 与 REL 格式

A REL 重定位项包含 r_addend 字段
B RELA 重定位项包含显式的 r_addend 字段 ✓ 正确答案
C x86-64 使用 REL 格式
D RELA 与 REL 结构完全相同
#

58. strip 与符号去除的工程意义

A strip 只影响运行性能
B strip 会增大文件体积
C strip 移除符号表以减小体积,但会降低调试可读性 ✓ 正确答案
D strip 后无法运行程序
#

59. x86-64 SysV 的 PLT 与 lazy binding 的栈布局

A _dl_runtime_resolve 不接收参数
B lazy binding 不涉及栈操作
C GOT 槽位在首次调用后仍指向同一地址
D PLT 项通过把符号序号压栈并跳转解析例程来完成 lazy binding ✓ 正确答案
#

60. System V AMD64 ABI 中 rdi、rsi、rdx、rcx、r8、r9 这 6 个整数参数寄存器

A 第 7 个参数优先用 r10 传递
B 所有参数都通过栈传递
C 前 6 个整数参数依次用 rdi、rsi、rdx、rcx、r8、r9 传递 ✓ 正确答案
D 浮点参数用整数寄存器传递
#

61. System V AMD64 中 rax 与 rdx 承载返回值(128 位返回值)的规则

A 128 位整数返回值使用 rax+rdx 拼接 ✓ 正确答案
B 所有返回值都存放在 rdx
C 浮点返回值使用 rax
D 128 位返回值只能通过内存返回
#

62. 可变参数(variadic)的 AL 寄存器(浮点个数)传递

A AL 保存返回值
B AL 保存整数参数个数
C 可变参数函数不需要 AL 寄存器
D 可变参数函数调用时 AL 寄存器保存浮点参数个数 ✓ 正确答案
#

63. 浮点参数通过 XMM0-XMM7 寄存器传递的规则

A 浮点参数用栈传递所有参数
B 浮点参数用整数寄存器传递
C XMM0-XMM7 用于传递前 8 个浮点参数 ✓ 正确答案
D XMM 寄存器与浮点无关
#

64. AAPCS(AArch64 Procedure Call Standard)与 SysV 的对照

A AAPCS 用 XMM0-7 传整数参数
B AAPCS 用 rdi-r9 传整数参数
C AAPCS 用 x0-x7 传前 8 个整数参数 ✓ 正确答案
D AAPCS 的浮点参数用 x0-x7 传递
#

65. PE 的 section,包括 .text、.data、.rsrc、.reloc 与 DLL 导入表

A 导入表只列出 DLL 名,不含函数
B .text 存可写数据
C .rsrc 存代码
D .reloc 存基址重定位表,.rsrc 存资源 ✓ 正确答案
#

66. PE(Portable Executable,Windows COFF 扩展)的 DOS stub 与 PE header

A DOS stub 的 e_lfanew 字段指向真正的 PE header ✓ 正确答案
B PE header 位于文件最开头
C DOS stub 用于现代 Windows 运行
D PE 签名是 "MZ"
#

67. COFF 的 PE32+(64 位 PE)格式

A PE32+ 的可选头使用 64 位字段以支持 64 位地址 ✓ 正确答案
B PE32+ 与 PE32 结构完全无关
C PE32+ 的 magic 为 0x10b
D PE32+ 只能用于 32 位系统
#

68. Windows DLL 的导入表(import table)与导出表(export table)

A 导出表列出 DLL 提供的符号,导入表列出依赖的符号 ✓ 正确答案
B 导入表提供 DLL 导出的符号
C 加载器不匹配导入与导出
D 导出表列出依赖的 DLL
#

69. DT_RPATH 与 DT_RUNPATH 的差异,即 RUNPATH 不传递给子进程

A DT_RUNPATH 只作用于当前对象,不传递给子进程 ✓ 正确答案
B DT_RPATH 不传递给子进程
C DT_RUNPATH 优先级高于 LD_LIBRARY_PATH
D DT_RPATH 与 DT_RUNPATH 语义完全相同
#

70. RPATH、RUNPATH、LD_LIBRARY_PATH 的库搜索路径优先级

A DT_RPATH 优先级低于 LD_LIBRARY_PATH
B DT_RUNPATH 的优先级低于 LD_LIBRARY_PATH ✓ 正确答案
C LD_LIBRARY_PATH 优先级最低
D 默认路径优先级最高
#

71. dlmopen 的命名空间隔离

A dlmopen 只有单一命名空间
B dlmopen 与 dlopen 完全等价
C dlmopen 无法区分库版本
D dlmopen 把库加载到独立命名空间以隔离同名符号 ✓ 正确答案
#

72. 版本脚本与符号版本(symbol versioning)的 ABI 兼容性

A 符号版本化让同一符号对应多个版本,实现多版本 ABI 共存 ✓ 正确答案
B 符号版本化只支持单一版本
C 版本脚本无法定义版本继承
D 符号版本化会破坏 ABI 兼容
#

73. 动态库的 SONAME 与版本号管理

A SONAME 指文件名而非版本
B SONAME 记录在 DT_SONAME 中,作为库的 ABI 版本标识 ✓ 正确答案
C 主版本号兼容时递增
D SONAME 与动态链接无关
#

74. ABI(Application Binary Interface)的范围,涵盖传参规则、数据布局、名称修饰与调用堆栈布局

A ABI 改变不影响二进制兼容
B ABI 只涉及数据布局
C ABI 与跨语言互操作无关
D ABI 涵盖传参规则、数据布局、名称修饰与调用堆栈布局 ✓ 正确答案
#

75. C 标准的版本(C89、C99、C11、C17、C23)的兼容性

A C99 是最早的 C 标准
B C11 引入原子操作与线程等新特性 ✓ 正确答案
C C 标准版本决定 ABI 兼容性
D C23 没有新增特性
#

76. C++ ABI 的对象布局(vptr、vtable)与 RTTI 的稳定性

A 对象布局可随意改变而保持 ABI 兼容
B vtable 不含虚函数地址
C RTTI 与对象布局无关
D 有虚函数的类对象开头含 vptr,vtable 含虚函数地址与 RTTI 信息 ✓ 正确答案
#

77. libstdc++ 与 libc++ 的 ABI 不兼容问题

A 两个标准库可以随意混用
B libstdc++ 与 libc++ 的内部布局与符号可能不同,混用会导致 ABI 不兼容 ✓ 正确答案
C 标准库内部布局由 C 标准定义
D 混用不影响运行
#

78. abi-compliance-checker、abidiff 等 ABI 兼容性测试工具

A 这些工具只检测运行时性能
B abidiff 比较库版本以检测符号与布局等 ABI 破坏 ✓ 正确答案
C abi-compliance-checker 无法比较结构体布局
D 这些工具与库升级无关
#

79. ABI 版本化(symbol versioning)的 Soname 演进

A symbol versioning 在符号粒度提供版本,Soname 在库粒度标识 ABI 主版本 ✓ 正确答案
B Soname 只影响符号版本化
C symbol versioning 与 Soname 无关
D 破坏性改动不改变 Soname