手动通过动态加载器启动程序时,GDB无法在main()处断点的原因及解决方法
main() When Launching via Dynamic Loader The issue you're facing happens because the static .text offset you used with add-symbol-file doesn't match the actual memory address where your a.out is loaded (thanks to ASLR and dynamic loading). Here's how to fix it properly:
Step-by-Step Solution
Option 1: Manually Calculate Load Address
- Start GDB with your dynamic loader and target binary:
gdb -q --args /lib64/ld-linux-x86-64.so.2 ./a.out - Enable stopping on shared library load events so we can pause before your program executes:
(gdb) set stop-on-solib-events 1 - Launch the program and continue past initial loader events:
(gdb) run # You'll see a stop due to shared library event (gdb) continue # Repeat continue until libc is loaded, then press Ctrl+C to pause the program - Find the actual load base address of your
a.out:
Look for the line corresponding to(gdb) info proc mappings./a.outand note its starting address (e.g.,0x555555554000). - Calculate the real
.textaddress by adding the static offset fromreadelf(0x1050in your case) to the load base:Real .text address = load_base + 0x1050 - Load the symbol table at the correct address:
(gdb) add-symbol-file ./a.out 0x<calculated_real_text_address> # Type 'y' when prompted to confirm - Now set your breakpoint and continue:
Your program will now stop at(gdb) break main (gdb) continuemain()as expected.
Option 2: Use exec-wrapper (Simpler)
This method lets GDB handle the symbol table automatically, no manual calculations needed:
- Start GDB by loading your target binary first:
gdb -q ./a.out - Set the dynamic loader as the execution wrapper:
If you're testing a custom glibc, replace the path with your custom loader (e.g.,(gdb) set exec-wrapper /lib64/ld-linux-x86-64.so.2/path/to/custom-glibc/lib/ld-linux-x86-64.so.2). - Run the program normally:
GDB will correctly resolve the(gdb) runmain()breakpoint without extra steps.
Why Your Original Attempt Failed
The 0x1050 from readelf is a static offset relative to the ELF file's base, not the actual memory address where a.out is loaded. When using the dynamic loader, your binary is placed at a random memory address (due to ASLR), so loading symbols at the static offset caused GDB to map main() to the wrong memory location—hence the breakpoint never triggered.
内容的提问来源于stack exchange,提问作者vinit Tirnagarwar

