I am trying to set breakpoints in a MIPS32r6 program that computes the Mandelbrot Set in Brainfsck. The program itself is written in C++, compiled with Clang, and I am debugging with LLDB.
The issue that I am having is that when in LLDB, I can set certain breakpoints, mainly on lower line numbers, with no issues. However, after Line #70 in Main.cpp, the breakpoints are coming up as 'unresolved' (even though executing breakpoint list shows them with completely reasonable addresses). That is to say, all breakpoints that I try to set after Line #70 are coming up as unresolved, and all reasonable breakpoints before Line #70 resolve without issue.
I've placed a copy of the binary that I've linked here: http://filebin.ca/2tJzo2LLBJWO/MipsTest.bin
And a copy of Main.cpp here: https://paste.ee/p/WYs8Y
I am building with the following options:
clang -mcompact-branches=always -fasynchronous-unwind-tables -funwind-tables -fexceptions -fcxx-exceptions -mips32r6 -O0 -g -glldb ...
lld --discard-none -znorelro --eh-frame-hdr ...
At this point, I am unsure as to what might be causing this issue.
I'd try doing target modules dump line-table Main.cpp in lldb to see what lldb thinks the line table looks like. Then look at the binary's DWARF line table with something like readelf --debug-dump=decodedline MipsTest.bin (I think that's right - I'm looking at a readelf main page on the web).
Using your sample binary, I get:
(lldb) b s -l 72
Breakpoint 1: where = MipsTest.bin`main + 544 at Main.cpp:72, address = 0x000134a0
So we found an address for the breakpoint. If it is unresolved when you run, that means we weren't able to implement the breakpoint at that address (e.g. for some reason couldn't write the trap into the program memory there.)
Related
I am currently self-studying 2020 MIT 6.S081: Operating System Engineering https://pdos.csail.mit.edu/6.828/2020/schedule.html. I have followed all the steps for MAC OS to set up the environment correctly.
When I launched gdb and qemu together, I was able to break points normally when debugging the kernel executable.
However, when I attempted to do the same thing for the user executables, I was unable to break any points with the error:
Cannot access memory at address 0x...
It turned out I can set break points for some particular lines, but when I hit continue, another error has shown in the screenshot above.
Any way to get around this? Thank you!
I'm also self-studying 6.S081 and have had the same issue. I solved this just now so try this.
In Makefile, add -gdwarf-2 option to CFLAGS variable:
CFLAGS = -Wall -Werror -O -fno-omit-frame-pointer -ggdb -gdwarf-2
In my Makefile it's on line 94, and I didn't change other options.
I find this solution from here:
http://staff.ustc.edu.cn/~bjhua/courses/ats/2014/hw/hw-interface.html (search 'error reading variable' in the page)
https://www.reddit.com/r/RISCV/comments/plgwyk/comment/hcalnf1/?utm_source=share&utm_medium=web2x&context=3
and one more thing: If you successfully solve the problem with this but fail to watch variables in gdb, try chainging -O option for CFLAGS to -O0. It would prevent your code from being optimized (ref). (For me, this doesn't work. my code start to stuck frequently after changing this option so I just quit watching variables)
You can check out whether your gdb has warned you can't use file .gdbinit to start gdb? If not, you can simply add a line to .gdbinit: set riscv use-compressed-breakpoints yes,like this:
set confirm off
set architecture riscv:rv64
target remote 127.0.0.1:26000
symbol-file kernel/kernel
set disassemble-next-line auto
set riscv use-compressed-breakpoints yes
then use riscv64-unknown-elf-gdb to start gdb.You will see it work well.
But if you have the warning, then you should use
riscv64-unknown-elf-gdb -iex 'add-auto-load-safe-path .' to start gdb additionally.
I invoked gdb to attach a current running process with this command sudo gdb binary PID. After that I set breakpoints and typed continue in gdb. Then I sent a request to this process to hit the breakpoint. After that, when I type command list, it only shows one line instead of multiple lines as expected, and it only shows line number instead of contents. And may I ask what does the output of command n mean? On the internet some docs mentioned it means the next line to be executed. But from the output itself, it doesn't make too much sense to me(after two n commands the last l command shows 169 instead of 172 or 174). Can anyone help answer above two questions? Really appreciate it.
(gdb) l
164 in CBFEMultiSectionResponseModule.cc
(gdb) n
172 in CBFEMultiSectionResponseModule.cc
(gdb) l
167 in CBFEMultiSectionResponseModule.cc
(gdb) n
174 in CBFEMultiSectionResponseModule.cc
(gdb) l
169 in CBFEMultiSectionResponseModule.cc
The build command line for this source file is like this:
/usr/bin/g++ -c -fPIC -DMODULEADAPTER_BUILTIN_VERSION=\"2.36.375.10894.aff30c2\" -DLINUX -D_GNU_SOURCE -D_THREAD_SAFE -DUSE_STD_YUTSTRING -I../api -I. -I/home/y/include/ydisc \
-I/home/y/include/avro -I../.. -I../../.. -I../../../external_interfaces -I../../../sg_interfaces -I/home/y/include64 -I/home/y/include
\-fPIC -g -O2 -Wall -Werror -Wno-invalid-offsetof -fno-strict-aliasing -pipe -MD -MP
\-DYAHOO_PLATFORM_MAJOR=6 -DYAHOO_PLATFORM_MINOR=10 CBFEMultiSectionResponseModule.cc -o x86_64-linux-gcc/CBFEMultiSectionResponseModule.o
This is the filesystem type:
-bash-4.1$ df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 246G 97G 137G 42% /
tmpfs tmpfs 12G 30M 12G 1% /dev/shm
Below is the output of info source:
(gdb) info source
Current source file is CBFEMultiSectionResponseModule.cc
Compilation directory is /home/myusername/ufe/modules/multisectionresponse/impl
Source language is c++.
Compiled with DWARF 2 debugging format.
Does not include preprocessor macro info.
Below is the output of shell cat:
(gdb) shell cat /home/myusername/ufe/modules/multisectionresponse/impl/CBFEMultiSectionResponseModule.cc
cat: /home/myusername/ufe/modules/multisectionresponse/impl/CBFEMultiSectionResponseModule.cc: No such file or directory
when I type command list, it only shows one line instead of multiple lines as expected, and it only shows line number instead of contents
This is most likely happening because GDB has no access to the source. The sudo is the key here. Your source likely resides on a filesystem that doesn't allow root access, such as NFS.
it doesn't make too much sense to me(after two n commands the last l command shows 169 instead of 172 or 174).
You are debugging optimized code. See e.g. this answer.
Update:
The path to source is correct in the compilation environment. However, the runtime environment is different than the compilation env ..
Well, why didn't you tell us that?
My answer is correct: GDB doesn't list source because source is inaccessible (it's just inaccessible for a different reason from what I guessed).
If you want GDB list command to work in the runtime environment, then you must make the source available (though not necessarily in the same location; use dir command to point GDB to the location where sources are available).
Update 2:
. I used to think GDB has some magic ways to get the source code from the binary.
The binary does not contain sources (that would make significantly larger). Instead, it contains references to the source locations.
In particular, the compiler encodes into the binary for each translation unit (each .cpp file):
Compilation directory
Name of the source file(s) (there could be more than one due to #includes).
A mapping from program counter to file/line that the particular chunk of assembly was generated for.
(There is additional info describing variable locations, types, etc. But these are irrelevant to the list command.)
GDB decodes above into, locates the source file(s), and allows you to set breakpoints by file/line, lists the source when you hit the breakpoint, etc.
I created a Hello World example in C++ and tried to debug it with lldb from the terminal on Mac OSX.
> lldb a.out
Current executable set to 'a.out' (x86_64).
I can set breakpoints on names (eg. 'main'), but not on line numbers. If I try
breakpoint set --file test.c --line 5
or
b test.c:5
I get
Breakpoint 1: no locations (pending).
WARNING: Unable to resolve breakpoint to any actual locations.
The file 'test.c' is located in the current folder. What goes wrong?
Acording to Dwarf Debugging Information Format, the line number, file location information are stored in the Dwarf format. Such information is what GDB used to set line number as a breakpoint.
Usually, the Dwarf format information is generated by compiler, such as GCC with the -g options. Please try with -g options to see whether it works.
Meanwhile, there also some other debug helpful options in GCC which might be more helpful to you, such as -g3, compiler will generate more detail information for debug, such as macros.
Afternoon,everbody.
I have an application 'test' compiled by main.c . A dynamic liabrary 'libtest.so' which is compiled by test.cpp with '-g'. In main.c I invoke the 'libtest.so' with 'dlopen' . And now I want to set a breakpoint in test.cpp ,but the gdb never hit it. I do as follow:
gdb ./test -d /home/lcl/test
break test.cpp:35
run
can anybody give me some tips ,thanks!
You should first verify that dlopen is actually succeeding (it's likely that it's not).
To do so:
set a breakpoint in main.c after dlopen.
confirm that returned handle is not NULL
At that point, GDB should have loaded symbols for libtest.so, and libtest.so should show up in info shared GDB output.
If everything looks good, info break should show an active breakpoint in test.cpp:35 at some address. If that breakpoint is never hit, it's likely that you never actually exercise that line of code.
I'm developing on an ARM9E processor running Linux. Sometimes my application crashes with the following message :
[ 142.410000] Alignment trap: rtspserverd (996) PC=0x4034f61c
Instr=0xe591300c Address=0x0000000d FSR 0x001
How can I translate the PC address to actual source code? In other words, how can I make sense out of this message?
With objdump. Dump your executable, then search for 4034f61c:.
The -x, --disassemble, and -l options are particularly useful.
You can turn on listings in the compiler and tell the linker to produce a map file. The map file will give you the meaning of the absolute addresses up to the function where the problem occurs, while the listing will help you pinpoint the exact location of the exception within the function.
For example in gcc you can do
gcc -Wa,-a,-ad -c foo.c > foo.lst
to produce a listing in the file foo.lst.
-Wa, sends the following options to the assembler (gas).
-a tells gas to produce a listing on standard output.
-ad tells gas to omit debug directives, which would otherwise add a lot of clutter.
The option for the GNU linker to produce a map file is -M or --print-map. If you link with gcc you need to pass the option to the linker with an option starting with -Wl,, for example -Wl,-M.
Alternatively you could also run your application in the debugger (e.g. gdb) and look at the stack dump after the crash with the bt command.