In gdb, how do I disassemble the previous instruction of an address? - gdb

We know that disassembling instructions after a given address (inclusive) can be achieved by something like:
x/5i address
which will print 5 instructions, but how do I disassemble the previous instruction?
I am debugging JIT code so things like disassembling a line doesn't work. I could disassemble a random range containing address like:
disas address-10 address+10
but this is very awkward and you'll see (bad) (hopefully not in the middle!) and start to worry that you are not getting something right. What I am looking for is something like:
x/-5i address
, but the above won't work.

x/-5i address doesn't work
On x86, or any architecture with variable instruction size, you can't in general know the address of the start of previous instruction, and so you can't reliably disassemble previous instruction.
What I do (very similar to what you do): x/15i $pc-35. When you step back by sufficient number of bytes (35 here) the instruction stream disassembly usually re-synchronizes, you only see one or two (bad) instructions at the beginning, but instructions around $pc look correct.

You can disassemble from the current instruction ($pc), and then just try to disassemble from a few bytes backwards until the second instruction you see is correct.
(lldb) x/3i $pc
-> 0xeccac5d4: 0x6913 ldr r3, [r2, #0x10]
0xeccac5d6: 0xaa02 add r2, sp, #0x8
0xeccac5d8: 0x4798 blx r3
(lldb) x/3i $pc-1
0xeccac5d3: 0x1368 asrs r0, r5, #0xd
0xeccac5d5: 0x0269 lsls r1, r5, #0x9
0xeccac5d7: 0x98aa ldr r0, [sp, #0x2a8]
(lldb) x/3i $pc-2
0xeccac5d2: 0x6802 ldr r2, [r0]
-> 0xeccac5d4: 0x6913 ldr r3, [r2, #0x10] <------ Correct!
0xeccac5d6: 0xaa02 add r2, sp, #0x8

Related

What are those numbers in gdb?

I disassemble my C code (just printf("hello world") ) in gdb and I got
0x0000000000001135 <+0>: push rbp
0x0000000000001136 <+1>: mov rbp,rsp
0x0000000000001139 <+4>: lea rdi [rip+0xec4] # 0x2004
0x0000000000001140 <+11>: mov eax,0x0
0x0000000000001145 <+16>: call 0x1030 <printf#plt>
0x000000000000114a <+21>: mov eax,0x0
0x000000000000114f <+26>: pop rbp
0x0000000000001150 <+27>: ret
I set break point to main and exam rip register.
rip 0x555555555139 0x555555555139 <main+4>
What are those numbers in font of < > in gdb?
I can only access the memory that rip point to.
if those numbers aren't memories can I change format that make gdb display memory?
Sorry for my bad English.
What are those numbers in font of < > in gdb? I can only access the memory that rip point to.
You are dealing with a position independent executable, which is linked to load at address 0, but is relocated at runtime to a different address (in your case, 0x555555554000).
You likely performed disas before running the application (i.e. before the relocation happened). If instead you do this:
(gdb) start
(gdb) disas main
then GDB will show you relocated instructions.

how to get the info via the address of library(so) when in gdb

The process has crashed and grave(tombstone) been generated. It was triggered by signal 6(SIGABRT). And the backtrace is shallow:
signal 6 (SIGABRT), code 0 (?), fault addr --------
r0 00000000 r1 000008b5 r2 00000006 r3 000008b5
r4 00000006 r5 00000002 r6 2b094be4 r7 0000010c
r8 00000038 r9 00000002 sl 2c653680 fp 2c653c98
ip 2c655920 sp 2c653560 lr 2af9ecf4 pc 2af9d8d4 cpsr 20000010
backtrace:
#00 pc 0002c8d4 /lib/libc.so.6 (raise+60)
#01 pc ffffffff <'unknown'>
in the stack, find the trace about the suspected library and also in the thread, transfer the address via the maps. To get more info about the symbols with the tool address2line. While the symbol may be in the .data section. The output like this:
$d
crtstuff.c:?
Then I want to get the info via the address of near the accident point from the library(so) in the runtime by gdb. Whether it feasible? If yes, how to do it?
how to do it?
I think you are looking for (gdb) info symbol 0x123456

find where the interrupt happened on cortex-m4

I am trying to find where in my code a specific interrupt happened. In this case it is on a stm32f4 microcontroller and the interrupt is the SysTick_Handler.
What i want is basically to figure out from where the systick interrupt happened. I am using arm-none-eabi-gdb to try to find the backtrace, but the only information i am getting from there is:
(gdb) bt
#0 SysTick_Handler () at modules/profiling.c:66
#1 <signal handler called>
#2 0x55555554 in ?? () Backtrace stopped: previous frame identical to this frame (corrupt stack?)
How can I get some information about where the program was before the interrupt fired?
Looking at the arm documentation here, it seems I should be able to read the stack pointer, and get the PC from there. But then this is exactly what the unwinder in GDB is doing isnt it?
You were on the right track at the end of your question. The ARM Cortex-M cores have two stack pointers, the main stack pointer (MSP, used for interrupts) and the process stack pointer (PSP, used for tasks).
When an interrupt with priority comes in, the current register values (for most of the registers) are pushed onto the current stack (PSP if interrupting the background application, or MSP if interrupting a lower priority interrupt), and then the stack is switched to the MSP (if not already there).
When you first enter an interrupt, the link register (LR, return address) will have a value that is mostly F's rather than an actual return address. This value tells the core how to exit when branched to. Typically, you'll see a value of 0xFFFFFFFD if the background task was interrupted, or 0xFFFFFFF1 if a lower priority interrupt was interrupted. These values will differ if you are using the floating point unit. The magic in this value, though, is that bit 2 (0x4) tells you whether your stack frame is on the PSP or MSP.
Once you determine which stack your frame is on, you can find the address you were executing from by looking at the appropriate stack pointer minus 24 (6 32-bit locations). See Figure 2.3 in your link. This will point you to the PC from which you were interrupted.
As many of you commented, the PC would be in two different stacks, the way I solved it was by actually finding a HardFault_Handling code in assembly and taking what i needed from there. To get the PC value correctly I am using the following code.
register int *r0 __asm("r0");
__asm( "TST lr, #4\n"
"ITE EQ\n"
"MRSEQ r0, MSP\n"
"MRSNE r0, PSP\n" // stack pointer now in r0
"ldr r0, [r0, #0x18]\n" // stored pc now in r0
//"add r0, r0, #6\n" // address to stored pc now in r0
);
The value of where the interrupt happended can now be accessed by
uint32_t PC = *r0;
and can now be used for whatever I want it. Unfortunately I did not manage to get GDB to unwind the stack automatically for me. But at least I found out where the interrupt was firing, which was the goal.
We keep seeing this question in various forms and folks keep saying there are two stacks. So I tried it myself with the systick.
The documentation says that we are in thread mode out of reset, and if you halt with openocd it says that
target halted due to debug-request, current mode: Thread
I have some code to dump registers:
20000000 APSR
00000000 IPSR
00000000 EPSR
00000000 CONTROL
00000000 SP_PROCESS
20000D00 SP_PROCESS after I modified it
20000FF0 SP_MAIN
20000FF0 mov r0,sp
then I dump the stack up to 0x20001000 which is where I know my stack started
20000FF0 00000000
20000FF4 00000000
20000FF8 00000000
20000FFC 0100005F
I setup and wait for a systick interrupt, the handler dumps registers and ram and then goes into an infinite loop. bad practice in general but just debugging/learning here. Before the interrupt I prep some registers:
.thumb_func
.globl iwait
iwait:
mov r0,#1
mov r1,#2
mov r2,#3
mov r3,#4
mov r4,#13
mov r12,r4
mov r4,#15
mov r14,r4
b .
and in the handler I see
20000000 APSR
0000000F IPSR
00000000 EPSR
00000000 CONTROL
20000D00 SP_PROCESS
20000FC0 SP_MAIN
20000FC0 mov r0,sp
20000FC0 0000000F
20000FC4 20000FFF
20000FC8 00000000
20000FCC FFFFFFF9 this is our special lr (not one rjp mentioned)
20000FD0 00000001 this is r0
20000FD4 00000002 this is r1
20000FD8 00000003 this is r2
20000FDC 00000004 this is r3
20000FE0 0000000D this is r12
20000FE4 0000000F this is r14/lr
20000FE8 01000074 and this is where we were interrupted from
20000FEC 21000000 this is probably the xpsr mentioned
20000FF0 00000000 stuff that was there before
20000FF4 00000000
20000FF8 00000000
20000FFC 0100005F
01000064 <iwait>:
1000064: 2001 movs r0, #1
1000066: 2102 movs r1, #2
1000068: 2203 movs r2, #3
100006a: 2304 movs r3, #4
100006c: 240d movs r4, #13
100006e: 46a4 mov ip, r4
1000070: 240f movs r4, #15
1000072: 46a6 mov lr, r4
1000074: e7fe b.n 1000074 <iwait+0x10>
1000076: bf00 nop
So in this case, straight out of the ARM documentation, it is not using the sp_process it is using sp_main. It is pushing the items the manual says it is pushing including the interrupted/return address which is 0x1000074.
Now, if I set the SPSEL bit (be careful to set the PSP first), it appears that a mov r0,sp in application/thread mode uses the PSP not MSP. But then the handler uses msp for a mov r0,sp but appears to put the
before in thread/foreground
20000000 APSR
00000000 IPSR
00000000 EPSR
00000000 SP_PROCESS
20000D00 SP_PROCESS modified
00000000 CONTROL
00000002 CONTROL modified
20000FF0 SP_MAIN
20000D00 mov r0,sp
now in the handler
20000000 APSR
0000000F IPSR
00000000 EPSR
00000000 CONTROL (interesting!)
20000CE0 SP_PROCESS
20000FE0 SP_MAIN
20000FE0 mov r0,sp
dump of that stack
20000FE0 0000000F
20000FE4 20000CFF
20000FE8 00000000
20000FEC FFFFFFFD
20000FF0 00000000
20000FF4 00000000
20000FF8 00000000
20000FFC 0100005F
dump of sp_process stack
20000CE0 00000001
20000CE4 00000002
20000CE8 00000003
20000CEC 00000004
20000CF0 0000000D
20000CF4 0000000F
20000CF8 01000074 our return value
20000CFC 21000000
So to be in this position of dealing with the alternate stack that folks keep mentioning, you have to put yourself in that position (or some code you rely on). Why you would want to do that for simple bare metal programs, who knows, the control register of all zeros is nice and easy, can share one stack just fine.
I dont use gdb, but you need to get it to dump all the registers sp_process and sp_main then depending on what you find, then dump a dozen or so words at each and in there you should see the 0xFFFFFFFx as a marker then count down from that to see the return address. You can have your handler read the two stack pointers as well then you can look at gprs. With gnu assembler mrs rX,psp; mrs rX,msp; For the process and main stack pointers.
This is called DEBUGGING. The easiest way to get started is to just stick a bunch of printf() calls here and there throughout the code. Run the program. If it prints out:
got to point A
got to point B
got to point C
and dies, then you know it died between "C" and "D." You can now refine that downwards by festooning the code between "C" and "D" with more closely spaced printf() calls.
This is the best way for a beginner to get started. Many seasoned experts also prefer printf() for debugging. Debuggers can get in the way.

segmentation fault has occurred on a code which was not compiled using debugger flags

one of process on my system has got segmentation fault .
From core files , I got the below information .
#0 0x00007f8768c06cfb in TestDummy::work() () from libCont.so
#1 0x00007f8768bfb5ee in Test::work() () from libCont.so
#2 0x00007f8768c5fa7b in Test::worker_threads() () from libCont.so
#3 0x00007f873fffe830 in ?? ()
#4 0x0000000000000000 in ?? ()
Please note I am unable to re create this segmentation fault , all i have is this core file on a system to identify what went wrong .
Note: code was not compiled using debugger flag i.e "g++ -g" , so debug information is not available .
What I tried
I tried to dissemble and read complete frame 0 to identify the exact crash point but it didn't help .
can anybody let me know a way to debug it further?
What I tried I tried to dissemble and read complete frame 0 to identify the exact crash point but it didn't help
You don't need to identify the exact crash point: GDB has already told you what it is: it's the instruction at address 0x7f8768c06cfb.
What you are probably saying is "despite looking at disassembly, I still can't understand which source line caused the problem". We could help you with that, but only if you actually show the source and the disassembly in your question.
Your only other choices are:
Find a local guru who you can show the source and the disassembly, and who will help you the same way we would, or
Do what Lightness Races in Orbit told you to do: rebuild your binary with exactly the same flags, but add -g as well. Assuming you have a hermetic build and can rebuild your original binary in a close enough state (output from nm new-binary should match output from nm old-binary), GDB will then tell you exactly what line the address 0x7f8768c06cfb corresponds to.
Note: you don't actually have to rebuild the entire binary with -g. Rebuilding just the source containing TestDummy::work() and re-linking libCont.so should be enough.
I think there a way by which we can debug the core which is not compiled using debugger flags . I would like to explain it with below example .
(gdb) disassemble
Dump of assembler code for function mystrcpy:
0x0804852a <+0>: push %ebp
0x0804852b <+1>: mov %esp,%ebp
0x0804852d <+3>: sub $0x10,%esp
0x08048530 <+6>: mov 0x8(%ebp),%eax
0x08048533 <+9>: mov %eax,-0x4(%ebp)
0x08048536 <+12>: jmp 0x8048540 <mystrcpy+22>
0x08048538 <+14>: addl $0x1,0xc(%ebp)
0x0804853c <+18>: addl $0x1,0x8(%ebp)
0x08048540 <+22>: mov 0xc(%ebp),%eax
0x08048543 <+25>: movzbl (%eax),%edx
0x08048546 <+28>: mov 0x8(%ebp),%eax
=> 0x08048549 <+31>: mov %dl,(%eax)
0x0804854b <+33>: mov 0x8(%ebp),%eax
0x0804854e <+36>: movzbl (%eax),%eax
0x08048551 <+39>: test %al,%al
0x08048553 <+41>: jne
0x8048538 <mystrcpy+14>
0x08048555 <+43>: mov -0x4(%ebp),%eax
0x08048558 <+46>: leave
0x08048559 <+47>:
ret End of assembler dump.
Now , line which is actually showing "=>" symbol is the culprit .(=> 0x08048549 <+31>: mov %dl,(%eax) )
We can use gdb commands to figure out what had happened with line which is showing the problem .
gdb) print $eax //print command
$1 = 0
(gdb) print $dl
$2 = 118
(gdb) print/c $dl
$3 = 118 'v‘
(gdb) info frame //info frame command
Stack level 0, frame at 0xffbf8b90: eip = 0x8048549 in mystrcpy; saved eip = 0x80485cd called by frame at 0xffbf8bc0 Arglist at 0xffbf8b88, args: Locals at 0xffbf8b88, Previous frame's sp is 0xffbf8b90 Saved registers: ebp at 0xffbf8b88, eip at 0xffbf8b8c
(gdb) x/x $ebp+4 //base pointer + 4
0xffbf8b8c: 0x080485cd
(gdb) info symbol 0x080485cd //info symbol command
connect + 115 in section .text of /home/vmahajan/a.out
(gdb) x/x $ebp+4
0xffbf8b8c: 0x080485cd
(gdb) x/x $ebp+8
0xffbf8b90: 0x00000000
(gdb) x/x $ebp+12
0xffbf8b94: 0xffbf91f3
(gdb) print/s (char *)0xffbf91f3
$5 = 0xffbf91f3 "vishal“

Library function objdump output

I have the following objdump output when debugging a crash. I could narrow down the issue to the following function LanManager::Interface() library function, but with my little experience with object code I haven't been able to work out much more sense from the objdump output.
Below is the beginning part of that library function. I'd like to know:
Whether the beginning address is the address of the function itself?
What is the relation of that function address and the address of the main executable that uses the function?
A brief explanation of the three columns in this objdump output.
What is _init? Is that the beginning of the function?
Is there any way to work out what <_init+0x10e4> is pointing to?
I won't expect a complete answer, just anything that sheds some light would be appreciated.
0003629c <LanManager::Interface()>:
3629c: e1a0c00d mov ip, sp
362a0: e92dd9f0 push {r4, r5, r6, r7, r8, fp, ip, lr, pc}
362a4: e59f40b8 ldr r4, [pc, #184] ; 36364 <LanManager::Interface()+0xc8>
362a8: e24cb004 sub fp, ip, #4 ; 0x4
362ac: e24dd004 sub sp, sp, #4 ; 0x4
362b0: e59f70b0 ldr r7, [pc, #176] ; 36368 <LanManager::Interface()+0xcc>
362b4: e08f4004 add r4, pc, r4
362b8: e59f50ac ldr r5, [pc, #172] ; 3636c <LanManager::Interface()+0xd0>
362bc: e7940007 ldr r0, [r4, r7]
362c0: ebff6dc9 bl 119ec <_init+0x10e4>
362c4: e7942005 ldr r2, [r4, r5]
362c8: e5923000 ldr r3, [r2]
362cc: e3530000 cmp r3, #0 ; 0x0
362d0: 0a000005 beq 362ec <LanManager::Interface()+0x50>
362d4: e7943005 ldr r3, [r4, r5]
362d8: e7940007 ldr r0, [r4, r7]
362dc: e5934000 ldr r4, [r3]
I'll try to shed a little light here, but for more depth you may want to check out a text on assembly programming in ARM or reverse engineering.
You're looking at the disassembly for LanManager::Interface. Yes, 0003629c is the value of the function pointer itself. Your three columns look like:
| address | opcodes | disassembly |
_init is another symbol somewhere in the file you disassembled. It seems kinda weird that LanManager::Interface would branch to some location a whole page away from the start of another function.
When a binary has had its symbols stripped, and objdump is trying to determine the symbolic name for an address, it will keep scanning backwards until it eventually finds one. Likely that _init is just the entry point or something, I've forgotten the names emitted by the compiler off the top of my head.
You can poke around in gdb and disassemble specific addresses with (gdb) disas *0x119ec. However you really never say what sort of crash you're looking at in the first place... if you wrote a program that's dying on a library call I would spend more time looking at arguments you passed in.