You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何共享库采用GOT(全局偏移表)实现?无法直接修改.text段mov指令的原因

Why Shared Libraries Use GOT Instead of Modifying .text Directly

Great question—this is one of those core dynamic linking concepts that feels counterintuitive at first, but makes perfect sense once you dig into the constraints of modern OSes and shared library design. Let’s break down the key reasons:

1. .text is Read-Only & Shared Across Processes

Modern operating systems map the .text segment of a shared library as read-only and memory-shared across all processes that use the library. This is a huge memory-saver—instead of every process having its own copy of the library’s code, they all share the same physical pages.

If the dynamic linker tried to modify the address in a mov instruction directly in .text, that would trigger a copy-on-write (CoW) event: the OS would create a private copy of that .text page for the process. Do this for enough references, and you lose all the memory efficiency that shared libraries were designed for.

The Global Offset Table (GOT) lives in the .data segment (which is writable and private per process), so modifying GOT entries doesn’t affect the shared .text pages at all.

2. Position-Independent Code (PIC) Requirements

Shared libraries need to be position-independent—meaning they can be loaded at any arbitrary memory address (thanks to ASLR, Address Space Layout Randomization, a critical security feature).

If .text had hardcoded absolute addresses (like mov rax, 0x12345678), the library would break if loaded at a different base address. With GOT, the .text instructions only reference the GOT using relative offsets (e.g., mov rax, [rip + 0x123] on x86-64). These offsets stay the same no matter where the library is loaded, so .text never needs modification.

3. Efficient Symbol Relocation

Imagine a shared library symbol (like printf) is referenced 50 times across .text. If we had to modify each mov instruction individually, the dynamic linker would have to perform 50 separate write operations during startup.

With GOT, we only need to update one GOT entry for that symbol. Every reference in .text points to that single GOT entry, cutting down on relocation work significantly and speeding up program startup.

4. Lazy Binding (Delayed Symbol Resolution)

Most programs don’t use every symbol in a shared library right away. Lazy binding lets the dynamic linker resolve symbols only when they’re first called, instead of during startup—this reduces initial load time.

GOT works hand-in-hand with the Procedure Linkage Table (PLT) to make this possible:

  • The first time you call a function like printf, you jump to the PLT entry.
  • The PLT triggers the dynamic linker to look up printf’s address and write it into the corresponding GOT entry.
  • All subsequent calls skip the PLT and read the resolved address directly from the GOT.

This kind of runtime dynamic update would be impossible if we were modifying .text directly—you can’t easily patch instructions on the fly without breaking the read-only constraint and shared memory model.

A Quick Note on Non-PIC Libraries

Older systems allowed non-PIC shared libraries, where the dynamic linker did modify .text directly. But this approach has major downsides:

  • No memory sharing of .text pages (each process gets its own copy).
  • Incompatibility with ASLR, which is standard now for security.
  • Slower startup due to more relocation work.

So GOT is the modern, efficient, and secure solution to all these problems.

内容的提问来源于stack exchange,提问作者Jason Yu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 08:31:19