11

I am using GDB to debug a program that uses libpthread. There is an error happening in pthread_create and need to step into that function. Unfortunately when I am debugging my program, it does not load the shared library symbols properly so I can't step over the source code and examine program behaviour meaningfully.. This is the output as soon as I start gdb.

Remote debugging using 127.0.0.1:21293
warning: limiting remote suggested packet size (206696 bytes) to 16384
Failed to read a valid object file image from memory.

So I believe the last message is related to the failure to read debugging symbols. This is despite having the libc6-dbg package installed. This is the truncated output of "where" at a point just before a SIGSEGV is encountered (in pthread_create, the function I want to examine in the debugger)

#0  0x68200ce2 in ?? ()
#1  0x68403cbf in ?? ()
#2  0x687571b0 in ?? ()
#3  0x6874c638 in ?? ()
#4  0x68867a72 in ?? ()
....

The process' /proc/.../maps shows where libpthread is mapped into memory.

683f8000-68410000 r-xp 00000000 08:01 3017052                            /lib/i386-linux-gnu/i686/cmov/libpthread-2.19.so
68410000-68411000 r--p 00017000 08:01 3017052                            /lib/i386-linux-gnu/i686/cmov/libpthread-2.19.so
68411000-68412000 rw-p 00018000 08:01 3017052                            /lib/i386-linux-gnu/i686/cmov/libpthread-2.19.so

I believe that if I could only manually load the debugging symbols into gdb, then I will be able to step over the source code and find the source of my memory error. However I am unsure about how to do this.

I am debugging a 32 bit program on x86_64 Debian. What should I do to load libpthread symbols into GDB so that I can debug it meaningfully?

YardGlassOfCode
  • 316
  • 1
  • 2
  • 8
  • Why do you want to debug libpthread? It's extremely likely that libpthread is blameless. It seems obvious to me that something is wrong with your arguments to `pthread_create()` - Are you corrupting the `pthread_attr_t` struct, or passing `NULL` for the callback, or doing anything else subtly invalid? – Iwillnotexist Idonotexist May 16 '15 at 23:34
  • Assuming that it's a problem passing parameters to `pthread_create()` it doesn't hurt to suppress meaningless error messages from gdb. – Iharob Al Asimi May 16 '15 at 23:38
  • Oh, and does the error occur in the new thread, or the old thread, and has the new thread been created by the time of the segfault? – Iwillnotexist Idonotexist May 16 '15 at 23:39
  • I have checked the non-callback arguments and they don't appear to be problematic. I put debug traces in the the callback and I get no output from them. I figured it would be a good idea to see what happens in pthread_create to trace invalid behaviour to my program. I do NOT think pthread_create is buggy, however. Perhaps a rethink is needed? – YardGlassOfCode May 16 '15 at 23:48
  • The error you quote (`Failed to read a valid object file image from memory.`) occurs exactly once in all of GDB, and is a result of GDB's failure to find the header of an (ELF) binary object in the debugged process' memory - as though you had a GDB that doesn't support 32-bit debugging (unlikely), or maybe an exotic binary format. As an aside, can I ask you why you're debugging remotely when the binary is on localhost? – Iwillnotexist Idonotexist May 16 '15 at 23:53
  • It's complicated but I am debugging a process spawned by WINE. – YardGlassOfCode May 16 '15 at 23:58
  • Ooooooh. That explains _a lot_! Your GDB is expecting a Linux ELF executable; You're running a (Windows) PE executable. Your GDB might not have been configured to debug PE executables, or might not have been told and may be unable to guess, that it's actually a PE executable. – Iwillnotexist Idonotexist May 17 '15 at 00:00
  • Hang on, it's not a Windows executable. This process called "services.exe" but it is written for Wine i.e. it is one of Wine's subsystems – YardGlassOfCode May 17 '15 at 00:02
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/77989/discussion-between-iwillnotexist-idonotexist-and-yardglassofcode). – Iwillnotexist Idonotexist May 17 '15 at 00:02

1 Answers1

14

Loading debug symbols for a shared library

If the shared library is stripped, and the debug symbols are provided as a separate file, you need to load them after the shared library was loaded by the linker. The symbols should be loaded on the memory address where the shared library is loaded.

Following is an example of loading the symbols:

  1. start gdb

    ~$ gdb a.out
    GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
    Copyright (C) 2020 Free Software Foundation, Inc.
    (gdb) info sharedlibrary
    No shared libraries loaded at this time.
    
  2. Create break point (on main or any other place) and start the debug

    (gdb) b 35
    Breakpoint 1 at 0xd7c: file test.c, line 35.
    (gdb) r
    Starting program: /root/testing/lib-test/a.out
    
  3. Find the memory location where the shared library that you want to debug was loaded (in this example the library is libtest.so.1

    (gdb) info sharedlibrary
    From                To                  Syms Read   Shared Object Library
    0x0000fffff7fcd0c0  0x0000fffff7fe5468  Yes (*)     /lib/ld-linux-aarch64.so.1
    0x0000fffff7f9f890  0x0000fffff7fb65c0  Yes (*)     /usr/local/lib/libtest.so.1
    0x0000fffff7e4bbc0  0x0000fffff7f3b190  Yes         /lib/aarch64-linux-gnu/libc.so.6
    0x0000fffff7dfea50  0x0000fffff7e0ddec  Yes         /lib/aarch64-linux-gnu/libpthread.so.0
    

    so, the library is loaded starting from memory address 0x0000fffff7f9f890

  4. Load the symbol file with the address from the share library

    (gdb) add-symbol-file ./libsrc/libtest.dbg 0x0000fffff7f9f890
    add symbol table from file "./libsrc/libtest.dbg" at
     .text_addr = 0xfffff7f9f890
    (y or n) y
    Reading symbols from ./libsrc/libtest.dbg...
    

After this, you can trace the execution flow inside the library, list the lines of the source code, inspect variables by name, etc.

jordanvrtanoski
  • 5,104
  • 1
  • 20
  • 29