umanovskis / baremetal-arm

An ebook about bare-metal programming for ARM
Other
626 stars 130 forks source link

04_cenv: data abort bug #25

Closed qianfan-Zhao closed 5 months ago

qianfan-Zhao commented 1 year ago

Hi:

04_cenv example doesn't work on my qemu env, data abort bug happens, next is the u-boot logs:

## Booting kernel from Legacy Image at 60000000 ...
   Image Name:
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    502 Bytes = 502 Bytes
   Load Address: 60000000
   Entry Point:  60000000
   Verifying Checksum ... OK
   Loading Kernel Image ... OK

Starting kernel ...

data abort
pc : [<60000080>]          lr : [<7ff974f0>]
sp : 70003008  ip : 7fef5976     fp : 00000000
r10: 7fef6a6c  r9 : 7fef5ef8     r8 : 00000001
r7 : 00000000  r6 : 60000000     r5 : 7ffd85cc  r4 : 00000000
r3 : 7fef5fa8  r2 : 70000008     r1 : 70000000  r0 : 600001ee
Flags: Nzcv  IRQs on  FIQs on  Mode SVC_32
Code: e59f0050 e59f1050 e59f2050 e1510002 (b4903004)
Resetting CPU ...

resetting ...

Next is the asm code disassembly by objdump.

60000070:   e59f0050    ldr r0, [pc, #80]   ; 600000c8 <Abort_Exception+0x1c>
60000074:   e59f1050    ldr r1, [pc, #80]   ; 600000cc <Abort_Exception+0x20>
60000078:   e59f2050    ldr r2, [pc, #80]   ; 600000d0 <Abort_Exception+0x24>

6000007c <data_loop>:
6000007c:   e1510002    cmp r1, r2
60000080:   b4903004    ldrlt   r3, [r0], #4
60000084:   b4813004    strlt   r3, [r1], #4
60000088:   bafffffb    blt 6000007c <data_loop>
6000008c:   e3a00000    mov r0, #0
60000090:   e59f103c    ldr r1, [pc, #60]   ; 600000d4 <Abort_Exception+0x28>
60000094:   e59f203c    ldr r2, [pc, #60]   ; 600000d8 <Abort_Exception+0x2c>

...

600000c8:   600001ee    .word   0x600001ee
600000cc:   70000000    .word   0x70000000
600000d0:   70000008    .word   0x70000008

Seems data abort is trigger by unaligned memory access, _text_end is not an aligned address.

$ arm-none-eabi-objdump -t cenv.elf | grep text_end
600001ee g       .text  00000000 _text_end

Apply this patch to make sure text section aligned, this example can work fine again.

diff --git a/src/04_cenv/linkscript.ld b/src/04_cenv/linkscript.ld
index ab58e41..eb5f558 100644
--- a/src/04_cenv/linkscript.ld
+++ b/src/04_cenv/linkscript.ld
@@ -14,6 +14,7 @@ SECTIONS
         startup.o (.vector_table)
         *(.text*)
         *(.rodata*)
+        . = ALIGN(4);
      } > ROM
     _text_end = .;
     .data : AT(ADDR(.text) + SIZEOF(.text))

Now _text_end is an aligned address.

$  arm-none-eabi-objdump -t cenv.elf | grep text_end
600001f0 g       .text  00000000 _text_end
glazkinsergey commented 5 months ago

@qianfan-Zhao how you know? Explain please

qianfan-Zhao commented 5 months ago

u-boot report the register values when bug happens, you can read the PC value:

data abort
pc : [<60000080>]          lr : [<7ff974f0>]

disassembly the code in this location:

60000080:   b4903004    ldrlt   r3, [r0], #4

R0 is also printed by u-boot, it's value is r0 : 600001ee, that is not a aligned value.

jannes commented 2 months ago

@qianfan-Zhao could you guess why the symbol was apparently aligned for the author (the pdf shows it at 600001ea)? maybe the linker version implicitly aligned it? just very curious :)

qianfan-Zhao commented 2 months ago

@qianfan-Zhao could you guess why the symbol was apparently aligned for the author (the pdf shows it at 600001ea)? maybe the linker version implicitly aligned it? just very curious :)

I think it is a behavier of the gcc, this code is developed at many years ago and gcc also has many versions this years.