I am currently trying to get backtrace based on stack pointer and link register on ARM64 device using C program.
Below is example of objdump
bar() calls foo() with 240444: ebfffd68 bl 23f9ec <foo##Base>
I can get link register (lr) and from that getting 23f9ec, save it to backtrace list as last routine.
My question: From below assembly code with current lr 0023f9ec <foo##Base>:, how to calculate to get previous routine with lr is 0023fe14 <bar##Base> using C language?
here is my implementation, but getting wrong previous lr
int bt(void** backtrace, int max_size) {
unsigned long* sp = __get_SP();
unsigned long* ra = __get_LR();
int* funcbase = (int*)(int)&bt;
int spofft = (short)((*funcbase));
sp = (char*)sp-spofft;
unsigned long* wra = (unsigned long*)ra;
int spofft;
int depth = 0;
while(ra) {
wra = ra;
while((*wra >> 16) != 0xe92d) {
wra--;
}
if(wra == 0)
return 0;
spofft = (short)(*wra & 0xffff);
if(depth < max_size)
backtrace[depth] = ra;
else
break;
ra =(unsigned long *)((unsigned long)ra + spofft);
sp =(unsigned long *)((unsigned long)sp + spofft);
depth++;
}
return 1;
}
0023f9ec <foo##Base>:
23f9ec: e92d42f3 push {r0, r1, r4, r5, r6, r7, r9, lr}
23f9f0: e1a09001 mov r9, r1
23f9f4: e1a07000 mov r7, r0
23f9f8: ebfffff9 bl 23f9e4 <__get_SP##Base>
23f9fc: e59f4060 ldr r4, [pc, #96] ; 23fa64 <foo##Base+0x78>
23fa00: e08f4004 add r4, pc, r4
23fa04: e1a05000 mov r5, r0
23fa08: ebfffff3 bl 23f9dc <__get_LR##Base>
23fa0c: e59f3054 ldr r3, [pc, #84] ; 23fa68 <foo##Base+0x7c>
23fa10: e3002256 movw r2, #598 ; 0x256
23fa14: e59f1050 ldr r1, [pc, #80] ; 23fa6c <foo##Base+0x80>
23fa18: e7943003 ldr r3, [r4, r3]
23fa1c: e08f1001 add r1, pc, r1
23fa20: e5934000 ldr r4, [r3]
23fa24: e1a03005 mov r3, r5
23fa28: e6bf4074 sxth r4, r4
23fa2c: e58d4004 str r4, [sp, #4]
23fa30: e1a06000 mov r6, r0
23fa34: e58d0000 str r0, [sp]
23fa38: e59f0030 ldr r0, [pc, #48] ; 23fa70 <foo##Base+0x84>
23fa3c: e08f0000 add r0, pc, r0
23fa40: ebfd456d bl 190ffc <printf#plt>
23fa44: e1a03009 mov r3, r9
23fa48: e1a02007 mov r2, r7
23fa4c: e1a01006 mov r1, r6
23fa50: e0640005 rsb r0, r4, r5
23fa54: ebffff70 bl 23f81c <get_prev_sp_ra2##Base>
23fa58: e3a00000 mov r0, #0
23fa5c: e28dd008 add sp, sp, #8
23fa60: e8bd82f0 pop {r4, r5, r6, r7, r9, pc}
23fa64: 003d5be0 eorseq r5, sp, r0, ror #23
23fa68: 000026c8 andeq r2, r0, r8, asr #13
23fa6c: 002b7ba6 eoreq r7, fp, r6, lsr #23
23fa70: 002b73e5 eoreq r7, fp, r5, ror #7
0023fe14 <bar##Base>:
23fe14: e92d4ef0 push {r4, r5, r6, r7, r9, sl, fp, lr}
23fe18: e24dde16 sub sp, sp, #352 ; 0x160
23fe1c: e59f76a8 ldr r7, [pc, #1704] ; 2404cc <bar##Base+0x6b8>
23fe20: e1a04000 mov r4, r0
23fe24: e59f66a4 ldr r6, [pc, #1700] ; 2404d0 <bar##Base+0x6bc>
23fe28: e1a03000 mov r3, r0
23fe2c: e59f26a0 ldr r2, [pc, #1696] ; 2404d4 <bar##Base+0x6c0>
23fe30: e08f7007 add r7, pc, r7
23fe34: e08f6006 add r6, pc, r6
23fe38: e3a00000 mov r0, #0
23fe3c: e08f2002 add r2, pc, r2
23fe40: e1a05001 mov r5, r1
23fe44: e3a01003 mov r1, #3
23fe48: e59f9688 ldr r9, [pc, #1672] ; 2404d8 <bar##Base+0x6c4>
.....................................................................
24043c: e3a0100f mov r1, #15
240440: e1a0000a mov r0, sl
240444: ebfffd68 bl 23f9ec <foo##Base>
240448: e59f2108 ldr r2, [pc, #264] ; 240558 <bar##Base+0x744>
24044c: e3a01003 mov r1, #3
240450: e08f2002 add r2, pc, r2
240454: e1a05000 mov r5, r0
240458: e1a03000 mov r3, r0
24045c: e3a00000 mov r0, #0
I don't think there's an easy way to do this.
Normally the register ABI of any operating system contains a "frame pointer" register. For example, on Apple's armv7 ABI, this is r7:
0x10006fc0 b0b5 push {r4, r5, r7, lr}
0x10006fc2 02af add r7, sp, 8
0x10006fc4 0448 ldr r0, [0x10006fd8]
0x10006fc6 d0e90c45 ldrd r4, r5, [r0, 0x30]
0x10006fca 0020 movs r0, 0
0x10006fcc fff7a6ff bl 0x10006f1c
0x10006fd0 0019 adds r0, r0, r4
0x10006fd2 6941 adcs r1, r5
0x10006fd4 b0bd pop {r4, r5, r7, pc}
If you dereference r7 there, you get to a pair of pointers, the second of which is lr, and the first of which is the r7 of the calling function, allowing you to repeat this process until you reach the bottom of the stack.
Judging by the assembly you posted, the codebase you're looking at doesn't have that. This means that the only way to obtain the return address is the same way that the code itself does: step forward through each instruction and parse/interpret them until you reach something that loads into pc. This is of course imperfect, since there may be functions in your call stack that do not ever return, but there's not much you can do about that.
It may be tempting to search backwards instead, and while you can do a heuristic approach and probably reach quite reasonable results with it, that is even less reliable than searching forward, since you have absolutely no way of telling whether you arrived at address X by stepping forward from the previous instruction or by explicitly jumping there from somewhere else.
thanks to other posts here, I managed to build and install Valgrind for ARM:
make clean
make distclean
export PATH=$PATH:/usr/local/angstrom/arm/bin
export CROSS_COMPILE=/usr/local/angstrom/arm/bin/arm-angstrom-linux-gnueabi-
export CC=${CROSS_COMPILE}gcc
export CPP=${CROSS_COMPILE}cpp
export CXX=${CROSS_COMPILE}g++
export LD=${CROSS_COMPILE}ld
export AR=${CROSS_COMPILE}ar
export RANLIB=${CROSS_COMPILE}ranlib
sed -i -e "s#armv7#arm#g" configure
./configure --host=arm-none-linux-gnueabi \
--host=arm-none-linux-gnueabi \
--prefix=/opt/valgrind/ \
CFLAGS=-static
make
make install
and copied it into the same path on the ARMv5 machine.
I am running an ARMv5 and apparently Valgrind is still not supporting ARMv5.
When starting Valgrind, I'll get
Illegal instruction
and I suppose this is, because Valgrind needs the ARMv7 instruction set?
So:
did I make any error in configure when cross-compiling valgrind?
is there any way to get Valgrind up and running on ARMv5 or even only the vgdb or Memcheck tool included in Valgrind?
Is there any other tool to do memchecks on ARMv5, I have heard about
Adress Sanitizer or
Malloc_Check
and are they recommendable for ARMv5?
Thanks a lot for help and support!
BR Florian
I have created a core dump and run gdb, unfortunately without debugging symbols:
What command should i used?
[New Thread 10495]
Core was generated by `/opt/valgrind/bin/valgrind'.
Program terminated with signal 4, Illegal instruction.
#0 0x38035804 in ?? ()
(gdb) list
305 platform ? platform : "unknown");
306
307 return platform;
308 }
309
310 /* Where we expect to find all our aux files */
311 static const char *valgrind_lib = VG_LIBDIR;
312
313 int main(int argc, char** argv, char** envp)
314 {
(gdb) info frame
Stack level 0, frame at 0x38ac7894:
pc = 0x38035804; saved pc 0x380425e0
called by frame at 0x38ac7894
Cannot access memory at address 0x0
Arglist at 0x38ac7894, args:
Locals at 0x38ac7894, Previous frame's sp is 0x38ac7894
(gdb) list main
326
327 /* Start the debugging-log system ASAP. First find out how many
328 "-d"s were specified. This is a pre-scan of the command line.
329 At the same time, look for the tool name. */
330 loglevel = 0;
331 for (i = 1; i < argc; i++) {
332 if (argv[i][0] != '-') {
333 clientname = argv[i];
334 break;
335 }
(gdb) disassemble main
Dump of assembler code for function main:
0x000087b4 <+0>: cmp r0, #1
0x000087b8 <+4>: push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
0x000087bc <+8>: mov r10, r0
0x000087c0 <+12>: sub sp, sp, #12
0x000087c4 <+16>: mov r11, r1
0x000087c8 <+20>: mov r9, r2
0x000087cc <+24>: ble 0x8c90 <main+1244>
0x000087d0 <+28>: ldr r4, [r1, #4]
0x000087d4 <+32>: ldrb r3, [r4]
0x000087d8 <+36>: cmp r3, #45 ; 0x2d
0x000087dc <+40>: movne r8, #0
0x000087e0 <+44>: movne r7, r8
0x000087e4 <+48>: bne 0x8820 <main+108>
0x000087e8 <+52>: ldr r0, [pc, #1372] ; 0x8d4c <main+1432>
0x000087ec <+56>: bl 0x29d20 <strlen>
0x000087f0 <+60>: mov r8, #0
0x000087f4 <+64>: mov r5, #1
0x000087f8 <+68>: mov r7, r8
0x000087fc <+72>: mov r6, r0
0x00008800 <+76>: cmp r6, #3
0x00008804 <+80>: bhi 0x8b70 <main+956>
0x00008808 <+84>: cmp r6, #0
0x0000880c <+88>: bne 0x8a00 <main+588>
0x00008810 <+92>: add r0, r5, #1
0x00008814 <+96>: cmp r10, r0
0x00008818 <+100>: ble 0x8b90 <main+988>
0x0000881c <+104>: ldr r4, [r11, r0, lsl #2]
0x00008820 <+108>: mov r0, r8
0x00008824 <+112>: ldr r1, [pc, #1316] ; 0x8d50 <main+1436>
0x00008828 <+116>: bl 0xa258 <vgPlain_debugLog_startup>
0x0000882c <+120>: cmp r7, #0
0x00008830 <+124>: mov r10, r7
0x00008834 <+128>: beq 0x8bac <main+1016>
0x00008838 <+132>: mov r3, r7
0x0000883c <+136>: mov r0, #1
0x00008840 <+140>: ldr r1, [pc, #1292] ; 0x8d54 <main+1440>
0x00008844 <+144>: ldr r2, [pc, #1292] ; 0x8d58 <main+1444>
0x00008848 <+148>: bl 0x9ff0 <vgPlain_debugLog>
0x0000884c <+152>: cmp r4, #0
0x00008850 <+156>: beq 0x8bc8 <main+1044>
0x00008854 <+160>: mov r0, r4
0x00008858 <+164>: bl 0x8278 <select_platform>
0x0000885c <+168>: subs r8, r0, #0
0x00008860 <+172>: beq 0x8c6c <main+1208>
0x00008864 <+176>: mov r0, #1
0x00008868 <+180>: ldr r1, [pc, #1252] ; 0x8d54 <main+1440>
0x0000886c <+184>: ldr r2, [pc, #1256] ; 0x8d5c <main+1448>
0x00008870 <+188>: mov r3, r8
0x00008874 <+192>: bl 0x9ff0 <vgPlain_debugLog>
0x00008878 <+196>: mov r0, #0
0x0000887c <+200>: mov r5, r0
0x00008880 <+204>: add r4, r0, #500 ; 0x1f4
0x00008884 <+208>: mov r1, r4
0x00008888 <+212>: mov r0, r5
0x0000888c <+216>: bl 0x290ec <realloc>
0x00008890 <+220>: subs r5, r0, #0
0x00008894 <+224>: beq 0x8c88 <main+1236>
0x00008898 <+228>: ldr r0, [pc, #1216] ; 0x8d60 <main+1452>
0x0000889c <+232>: mov r1, r5
0x000088a0 <+236>: mov r2, r4
0x000088a4 <+240>: bl 0x2d760 <readlink>
0x000088a8 <+244>: cmn r0, #1
0x000088ac <+248>: beq 0x8c44 <main+1168>
0x000088b0 <+252>: cmp r0, r4
0x000088b4 <+256>: beq 0x8880 <main+204>
0x000088b8 <+260>: movcc r3, #0
0x000088bc <+264>: movcc r6, r5
0x000088c0 <+268>: strbcc r3, [r5, r0]
0x000088c4 <+272>: bcs 0x8d38 <main+1412>
0x000088c8 <+276>: ldr r0, [pc, #1172] ; 0x8d64 <main+1456>
0x000088cc <+280>: bl 0x29d20 <strlen>
0x000088d0 <+284>: mov r4, r0
0x000088d4 <+288>: mov r0, r6
0x000088d8 <+292>: bl 0x29d20 <strlen>
0x000088dc <+296>: add r4, r4, r0
0x000088e0 <+300>: add r0, r4, #2
0x000088e4 <+304>: bl 0x28928 <malloc>
0x000088e8 <+308>: subs r7, r0, #0
0x000088ec <+312>: beq 0x8ca4 <main+1264>
0x000088f0 <+316>: ldr r1, [pc, #1132] ; 0x8d64 <main+1456>
0x000088f4 <+320>: bl 0x29b00 <strcpy>
0x000088f8 <+324>: ldr r1, [pc, #1128] ; 0x8d68 <main+1460>
0x000088fc <+328>: mov r0, r7
0x00008900 <+332>: bl 0x29994 <strcat>
0x00008904 <+336>: mov r0, r7
0x00008908 <+340>: mov r1, r6
0x0000890c <+344>: bl 0x29994 <strcat>
0x00008910 <+348>: ldr r3, [r9]
0x00008914 <+352>: cmp r3, #0
0x00008918 <+356>: moveq r4, r3
0x0000891c <+360>: moveq r5, #2
0x00008920 <+364>: moveq r0, #8
0x00008924 <+368>: beq 0x8944 <main+400>
0x00008928 <+372>: mov r4, #0
0x0000892c <+376>: add r4, r4, #1
0x00008930 <+380>: ldr r3, [r9, r4, lsl #2]
0x00008934 <+384>: cmp r3, #0
0x00008938 <+388>: bne 0x892c <main+376>
0x0000893c <+392>: add r5, r4, #2
0x00008940 <+396>: lsl r0, r5, #2
0x00008944 <+400>: bl 0x28928 <malloc>
0x00008948 <+404>: subs r6, r0, #0
0x0000894c <+408>: beq 0x8cac <main+1272>
0x00008950 <+412>: cmp r4, #0
0x00008954 <+416>: moveq r1, r4
0x00008958 <+420>: moveq r0, #4
0x0000895c <+424>: moveq r2, #2
0x00008960 <+428>: beq 0x8994 <main+480>
0x00008964 <+432>: mov r1, #0
0x00008968 <+436>: mov r2, r1
0x0000896c <+440>: ldr r3, [r9, r2]
0x00008970 <+444>: add r1, r1, #1
0x00008974 <+448>: cmp r4, r1
0x00008978 <+452>: str r3, [r6, r2]
0x0000897c <+456>: add r2, r2, #4
0x00008980 <+460>: bgt 0x896c <main+440>
0x00008984 <+464>: add r3, r4, #1
0x00008988 <+468>: add r2, r3, #1
0x0000898c <+472>: lsl r1, r4, #2
0x00008990 <+476>: lsl r0, r3, #2
0x00008994 <+480>: cmp r2, r5
0x00008998 <+484>: str r7, [r6, r1]
0x0000899c <+488>: mov r3, #0
0x000089a0 <+492>: str r3, [r6, r0]
0x000089a4 <+496>: bne 0x8cb4 <main+1280>
0x000089a8 <+500>: ldr r0, [pc, #956] ; 0x8d6c <main+1464>
0x000089ac <+504>: bl 0x12650 <getenv>
0x000089b0 <+508>: subs r3, r0, #0
0x000089b4 <+512>: ldrne r0, [pc, #948] ; 0x8d70 <main+1468>
0x000089b8 <+516>: ldreq r0, [pc, #944] ; 0x8d70 <main+1468>
0x000089bc <+520>: strne r3, [r0]
0x000089c0 <+524>: ldr r0, [r0]
0x000089c4 <+528>: bl 0x29d20 <strlen>
0x000089c8 <+532>: mov r4, r0
0x000089cc <+536>: mov r0, r10
0x000089d0 <+540>: bl 0x29d20 <strlen>
0x000089d4 <+544>: mov r5, r0
0x000089d8 <+548>: mov r0, r8
0x000089dc <+552>: bl 0x29d20 <strlen>
0x000089e0 <+556>: add r4, r4, r5
0x000089e4 <+560>: add r4, r4, #3
0x000089e8 <+564>: add r0, r4, r0
0x000089ec <+568>: bl 0x28928 <malloc>
0x000089f0 <+572>: subs r4, r0, #0
0x000089f4 <+576>: bne 0x8cc8 <main+1300>
0x000089f8 <+580>: ldr r0, [pc, #884] ; 0x8d74 <main+1472>
0x000089fc <+584>: bl 0x8234 <barf>
0x00008a00 <+588>: ldrb r2, [r4, #1]
0x00008a04 <+592>: cmp r6, #1
0x00008a08 <+596>: movls r3, #0
0x00008a0c <+600>: movhi r3, #1
0x00008a10 <+604>: cmp r2, #45 ; 0x2d
0x00008a14 <+608>: movne r3, #0
0x00008a18 <+612>: cmp r3, #0
0x00008a1c <+616>: sub r0, r2, #45 ; 0x2d
0x00008a20 <+620>: beq 0x8a50 <main+668>
0x00008a24 <+624>: ldrb r0, [r4, #2]
0x00008a28 <+628>: cmp r6, #2
0x00008a2c <+632>: movls r3, #0
0x00008a30 <+636>: movhi r3, #1
0x00008a34 <+640>: cmp r0, #0
0x00008a38 <+644>: movne r3, #0
0x00008a3c <+648>: cmp r3, #0
0x00008a40 <+652>: ldrne r1, [pc, #772] ; 0x8d4c <main+1432>
0x00008a44 <+656>: ldrbne r2, [r4, #3]
0x00008a48 <+660>: ldrbne r3, [r1, #3]
0x00008a4c <+664>: rsbne r0, r3, r2
0x00008a50 <+668>: cmp r0, #0
0x00008a54 <+672>: beq 0x8810 <main+92>
0x00008a58 <+676>: ldr r0, [pc, #792] ; 0x8d78 <main+1476>
0x00008a5c <+680>: bl 0x29d20 <strlen>
0x00008a60 <+684>: cmp r0, #3
0x00008a64 <+688>: bhi 0x8c10 <main+1116>
0x00008a68 <+692>: cmp r0, #0
0x00008a6c <+696>: beq 0x8c08 <main+1108>
0x00008a70 <+700>: ldrb r2, [r4, #1]
0x00008a74 <+704>: cmp r0, #1
0x00008a78 <+708>: movls r3, #0
0x00008a7c <+712>: movhi r3, #1
0x00008a80 <+716>: cmp r2, #100 ; 0x64
0x00008a84 <+720>: movne r3, #0
0x00008a88 <+724>: cmp r3, #0
0x00008a8c <+728>: sub r2, r2, #100 ; 0x64
0x00008a90 <+732>: beq 0x8ac0 <main+780>
0x00008a94 <+736>: ldrb r2, [r4, #2]
0x00008a98 <+740>: cmp r0, #2
0x00008a9c <+744>: movls r3, #0
0x00008aa0 <+748>: movhi r3, #1
0x00008aa4 <+752>: cmp r2, #0
0x00008aa8 <+756>: movne r3, #0
0x00008aac <+760>: cmp r3, #0
0x00008ab0 <+764>: ldrne r1, [pc, #704] ; 0x8d78 <main+1476>
0x00008ab4 <+768>: ldrbne r2, [r4, #3]
0x00008ab8 <+772>: ldrbne r3, [r1, #3]
0x00008abc <+776>: rsbne r2, r3, r2
0x00008ac0 <+780>: cmp r2, #0
0x00008ac4 <+784>: beq 0x8c08 <main+1108>
0x00008ac8 <+788>: ldr r0, [pc, #684] ; 0x8d7c <main+1480>
0x00008acc <+792>: bl 0x29d20 <strlen>
0x00008ad0 <+796>: cmp r0, #6
0x00008ad4 <+800>: mov r1, r0
0x00008ad8 <+804>: bhi 0x8be4 <main+1072>
0x00008adc <+808>: cmp r0, #3
0x00008ae0 <+812>: bhi 0x8c24 <main+1136>
0x00008ae4 <+816>: cmp r0, #0
0x00008ae8 <+820>: beq 0x8b80 <main+972>
0x00008aec <+824>: ldrb r3, [r4, #1]
0x00008af0 <+828>: cmp r3, #45 ; 0x2d
0x00008af4 <+832>: movne r0, #0
0x00008af8 <+836>: moveq r0, #1
0x00008afc <+840>: cmp r1, #1
0x00008b00 <+844>: movls r2, #0
0x00008b04 <+848>: andhi r2, r0, #1
0x00008b08 <+852>: cmp r2, #0
0x00008b0c <+856>: beq 0x8b44 <main+912>
0x00008b10 <+860>: ldrb r3, [r4, #2]
0x00008b14 <+864>: cmp r3, #116 ; 0x74
0x00008b18 <+868>: movne r0, #0
0x00008b1c <+872>: moveq r0, #1
0x00008b20 <+876>: cmp r1, #2
0x00008b24 <+880>: movls r2, #0
0x00008b28 <+884>: andhi r2, r0, #1
0x00008b2c <+888>: cmp r2, #0
0x00008b30 <+892>: beq 0x8b44 <main+912>
0x00008b34 <+896>: ldrb r3, [r4, #3]
0x00008b38 <+900>: cmp r3, #111 ; 0x6f
0x00008b3c <+904>: movne r0, #0
0x00008b40 <+908>: moveq r0, #1
0x00008b44 <+912>: cmp r0, #0
0x00008b48 <+916>: bne 0x8b80 <main+972>
0x00008b4c <+920>: add r5, r5, #1
0x00008b50 <+924>: cmp r10, r5
0x00008b54 <+928>: ble 0x8b90 <main+988>
0x00008b58 <+932>: ldr r4, [r11, r5, lsl #2]
0x00008b5c <+936>: ldrb r3, [r4]
0x00008b60 <+940>: cmp r3, #45 ; 0x2d
0x00008b64 <+944>: bne 0x8820 <main+108>
0x00008b68 <+948>: cmp r6, #3
0x00008b6c <+952>: bls 0x8808 <main+84>
0x00008b70 <+956>: mov r0, r4
0x00008b74 <+960>: ldr r1, [pc, #464] ; 0x8d4c <main+1432>
0x00008b78 <+964>: bl 0x29acc <strcmp>
0x00008b7c <+968>: b 0x8a50 <main+668>
0x00008b80 <+972>: add r5, r5, #1
0x00008b84 <+976>: cmp r10, r5
0x00008b88 <+980>: add r7, r4, #7
0x00008b8c <+984>: bgt 0x8b58 <main+932>
0x00008b90 <+988>: mov r0, r8
0x00008b94 <+992>: ldr r1, [pc, #436] ; 0x8d50 <main+1436>
0x00008b98 <+996>: bl 0xa258 <vgPlain_debugLog_startup>
0x00008b9c <+1000>: cmp r7, #0
0x00008ba0 <+1004>: mov r10, r7
0x00008ba4 <+1008>: mov r4, #0
0x00008ba8 <+1012>: bne 0x8838 <main+132>
0x00008bac <+1016>: mov r0, #1
0x00008bb0 <+1020>: ldr r1, [pc, #412] ; 0x8d54 <main+1440>
0x00008bb4 <+1024>: ldr r2, [pc, #452] ; 0x8d80 <main+1484>
0x00008bb8 <+1028>: bl 0x9ff0 <vgPlain_debugLog>
0x00008bbc <+1032>: cmp r4, #0
0x00008bc0 <+1036>: ldr r10, [pc, #444] ; 0x8d84 <main+1488>
0x00008bc4 <+1040>: bne 0x8854 <main+160>
0x00008bc8 <+1044>: mov r0, #1
0x00008bcc <+1048>: ldr r1, [pc, #384] ; 0x8d54 <main+1440>
0x00008bd0 <+1052>: ldr r2, [pc, #432] ; 0x8d88 <main+1492>
0x00008bd4 <+1056>: ldr r3, [pc, #432] ; 0x8d8c <main+1496>
0x00008bd8 <+1060>: bl 0x9ff0 <vgPlain_debugLog>
0x00008bdc <+1064>: ldr r8, [pc, #424] ; 0x8d8c <main+1496>
0x00008be0 <+1068>: b 0x8878 <main+196>
0x00008be4 <+1072>: mov r0, r4
0x00008be8 <+1076>: ldr r1, [pc, #396] ; 0x8d7c <main+1480>
0x00008bec <+1080>: mov r2, #7
0x00008bf0 <+1084>: bl 0x29e90 <strncmp>
0x00008bf4 <+1088>: rsbs r0, r0, #1
0x00008bf8 <+1092>: movcc r0, #0
0x00008bfc <+1096>: cmp r0, #0
0x00008c00 <+1100>: beq 0x8b4c <main+920>
0x00008c04 <+1104>: b 0x8b80 <main+972>
0x00008c08 <+1108>: add r8, r8, #1
0x00008c0c <+1112>: b 0x8ac8 <main+788>
0x00008c10 <+1116>: mov r0, r4
0x00008c14 <+1120>: ldr r1, [pc, #348] ; 0x8d78 <main+1476>
0x00008c18 <+1124>: bl 0x29acc <strcmp>
0x00008c1c <+1128>: mov r2, r0
0x00008c20 <+1132>: b 0x8ac0 <main+780>
0x00008c24 <+1136>: mov r0, r4
0x00008c28 <+1140>: ldr r1, [pc, #332] ; 0x8d7c <main+1480>
0x00008c2c <+1144>: bl 0x29acc <strcmp>
0x00008c30 <+1148>: rsbs r0, r0, #1
0x00008c34 <+1152>: movcc r0, #0
0x00008c38 <+1156>: cmp r0, #0
0x00008c3c <+1160>: beq 0x8b4c <main+920>
0x00008c40 <+1164>: b 0x8b80 <main+972>
0x00008c44 <+1168>: ldr r4, [pc, #324] ; 0x8d90 <main+1500>
0x00008c48 <+1172>: ldr r1, [pc, #324] ; 0x8d94 <main+1504>
0x00008c4c <+1176>: ldr r2, [pc, #268] ; 0x8d60 <main+1452>
0x00008c50 <+1180>: ldr r0, [r4]
0x00008c54 <+1184>: bl 0x1b4c0 <fprintf>
0x00008c58 <+1188>: ldr r0, [r4]
0x00008c5c <+1192>: ldr r1, [pc, #308] ; 0x8d98 <main+1508>
0x00008c60 <+1196>: bl 0x1b4c0 <fprintf>
0x00008c64 <+1200>: ldr r6, [pc, #304] ; 0x8d9c <main+1512>
0x00008c68 <+1204>: b 0x88c8 <main+276>
0x00008c6c <+1208>: mov r0, #1
0x00008c70 <+1212>: ldr r1, [pc, #220] ; 0x8d54 <main+1440>
0x00008c74 <+1216>: ldr r2, [pc, #292] ; 0x8da0 <main+1516>
0x00008c78 <+1220>: ldr r3, [pc, #268] ; 0x8d8c <main+1496>
0x00008c7c <+1224>: bl 0x9ff0 <vgPlain_debugLog>
0x00008c80 <+1228>: ldr r8, [pc, #260] ; 0x8d8c <main+1496>
0x00008c84 <+1232>: b 0x8878 <main+196>
0x00008c88 <+1236>: ldr r0, [pc, #276] ; 0x8da4 <main+1520>
0x00008c8c <+1240>: bl 0x8234 <barf>
0x00008c90 <+1244>: mov r0, #0
0x00008c94 <+1248>: ldr r1, [pc, #180] ; 0x8d50 <main+1436>
0x00008c98 <+1252>: bl 0xa258 <vgPlain_debugLog_startup>
0x00008c9c <+1256>: mov r4, #0
0x00008ca0 <+1260>: b 0x8bac <main+1016>
0x00008ca4 <+1264>: ldr r0, [pc, #252] ; 0x8da8 <main+1524>
0x00008ca8 <+1268>: bl 0x8234 <barf>
0x00008cac <+1272>: ldr r0, [pc, #248] ; 0x8dac <main+1528>
0x00008cb0 <+1276>: bl 0x8234 <barf>
0x00008cb4 <+1280>: ldr r0, [pc, #244] ; 0x8db0 <main+1532>
0x00008cb8 <+1284>: ldr r1, [pc, #244] ; 0x8db4 <main+1536>
0x00008cbc <+1288>: movw r2, #463 ; 0x1cf
0x00008cc0 <+1292>: ldr r3, [pc, #240] ; 0x8db8 <main+1540>
0x00008cc4 <+1296>: bl 0xd5dc <__assert_fail>
0x00008cc8 <+1300>: ldr r3, [pc, #160] ; 0x8d70 <main+1468>
0x00008ccc <+1304>: ldr r1, [pc, #232] ; 0x8dbc <main+1544>
0x00008cd0 <+1308>: ldr r2, [r3]
0x00008cd4 <+1312>: mov r3, r10
0x00008cd8 <+1316>: str r8, [sp]
0x00008cdc <+1320>: bl 0x1b4e0 <sprintf>
0x00008ce0 <+1324>: mov r3, r4
0x00008ce4 <+1328>: mov r0, #1
0x00008ce8 <+1332>: ldr r1, [pc, #100] ; 0x8d54 <main+1440>
0x00008cec <+1336>: ldr r2, [pc, #204] ; 0x8dc0 <main+1548>
0x00008cf0 <+1340>: bl 0x9ff0 <vgPlain_debugLog>
0x00008cf4 <+1344>: mov r1, r11
0x00008cf8 <+1348>: mov r2, r6
0x00008cfc <+1352>: mov r0, r4
0x00008d00 <+1356>: bl 0x2ca60 <execve>
0x00008d04 <+1360>: ldr r3, [pc, #132] ; 0x8d90 <main+1500>
0x00008d08 <+1364>: ldr r4, [r3]
0x00008d0c <+1368>: bl 0xd5c0 <__errno_location>
0x00008d10 <+1372>: ldr r0, [r0]
0x00008d14 <+1376>: bl 0x29b60 <strerror>
0x00008d18 <+1380>: mov r2, r10
0x00008d1c <+1384>: mov r3, r8
0x00008d20 <+1388>: ldr r1, [pc, #156] ; 0x8dc4 <main+1552>
0x00008d24 <+1392>: str r0, [sp]
0x00008d28 <+1396>: mov r0, r4
0x00008d2c <+1400>: bl 0x1b4c0 <fprintf>
0x00008d30 <+1404>: mov r0, #1
0x00008d34 <+1408>: bl 0x12768 <exit>
0x00008d38 <+1412>: ldr r0, [pc, #136] ; 0x8dc8 <main+1556>
0x00008d3c <+1416>: ldr r1, [pc, #112] ; 0x8db4 <main+1536>
0x00008d40 <+1420>: movw r2, #438 ; 0x1b6
0x00008d44 <+1424>: ldr r3, [pc, #108] ; 0x8db8 <main+1540>
0x00008d48 <+1428>: bl 0xd5dc <__assert_fail>
0x00008d4c <+1432>: ; <UNDEFINED> instruction: 0x000672b4
0x00008d50 <+1436>: andeq r7, r6, r4, asr #5
0x00008d54 <+1440>: andeq r7, r6, r0, asr #2
0x00008d58 <+1444>: andeq r7, r6, r12, asr #5
0x00008d5c <+1448>: andeq r7, r6, r12, lsl #5
0x00008d60 <+1452>: andeq r7, r6, r0, lsr #7
0x00008d64 <+1456>: andeq r7, r6, r8, lsr r4
0x00008d68 <+1460>: andeq r8, r7, r0, asr #24
0x00008d6c <+1464>: muleq r6, r0, r4
0x00008d70 <+1468>: strdeq r4, [r8], -r0
0x00008d74 <+1472>: andeq r7, r6, r0, lsr #9
0x00008d78 <+1476>: ; <UNDEFINED> instruction: 0x000672b8
0x00008d7c <+1480>: ; <UNDEFINED> instruction: 0x000672bc
0x00008d80 <+1484>: andeq r7, r6, r4, ror #5
0x00008d84 <+1488>: andeq r7, r6, r4, lsl r3
0x00008d88 <+1492>: andeq r7, r6, r0, lsr #6
0x00008d8c <+1496>: andeq r7, r6, r8, lsl #4
0x00008d90 <+1500>: andeq r4, r8, r8, lsr #20
0x00008d94 <+1504>: ; <UNDEFINED> instruction: 0x000673b0
0x00008d98 <+1508>: andeq r7, r6, r8, ror #7
0x00008d9c <+1512>: andeq r9, r7, r8, lsl #29
0x00008da0 <+1516>: andeq r7, r6, r4, asr r3
0x00008da4 <+1520>: andeq r7, r6, r8, lsl #7
0x00008da8 <+1524>: andeq r7, r6, r12, asr #8
0x00008dac <+1528>: andeq r7, r6, r8, ror #8
0x00008db0 <+1532>: andeq r7, r6, r4, lsl #9
0x00008db4 <+1536>: muleq r6, r0, r1
0x00008db8 <+1540>: andeq r7, r6, r0, lsr r5
0x00008dbc <+1544>: ; <UNDEFINED> instruction: 0x000674bc
0x00008dc0 <+1548>: andeq r7, r6, r8, asr #9
0x00008dc4 <+1552>: ldrdeq r7, [r6], -r8
0x00008dc8 <+1556>: andeq r7, r6, r12, lsr #8
I'm working on a context switch in ARM v6 assembly. I posted about writing the switch in C, but assembly seems to be safer and more reliable. I've spent a while checking all the offsets and being careful not to delete data from registers, but the context switch just doesn't seem to work properly. I have set up and tested timer interrupts without switching context.
Here's my code:
interrupt_asm:
//store basic interrupt stuff
sub lr, lr, #4
//call the interrupt vector
push { r0-r12 }
mov r0, lr # Pass old pc
bl interrupt_vector # C function
pop { r0-r12 }
# save_current_thread:
//remember r1 so you can use it for r0
push {r1}
mov r1, r0 //store r0 so it can be restored
push {r2, r3}
bl get_current_thread //r0 now has the address of CURRENT_THREAD
pop {r2, r3}
add r0, r0, #4 // r0 = &CURRENT_THREAD.r0
str r1, [r0] // save what the r0 was
pop {r1} // restore r1
add r0, r0, #4 // r0 = &CURRENT_THREAD.r1
str r1, [r0] // save r1
//r2
add r0, r0, #4
str r2, [r0]
//r3
add r0, r0, #4
str r3, [r0]
//r4
add r0, r0, #4
str r4, [r0]
//r5
add r0, r0, #4
str r5, [r0]
//r6
add r0, r0, #4
str r6, [r0]
//r7
add r0, r0, #4
str r7, [r0]
//r8
add r0, r0, #4
str r8, [r0]
//r9
add r0, r0, #4
str r9, [r0]
//r10
add r0, r0, #4
str r10, [r0]
//r11
add r0, r0, #4
str r11, [r0]
//r12
add r0, r0, #4
str r12, [r0]
//store SVC sp, lr, and pc
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0x13
msr cpsr_c, r1
//sp
add r0, r0, #4
str sp, [r0]
//lr
add r0, r0, #4
str lr, [r0]
//back to IRQ land
mrs r1, cpsr
bic r1, r1, #0x1F
orr r1, r1, #0x12
msr cpsr_c, r1
//pc THIS NEEDS TO BE LR
add r0, r0, #4
str lr, [r0]
//cpsr
add r0, r0, #4
mrs r1, cpsr
str r1, [r0]
//spsr
add r0, r0, #4
mrs r1, spsr
str r1, [r0]
push {r2, r3}
bl increment_thread //r0 now has the address of our next thread
pop {r2, r3}
# restore_thread:
//were pushing in order, so from the bottom up our stack is: r0, ... r12, sp, lr, pc, spsr
add r0, r0, #4 //r0 = &CURRENT_THREAD.r0
ldr r1, [r0] //r1 = thread.r0
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r1
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r2
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r3
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r4
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r5
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r6
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r7
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r8
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r9
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r10
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r11
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.r12
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.sp
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.lr
push {r1}
add r0, r0, #4
ldr r1, [r0] //r1 = thread.pc
push {r1}
add r0, r0, #8 //skip cpsr - agreed
ldr r1, [r0] //r1 = thread.spsr
push {r1}
//Our stack now looks like spsr, pc, lr, sp, r12, ... r0 (in order of popping)
pop {r1} //this was the spsr - SPSR
pop {lr} //this was the pc - PC (from thread)
pop {r2} //this was the lr - LR (from thread)
pop {r3} //this was the sp - SP (from thread)
//switch to SVC
mrs r0, cpsr
bic r0, r0, #0x1F
orr r0, r0, #0x13
msr cpsr_c, r0
msr spsr, r1 //restore spsr
mov lr, r2 //restore lr to be old lr
mov sp, r3 //restore sp
//switch to IRQ
// mrs r0, cpsr
// bic r0, r0, #0x1F
// orr r0, r0, #0x12
// msr cpsr_c, r0
cps #0x12
//our stack now just has the normal registers in it. Restore them
pop {r12}
pop {r11}
pop {r10}
pop {r9}
pop {r8}
pop {r7}
pop {r6}
pop {r5}
pop {r4}
pop {r3}
pop {r2}
pop {r2}
pop {r1}
pop {r0}
push {lr}
ldm sp!, {pc}^
A thread looks like this:
typedef struct __attribute__((packed, aligned(8))) {
void (*run)();
unsigned r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12, sp, lr, pc;
unsigned cpsr, spsr;
unsigned id;
unsigned priority;
thread_status status;
wait_event wait_status;
} thread_t;
Do you have any advice about what's going on? An interrupt occurs and it never goes back to a new thread. I've debugged with GDB simulator but can't seem to nail down the issue.
The C function interrupt_vector just does this:
void interrupt_vector(unsigned pc) {
CURRENT_THREAD.pc = pc;
printf(" interrupt vector (pc = 0x%08x | thread.r0 = 0x%08x)\n", pc, CURRENT_THREAD.r0);
armtimer_clear_interrupt();
}
My other C functions are literally one line, and I've looked at their disassembly:
void increment_thread(){
// Not trying to actually increment yet
__asm__ volatile("mov r0, %0" : : "r" ((unsigned) &CURRENT_THREAD));
}
void get_current_thread(){
__asm__ volatile("mov r0, %0" : : "r" ((unsigned) &CURRENT_THREAD));
}