Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LLDB not showing source code

Tags:

I am trying to debug a C++ program I am writing, but when I run it in LLDB and stop the program, it only shows me the assembler, not the original source. e.g. after the crash I’m trying to debug:

Process 86122 stopped * thread #13: tid = 0x142181, 0x0000000100006ec1 debug_build`game::update() + 10961, stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)     frame #0: 0x0000000100006ec1 debug_build`game::update() + 10961 debug_build`game::update: ->  0x100006ec1 <+10961>: movq   (%rdx), %rdx     0x100006ec4 <+10964>: movq   %rax, -0xb28(%rbp)     0x100006ecb <+10971>: movq   -0x1130(%rbp), %rax     0x100006ed2 <+10978>: movq   0x8(%rax), %rsi 

I am compiling with -O0 -g. I see the same thing when running the debugger via Xcode (I’m on OSX) or from the command line.

What else might I need to do to get the source code to show up in LLDB?

Additional notes

Here is an example of a typical build command:

clang++ -std=c++1y -stdlib=libc++ -fexceptions -I/usr/local/include -c -O2 -Wall -ferror-limit=5 -g -O0 -ftrapv lib/format.cpp -o format.o 

The earlier -O2 is there because that’s the default I’m using, but I believe the later -O0 overrides it, right?

What I’ve tried

  1. I’ve recreated this problem with a simple ‘hello world’ program using the same build settings.

  2. After some searching, I tried running dsymutil main.o which said warning: no debug symbols in executable (-arch x86_64), so perhaps the debug symbols are not being generated by my build commands?

  3. I also tried adding -gsplit-dwarf to the build commands but with no effect.

  4. Here is the link command from my ‘hello world’ version:

    clang++ main.o -L/usr/local/lib -g -o hello

  5. I ran dwarfdump (I read about it here) on the executable and object files. It looks to my untrained eye like the debug symbols are present in the object files, but not in the executable itself (unless dwarfdump only works on object files, which is possible). So maybe the linking stage is the issue. Or maybe there’s a problem with the DWARF.

  6. I have now got this working in the ‘hello world’ program, through issuing build commands one-by-one in the terminal. I am therefore guessing this may be an issue with my build system (Tup), possibly running the commands with a different working directory so the paths get mangled or something.

like image 680
Leo Avatar asked May 01 '16 15:05

Leo


People also ask

Does Xcode use LLDB?

Xcode uses the LLDB as the default debugging tool. The full form of LLDB is Low-level debugger. Breakpoints help a developer to stop the execution of the program at any point. Stopping the execution of the program at any point helps to know the current state of that program and its properties.

How do you set a breakpoint in LLDB?

In lldb you can set breakpoints by typing either break or b followed by information on where you want the program to pause. After the b command, you can put either: a function name (e.g., b my_subroutine ) a line number (e.g., b 12 )

Is LLDB the same as GDB?

In brief, LLDB and GDB are two debuggers. The main difference between LLDB and GDB is that in LLDB, the programmer can debug programs written in C, Objective C and C++ while, in GDB, the programmer can debug programs written in Ada, C, C++, Objective C, Pascal, FORTRAN and Go.

Is GDB better than LLDB?

Both GDB and LLDB are of course excellent debuggers without doubt. GDB is debugger part of the GNU project created to work along the GNU compiler. LLDB is debugger part of the LLVM project created to work along LLVM compiler. The majority of the commands are the same.


Video Answer


1 Answers

When you add the -g command line option to clang, DWARF debug information is put in the .o file. When you link your object files (.o, ranlib archives aka static libraries aka .a files) into an executable/dylib/framework/bundle, "debug notes" are put in the executable to say (1) the location of the .o etc files with the debug information, and (2) the final addresses of the functions/variables in the executable binary. Optimization flags (-O0, -O2 etc) do not have an impact on debug information generation - although debugging code compiled with optimization is much more difficult than debugging code built at -O0.

If you run the debugger on that executable binary -- without any other modification -- the debugger will read the debug information from the .o etc files as long as they're still on the filesystem at the same file path when you built the executable. This makes iterative development quick - no tool needs to read, update, and output the (large) debug information. You can see these "debug notes" in the executable by running nm -pa exename and looking for OSO entries (among others). These are stabs nlist entries and running strip(1) on your executable will remove them.

If you want to collect all of the debug information (in the .o files) into a standalone bundle, then you run dsymutil on the executable. This uses the debug notes (assumptions: (1) the .o files are still in their orig location, and (2) the executable has not been stripped) to create a "dSYM bundle". If the binary is exename, the dSYM bundle is exename.dSYM. When the debugger is run on exename, it will look next to that binary for the dSYM bundle. If not found there, it will do a Spotlight search to see if the dSYM is in a spotlight-indexed location on your computer.

You can run dwarfdump on .o files, or on the dSYM bundle -- they both have debug information in them. dwarfdump won't find any debug information in your output executable.

So, the normal workflow: Compile with -g. Link executable image. If iterative development, run debugger. If shipping/archiving the binary, create dSYM, strip executable.

like image 170
Jason Molenda Avatar answered Sep 19 '22 14:09

Jason Molenda