Linking and Relocation Mechanisms
Object File Format Comparison
ELF/PE/COFF Core Structure Comparison:
| Feature | ELF (Linux) | PE (Windows) | COFF (Legacy Windows) |
|---|---|---|---|
| File Header | Elf_Ehdr | IMAGE_NT_HEADERS | IMAGE_FILE_HEADER |
| Section Table | Elf_Shdr | IMAGE_SECTION_HDR | IMAGE_SECTION_HDR |
| Symbol Table | Elf_Sym | IMAGE_SYMBOL | IMAGE_SYMBOL |
| Relocation Table | Elf_Rel/Elf_Rela | IMAGE_RELOC | IMAGE_RELOC |
| Dynamic Linking | .dynamic section | Import/Export tables | Limited support |
ELF File Example:
# View ELF header information
readelf -h /bin/ls
# Output key fields:
# Type: EXEC (Executable file)
# Machine: x86-64
# Entry point address: 0x400520
Symbol Table and Relocation
Symbol Representation Example (ELF):
// Symbol type definitions
#define STT_NOTYPE 0 // Unspecified type
#define STT_OBJECT 1 // Data object
#define STT_FUNC 2 // Function
#define STT_SECTION 3 // Section
// Symbol binding attributes
#define STB_LOCAL 0 // Local symbol
#define STB_GLOBAL 1 // Global symbol
#define STB_WEAK 2 // Weak symbol
Relocation Table Processing Flow:
- Calculate symbol virtual address (VA)
- Determine relocation type (e.g., R_X86_64_PC32)
- Apply offset correction:
// R_X86_64_PC32 relocation formula
*reloc_addr = (symbol_addr - reloc_addr - 4) & 0xFFFFFFFF;
Linker Working Principles
Static Linking Process:
- Symbol resolution: Build global symbol table
- Relocation merging: Merge identical sections
- Address allocation: Determine final VA
- Relocation correction: Fix all references
Dynamic Linking Key Mechanisms:
// Dynamic linker (ld.so) workflow
1. Load dependent libraries (recursively resolve DT_NEEDED)
2. Symbol address binding (PLT/GOT mechanism)
3. Initialize .init_array section
4. Lazy binding
PLT/GOT Dynamic Call Example:
; Dynamic function call process
call printf@PLT
; Actually expands to:
jmp *[GOT_offset] ; First call jumps to resolution code
; After resolution, GOT stores real address
Shared Libraries and Dynamic Loading
dlopen Dynamic Loading Process:
void* handle = dlopen("libfoo.so", RTLD_LAZY);
void (*func)() = dlsym(handle, "foo_func");
func();
dlclose(handle);
LD_PRELOAD Hijacking Principle:
# Override functions via preloaded library
LD_PRELOAD=./hack.so ./program
# Same-name function in hack.so is resolved preferentially
Position-Independent Code (PIC)
PIC Implementation Key Technologies:
- GOT (Global Offset Table):
- Stores global variable/function addresses
- Dynamically resolved at runtime
- PLT (Procedure Linkage Table):
- Lazy binding mechanism
- Resolve function addresses on demand
PIC Function Call Example:
; PIC function call
call puts@PLT
; Corresponding assembly:
jmp *[GOT + puts_offset] ; First call triggers resolution
Debugging and Disassembly Techniques
Debugging Information Formats
DWARF Debugging Information Structure:
.debug_info # Core debugging information
.debug_abbrev # Abbreviation table
.debug_line # Line number information
.debug_str # String pool
.debug_loc # Variable locations
PDB (Windows) Key Structures:
- TPI Stream (Type information)
- DBI Stream (Debugging information)
- Symbol Records (Symbol table)
Disassembly Tool Comparison
IDA Pro Advanced Features:
- FLIRT signature recognition for library functions
- Cross-reference analysis (Xrefs)
- Pseudocode generation (Hex-Rays Decompiler)
Ghidra Unique Features:
- Open-source scripting engine (Python/Java)
- Collaborative analysis server
- Custom decompiler
Debugging Techniques in Practice
GDB Advanced Usage:
# Conditional breakpoint
break file.c:123 if variable == 42
# Memory watchpoint
watch *(int*)0x7fffffffdcfc
# Disassemble current function
disassemble /m function_name
# Modify register value
set $rax = 0x1234
WinDbg Debugging Commands:
# Kernel debugging example
bp ntoskrnl.exe!IofCallDriver
dt _DEVICE_OBJECT 0xffffe00012345678
Reverse Engineering Fundamentals
Function Recognition Techniques:
- Entry characteristics (prologue/epilogue)
- Calling convention analysis (cdecl/stdcall)
- String cross-references
- Imported function calls
Control Flow Analysis Methods:
; Basic block division example
block1:
cmp eax, ebx
jne block2
jmp block3
block2:
mov ecx, edx
block3:
ret
Assembly Optimization Refactoring
Code Optimization Case:
; Before optimization
mov eax, [mem1]
add eax, [mem2]
mov [mem3], eax
; After optimization (reduce memory accesses)
mov eax, [mem1]
add eax, [mem2] ; Keep result in register
mov [mem3], eax
Structure Refactoring Example:
// Reverse-engineer structure from assembly
struct Example {
int a; // offset 0
char b; // offset 4
double c; // offset 8
};
Compiler and Assembly Interaction
Compiler Assembly Output
GCC Assembly Generation Example:
gcc -S -O2 test.c -o test.s
# Key compilation options:
# -fomit-frame-pointer (omit frame pointer)
# -masm=intel (Intel syntax)
# -fverbose-asm (add comments)
MSVC Assembly Output:
cl /FAtest.asm /Fa test.c
# View calling convention differences:
# __cdecl (caller cleans stack)
# __stdcall (callee cleans stack)
High-Level Language Mapping
Function Calling Convention Comparison:
| Feature | x86 cdecl | x64 System V | ARM AAPCS |
|---|---|---|---|
| Parameter Passing | Stack | Registers + Stack | Registers + Stack |
| Return Value | EAX | XMM0/RAX | R0 |
| Stack Cleanup | Caller | Callee | Callee |
| Register Preservation | EBX/ESI/EDI/EBP | RBX/RBP/R12-R15 | R4-R11 |
Loop Optimization Case:
// Original code
for(int i=0; i<n; i++) {
a[i] = b[i] + c[i];
}
// Compiler-optimized assembly
mov rsi, b
mov rdi, c
mov rdx, a
mov ecx, n
rep movsq ; SIMD-optimized version
Compiler Optimization Options
GCC Optimization Level Comparison:
| Level | Optimization Focus | Typical Techniques |
|---|---|---|
| -O0 | Debug support | No optimization |
| -O1 | Basic optimization | Remove redundant code |
| -O2 | Balanced optimization | Function inlining, loop unrolling |
| -O3 | Aggressive optimization | Auto-vectorization, function inlining |
| -Os | Code size optimization | Instruction selection optimization |
Specific Optimization Flags:
-fprofile-generate # Profile-guided optimization
-flto # Link-time optimization
-fvectorize # Auto-vectorization
Inline Assembly Interaction
GCC Inline Assembly Syntax:
asm volatile (
"movl %1, %%eax
\t"
"addl $1, %%eax
\t"
"movl %%eax, %0"
: "=r"(result) // Output operand
: "r"(input) // Input operand
: "%eax" // Clobbered registers
);
Constraint Descriptions:
| Constraint | Meaning | Example |
|---|---|---|
| r | Any general register | “r”(var) |
| m | Memory reference | “m”(ptr) |
| =r | Output operand (write) | “=r”(res) |
| +r | Input/output operand | “+r”(val) |
Compiler Security Mechanisms
Buffer Overflow Protection Techniques:
- Stack protection (Canary):
; GCC stack protection example
mov rax, fs:0x28 ; Load Canary value
mov [rbp-8], rax ; Store to stack frame
; Before function return, check
cmp [rbp-8], fs:0x28
je .no_overflow
call __stack_chk_fail
- Address Space Layout Randomization (ASLR):
- Randomize stack/heap/library load addresses
- Controlled via /proc/sys/kernel/randomize_va_space
- Control Flow Integrity (CFI):
- Validate indirect jump targets
- Shadow Stack technology
ROP Attack Protection:
# Enable RELRO protection
gcc -Wl,-z,relro,-z,now program.c
# Generate non-executable stack
gcc -fstack-protector-strong -z noexecstack
By deeply understanding these low-level technologies, developers can achieve:
- High-performance binary optimization
- Security vulnerability analysis and protection
- Cross-platform binary compatibility
- Complex system debugging capabilities
- Compiler-level performance tuning
- Advanced reverse engineering capabilities



