Sergey Kolesnik
Sergey Kolesnik

Reputation: 3640

GDB show current compiled binary file for function address on call stack

In visual studio you can see where the function is located, i.e. within which compiled binary file. For example: enter image description here

Is there a command for GDB?


Several versions of one symbol can be loaded twice in case you load a dll. And it is essential to know whether the code is being executed within the .exe or one of loaded .dll libs. Visual Studio debugger shows this info like on the screenshot provided (though it is for C#, I just copied it from the web site).

When I used Visual Studio, I was able to spot some cases, when the code expected to be executed within a .dll was executed within .exe. Of course this was due to a mistake in linking command. But this kind of mistakes may be hard to spot, and seeing the current binary file of execution helps a lot.

Upvotes: 1

Views: 2508

Answers (2)

Mark Plotnick
Mark Plotnick

Reputation: 10261

Disclaimer: this is for GDB on GNU/Linux, working with ELF files. The GDB manual doesn't say that the commands I show here are Linux-specific, but I don't know whether they'll produce similar results on Windows.

GDB's info symbol command, given an address, will output the closest symbol (and offset), filename and section of the object file corresponding to that address.

Here's an example where the main program accesses the foo function from two different shared libraries. foo just calls lseek, which will be a convenient spot to place a breakpoint because it isn't used anywhere else in the program, including the dl functions.

$ nl -ba a.c
     1  #include <sys/types.h>
     2  #include <unistd.h>
     3  void foo() {
     4          lseek(0, 0, SEEK_CUR);
     5  }
$ cc -fpic -shared -g a.c -o a.so

$ nl -ba b.c
     1  #include <sys/types.h>
     2  #include <unistd.h>
     3  void foo() {
     4          lseek(0, 0, SEEK_CUR);
     5  }
$ cc -fpic -shared -g b.c -o b.so
$ nl -ba main.c
     1  #include <dlfcn.h>
     2  #include <unistd.h>
     3  #include <stdio.h>
     4  int main() {
     5          void *a = dlopen("./a.so", RTLD_LAZY|RTLD_LOCAL);
     6          void *b = dlopen("./b.so", RTLD_LAZY|RTLD_LOCAL);
     7
     8          void (*afoo)() = (void (*)()) dlsym(a, "foo");
     9          void (*bfoo)() = (void (*)()) dlsym(b, "foo");
    10
    11          (*afoo)();
    12          (*bfoo)();
    13  }
$ cc main.c -g -ldl -o main

Here's the GDB session. The bt command will show the PC address of each frame, as well as the name of the source file, since everything was compiled with GCC's -g option. The info sym command will show the name of the executable or object file.

$ gdb -q ./main
(gdb) start
Temporary breakpoint 1, main () at main.c:5
5               void *a = dlopen("./a.so", RTLD_LAZY|RTLD_LOCAL);
(gdb) b lseek
Breakpoint 2 at 0x7ffffef38d30: file ../sysdeps/unix/syscall-template.S, line 84.
(gdb) c
Continuing.

Breakpoint 2, lseek64 () at ../sysdeps/unix/syscall-template.S:84
84      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) bt
#0  lseek64 () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007ffffec40688 in foo () at a.c:4
#2  0x000000000800078b in main () at main.c:11
(gdb) info sym 0x00007ffffec40688
foo + 24 in section .text of ./a.so
(gdb) c
Continuing.

Breakpoint 2, lseek64 () at ../sysdeps/unix/syscall-template.S:84
84      T_PSEUDO (SYSCALL_SYMBOL, SYSCALL_NAME, SYSCALL_NARGS)
(gdb) bt
#0  lseek64 () at ../sysdeps/unix/syscall-template.S:84
#1  0x00007ffffea30688 in foo () at b.c:4
#2  0x0000000008000796 in main () at main.c:12
(gdb) info sym 0x00007ffffea30688
foo + 24 in section .text of ./b.so

Upvotes: 3

Klaus
Klaus

Reputation: 25613

The debug information stored within an executable gives the information from which source file and from which line of the source the current code was generated. Intermediate files like object files are NOT part of such information and also not always available at all. If you compile your code in a single step ( compile & link ) you will have only some temporary generated files somewhere. Especially in this case, it makes no sense to reference on the object files.

The information you showed from VS is also the source code location!

You also should notice that a compiled language like C and C++ is quite different to something like C#, even if there is also some kind of "byte code generation" or whatever.

Maybe I have a misunderstanding, but what is the need to see the name of an intermediate object file where the current code was generated/placed between compiling and linking? The binary itself is the full linked program, so the name of the binary will always be the name of the executable you have started and you are currently debugging.

If you really need to know which object file contains the code you are looking for, you can use objdump -t to get a list of all symbols for the complete binary and also for all the object files. In case of C++ you should use it in combination with demangling, maybe with c++filt on hand.

Upvotes: 0

Related Questions