3

let's say I have a source file dll.c that use dlopen and dlsym functions to load a shared library called F.so in run time.

dll.c has a reference to some_function(), and F.so has the definition of some_function().

and let's say the picture below is the executable object prog which is obtained by

linux> gcc -rdynamic -o prog dll.c -ldl

enter image description here

so .text section contains the reference of some_function() that needs to be resolved when the porgram load F.so and start to call some_function()

My questions are:

  1. It seems to me that the .text section(where some_function() belongs to) in RAM(executable is copied into memory) needs to be modified by the dynamic linker so that the reference of some_function() can be resolved, is my understanding correct?

  2. If the dynamic linker needs to modify the .text section in RAM, how does it do it? from my understanding, .text section is read-only segment in RAM, how can a read-only segment be modified if it is called read-only?

  • 1
    Multiply posted at stackoverflow.com/q/63708380/340790 . This account has also multiply posted several questions posted by another account that is a prolific multi-poster. – JdeBP Sep 15 at 7:59
4

Two features of ELF are missing from your diagram and are used for dynamic linking: the global offset table (GOT) and the procedure linkage table (PLT). The GOT is a table of offsets used for a variety of purposes, and the PLT is a table of procedure stubs used for indirect jumps. The GOT is typically read-write; the PLT can be either read-write, or read-only (and then backed by GOT entries or a separate PLT-specific GOT).

This allows the dynamic linker to update symbol addresses without touching read-only data.

Some older binaries require modifying relocation data in read-only segments; this isn’t a problem for the dynamic linker, but it does mean that the corresponding areas of memory can no longer be shared among processes in memory.

See How to Write Shared Libraries for details.

| improve this answer | |
2

A.1

Depending on the cpu, the code in the .text section for calling the some_function() will be some kind of indirect call. It will compute the address at runtime, possibly caching the result for efficiency. This allows the .text to be unchanged and therefore it can be shared. The code is usually very slightly bigger and slower.

A.2

The assumption is false, so this question doesn't arise. However there is nothing stopping the kernel making a copy of a page of memory and giving it different read/write/execute properties and mapping the new page in at the same address. This can be done for example by the ptrace system call and is used by debuggers to plant software breakpoints.

| improve this answer | |

Not the answer you're looking for? Browse other questions tagged or ask your own question.