printing stack with variable names with gdb? - c

I was just reading this article.
In the article, the author uses gdb to look around in a c executable.
At one point, when a breakpoint is hit, the author says to have a look at the stack, and shows this output:
STACK:
0x00007fffffffdf40│+0x0000: 0x00007fffffffe058 → 0x00007fffffffe380
0x00007fffffffdf48│+0x0008: 0x0000000100401050
0x00007fffffffdf50│+0x0010: 0x00007fffffffe050 → 0x0000000000000001
0x00007fffffffdf58│+0x0018: 0x0000000000402004 → “p#ssw0rD”
0x00007fffffffdf60│+0x0020: 0x0000000000000000 ← $rbp
0x00007fffffffdf68│+0x0028: 0x00007ffff7ded0b3 → <__libc_start_main+243> mov edi, eax
0x00007fffffffdf70│+0x0030: 0x00007ffff7ffc620 → 0x0005043700000000
0x00007fffffffdf78│+0x0038: 0x00007fffffffe058 → 0x00007fffffffe380 →
This is nice, but how do I generate this output in gdb?
I've been googling for a while with no luck
Also, in this output there is two different columns of hex adresses, I'm guessing one points to the stack, what is the other one? and which is which?

The author doesn't state it explicitly, but in their gdb output you can see the prompt gef>. This indicates they are likely making use of the gef addon for gdb.
I have never used this addon myself, but you can see in some of the example output on the gef site that the addon has a stack view identical to the output you gave above.
The gef addon makes use of gdb's Python API to provide additional features for gdb, one of which appears to be the alternative stack view.

Related

Debugging C: GDB returns "address where <file> has been loaded is missing"

I'm very new to the C language and have been tasked with modifying GRUB. What a way to learn, right? Anyway, I'm trying to debug my modified GRUB using VMWare and GDB. I've been able to get the debugger working before, but for some reason, every time I load up my VM and connect GDB, during the loading process of GRUB, I get:
.loadsym.gdb:1: Error in sourced command file:
The address where biosdisk.module has been loaded is missing
and I have no idea what to do about it. My first thought was, "Oh, I'll just add-symbol-file <file> and that'll fix it!" but apparently that tells GDB to forget every other symbol it loaded???? So I can't add the symbol-file and set a breakpoint.
My googling only returns one semi-relevant post that doesn't really go all that in-depth on fixing the issue.
This output may also be relevant.
info file biosdisk.module
Symbols from "H:\Workspace\GRUB\Bootloader\Trunk\grub-core\kernel.exec".
Remote serial target in gdb-specific protocol:
Debugging a target over a serial line.
While running this, GDB does not access memory from...
Local exec file:
`H:\Workspace\GRUB\Bootloader\Trunk\grub-core\kernel.exec', file type elf32-i386.
Entry point: 0x9000
0x00009000 - 0x0000e6e0 is .text
0x0000e6e0 - 0x0000f68d is .rodata
0x0000f6a0 - 0x0000fe74 is .data
0x0000fe80 - 0x000175d4 is .bss
Ended up being that my codebase wasn't the same. That is, on my Windows host, I had one copy of my code and on my Ubuntu VM was another.
Using version control solved this issue.

Is there an equivalent of dds on lldb

I am trying to debug an issue on OSX and lldb is getting in my way. I think my program has a corrupted stack, and I would like to be able to manually walk the stack.
In WinDBG, there is a command called dds that I can use to dump all the pointers on the stack (basically, walking from rsp, walking towards higher addresses) and resolve all pointers to symbols (and print nothing if it does not correspond to code), I am looking for a similar command on lldb. I know I could memory read --format x manually one by one and then look them up using image lookup, but that would be too time consuming.
There isn't a built-in command to do the walk itself, so you will have to page through the memory up from rsp by hand.
But you might find the "A" format helpful for this task. That will print the memory as a list of address-sized words, and for any values that point into TEXT or DATA it will print the symbol's name. Like:
(lldb) mem read -fA `$rsp - 16 * 8` `$rsp` -fA
0x7ffeefbff660: 0x0000000000000000
0x7ffeefbff668: 0x00007ffeefbff660
0x7ffeefbff670: 0x0000003002000000
0x7ffeefbff678: 0x00007fff6e2ee568 libsystem_platform.dylib`__platform_sigaction + 103
0x7ffeefbff680: 0x0000000000000000
0x7ffeefbff688: 0x0000000000000000
0x7ffeefbff690: 0x0000000000013dc9
0x7ffeefbff698: 0x0000000000000000
0x7ffeefbff6a0: 0x00007fff6e238fe2 libsystem_kernel.dylib`__sigaction + 10
0x7ffeefbff6a8: 0x0000000000000000
0x7ffeefbff6b0: 0x000000000000001e
0x7ffeefbff6b8: 0x0000000000013dc9
0x7ffeefbff6c0: 0x00007ffeefbff700
0x7ffeefbff6c8: 0x0000000100002020 _dyld_private
0x7ffeefbff6d0: 0x000000000000000e
0x7ffeefbff6d8: 0x0000000100000f45 signals`main + 53 at signals.c:13:3

LPCXpresso error CreateProcess: No such file or directory

I know there are multiple questions regarding this subject, but they did not help.
When trying to compile, whatever, I keep getting the same error:
arm-none-eabi-gcc.exe: error: CreateProcess: No such file or directory
I guess it means that it can not find the compiler.
I have tried tweaking the path settings
C:\Windows\system32;C:\Windows;C:\Windows\System32\Wbem;C:\nxp\LPCXpresso_7.6.2
326\lpcxpresso\tools\bin;
Seems to be right?
I have tried using Sysinternals process monitor
I can see that a lot of arm-none-eabi-gcc.exe are getting a result of name not found but there are a lot of successful results too.
I have also tried reinstalling the compiler and the LPCXpresso, no luck.
If i type arm-none-eabi-gcc -v i get the version, so it means its working
but when i am trying to compile in CMD like this arm-none-eabi-gcc led.c
i get the same error as stated above
arm-none-eabi-gcc.exe: error: CreateProcess: No such file or directory
Tried playing around more with PATH in enviroments, no luck. I feel like something is stopping LPCXpresso from finding the compiler
The only Antivirus this computer has is Avira and i disabled it. I also allowed compiler and LPCXpresso through the firewall
I have tried some more things, i will add it shortly after trying to duplicate the test.
It seems your problem is a happy mess with Vista and GCC. Long story short, a CRT function, access, has a different behavior on Windows and Linux. This difference is actually mentioned on Microsoft documentation, but the GCC folks didn't notice. This leads to a bug on Vista because this version of Windows is more strict on this point.
This bug is mentioned here : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=33281
I have no proof that your problem comes from here, but the chances are good.
The solutions :
Do not use Vista
Recompile arm-none-eabi-gcc.exe with the flag -D__USE_MINGW_ACCESS
Patch arm-none-eabi-gcc.exe
The 3rd is the easiest, but it's a bit tricky. The goal is to hijack the access function and add an instruction to prevent undesired behavior. To patch your gcc, you have two solutions : you upload your .exe and I patch it for you, or I give you the instructions to patch it yourself. (I can also patch it for you, then give the instructions if it works). The patching isn't really hard and doesn't require advanced knowledge, but you must be rigorous.
As I said, I don't have this problem myself, so I don't know if my solution really works. The patch seems to be working for this problem.
EDIT2:
The exact problem is that the linux access have a parameter flag to check whether a file is executable. The Windows access cannot check for this. The behavior of most Windows versions is just to ignore this flag, and check if the file exists instead, which will usually give the same behavior. The problem is that Vista doesn't ignore this, and whenever the access is used to check for executability, it will return an error. This lead to GCC programs to think that some executables are not here. The patch induced by -D__USE_MINGW_ACCESS, or done manually, is to delete the flag when access is called, thus checking for existence instead just like other Windows versions.
EDIT:
The patching is actually needed for every GCC program that invokes other executables, and not only gcc.exe. So far there is only gcc.exe and collect2.exe.
Here are the patching instruction :
Backup your arm-none-eabi-gcc.exe.
Download and install CFF Explorer (direct link here).
Open arm-none-eabi-gcc.exe with CFF Explorer.
On the left panel, click on Import Directory.
In the module list that appears, click on the msvcrt.dll line.
In the import list that appears, find _access. Be careful here, the list is long, and there are multiple _access entries. The last one (the very last entry for me) is probably the good one.
When you click on the _access line, an address should appear on the list header, in the 2nd column 2nd row, just below FTs(IAT). Write down that address on notepad (for me, it is 00180948, it may be different). I will refer to this address as F.
On the left panel, click on Address Converter.
Three fields should appear, enter address F in the File Offset field.
Write down on notepad a 6 bytes value : the first two bytes are FF 25, the last 4 are the address that appeared in the VA field, IN REVERSE. For example, if 00586548 appeared in the VA field, write down FF 25 48 65 58 00 (spaces added for legibility). I will refer to this value as J. This value J is the instruction that jumps to the _access function.
On the left panel, click on Section Headers.
In the section list that appeared on the right, click on the .text line (the .text section is where the code resides).
In the editor panel that appeared below, click on the magnifier and, in the Hex search bar, search for a series of 11 90 (9090909090..., 90 is NOP in assembly). This is to find a code cave (unused space) to insert the patch, which is 11 bytes long. Once you found a code cave, write down the offset of the first 90. The exact offset is displayed on the very bottom as Pos : xxxxxxxx. I will refer to this offset as C.
Use the editor to change the sequence of 11 90 : the first 5 bytes are 80 64 E4 08 06. These 5 bytes are the instruction that prevents the wrong behavior. The last 6 bytes are the value J (edit the next 6 bytes to J, ex. FF 25 48 65 58 00), to jump back to the _access function.
Click on the arrow icon (Go To Offset) a bit below, and enter 0, to navigate to the beginning of the file.
Use the Hex search bar again to search for value J. If you find the bytes you just modified, skip. The J value you need is located around many value containing FF 25 and 90 90. That is the DLL jump table. Write down the offset of the value J you found (offset of the first byte, FF). I will refer to this offset as S. Note 1: If you can't find the value, maybe you picked the wrong _access in step 6, or did something wrong between step 6 to 10. Note 2: The search bar doesn't loop when it hit the end; go to offset 0 manually to re-find.
Use a hexadecimal 32-bit 2-complement calculator (like this one : calc.penjee.com) to calculate C - S - 5. If your offset C is 8C0 and your offset S is 6D810, you must obtain FF F9 30 AB (8C0 minus 6D810, minus 5).
Replace the value J you found in the file (at step 16) by 5 bytes : the first byte is E9, the last 4 are the result of the last operation, IN REVERSE. If you obtained FF F9 30 AB, you must replace the value J (ex: FF 25 48 65 58 00) by E9 AB 30 F9 FF. The 6th byte of J can be left untouched. These 5 bytes are the jump to the patch.
File -> Save
Notes : You should have modified a total of 16 bytes. If the patched program crash, you did something wrong. Even if it doesn't work, this patch can't induce a crash.
Let me know if you have difficulties somewhere.

linker issue or other? dynamically loaded lib

My program loads a dynamic library, but after it tries to load it (it doesn't seem to, or at least something's amiss with the loading. A free() throws an error, and I commented out that line.)
I get the following in gdb.
Program received signal SIGSEGV, Segmentation fault.
__strlen_ia32 () at ../sysdeps/i386/i686/multiarch/../../i586/strlen.S:99
99 ../sysdeps/i386/i686/multiarch/../../i586/strlen.S: No such file or directory.
in ../sysdeps/i386/i686/multiarch/../../i586/strlen.S
How would I go about addressing this?
EDIT1:
The above issue was due to me not having an xml file where it should have been.
Here's the first error that I covered up to get to the initial error I showed.
(gdb) s
__dlopen (file=0xbfffd03c "/usr/lib/libvisual-0.5/actor/actor_AVS.so", mode=1)
at dlopen.c:76
76 dlopen.c: No such file or directory.
in dlopen.c
(gdb) bt
#0 __dlopen (file=0xbfffd03c "/usr/lib/libvisual-0.5/actor/actor_AVS.so",
mode=1) at dlopen.c:76
#1 0xb7f8680d in visual_plugin_get_references (
pluginpath=0xbfffd03c "/usr/lib/libvisual-0.5/actor/actor_AVS.so",
count=0xbfffd020) at lv_plugin.c:834
#2 0xb7f86168 in plugin_add_dir_to_list (list=0x804e428,
dir=0x804e288 "/usr/lib/libvisual-0.5/actor") at lv_plugin.c:609
#3 0xb7f86b2b in visual_plugin_get_list (paths=0x804e3d8,
ignore_non_existing=1) at lv_plugin.c:943
#4 0xb7f9c5db in visual_init (argc=0xbffff170, argv=0xbffff174)
at lv_libvisual.c:370
#5 0x080494b7 in main (argc=2, argv=0xbffff204) at client.c:32
(gdb) quit
A debugging session is active.
Inferior 1 [process 3704] will be killed.
Quit anyway? (y or n) y
starlon#lyrical:client$ ls /usr/lib/libvisual-0.5/actor/actor_AVS.so
/usr/lib/libvisual-0.5/actor/actor_AVS.so
starlon#lyrical:client$
The file exists. Not sure what's up. Not sure what code to provide either.
Edit2: More info on the file. Permissions are ok.
816K -rwxr-xr-x 1 root root 814K 2011-11-08 15:06 /usr/lib/libvisual-0.5/actor/actor_AVS.so
You didn't tell what dynamic library it is.
If it is a free dynamic library -or a library whose source is accessible to you- you can compile it and use it with debugging enabled.
Several Linux distributions -notably Debian & Ubuntu- provide debugging variant of many libraries (e.g. GLibc, GTK, Qt, etc...), so you don't need to rebuild them. For example, Debian has libgtk-3-0 package (the binary libraries mostly), libgtk-3-dev the development files for it (headers, etc...) and libgtk-3-0-dbg (the debugging variant of the library). You need to set LD_LIBRARY_PATH appropriately to use it (since it is in /usr/lib/debug/usr/lib/libgdk-3.so.0.200.1).
Sometimes, using the debugging variants of system libraries help you to find bugs in your own code. (Of course, you also need to compile with -g -Wall your own code)
Turned out this was due to a faulty hard drive. Looks like I need a new one.

Most tricky/useful commands for gdb debugger [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 10 years ago.
Can you post your most tricky and useful commands while you run a debugger like gdb or dbx.
backtrace full: Complete backtrace with local variables
up, down, frame: Move through frames
watch: Suspend the process when a certain condition is met
set print pretty on: Prints out prettily formatted C source code
set logging on: Log debugging session to show to others for support
set print array on: Pretty array printing
finish: Continue till end of function
enable and disable: Enable/disable breakpoints
tbreak: Break once, and then remove the breakpoint
where: Line number currently being executed
info locals: View all local variables
info args: View all function arguments
list: view source
rbreak: break on function matching regular expression
Start gdb with a textual user interface
gdb -tui
Starting in gdb 7.0, there is reversible debugging, so your new favourite commands are:
* reverse-continue ('rc') -- Continue program being debugged but run it in reverse
* reverse-finish -- Execute backward until just before the selected stack frame is called
* reverse-next ('rn') -- Step program backward, proceeding through subroutine calls.
* reverse-nexti ('rni') -- Step backward one instruction, but proceed through called subroutines.
* reverse-step ('rs') -- Step program backward until it reaches the beginning of a previous source line
* reverse-stepi -- Step backward exactly one instruction
* set exec-direction (forward/reverse) -- Set direction of execution.
Instead of launching GDB with "-tui" param you can also switch to text mode after a while using by typing "wh".
thread apply all bt or thread apply all print $pc: For finding out quickly what all threads are doing.
For example the macros defined in stl-views.gdb
scripting gdb is a good trick, other than that I like
set scheduler locking on / off to prevent the running of other threads when you are stepping in one.
Using the -command=<file with gdb commands> option while firing up gdb. Same as -x <command file>. This command file can contain gdb commands like breakpoints, options, etc. Useful in case a particular executable needs to be put through successive debug runs using gdb.
Using .gdbinit (start up file where you can write macros and call from gdb). Place .gdbinit in your home directory so that it is picked up every time gdb is loaded
info threads to list all the active threads, and f(#) -> # thread number you want to switch to
sometime i use gdb to convert from hex to decimal or binary, its very handy instead of opening up a calculator
p/d 0x10 -> gives decimal equivalent of 0x10
p/t 0x10 -> binary equivalent of 0x10
p/x 256 -> hex equivalent of 256
Instead of starting gdb with the option -tui to see a child process that contains a screen that highlights where the executing line of code is in your program, jump in and out of this feature with C-x o and C-x a. This is useful if you're using the feature and what to temporarily not use it so you can use the up-arrow to get a previous command.
This can be useful, I am sure it could be improved though, help welcome:
define mallocinfo
set $__f = fopen("/dev/tty", "w")
call malloc_info(0, $__f)
call fclose($__f)
To debug STL, add content to .gdbinit, follow these instructions:
http://www.yolinux.com/TUTORIALS/GDB-Commands.html#STLDEREF

Resources