BrianSidebotham/arm-tutorial-rpi

part-1 / armc-03 : _start defaulting to 0x8024 (small stack @ 0x8000)

rwdavis3rd opened this issue · 8 comments

Hi Brian,

Thanks for your great tutorials! I wanted to alert you to a problem I just encountered, in case others experience similar...

I was compiling (build.sh) and trying to run part-1 / armc-03 and watching for a blinking LED, with no joy. A clue as to the problem was coming out of the linker:

/arm-none-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000008024.

Using objdump to produce a disassembly listing, I found the linker was putting a small stack (space reservation) at 0x8000 and following that with the main() entry point. If I understand Pi booting correctly, that would have the CPU jumping into the stack instead of to main().

I've gotten relief by adding some linker directives: (file linker.ld)

MEMORY
{
    ram : ORIGIN = 0x8000, LENGTH = 20K
}

SECTIONS
{
    .text : { *(.text*) } > ram
    .note.gnu.build-id : { *(.text*) } > ram    
    .bss : { *(.bss*) } > ram
}

And adding this, via the -T option, to the executable build:

${toolchain}gcc ${cflags} ${scriptdir}/*.c -T linker.ld -o ${kernel_elf}

In short, I had to force the .text section (i.e. the main() program) to be at the top of the img. This (finally) yielded a satisfying blink. :-)

For what it matters: I'm cross-compiling for pi0 from Ubuntu 18.04 using ARM Corp's gnu

    armc-03$ arm-none-eabi-gcc --version
    arm-none-eabi-gcc (GCC) 8.2.0
    Copyright (C) 2018 Free Software Foundation, Inc.
    This is free software; see the source for copying conditions.  There is NO
    warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Cheers!

Correction (sorry): the section that claimed the 0x8000 address was .note.gnu.build-id

Disassembly of section .note.gnu.build-id:

00008000 <.note.gnu.build-id>:
    8000:	00000004 	andeq	r0, r0, r4
    8004:	00000014 	andeq	r0, r0, r4, lsl r0
    8008:	00000003 	andeq	r0, r0, r3
    800c:	00554e47 	subseq	r4, r5, r7, asr #28
    8010:	84449b50 	strbhi	r9, [r4], #-2896	; 0xfffff4b0
    8014:	f8943dd3 			; <UNDEFINED> instruction: 0xf8943dd3
    8018:	01710b24 	cmneq	r1, r4, lsr #22
    801c:	757cf378 	ldrbvc	pc, [ip, #-888]!	; 0xfffffc88	; <UNPREDICTABLE>
    8020:	14b38c85 	ldrtne	r8, [r3], #3205	; 0xc85

Disassembly of section .text:

00008024 <main>:
    8024:	e59f30c4 	ldr	r3, [pc, #196]	; 80f0 <main+0xcc>
    8028:	e59f20c4 	ldr	r2, [pc, #196]	; 80f4 <main+0xd0>

By the time I got to part-2 / arm-06, where the use of a user-supplied linker script is illustrated, I got relief from the problem above by moving the inclusion of the .note.gnu.build-id waay down to the bottom of the script. So the last few lines of the modified rpi.x file looks like:

  /* DWARF Extension.  */
  .debug_macro    0 : { *(.debug_macro) }
  .debug_addr     0 : { *(.debug_addr) }
  .ARM.attributes 0 : { KEEP (*(.ARM.attributes)) KEEP (*(.gnu.attributes)) }
  .note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
  /DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) }
  .note.gnu.build-id : { *(.note.gnu.build-id) } 
}

Hi @rwdavis3rd

Could you provide me some further information? A linker that defaults _start to 0x8024 is very unusual behaviour.

I just tested with the compiler that the tutorial is built on (using the compiler/get_compiler.sh script) and everything looks right for the tutorial:

[bjs@localhost armc-03]$ ./build.sh rpi0
.../compiler/gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi-gcc -g -nostartfiles -mfloat-abi=hard -O0 -DRPI0 -mfpu=vfp -march=armv6zk -mtune=arm1176jzf-s .../part-1/armc-03/*.c -o .../part-1/armc-03/kernel.armc-03.rpi0.elf
.../compiler/gcc-arm-none-eabi-7-2018-q2-update/bin/../lib/gcc/arm-none-eabi/7.3.1/../../../../arm-none-eabi/bin/ld: warning: cannot find entry symbol _start; defaulting to 0000000000008000
.../compiler/gcc-arm-none-eabi-7-2018-q2-update/bin/arm-none-eabi-objcopy .../part-1/armc-03/kernel.armc-03.rpi0.elf -O binary .../part-1/armc-03/kernel.armc-03.rpi0.img

Can you give the output of ./arm-none-eabi-gcc --version for the compiler you're using?

We should probably move the compiler forward for the tutorial at some point, 7 is a bit old these days.

I'm torn between responding now, with what I know, or waiting longer (too long?) to respond after more complete research. I'll share what I (think I) know at this point, and expand further, as I learn more.

First, I was not using the same compiler as you. I went and found a version titled arm-2008q3 (version 8.2.0) and installed that on my Linux box for use. After I ran into differences from your experience, however, I re-checked and found, due to unexpected $PATH ordering, that I was running a still-different version of ARM cross-compiler which Xilinx supplies as part of their MPSoC Ultrascale Plus SDK at SDK/2019.1/gnu/aarch32/lin/gcc-arm-none-eabi/bin/gcc-arm-none-gcc. This version also reports that it's version 8.2.0. But it acts different (?!)

I corrected paths, so I was back at the version titled arm-2008q3, and hit a new problem. When building (say) part-2/armc-09 the compiler 2008-q3 says "sorry, unimplemented: -mfloat-abi=hard and VFP" ... this later element likely requested via the "-mfpu=vfp" parameter on compiles.

Switching back to the Xilinx-supplied compiler, this error stops, but I get the section .note.gnu.build-id as the first section in my image, which pushes _start to 0x8024 (which therefore won't boot.) That's the problem that started this whole dialog. :-)

My on-going compromise has been to modify the rpi.x script found in one of your tutorials, to push section .note.gnu.build-id to the bottom of the image, and to specify its use by the linker thru the -Wl,T,${scriptdir}/rpi.x option, both in build.sh and in later rpi0 cmake files, and then to continue use of the Xilinx-distributed compiler, which supports hardware floating point and VFP simultaneously.

Here's the --version output from that compiler

armc-09$ `which arm-none-eabi-gcc` --version
arm-none-eabi-gcc (GCC) 8.2.0
Copyright (C) 2018 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Cheers!

OK - this tutorial uses a hardware floating point Application Binary Interface. The compiler you've picked up (arm-2008q3) doesn't support the hard floating point ABI. You can omit the ABI reference if you want, but you'll have to do that throughout the entire tutorial.

The best solution is the recommended approach - use the compiler/get_compiler.sh script in the tutorial to get the tutorial's recommended (and tested) toolchain. Things will get more and more painful for you otherwise. This will also ensure you don't have path issues anymore because the tutorial doesn't need to add this compiler to your path.

Thanks for turning your experienced eye towards this. I'll switch to the recommended compiler.

If / when you move forward from --version 7.x, beware the dreaded .note.gnu.build-id section! :-)

Cheers!

[ ps: My cheap-and-cheerful, bit-bang JTAG controller arrives this week. Want to share notes? ]

The 7.x series had got a bit long in the tooth.

I've setup Travis to now correctly at least build all tutorials for all raspberry pi versions (There were a few fixes committed because of that).

That enables us to more confidently move forward with testing new compilers.

I've created an issue ( #24 ) in order to look at moving the compiler forward.

@rwdavis3rd I've not been able to re-create this and the compiler has moved forward to 9.2+ with no issues so I'm going to close this issue.

If you experience it again or have any further info, please open the issue again. Thanks.