Discussion:
Including a binary file into an .elf file - ld expert around?
Christoph Kukulies
2021-05-30 14:40:27 UTC
Permalink
I’m linking an object file to a .elf binary for downloading into an STM32F407-DISC1 target. Normally I could flash the binary (.bin) file.
But when I want to debug it, .ELF format comes into the scene.

Normally the process of generating the .BIN is that it is linked. After linking a piece of data is appended to the binary.
Say, the symbol of that end is „endOfPrimitives“, then another block of - let’s call them „tokens“, is appended to the file.

Now my problem: how can I tell the linker (ld) to include these data (maybe via loader map ) into the .ELF result?

I’ve read there is INPUT as a loader map command. But I don’t know how to cope with it.


Thanks for helping.

—
Christoph
Tomasz CEDRO
2021-05-30 15:49:29 UTC
Permalink
I’m linking an object file to a .elf binary for downloading into an STM32F407-DISC1 target. Normally I could flash the binary (.bin) file.
But when I want to debug it, .ELF format comes into the scene.
I am working with ZEPHYR RTOS for MCU firmware development (I used ARM
MBED for some time but left it behind). You may find some hints over
there:

https://docs.zephyrproject.org/latest/guides/build/index.html

I am using gcc-arm-embedded package that contains all necessary tools
for compile, debug, link, etc. Then I am using pyOCD to flash and
debug firmware.

Usually build process results in HEX BIN MAP and ELF generation. Most
important is ELF because it can be loaded into arm-none-eabi-gdb in
order to debug firmware, also it can be easily converted to HEX.

You can convert ELF to HEX with:

% arm-none-eabi-objcopy -O ihex firmware.elf firmware.hex

Then you can flash it with:

% pyocd flash firmware.hex

You are now sure that ELF is in sync with HEX. pyOCD even allows you
to flash ELF directly :-)

In order to debug firmware you launch pyocd as debugserver on one console:

% pyocd gdb

Then you attach to it with gdb in remote mode:

% arm-none-eabi-gdb firmware.elf
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) break main
(gdb) c

You should jump into the breakpoint main() now. You can set a
breakpoint in any source file line with `break main.c:<line_number>`.
`arm-none-eabi-gdb -tui` comes handy with ncurses based window showing
you the source code directly.

arm-none-eabi-objdump and arm-none-eab-objcopy are part of binutils
and comes really handy in various binary files analysis and
conversion.


I am not sure if I understand your problem correctly - you want to add
some token into the resulting firmware binary after compilation as
part of device provisioning?

If you use Zephyr or any other RTOS that allows you to define Flash
Map as partitions you can simply create a partition for your
provisioning data:

https://docs.zephyrproject.org/latest/reference/storage/nvs/nvs.html

More generic approach would probably imply using linker map script in
order to create you own region (or .data or .bss) of some size located
at some address then fill that memory region with data or linking them
at build time. Also you would have to map that region to some sort of
const or dynamic data type that will be used in your firmware
application (i.e. use that token as char[] holding the token). When
you know where excatly the data will be located in the firmware image
(that also implies target device memory) you can also write over the
BIN file in that place as part of provisioning. With linker script you
can create area that will be always present at some specific address
(and you can assume anyone interested will also know the location).
You can also obtain address for each created binary and then fill that
part of memory / firmware image if you want its location to change
somehow between builds and make reverse-engineering a bit harder.

Another approach is to create a self-test-and-provision routine as
part of your firmware, using non-volatile-memory-storage to store
keys/tokens, also you would have a self-test to verify device
operations any time. You could run that routine on first device run
after production in order to both provision device with unique data
and obtain self-test results - process can be automated and results
can be stored in the device database. If you do not want this kind of
stuff to occupy your flash memory you can build such
self-test-and-provsion to run from RAM, inject it and launch with
pyOCD over JTAG/SWD, it will provision and test your device, but it
will disappear after power-off.

In any case if you provision your devices you may also want to think
of some sort of firmware checksum dedicated to each image after token
is placed inside :-)

https://wiki.osdev.org/Linker_Scripts
https://hydrasky.com/malware-analysis/elf-file-chapter-2-relocation-and-dynamic-linking/
https://stackoverflow.com/questions/1563760/aligning-static-arrays-in-the-bss-section-of-linker-file

Hope any of this helps :-)
Tomek
--
CeDeROM, SQ7MHZ, http://www.tomek.cedro.info
Loading...