13

There are many questions related to specific errors why stepping into a shared library with gdb isn't working. None of them provide a systematic answer on how to confirm where the the cause is. This questions is about the ways to diagnose the setup.

Setup example

main.c

#include <stdio.h>
#include "myshared.h"

int main(void)
{
    int a = 3;
    print_from_lib();
    return 0;
}

myshared.h

void print_from_lib();

myshared.c

#include <stdio.h>

void print_from_lib()
{
    printf("Printed from shared library\n");
}

Place all the files in the same directory.

export LIBRARY_PATH=$PWD:$LIBRARY_PATH
export LD_LIBRARY_PATH=$PWD:$LD_LIBRARY_PATH
gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb

Getting the error

$ gdb ./app-ggdb 
GNU gdb (Ubuntu 7.12.50.20170314-0ubuntu1) 7.12.50.20170314-git
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
Printed from shared library
8       return 0;

gdb is not stepping inside of the function

Necessary but not sufficient checks

Debug symbols in the binaries

$ objdump --syms libmyshared-ggdb.so | grep debug
0000000000000000 l    d  .debug_aranges 0000000000000000              .debug_aranges
0000000000000000 l    d  .debug_info    0000000000000000              .debug_info
0000000000000000 l    d  .debug_abbrev  0000000000000000              .debug_abbrev
0000000000000000 l    d  .debug_line    0000000000000000              .debug_line
0000000000000000 l    d  .debug_str     0000000000000000              .debug_str

Symbols recognized by gdb

$ gdb ./app-ggdb
...### GDB STARTING TEXT
Reading symbols from app-ggdb...done.
(gdb) break 7
Breakpoint 1 at 0x78f: file main.c, line 7.
(gdb) run
Starting program: /home/user/share-lib-example/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb)(gdb) info sharedlibrary
From                To                  Syms Read   Shared Object Library
0x00007ffff7dd7aa0  0x00007ffff7df55c0  Yes         /lib64/ld-linux-x86-64.so.2
0x00007ffff7bd5580  0x00007ffff7bd5693  Yes         /home/user/share-lib-example/libmyshared-ggdb.so
0x00007ffff782d9c0  0x00007ffff797ed43  Yes         /lib/x86_64-linux-gnu/libc.so.6

Confirm .gdbinit isn't the cause

~/.gdbinit contains commands automatically executed upon starting gdb. ref.

Running gdb with the -nx flags can exclude .gdbinit as the source of the problem.

Question

Am looking for suggestions to complete the list of Necessary but not sufficient checks.

Current issue [Update from Mark Plotnick]

This step bug is reproducible on Ubuntu 17.04 amd64 with both a 64- and 32-bit executable and library.

The bug isn't reproducible on Ubuntu 17.04 i386. (gcc 6.3.0-12ubuntu2, gdb 7.12.50 and 8.0, no .gdbinit.).

Possibly relevant: gcc on 17.04 amd64 has been built (by Canonical) to generate pie executables by default.

Question

Can flags with which gcc was build with interfere with debugging? How can you identify if your gcc is the cause?

TheMeaningfulEngineer
  • 15,679
  • 27
  • 85
  • 143
  • From whoever cast a close, would appreciate a pointer on what part isn't clear. – TheMeaningfulEngineer Jul 23 '17 at 23:32
  • I'm just speculating, but *"Am looking for suggestions to complete the list of Necessary but not sufficient checks"* is not a real good question in my opinion. The grammar sounds like ESL; and "suggestions to complete the list" leaves a lot to be desired. I parse *"Necessary but not sufficient checks"* as, steps which you can perform that don't accomplish your goal. Its kind of a bogus question. – jww Jul 24 '17 at 01:21
  • @jww It is a path to provoke answers of `most useful things to try first if your debugging isn't working` before posting yet another `gdb and shared lib` type of question. Once a list of methods have been found that point to the solution, I will rephrase the question. Having just asked `Ways to debug gdb shared library` without an example looked like a way to get the question closed. :) – TheMeaningfulEngineer Jul 24 '17 at 03:56
  • GDB 7.11 can't reproduce your problem. In GDB, use `show env LD_LIBRARY_PATH` to ensure the library path is correct or you can use `set env LD_LIBRARY_PATH=.` to set it. – haolee Jul 24 '17 at 06:41
  • @haolee `show env LD_LIBRARY_PATH` is correct. Just tried also with gdb 8.0 same thing, `s` not stepping into `print_from_lib()`. Can you please explain what happened in your case? Perhaps as an answer with steps? – TheMeaningfulEngineer Jul 24 '17 at 08:19
  • @TheMeaningfulEngineer and Haolee - I beleve location has something to do with being able to step into shared objects. I seem to recall Debian and/or Fedora will not step into system shared objects by default, and you have to jump through hoops to do it. If I recall "system shared objects" are those located in `/lib`, `/usr/lib`, `/usr/local/lib`, etc. It regularly wastes my time for libraries I install into `/usr/local/lib`. I usually give up in frustration, and re-run the experiment with everything built in my home directory. In my home directory, I can step into shared objects. – jww Jul 24 '17 at 17:14
  • 3
    FWIW, this step bug is reproducible on Ubuntu 17.04 amd64 (which I believe is the same as what OP is running) with both a 64- and 32-bit executable and library, but the bug isn't reproducible on Ubuntu 17.04 i386. (gcc 6.3.0-12ubuntu2, gdb 7.12.50 and 8.0, no .gdbinit.) Possibly relevant: gcc on 17.04 amd64 has been built (by Canonical) to generate pie executables by default. – Mark Plotnick Jul 31 '17 at 20:09

3 Answers3

6

Your problem is self-imposed: don't do this: set step-mode on, and step will work as you expect.

From the GDB manual:

set step-mode
set step-mode on
The set step-mode on command causes the step command to stop at the first
instruction of a function which contains no debug line information
rather than stepping over it.

This is useful in cases where you may be interested in inspecting the machine
instructions of a function which has no symbolic info and do not want
GDB to automatically skip over this function.

You are interested in the opposite of the above -- you want to step into the print_from_lib function and avoid stopping inside the PLT jump stub and the dynamic loader's symbol resolution function.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • Thanks, updated based on your suggestion but it still isn't stepping into the library function. Is it ok to use `objdump --syms libmyshared-ggdb.so | grep debug` for checking the existence of debug symbols? There was one answer you gave where you suggested `readelf -d libmyshared-ggdb.so | grep DEBUG` which returns empty in this example. – TheMeaningfulEngineer Jul 24 '17 at 04:07
  • @TheMeaningfulEngineer I can't reproduce your observed behavior using GDB 7.9, 8.0.50.20170429-git, and 8.0.50.20170725-git. Are you *sure* you don't have another `set step-mode` in your `~/.gdbinit`? Maybe try running with `gdb -nx app-ggdb` to be sure? – Employed Russian Jul 25 '17 at 01:21
  • Tried it, unfortunately wasn't the cause. Great suggestion though, added it to the potential list of checks. After your suggestion I removed `set step-mode on` and it's just stepping over `print_from_lib();` now. – TheMeaningfulEngineer Jul 25 '17 at 06:24
6

GDB 7.11 can't reproduce this problem. This is my steps. I hope this will help you:

1.gcc -ggdb -c -Wall -Werror -fpic myshared.c -o myshared-ggdb.o
2.gcc -ggdb -shared -o libmyshared-ggdb.so myshared-ggdb.o
3.gcc -ggdb main.c -lmyshared-ggdb -o app-ggdb -L.
4.gdb ./app-ggdb

In GDB,

(gdb) set env LD_LIBRARY_PATH=.
(gdb) b main.c:7
Breakpoint 1 at 0x4006a5: file main.c, line 7.
(gdb) r
Starting program: /home/haolee/tmp/app-ggdb 

Breakpoint 1, main () at main.c:7
7       print_from_lib();
(gdb) s
print_from_lib () at myshared.c:5
5       printf("Printed from shared library\n");
(gdb) 

I step into the function print_from_lib successfully.

haolee
  • 892
  • 9
  • 19
4

Some more tests you can do on built shared library:

  1. file libmyshared-ggdb.so should report that library has debug info and not stripped.
  2. nm libmyshared-ggdb.so | grep print_from_lib should find the symbol for print_from_lib function.

If all above tests passed try to load the library directly in gdb and find the function:

gdb libmyshared-ggdb.so
(gdb) info functions print_from_lib

Function print_from_lib name should be printed. If not, something is wrong with gdb or gcc.

ks1322
  • 33,961
  • 14
  • 109
  • 164
  • Copy `libmyshared-ggdb.so` into `/usr/local/lib`. You likely won't be able to step it. – jww Aug 13 '17 at 01:29