I want to debug with stander library in gdb.
I ran gdb with argument -d to specify the source file of standard libary.
$ gdb ./test -d /usr/src/glibc/glibc-2.27/
test.cpp:
#include<iostream>
#include<string>
using namespace std;
int main(){
string hex("0x0010");
long hex_number = strtol(hex.c_str(), NULL, 16);
cout << hex_number << endl;
return 0;
}
However, gdb told me it can not find source file strtol.c.
(gdb) b 8
Breakpoint 1 at 0xc8c: file /home/purin/Desktop/CodeWork/adv_unix_programming/hw1/test.cpp, line 8.
(gdb) run
Starting program: /home/purin/Desktop/CodeWork/adv_unix_programming/hw1/test
Breakpoint 1, main () at /home/purin/Desktop/CodeWork/adv_unix_programming/hw1/test.cpp:8
8 long hex_number = strtol(hex.c_str(), NULL, 16);
(gdb) s
__strtol (nptr=0x7fffffffd820 "0x0010", endptr=0x0, base=16) at ../stdlib/strtol.c:106
106 ../stdlib/strtol.c: file or directory does not exits
(gdb) info source
Current source file is ../stdlib/strtol.c
Compilation directory is /build/glibc-OTsEL5/glibc-2.27/stdlib
Source language is c.
Producer is GNU C11 7.3.0 -mtune=generic -march=x86-64 -g -O2 -O3 -std=gnu11 -fgnu89-inline -fmerge-all-constants -frounding-math -fstack-protector-strong -fPIC -ftls-model=initial-exec -fstack-protector-strong.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
Since gdb can find source code if I execute this command:
(gdb) dir /usr/src/glibc/glibc-2.27/stdlib/
I am sure that I have strtol.c in path /usr/src/glibc/glibc-2.27/stdlib/strtol.c and the library has debug information.
Why gdb cannot search the directories under /usr/src/glibc/glibc-2.27/ to find out stdlib/strtol.c?
Maybe the reason is that if you join two paths /usr/src/glibc/glibc-2.27/ and ../stdlib/strtol.c you get the path /usr/src/glibc/stdlib/strtol.c, but not the expected path /usr/src/glibc/glibc-2.27/stdlib/strtol.c. The reason why ../stdlib/strtol.c is stored in the debug info, very likely is a build directory /build/glibc-OTsEL5/glibc-2.27/build used, and ../stdlib/strtol.c is the relative path to the build directory.
One of solutions is run
$ gdb ./test -d /usr/src/glibc/glibc-2.27/stdlib/
Related
I'm trying to get gdb working with C++ programs on Ubuntu 20.04. What I need is to be able to set a breakpoint (for example, break main.cpp:3 gdb command) and then run until the breakpoint, but at the moment both start and run fail because they "Cannot insert breakpoint" and "Cannot access memory". For me gdb fails even with very simple examples. This is main.cpp content:
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
I found somewhere that using -no-pie might help to get gdb working (with breakpoints), so I compile the program by running g++ -ggdb3 -no-pie -o main main.cpp (I also tried -g instead of -ggdb3, and -fno-PIE in addition to -no-pie). When I try to use gdb, it complains "Cannot insert breakpoint 1":
gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
Without -no-pie result is the same. Only thing that changes with or without -no-pie is the hexadecimal address, without -no-pie it is low like 0x1189 (as shown above), with -no-pie it can be 0x401176, but everything else exactly the same, I keep getting the "Cannot access memory at address" warning in both cases.
If I use starti instead of start, it works at first, but after a few nexti iterations it prints usual message "Cannot insteart breakpoint":
gdb -q main
Reading symbols from main...
(gdb) starti
Starting program: /tmp/main
Program stopped.
0x00007ffff7fd0100 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd0103 in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x4
0x00007ffff7fd0119 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd011c in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x1c
0x000055555556ca22 in ?? ()
(gdb) nexti
[Detaching after fork from child process 3829827]
...
[Detaching after fork from child process 3829840]
Hello World![Inferior 1 (process 3819010) exited normally]
So I can use nexti, but cannot use next and obviously cannot insert breakpoints.
I tried -Wl,-no-pie (by running g++ -Wl,-no-pie -ggdb3 -o main main.cpp; adding -no-pie does not change anything) but this option causes a strange linker error:
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
When I google the error, I only found advice to try -no-pie instead of -Wl,-no-pie, and no other solutions. Since debugging C++ programs is very common activity, I feel like I'm missing something obvious but I found no solution so far.
To make it easier to understand what exact commands I use and to make it clear I'm not mixing up directories and to show what versions of g++ and gdb I'm using, here is full terminal log:
$ ls
main.cpp
$ g++ --version | grep Ubuntu
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
$ g++ -ggdb3 -no-pie -o main main.cpp
$ ls
main main.cpp
$ gdb --version | grep Ubuntu
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
$ readelf -h main | grep 'Type: .*EXEC'
Type: EXEC (Executable file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x401176: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x401176
For completeness, I tried the same without -no-pie:
$ rm main
$ g++ -ggdb3 -o main main.cpp
$ readelf -h main | grep 'Type: .*'
Type: DYN (Shared object file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
As you can see the only difference with or without -no-pie is the memory address, but the issue and warnings are the same. Without -no-pie this may be expected, but I do not understand why this is happening if I compiled with -no-pie and what else I can try to solve the issue.
This:
g++ -ggdb3 -no-pie -o main main.cpp
should produce a non-PIE executable. You should be able to verify that it non-PIE by looking at readelf -h main | grep 'Type: .*EXEC' (PIE binaries have ET_DYN type).
This:
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
is unambiguously a PIE binary (a non-PIE binary will not have any code below 0x40000 on x86_64 Linux).
Conclusion: you are either debugging the wrong binary (e.g. you are compiling main in a different directory from the one in which you are debugging), or you are not telling is the whole story.
I am building a module in C++ to be used in Python. My flow is three steps: I compile the individual C++ sources into objects, create a library, and then run a setup.py script to compile the .pyx->.cpp->.so, while referring to the library I just created.
I know I can just do everything in one step with the Cython setup.py, and that is what I used to do. The reason for splitting it into multiple steps is I'd like the C++ code to evolve on its own, in which case I would just use the compiled library in Cython/python.
So this flow works fine, when there are no bugs. The issue is I am trying to find the source of a segfault, so I'd like to get the debugging symbols so that I can run with gdb (which I installed on OSX 10.14, it was a pain but it worked).
I have a makefile, which does the following.
Step 1: Compile individual C++ source files
All the files are compiled with the bare minimum flags, but -g is there:
gcc -mmacosx-version-min=10.7 -stdlib=libc++ -std=c++14 -c -g -O0 -I ./csrc -o /Users/colinww/system-model/build/data_buffer.o csrc/data_buffer.cpp
I think even here there is a problem: when I do nm -pa data_buffer.o, I see no debug symbols. Furthermore, I get:
(base) cmac-2:system-model colinww$ dsymutil build/data_buffer.o
warning: no debug symbols in executable (-arch x86_64)
Step 2: Compile cython sources
The makefile has the line
cd $(CSRC_DIR) && CC=$(CC) CXX=$(CXX) python3 setup_csrc.py build_ext --build-lib $(BUILD)
The relevant parts of setup.py are
....
....
....
compile_args = ['-stdlib=libc++', '-std=c++14', '-O0', '-g']
link_args = ['-stdlib=libc++', '-g']
....
....
....
Extension("circbuf",
["circbuf.pyx"],
language="c++",
libraries=["cpysim"],
include_dirs = ['../build'],
library_dirs=['../build'],
extra_compile_args=compile_args,
extra_link_args=link_args),
....
....
....
ext = cythonize(extensions,
gdb_debug=True,
compiler_directives={'language_level': '3'})
setup(ext_modules=ext,
cmdclass={'build_ext': build_ext},
include_dirs=[np.get_include()])
When this is run, it generates a bunch of compilation/linking commands like
gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/colinww/anaconda3/include -arch x86_64 -I/Users/colinww/anaconda3/include -arch x86_64 -I. -I../build -I/Users/colinww/anaconda3/lib/python3.7/site-packages/numpy/core/include -I/Users/colinww/anaconda3/include/python3.7m -c circbuf.cpp -o build/temp.macosx-10.7-x86_64-3.7/circbuf.o -stdlib=libc++ -std=c++14 -O0 -g
and
g++ -bundle -undefined dynamic_lookup -L/Users/colinww/anaconda3/lib -arch x86_64 -L/Users/colinww/anaconda3/lib -arch x86_64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.7/circbuf.o -L../build -lcpysim -o /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so -stdlib=libc++ -g
In both commands, the -g flag is present.
Step 3: Run debugger
Finally, I run my program with gdb
(base) cmac-2:sim colinww$ gdb python3
(gdb) run system_sim.py
It dumps out a ton of stuff related to system files (seems unrelated) and finally runs my program, and when it segfaults:
Thread 2 received signal SIGSEGV, Segmentation fault.
0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
(gdb) info local
No symbol table info available.
(gdb) where
#0 0x0000000a4585469e in cpysim::DataBuffer<double>::Write(long, long, double) () from /Users/colinww/system-model/build/circbuf.cpython-37m-darwin.so
#1 0x0000000a458d6276 in cpysim::ChannelFilter::Filter(long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#2 0x0000000a458b0d29 in __pyx_pf_6chfilt_6ChFilt_4filter(__pyx_obj_6chfilt_ChFilt*, long, long, long) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#3 0x0000000a458b0144 in __pyx_pw_6chfilt_6ChFilt_5filter(_object*, _object*, _object*) () from /Users/colinww/system-model/build/chfilt.cpython-37m-darwin.so
#4 0x000000010002f1b8 in _PyMethodDef_RawFastCallKeywords ()
#5 0x000000010003be64 in _PyMethodDescr_FastCallKeywords ()
As I mentioned above, I think the problem starts in the initial compilation step. This has nothing to do with cython, I'm just calling gcc from the command line, passing the -g flag.
(base) cmac-2:system-model colinww$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk/usr/include/c++/4.2.1
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.6.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
Any help is appreciated, thank you!
UPDATE
I removed the gcc tag and changed it to clang. So I guess now I'm confused, if Apple will alias gcc to clang, doesn't that imply that in "that mode" it should behave like gcc (and, implied, someone made sure it was so).
UPDATE 2
So, I never could get the debug symbols to appear in the debugger, and had to resort to lots of interesting if-printf statements, but the problem was due to an index variable becoming undefined. So thanks for all the suggestions, but the problem is more or less resolved (until next time). Thanks!
The macOS linker doesn't link debug information into the final binary the way linkers usually do on other Unixen. Rather it leaves the debug information in the .o files and writes a "debug map" into the binary that tells the debugger how to find and link up the debug info read from the .o files. The debug map is stripped when you strip your binary.
So you have to make sure that you don't move or delete your .o files after the final link, and that you don't strip the binary you are debugging before debugging it.
You can check for the presence of the debug map by doing:
$ nm -ap <PATH_TO_BINARY> | grep OSO
You should see output like:
000000005d152f51 - 03 0001 OSO /Path/To/Build/Folder/SomeFile.o
If you don't see that the executable probably got stripped. If the .o file is no around then somebody cleaned your build folder earlier than they should have.
I also don't know if gdb knows how to read the debug map on macOS. If the debug map entries and the .o files are present, you might try lldb and see if that can find the debug info. If it can, then this is likely a gdb-on-macOS problem. If the OSO's and the .o files are all present, then something I can't guess went wrong, and it might be worth filing a bug with http://bugreporter.apple.com.
I am learning linux, and my first step is to adapt my project for running on linux. Here is simple makefile (in educational purposes mostly), which generates out file:
#------------------------BUILD VARIABLES-----------------------------
# Directories, containing headers
INCLUDE_DIR = ../Include/
# Output directory which will contain output compiled file
OUTPUT_DIR = ../Bin/Debug/
SOURCES = EngineManager.cpp Geometry.cpp Main.cpp Model.cpp \
Shaders.cpp TGAImage.cpp
HEADERS = EngineManager.h Geometry.h Line.h Model.h Shaders.h \
TGAImage.h Triangle.h
#------------------------BUILD_RULES---------------------------------
TinyRenderBuilding : $(addprefix $(INCLUDE_DIR), $(HEADERS)) $(SOURCES)
mkdir -p $(OUTPUT_DIR)
g++ -std=c++14 -o $(OUTPUT_DIR)TinyRender.out -g -I$(INCLUDE_DIR) $(SOURCES)
I cannot understand, why does g++ not generate debug symbols? -g option is presented
To include debug symbols when compiling with g++ you need to pass the -g option.
In a make make file this usually means adding it to to CXXFLAGS.
Also make sure you pass the -g option when you create the executable: when you compile you turn .cpp files into .o files, when you do the linking you turn those .o files into your executable).
If you change the options before running make again be sure to run a make clean cause otherwise it won't get recompiled.
Finally, make sure that you do not have additional steps like strips command run on the executable (which would remove debugging symbols).
you can use
objdump --syms <executable-file>
to check if an executable have symbols.
when it doesn't have symbols it will say something like:
SYMBOL TABLE:
no symbols
(I'm no experto of C / C++ programming, I just run into this while I was trying to debug someone else code)
According to your makefile g++ should produce debug symbols (-g option is presented). To confirm this you can run file on resulting binary:
$ file a.out
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=9fe588c18099ef418daf288931bb033cc287922e, with debug_info, not stripped
(Note with debug_info string in output)
I'm not entirely sure, but you can try -g or -ggdb.You can do some research on these. We were using these parameters to debug the C program with the gdb tool.
I always use gdb in Linux and it works ok, this is my first time use gdb in mac which is different with Linux.
(gdb) b main
Breakpoint 1 at 0x100000ec4
(gdb) r
Starting program: /Users/vinllen/code/tmp/lhm/homework
warning: Could not open OSO archive file "/BinaryCache/corecrypto/corecrypto-233.1.2~26/Symbols/BuiltProducts/libcorecrypto_static.a"
warning: `/BinaryCache/coreTLS/coreTLS-35.20.2~10/Objects/coretls.build/coretls.build/Objects-normal/x86_64/system_coretls_vers.o': can't open to read symbols: No such file or directory.
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_ciphersuites.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_handshake.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_record.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_stream_parser.a"
Breakpoint 1, 0x0000000100000ec4 in main ()
(gdb) l
No symbol table is loaded. Use the "file" command.
(gdb) n
Single stepping until exit from function main,
which has no line number information.
It looks like command l and n cannot be execute correctly, what's the problem ?
Here is my Makefile:
objects = main.o conversion.o slitemlist.o uims.o testdrivers.o
homework:$(objects)
g++ -o homework $(objects)
conversion.o: conversion.h base.h
slitemlist.o: slitemlist.h base.h
uims.o: conversion.h base.h conversion.h slitemlist.h
testdrivers.o: testdrivers.h
.PHONY: clean
clean:
rm homework $(objects)
Here is my Makefile:
You will not have a good time debugging this program on Linux either: you've compiled it without debug symbols (the -g flag).
Your real question is not "how do I use GDB on MacOS", but rather "how do I write Makefile such that I can debug".
You should add a lines like this to your Makefile:
CFLAGS = -g
CXFLAGS = -g # if building C++
I have bunch of source code which I compiled using -ggdb3 flag.
I have copied the source code and executable to an another machine.
When I run the exe in gdb it does not show the statements at the line numbers when it breaks.
This is what I see
Breakpoint 1, TestCode (handler=0x806e110, args=0xffffd2b0)
at ../myfile.c:1080
1080 ../myfile.c: No such file or directory.
(gdb) n
1083 in ../myfile.c
(gdb)
1084 in ../myfile.c
(gdb)
1085 in ../myfile.c
I even tried setting the dir path using gdb dir command by giving the name of the topmost directory of the source code but no help.
Example my source code directory structure is like
C
|
--------------
| |
D E
|
F
|
-----------
| |
S T
The file I am debugging may be in some inner folder say F.
While I gave the path of folder C in gdb dir
dir /home/C
Any way to resolve this issue?
More details are:
> OS SUSE Linux Enterprise Server 11 (x86_64)
> gcc version 4.3.4 [gcc-4_3-branch revision 152973] (SUSE Linux)
> GNU gdb (GDB) SUSE (7.5.1-0.7.29)
Here are the Makefile details
#
# Makefile for building demo code on SUSE Linux
all : SLIBINSTALLDIR = $(SDESTDIR)$(SLIBDIR)
###########################################
# Defines #
###########################################
CC = --mode=compile gcc
LINK =$(DESTDIR)libtool --mode=link gcc
INDEPSDIR = ../../../../../dependencies/internal
MODULE = TestCode
INCLUDE = -I../ -I$(INDEPSDIR)/include
CFLAGS := $(CFLAGS) $(INCLUDE) -DN_PLAT_UNIX -DN_PLAT_GNU -DVERSION=0x00010002 -D_GNU_SOURCE -g -ggdb3
CSRC = ../myfile.c ../decode.c ../encode.c
COBJ = $(CSRC:.c=.o)
COBJ1 = $(CSRC:.c=.lo)
TestCode:$(COBJ)
$(LINK) $(CFLAGS) -o TestCode $(COBJ1) -all-static
DESRC = ../main.c
DEOBJ = $(DESRC:.c=.o)
You should define a source path substitution rule using command:
set substitute-path from to
It will substitute from part into to allowing to find sources in new location.
See https://sourceware.org/gdb/onlinedocs/gdb/Source-Path.html.
Also info sources command will be useful to remember from part in the command above in case you forgot where your sources were located before copying.