Related
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.
I am doing work on an ARM Cortex-M microcontroller using the arm-none-eabi version of GCC. I am also using -fnostdlib and -fnostdin.
In my code I am using memcpy and strlen. Both of these functions are built-in functions as per the GCC manual. When I use these function as is or as __buitin_..., I get undefined reference to ....
Why is GCC not generating the code as expected?
builtins are not real functions. Compiler is free to replace them with the "normal" function call. ARM b as in this example:
void *m(void *a, void *b, size_t size)
{
return __builtin_memcpy(a,b,size);
}
void *m1(void *a, void *b)
{
return __builtin_memcpy(a,b,16);
}
void *m2(void *a, void *b)
{
return __builtin_memcpy(a,b,200);
}
volatile int a[1000],b[10000], c[1000];
int main(void)
{
m((void *)a,(void *)b,16);
__asm(":::m");
m((void *)a,(void *)c,400);
}
The resulting code will depend on the ARM architecture (if not aligned accesses are legal).
CORTEX-M4 CORTEX-M0
m: m:
b memcpy push {r4, lr}
m1: bl memcpy
push {r4, r5} pop {r4, pc}
ldr r5, [r1] # unaligned m1:
ldr r4, [r1, #4] # unaligned push {r4, lr}
ldr r2, [r1, #8] # unaligned movs r2, #16
ldr r1, [r1, #12] # unaligned bl memcpy
str r1, [r0, #12] # unaligned pop {r4, pc}
str r5, [r0] # unaligned m2:
str r4, [r0, #4] # unaligned push {r4, lr}
str r2, [r0, #8] # unaligned movs r2, #200
pop {r4, r5} bl memcpy
bx lr pop {r4, pc}
m2: main:
movs r2, #200 ldr r0, .L6
b memcpy push {r4, r5, r6, lr}
main: movs r2, r0
push {r4, lr} ldr r3, .L6+4
ldr r3, .L8 ldmia r3!, {r1, r4, r5}
ldr r4, .L8+4 stmia r2!, {r1, r4, r5}
ldm r3, {r0, r1, r2, r3} ldr r3, [r3]
stm r4, {r0, r1, r2, r3} str r3, [r2]
:::m :::m
mov r2, #400 movs r2, #200
mov r0, r4 ldr r1, .L6+8
ldr r1, .L8+8 lsls r2, r2, #1
bl memcpy bl memcpy
movs r0, #0 movs r0, #0
pop {r4, pc} pop {r4, r5, r6, pc}
.L8: .L6:
.word b .word a
.word a .word b
.word c .word c
https://godbolt.org/z/fh68cv
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));
}
This question already has an answer here:
Rustc/LLVM generates faulty code for aarch64 with opt-level=0
(1 answer)
Closed 7 years ago.
I'm trying to get a small ARM kernel up and running on QEMU (Versatile Express for Cortex-A15). Currently it simply sets sp to the top of a small stack and sends a single character to UART0.
_start.arm:
.set stack_size, 0x10000
.comm stack, stack_size
.global _start
_start:
ldr sp, =stack+stack_size
bl start
1:
b 1b
.size _start, . - _start
start.c:
/* UART_0 is a struct overlaid on 0x1c090000 */
void printChar(char c)
{
while (UART_0->flags & TRANSMIT_FULL);
UART_0->data = c;
}
void start()
{
while (UART_0->flags & TRANSMIT_FULL);
UART_0->data = 'A';
printChar('a');
}
From GDB, I know that execution progresses through _start into start and successfully sends 'A' to UART_0. printChar gets called and completes, but doesn't seem to print anything to the serial port . When running without GDB, the kernel repeatedly prints 'A', though I'm not sure if this is the processor resetting or jumping incorrectly.
From objdump:
Disassembly of section .stub:
00010000 <_start>:
10000: e59fd004 ldr sp, [pc, #4] ; 1000c <__STACK_SIZE+0xc>
10004: eb000016 bl 10064 <start>
10008: eafffffe b 10008 <_start+0x8>
1000c: 000200d0 .word 0x000200d0
Disassembly of section .text:
00010010 <printChar>:
10010: e52db004 push {fp} ; (str fp, [sp, #-4]!)
10014: e28db000 add fp, sp, #0
10018: e24dd00c sub sp, sp, #12
1001c: e1a03000 mov r3, r0
10020: e54b3005 strb r3, [fp, #-5]
10024: e1a00000 nop ; (mov r0, r0)
10028: e3a03000 mov r3, #0
1002c: e3413c09 movt r3, #7177 ; 0x1c09
10030: e1d331ba ldrh r3, [r3, #26]
10034: e6ff3073 uxth r3, r3
10038: e2033020 and r3, r3, #32
1003c: e3530000 cmp r3, #0
10040: 1afffff8 bne 10028 <printChar+0x18>
10044: e3a03000 mov r3, #0
10048: e3413c09 movt r3, #7177 ; 0x1c09
1004c: e55b2005 ldrb r2, [fp, #-5]
10050: e6ff2072 uxth r2, r2
10054: e1c320b2 strh r2, [r3, #2]
10058: e24bd000 sub sp, fp, #0
1005c: e49db004 pop {fp} ; (ldr fp, [sp], #4)
10060: e12fff1e bx lr
00010064 <start>:
10064: e52db008 str fp, [sp, #-8]!
10068: e58de004 str lr, [sp, #4]
1006c: e28db004 add fp, sp, #4
10070: e1a00000 nop ; (mov r0, r0)
10074: e3a03000 mov r3, #0
10078: e3413c09 movt r3, #7177 ; 0x1c09
1007c: e1d331ba ldrh r3, [r3, #26]
10080: e6ff3073 uxth r3, r3
10084: e2033020 and r3, r3, #32
10088: e3530000 cmp r3, #0
1008c: 1afffff8 bne 10074 <start+0x10>
10090: e3a03000 mov r3, #0
10094: e3413c09 movt r3, #7177 ; 0x1c09
10098: e5d32002 ldrb r2, [r3, #2]
1009c: e3a02000 mov r2, #0
100a0: e3822041 orr r2, r2, #65 ; 0x41
100a4: e5c32002 strb r2, [r3, #2]
100a8: e5d32003 ldrb r2, [r3, #3]
100ac: e3a02000 mov r2, #0
100b0: e5c32003 strb r2, [r3, #3]
100b4: e3a00061 mov r0, #97 ; 0x61
100b8: ebffffd4 bl 10010 <printChar>
100bc: e24bd004 sub sp, fp, #4
100c0: e59db000 ldr fp, [sp]
100c4: e28dd004 add sp, sp, #4
100c8: e49df004 pop {pc} ; (ldr pc, [sp], #4)
000100cc <UART_0>:
100cc: 1c090000 ....
I may have missed something, but I am not seeing where you have enabled interrupts, or poll to see if you can send the next character. If you have enabled the interrupts and set up the UART hardware correctly, your driver my have a bug. If you have not setup the UART hardware correctly, it may not be generating interrupts, or it may not be doing the FIFO correctly, or any number of other problems.