Is $fp supposed to be equal $rbp in gdb? In other words, is frame pointer (in gdb terminology) equal to base pointer (in x86 terminology)?
According to https://sourceware.org/gdb/onlinedocs/gdb/Registers.html,
$fp is used for a register that contains a pointer to the current stack frame
In my C++ program they are not equal (stopped in a thread):
(gdb) p $fp
$12 = (void *) 0x7fffffffdae8
(gdb) p $rbp
$13 = (void *) 0x7fffffffdb20
gdb version is "GNU gdb (GDB) 7.12" if it matters
Is $fp == $rbp in gdb?
No, because not every processor has an RBP register to begin with.
Limiting discussion to x86_64 which does, no, because GDB documentation doesn't promise such equivalency. It promises that $fp is an alias to the register that contains a pointer to the current stack frame.
Depending on how the code has been compiled, and where exactly it is stopped, the "equivalent" register could be $rbp, $rsp, or such register may not exist at all. In the latter case, GDB appears to "synthesize" a frame pointer to point to where the locals would be stored (if the function has any).
On machines where code is routinely compiled with -fomit-frame-pointer (such as x86_64), talking about $fp is much less useful than talking about actual machine registers.
Related
I have written a subroutine using the avx2 instruction set (ymm registers), and now I want to debug it. My machine supports this instruction set, and the program can be executed without problems (no SIGILL exception).
But when I type 'tui reg vector' or 'info all-registers' to the gdb, it only shows the xmm registers. And the print command is not working, too:
(gdb) p $ymm0
$1 = void
(gdb) p/x $ymm0
$2 = Value can't be converted to integer.
I use the most current version gdb-8, so I think, it should know the avx2 instruction set.How can I persuade the debugger showing the hole ymm registers?Are there some config files I can edit to tell gdb the instruction set it shold use?
Kind regards
I want to print 1 words from the top of stack in the form of hexadecimal. To do so, I typed the following:
(gdb) x/1xw $esp
but GDB keeps popping up:
0xffffffffffffe030: Cannot access memory at address 0xffffffffffffe030
The program I'm trying to debug has already pushed a value onto stack so just in case if you're wondering that I might be trying to access kernel variables at the very beginning of program, it's not so.
Any idea?
0xffffffffffffe030 is a 64-bit constant, so you are running in x64-bit mode. But $esp is a 32-bit register (which GDB sign-extends to 64 bits in this context). The 64-bit stack pointer is called $rsp. Try this instead:
(gdb) x/1xw $rsp
I have read that GDB puts a int 3 (opcode CC) at the wanted adress in the target program memory.
Si this operation is erasing a piece of instruction (1 byte) in the program memory.
My question is: How and When GDB replaces the original opcode when the program continues ?
When i type disassemble in GDB, i do not see CC opcode. Is this because GDB knows it is him that puts the CC ?
Is there a way to do a raw disassemble, in order to see exactly what opcodes are loaded in memory at this instant ?
How and When GDB replaces the original opcode when the program continues ?
I use this as an interview question ;-)
On Linux, to continue past the breakpoint, 0xCC is replaced with the original instruction, and ptrace(PTRACE_SINGLESTEP, ...) is done. When the thread stops on the next instruction, original code is again replaced by the 0xCC opcode (to restore the breakpoint), and the thread continued on its merry way.
On x86 platforms that do not have PTRACE_SINGLESTEP, trap flag is set in EFLAGS via ptrace(PTRACE_SETREGS, ...) and the thread is continued. The trap flag causes the thread to immediately stop again (on the next instruction, just like PTRACE_SINGLESTEP would).
When i type disassemble in GDB, i do not see CC opcode. Is this because GDB knows it is him that puts the CC ?
Correct. A program could examine and print its own instruction stream, and you can observe breakpoint 0xCC opcodes that way.
Is there a way to do a raw disassemble, in order to see exactly what opcodes are loaded in memory at this instant ?
I don't believe there is. You can use (gdb) set debug infrun to observe what GDB is doing to the inferior (being debugged) process.
What i do not understand in fact is the exact role of SIGTRAP. Who is sending/receiving this signal ? The debugger or the target program?
Neither: after PTRACE_ATTACH, the kernel stops the inferior, then notifies the debugger that it has done so, by making debugger's wait return.
I see a wait(NULL) after the ptrace attach. What is the meaning of this wait?
See the explanation above.
Thread specific breakpoints?
For a thread-specific breakpoint, the debugger inserts a process-wide breakpoint (via 0xCC opcode), then simply immediately resumes any thread which hits the breakpoint, unless the thread is the specific one that you wanted to stop.
We have a posix mutli-threaded C++ program running on Linux 2.6.32, which core-dumps in one of the threads. Analysing the core file with gdb-7.2 corss-compiled, we see that the faulting instruction is here
0x11491178 <+208>: lwz r0,8(r9)
and registers in the frame show:
(gdb) info reg
r0 0x0 0
….
r9 0xdeaddead 3735936685
Which makes sense as r9 has an invalid address value(in fact heap scrub pattern we write) in the context of the process/thread.
The confusing bit is that r9 is loaded from like this
0x1149116c <+196>: lwz r9,0(r4)
and r4 contains the value of (first and only) function parameter "data". GDB tells me the following information about data:
(gdb) p data
$6 = (TextProcessorIF *) 0x4b3fe858
(gdb) p *data
$7 = {_vptr.TextProcessorIF = 0x128b5390}
(gdb) info symbol 0x128b5390
vtable for TextProcessorT<unsigned short> + 8 in section .rodata
Which is all correct in this context. So r9 should have had a value of 0x128b5390 instead of the pattern "0xdeaddead" which is written when the memory is free'd and given back to the heap.
So, why the register r9 contains the scrubbed value when the memory contains a legal object. My theory is that the core contains snapshot of the memory just as the process died which is much further down the line when the actual crash happened. After the SIGSEGV has been raised, this location of the heap memory can still be used by other threads as they are logging data till the time process dies. So, it is possible that the memory pointed to by data maybe have been allocated again and being used/been used at the time memory snapshot has been taken and preserved in core.
My question is:
A) Is my theory correct?
B) Am I right in presuming that the heap memory snapshot is not taken at the time crash (signal being raised) but at in the final moments of the process?
C) Address/location that caused a SIGSEGV can still be used (by other threads)?
Thanks!
Do you use signal handler(s) for SIGSEGV? Are they asynchronous and re-entrant?
See How to write a signal handler to catch SIGSEGV?
gdb provides functionality to read or write to a specific linear address, for example:
(gdb) x/1wx 0x080483e4
0x80483e4 <main>: 0x83e58955
(gdb)
but how do you specify a logical address ? I came accross the following instruction:
0x0804841a <+6>: mov %gs:0x14,%eax
how can i read the memory at "%gs:0x14" in gdb, or translate this logical address to a linear address that i could use in x command ?
note: i know that i could simply read %eax after this instruction, but that is not my concern
how can i read the memory at "%gs:0x14" in gdb
You can't: there is no way for GDB to know how the segment to which %gs refers to has been set up.
or translate this logical address to a linear address that i could use in x command
Again, you can't do this in general. However, you appear to be on 32-bit x86 Linux, and there you can do that -- the %gs is set up to point to the thread descriptor via set_thread_area system call.
You can do catch syscall set_thread_area in GDB, and examine the parameters (each thread will have one such call). The code to actually do that is here. Once you know how %gs has been set up, just add 0x14 to the base_addr, and you are done.
As answered in Using GDB to read MSRs, this is possible with gdb 8, using the registers $fs_base and $gs_base.
I think the easiest way to do this is to read the content of EAX register as you can see the value of %gs:0x14 is moved to EAX.
In GDB, set a breakpoint at the address right after 0x0804841a with break. For example
break *0x0804841e
Then run the program and you can print the contents of EAX register with
info registers eax