I have a binary abc.so which get crash, and its in stripped format so not able to get the other symbols details other than the address.
I wanted to debug the following address.
(gdb) bt #0 0xb438f92a in ?? () from /usr/lib/abc.so #1 0xb2aaac38 in ?? () from /usr/lib/abc.so
I tried using addr2line to find the file, linenumber and other info by running the following command:
addr2line -i -f -e libvega_webview.so 0xb438f92a
The above did not worked, so I realised may the the address which I am passing might not be the one. So I tried find the offset:
objdump -f adb.so output: adb.so: file format ittle start address 0x055f1300
offset: 0xb2aaac38 - 0x055f1300 ==> 0xad4b9938
and then:
addr2line -i -f -e libvega_webview.so 0xad4b9938
but still no luck, not sure what I am missing.
Can anyone please help me on this, not sure if I'm still calculating the correct offset.
I am trying to analyze segfault on a core file on linux. I am not sure if the following behavior is correct, thus i deliberately caused a segfault using
#include <signal.h>
int main() {
raise(SIGSEGV);
}
the binary is build with debug info i.e.
file mainTestFile
mainTestFile: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/l, for GNU/Linux 3.2.0, with debug_info, not stripped
notice how it does say "with debug_info, not stripped" at the end
when i execute the binary i get a core file generated which is called core-mainTestFile.20474
(In order to generate the core file i hat to set my ulimit to unlimited i.e.
ulimit -c unlimited
)
if i run only the binary under GDB and do backtrace "bt" then i get the segfault and i get all names of the functions involved
printed nicely i.e. notice how the gdb says when starting "reading symbols from ./mainTestFile...done."
gdb ./mainTestFile
GNU gdb (Ubuntu 8.1-0ubuntu3) 8.1.0.20180409-git
....
reading symbols from ./mainTestFile...done.
(gdb) run
Starting program: /src/exe/mainTestFile
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Program received signal SIGSEGV, Segmentation fault.
__GI_raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
51 ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
(gdb) bt
#0 __GI_raise (sig=<optimized out>) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x0000000000402dad in main (argc=1, argv=0x7fffffffda38) at /src/exe/main.cpp:53
(gdb)
however if i try to anaylise only the core file with gdb like that
gdb -c core-mainTestFile.20474
then i get only question marks
the when i execute "bt" then i do not see the names of the methods, instead i get question marks
(gdb) bt
#0 0x00007f34d8842e97 in ?? ()
#1 0x0000000000000000 in ?? ()
they only workaround i found is to supply the binary directly at the command line then it all gets printed nicely.
even if i try to tell GDB to use the symbols file and point that to the binary file which does have the symbols
i.e.
symbol-file /src/exe/mainTestFile
then GDB says
Reading symbols from /src/exe/mainTestFile...done
and when i execute bt i see the question marks again? Why is that. Is GDB not able to get the symbols out of the binary?
it only works if supply the binary directly on the command like like:
gdb /src/exe/mainTestFile -c core-mainTestFile.20474
my question is should the GDB be able to read symbols of the binary when directly supplying him the binary over the "symbol-file" command or not. Why is this working when supping him directly the binary over the command line, what is the difference?
should the GDB be able to read symbols of the binary when directly supplying him the binary over the "symbol-file" command or not.
In theory, using symbol-file and core-file commands in either order in GDB should be equivalent.
But there is a bug: symbol-file followed by core-file works, and the opposite order doesn't.
Since generally the end-user can always rearrange his commands into the order that works, this has never propagated to the top of any GDB developer's queue of things to fix.
Related bug (but not an exact duplicate).
trace point can be traced, but trace actions does not work normally.
at the last of gdb side below shows trace point is traced.
but "collect $regs" does not work as expected.
my platform is RH6.4.
1. gdbserver side.
gdbserver :10000 ./a.out
Process ./a.out created; pid = 10466
Listening on port 10000
Remote debugging from host 127.0.0.1
2. gdb side.
gdb a.out
(gdb) target remote :10000
Remote debugging using :10000
Reading symbols from /lib64/ld-linux-x86-64.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib64/ld-linux-x86-64.so.2
0x00000033b7000b00 in _start () from /lib64/ld-linux-x86-64.so.2
Created trace state variable $trace_timestamp for target's variable 1.
Missing separate debuginfos, use: debuginfo-install glibc-2.12-1.107.el6.x86_64
(gdb) trace main
Tracepoint 1 at 0x400541: file a.c, line 12.
(gdb) actions 1
collect $regs
end
(gdb) tstart
(gdb) break 15
Breakpoint 2 at 0x40055f: file a.c, line 15.
Breakpoint 2, main (argc=1, argv=0x7fffca819f08) at a.c:18
18 sleep (1);
(gdb) cont
Continuing.
(gdb) tstop
(gdb) tfind
Found trace frame 0, tracepoint 1
12 c = 2;
I suppose you expected tracepoint to be in actual main declaration line in the source file, am I wrong?
The important part is that it is placed in function's entry point, this is, actually, first function's code line that, looking at the information you provided, it should be c = 2;
On the other hand, this is just a stupid detail, please note that you have no code at line 15 and breakpoint has been set at line 18.
Edit:
According to your comments, you expected tfind to dump all collected registers but you would need an extra step for this: by using tfind with no argument you selected next tracepoint (first one in this case) and, to dump this tracepoint's action collected info, you should call tdump
I have an incomplete stacktrace which stops at a known library (linux i686 architecture). In order to ascertain the function last called, I am trying to map $eip as output by gdb, to an address within a file generated by "objdump -d library.so".
I thought I might be able to use the From address output from "info shared" within gdb, along with the $eip to calculate an offset, which I could then translate to an offset from the disassembly text section of the objdump -d output?
Not sure if this approach is sensible, but trying it in a simple test harness app with a shared library does not give me an address within the right function.
Any help much appreciated.
I thought I might be able to use the From address output from "info shared" within gdb, along with the $eip to calculate an offset, which I could then translate to an offset from the disassembly text section of the objdump -d output?
Yes, that is exactly what you need to do.
The From address in GDB display tells you where .text section of the shared library was located.
The readelf -S foo.so | grep '\.text' will tell you offset of .text in the foo.so itself. Subtract one from the other, and you get the relocation for that shared library (it will be page-aligned).
Now take the $eip from GDB, subtract relocation, and you'll get an address that will match output of nm and objdump for foo.so.
However, GDB will have already completed all of the above steps internally. If it wasn't able to deduce which function $eip ended up in, you shouldn't expect that performing these steps manually will produce any better result.
I'm trying to disassemble a program to see a syscall assembly instruction (the INT instruction, I believe) and the handler with GDB and have written a little program (see below) for it that opens and closes a file.
I was able to follow the call to fopen with GDB until it executed a call.
When I tried to tell GDB "disassemble 0x...." (address of call) it responded with 'No function contains specified address.'
Is it possible to force GDB to disassemble (or display it in assembler as good as possible) that memory address? If so, how?
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE* f;
f = fopen("main.c", "r");
if (!f) {
perror("open");
return -1;
}
fclose(f);
return 0;
}
Yeah, disassemble is not the best command to use here.
The command you want is "x/i" (examine as instructions):
(gdb) x/i 0xdeadbeef
Do you only want to disassemble your actual main? If so try this:
(gdb) info line main
(gdb) disas STARTADDRESS ENDADDRESS
Like so:
USER#MACHINE /cygdrive/c/prog/dsa
$ gcc-3.exe -g main.c
USER#MACHINE /cygdrive/c/prog/dsa
$ gdb a.exe
GNU gdb 6.8.0.20080328-cvs (cygwin-special)
...
(gdb) info line main
Line 3 of "main.c" starts at address 0x401050 <main> and ends at 0x401075 <main+
(gdb) disas 0x401050 0x401075
Dump of assembler code from 0x401050 to 0x401075:
0x00401050 <main+0>: push %ebp
0x00401051 <main+1>: mov %esp,%ebp
0x00401053 <main+3>: sub $0x18,%esp
0x00401056 <main+6>: and $0xfffffff0,%esp
0x00401059 <main+9>: mov $0x0,%eax
0x0040105e <main+14>: add $0xf,%eax
0x00401061 <main+17>: add $0xf,%eax
0x00401064 <main+20>: shr $0x4,%eax
0x00401067 <main+23>: shl $0x4,%eax
0x0040106a <main+26>: mov %eax,-0xc(%ebp)
0x0040106d <main+29>: mov -0xc(%ebp),%eax
0x00401070 <main+32>: call 0x4010c4 <_alloca>
End of assembler dump.
I don't see your system interrupt call however. (its been a while since I last tried to make a system call in assembly. INT 21h though, last I recall
This isn't the direct answer to your question, but since you seem to just want to disassemble the binary, perhaps you could just use objdump:
objdump -d program
This should give you its dissassembly. You can add -S if you want it source-annotated.
You can force gcc to output directly to assembly code by adding the -S switch
gcc -S hello.c
fopen() is a C library function and so you won't see any syscall instructions in your code, just a regular function call. At some point, it does call open(2), but it does that via a trampoline. There is simply a jump to the VDSO page, which is provided by the kernel to every process. The VDSO then provides code to make the system call. On modern processors, the SYSCALL or SYSENTER instructions will be used, but you can also use INT 80h on x86 processors.
If all that you want is to see the disassembly with the INTC call, use objdump -d as someone mentioned but use the -static option when compiling. Otherwise the fopen function is not compiled into the elf and is linked at runtime.
gdb disassemble has a /m to include source code alongside the instructions. This is equivalent of objdump -S, with the extra benefit of confining to just the one function (or address-range) of interest.
You don't have to use gdb. GCC will do it.
gcc -S foo.c
This will create foo.s which is the assembly.
gcc -m32 -c -g -Wa,-a,-ad foo.c > foo.lst
The above version will create a listing file that has both the C and the assembly generated by it. GCC FAQ
full example for disassembling a memory range to C
/opt/gcc-arm-none-eabi-9-2019-q4-major/bin/arm-none-eabi-gdb
(gdb)file /root/ncs/zephyr/samples/hello_world/build_nrf9160dk_nrf9160ns/zephyr/zephyr.elf
(gdb) directory /root/ncs/zephyr/samples/hello_world/src
#here you want 1
(gdb) info line* 0x000328C0
#here you want 2, -0x04 ~ +0x04 is your range size
(gdb) disassemble /m 0x000328C0-0x04, 0x000328C0+0x04
#here with binary code
(gdb) disassemble /r 0x000328C0-0x04, 0x000328C0+0x04
(gdb) info thread
(gdb) interpreter-exec mi -thread-info
The accepted is not really correct. It does work in some circumstances.
(gdb) disas STARTADDRESS ENDADDRESS
The highest upvoted answer is correct. Read no further is you don't wish to understand why it is correct.
(gdb) x/i 0xdeadbeef
With an appropriately meaningless hex address.
I have an STM32 and I have relocated the code with PIC. The normal boot address is 0x8000000, with a 0x200 vector table. So a normal entry is 0x8000200. However, I have programmed the binary to 0x80040200 (two NOR flash sectors away) and wish to debug there.
The issue gdb has with this is 'file foo.elf' is showing that code is in the first range. Special command like 'disassemble' will actually look at the binary on the host. For the cross debug case, gdb would have to look at memory on the remote which could be expensive. So, it appears that the 'x /i' (examine as code) is the best option. The debug information that gdb depends on (where routines start/end) is not present in a random binary chunk.
To combine the answers above for PIC code on an embedded cross system,
You need to create multiple elf files, one for each possible target location. Use the GDB's file command to select the one with proper symbol locations.
This will NOT work for Cross development
You can use generating gcc debug symbols. The steps are,
Build normal link address.
Extract symbols.
Use symbol-file with an offset for the runtime address.
(gdb) help symbol-file
Load symbol table from executable file FILE.
Usage: symbol-file [-readnow | -readnever] [-o OFF] FILE
OFF is an optional offset which is added to each section address.
You can then switch symbol files to a relocated run address to use the first answer.
If you have a case where the code is relocated, but data is absolute, you need to link twice and choose the relocated elf files (symbols only are relocated and code is the same). This is desirable with NOR flash that is XIP (execute-in-place) as the memory devices for .text and .rodata are different from .data and .bss. Ie, many lower-to-middle scale embedded devices. However, gcc does not support this code generation option (at least on ARM). You must use a 'static base' register (for example, r9 as u-boot does).
There is another way which I wanted to presetn using gdb on top of the suggestions above:
Launch your program with gdb, and set a break point on main break *main and run
The you can use info proc mappings.