I'm working on a really big project which I would like to debug with gdb. Unfortunately, compiling with -g flag takes two days and a half and output libraries that are larger than 60Go (project takes ~1Go without -g).
is there a simpler way to obtain a symbols table (i.e. be able to backtrace) and if yes, how ?
I've seen that gdb offers three levels of debugging (-g level as described here), would it help ? Would string ?
Thanks in advance.
For a backtrace with just function names, you don't need -g at all.
For a backtrace with file and line info, using recent GCC versions, try -gmlt option (minimal line table). Note that no local variable info will be available in GDB.
If you want local variables, you'll probably want to use -gdwarf-4.
The documentation you pointed at is for gcc-2.95. That is an ancient version. If you are still using it, your first task should be to switch to (current) gcc-4.6.2
If you have an idea about source files you want to debug compile them with -g option. Make sure you link with -g option too. Now you have a partial debug image.
Related
I have an elf file, while analysing the mapfile and elf using elfparser, I saw a section called .Debug_info, which is taking largest memory.
I am compiling for xtensa DSP, using xt-xc++, I haven't used -g option also given -o2 optimization level.
is it possible to remove this for release builds?
section called .debug_info, which is taking largest memory.
Note that this section does not have SHF_ALLOC flag, and therefore does not take any RAM at runtime (it only takes space in the filesystem). Of course if you use ramdisk, then that section still does cost you RAM in the end.
is it possible to remove this for release builds?
Yes: none of the .debug* sections are necessary at runtime, and all of them can be safely stripped.
-g0 and -s option didn't work.
It's likely that you are getting .debug_* sections from libraries that you are linking in, and not from your own code. The -g was present when the libraries were compiled, so building with -g0 doesn't have any effect.
It's surprising that -s didn't work, but maybe your compiler interprets this flag differently.
In any case, you should use strip --strip-debug to get rid of .debug_* sections (note: this does not remove the symbol table).
The best practice is actually to compile all your code with full debug info (-g), save the full debug binary for post-mortem analysis, use strip --strip-debug to make a release binary, and use that binary for actual distribution.
If/when the release binary crashes and leaves a core dump, having (saved) full-debug exactly matching binary greatly improves post-mortem analysis you can do.
I have seen one other answer link but what I don't understand is what is basis.cm and what's it's use?
You are asking two questions.
What is basis.cm and what's it's use?
This is the Basis library. It allows the use of built-in functions.
How to compile and execute a stand-alone SML-NJ executable
Assuming you followed Jesper Reenberg's tutorial on how to execute a heap image, the next thing you need in order to have SML/NJ produce a stand-alone executable is to convert this heap image. One should hypothetically be able to do this using heap2exec, a tool that takes the heap image, e.g. the .x86-linux file generated on my system, and generates an .asm file that can be assembled and linked.
Unfortunately, this tool is not very well-maintained, so you have to
Go to the smlnj.org page and fix the download-link by removing 'www.' (this page and the SourceForge page don't contain the same explanations or assumptions about argument count, and neither page's download link work).
Download and extract this tool, and fix the 'build' script so it points to your ml-build tool
Fix the tool's argument use by changing [inf, outf] to [_, inf, outf]
Run ./build which generates 'heap2asm.x86-linux' on my system
For example, in order to generate an .asm file for the heap2asm program itself, run
sml #SMLload heap2asm.x86-linux heap2asm.x86-linux heap2asm.s
At this point, I have unfortunately been unable to produce an executable that works. E.g. if you run gcc -c heap2asm.s and ld heap2asm.o, you get a warning of a missing _start label. The resulting executable segfaults even if you rename the existing _sml_heap_image label to _start. That is, it seems that a piece of entry code that the runtime environment normally delivers is missing here.
At this point, discard SML/NJ and use MLton for producing stand-alone binaries.
I'm having trouble using lldb to debug on MacOsX with clang++. I'm using a makefile to compile a projet in C++, and I don't know if the debug option has to be enabled in the compilation command.
Here is an extract of my makefile
FLAGS =-g -Wall -O0
[...]
clang++ $(FLAGS) $^ -o $#
When I try running lldb with this configuration of my makefile, it return an error :
Breakpoint 1: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
I suppose I have to enable the debug tools on my makefile, but I haven't found how to do this on internet. I tried with the -g and the -ggdb options, without success.
However, when I try to set a breakpoint differently, it works (but setting a breakpoint on a specific fonction doesn't interest me...) :
breakpoint set -n fonction
Breakpoint 1: [...]
I didn't manage to find answers on internet, so I would be interested in having some help ! Thank you !
It looks like somewhere along the way the debug information is getting lost. One possibility is that your CFLAGS are getting reset before you get to building the .o files you care about, so the .o files don't have debug info. One easy way to check that is run
$ otool -l my_file.o | grep debug_info
sectname __debug_info
If you don't see that "sectname" output, then your .o file has no debug information.
Run your makefile and look at the build line for my_file.c and make sure there really is a -g option being passed. -ggdb doesn't actually do anything special for clang so -g is all you need...
If the .o file has debug information, then it must be getting lost when you build the final binary.
Mac OS X is a little funny in how it handles debug information. It doesn't write the debug information into the final image, but rather writes a "debug-map" into the executable, and leaves the debug info in the .o file. That debug-map gets stripped when you strip a binary, so if you strip your executable that will remove the link to the debug information. And of course, if you delete the .o files after building, that will also remove the debug information.
I finally installed gdb, and I managed to debug normally. But after reading your post, you make me realize I have maybe delete the .o when compiling. I didn't thought about it, as lldb was able to set break point in some cases (at a specific fonction) but not in other cases (at a specific line).
As I am using a makefile, I forgot to delete the auto delete of all the .o after compiling, and I think that may cause the issue. Now, if I let the .o, that works perfectly. But this is surprising me a lot, as my makefile was the same as my colleague and he was able to debug with gdb without any kind of problem.
Thanks a lot for all your informations.
List items 1- 4 are the steps that I did.
List item 5 describes the problem
List item 6 provides additional information
I have compiled a C source code say c1.c with -g flag.
I have also a
dynamic shared library say liba1.so built with -g for all the source
files that it has.
I built the executable say exe1 by linking c1.o (c1.c object code) with the liba1.so .
I do gdb exe1. and am able to step through the sources of c1.c. When c1 calls the shared library, I am also able to put a breakpoint on a function in the shared library.
However, when I try to step through the function, it says that "Single stepping until exit from function foo1 ,which has no line number information" Also it should ordinarily show the value of the parameters passed into the function foo1 but does not do that. This happens for all functions in the shared library including some very big ones so the values cannot be optimized out
I did an objdump -t on the shared library AND the executable - it shows the symbol table (the fact that I can set a breakpoint on the function also supports this). Also, I can see the values of the variables used in the file c1.c So what should I do in order to ensure that I can see the values of the local variables inside the shared library. Here are the other arguments that are being used to compile the shared library "-O2 -std=gnu99 -Werror -fno-stack-protector -Wstack-protector --param ssp-buffer-size=1 -g -nostdinc". doing info f and trying to look at memory addresses on the frame also does not give any information.
I am looking for some suggestion to at least troubleshoot it. Can I know using objdump (or any other utility) if a shared library has line number information.
I am looking for some suggestion to at least troubleshoot it.
The most likely reason for no line number information, is that there is in fact no line number information, and the most likely reason for that is that you have two copies of liba1.so -- one that has debug info, and one that doesn't, and you are loading at runtime the latter.
First step: (gdb) info shared will tell you exactly which liba1.so is loaded.
If it is in fact the version that you've just built with -g, you should verify that it does have the debug info you are expecting. The exact commands for doing so are platform specific (and you didn't tell which platform you are on). On an ELF platform, objdump -g liba1.so or readelf -w liba1.so should work.
One common reason for -g code to not have debug info is presence of -s (strip) flag on the link line; make sure you don't have "stray" flags on your link line. Some platforms also require -g to be used at link time in addition to compile time.
How do I analyze the core dump (using gdb)
which is not compiled with -g GCC option ?
Generate a map file. The map file will tell you the address that each function starts at (as an offset from the start of the exe so you will need to know the base address its loaded too). So you then look at the instruction pointer and look up where it falls in the map file. This gives you a good idea of the location in a given function.
Manually unwinding a stack is a bit of a black art, however, as you have no idea what optimisations the compiler has performed. When you know, roughly, where you are in the code you can generally work out what ought to be on the stack and scan through memory to find the return pointer. its quite involved however. You effectively spend a lot of time reading memory data and looking for numbers that look like memory addresses and then checking that to see if its logical. Its perfectly doable and I, and I'm sure many others, have done it lots of times :)
With ELF binaries it is possible to separate the debug symbols into a separate file. Quoting from objcopy man pages:
Link the executable as normal (using the -g flag). Assuming that is is called foo then...
Run objcopy --only-keep-debug foo foo.dbg to create a file containing the debugging info.
Run objcopy --strip-debug foo to create a stripped executable.
Run objcopy --add-gnu-debuglink=foo.dbg foo to add a link to the debugging info into the stripped executable.
that should not be a problem , you can compile the source again with -g option and pass gdb the core and the new compiled debug binary, it should work without any problem.
BTW You can generate a map file with the below command in gcc
gcc -Wl,-Map=system.map file.c
The above line should generate the map file system.map, Once the map file is generated you can map the address as mentioned above but i am not sure how are you going to map the share library, this is very difficult