I'm afraid not.
The compiled binary is processed through the transfer phase by the linker, which links each symbol reference in the code to the run-time address.
You can do a simple experiment to find out the differences, here is a program that displays "Hello World":
// main.c
Using gcc -c , you can compile the source code into a roaming object:
$ gcc -c main.o
$ readelf -s main.o Symbol table '.symtab' contains 10 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FILE LOCAL DEFAULT ABS main.c 2: 00000000 0 SECTION LOCAL DEFAULT 1 3: 00000000 0 SECTION LOCAL DEFAULT 3 4: 00000000 0 SECTION LOCAL DEFAULT 4 5: 00000000 0 SECTION LOCAL DEFAULT 5 6: 00000000 0 SECTION LOCAL DEFAULT 7 7: 00000000 0 SECTION LOCAL DEFAULT 6 8: 00000000 29 FUNC GLOBAL DEFAULT 1 main 9: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
You can see that the value of the main function is 0x0, which means that it has not yet been moved and can be associated with others.
But when you compile the file using the gcc command to generate the executable:
$ gcc main.c $ readelf -s a.out | grep main 2: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC _2.0 (2) 39: 00000000 0 FILE LOCAL DEFAULT ABS main.c 51: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@ @GLIBC_ 62: 080483c4 29 FUNC GLOBAL DEFAULT 13 main
Now you can see that the address of the main function has been moved to 0x80483c4, which is the address of the runtime of the function code. Generating a.out can no longer be linked to others, as there may be a violation of the runtime address for this.
Generally speaking, the movement phase cannot be canceled because some information about the symbol is lost after the phase.
For more information, I suggest you read the chapter “Binding” in the book “Computer System: A Programmer's Perspective” , which talks a lot about linking and moving.
source share