I want to link in raw binary data. I'd like to either put it at a particular address, or have it link to a symbol (char* mydata, for instance) I have defined in code. Since it's not an obj file, I can't simply link it in.
A similar post (Include binary file with GNU ld linker script) suggests using objcopy with the -B bfdarch
option. objcopy responds with "archictecture bfdarch unknown".
Yet another answer suggests transforming the object into a custom LD script and then include that from the main LD script. At this point, I may as well just be using a C include file (which is what I am doing Now) so I'd rather not do that.
Can I use objcopy to accomplish this, or is there another way?
The following example works for me:
$ dd if=/dev/urandom of=binblob bs=1024k count=1
$ objcopy -I binary -O elf32-little binblob binblob.o
$ file binblob.o
binblob.o: ELF 32-bit LSB relocatable, no machine, version 1 (SYSV), not stripped
$ nm -S -t d binblob.o
0000000001048576 D _binary_binblob_end
0000000001048576 A _binary_binblob_size
0000000000000000 D _binary_binblob_start
I.e. no need to specify the BFD arch for binary data (it's only useful / necessary for code). Just say "the input is binary", and "the output is ...", and it'll create you the file. Since pure binary data isn't architecture-specific, all you need to tell it is whether the output is 32bit (elf32-...
) or 64bit (elf64-...
), and whether it's little endian / LSB (...-little
, as on ARM/x86) or big endian / MSB (...-big
, as e.g. on SPARC/m68k).
Edit:
Clarification on the options for objcopy
:
- the usage of the
-O ...
option controls:- bit width (whether the ELF file will be 32-bit or 64-bit)
- endianness (whether the ELF file will be LSB or MSB)
- the usage of the
-B ...
option controls the architecture the ELF file will request
You have to specifiy the -O ...
but the -B ...
is optional. The difference is best illustrated by a little example:
$ objcopy -I binary -O elf64-x86-64 foobar foobar.o $ file foobar.o foobar.o: ELF 64-bit LSB relocatable, no machine, version 1 (SYSV), not stripped $ objcopy -I binary -O elf64-x86-64 -B i386 foobar foobar.o $ file foobar.o foobar.o: ELF 64-bit LSB relocatable, AMD x86-64, version 1 (SYSV), not stripped
I.e. just the output format specifier elf64-x86-64
doesn't tie the generated binary to a specific architecture (that's why file
says no machine
). The usage if -B i386
does so - and in that case, you're told this is now AMD x86-64
.
The same would apply to ARM; -O elf32-little
vs. -O elf32-littlearm -B arm
is that in the former case, you end up with a ELF 32-bit LSB relocatable, no machine, ...
while in the latter, it'll be an ELF 32-bit LSB relocatable, ARM...
.
There's some interdependency here as well; you have to use -O elf{32|64}-<arch>
(not the generic elf{32|64}-{little|big}
) output option to be able to make -B ...
recognized.
See objcopy --info
for the list of ELF formats / BFD types that your binutils can deal with.
Another approach might be to use xxd.
xxd -i your_data your_data.c
In the file you'll get two symbols unsigned char your_data[]
and unsigned int your_data_len
. First one will be a huge array containing your data, second one will be the lenght of that array.
Compilation of created C file might be time taking, so if you are using a build system / Makefile handle it properly avoiding unnecessary recompilations.
xxd
should be part of vim
(vim-common
) package for your Linux distribution.
A quick way to do it would be to put the data in its own .c file (.c not .h) so that it becomes a .o by itself then in the linker script you can define a specific memory space and section entry for that .o file and put it wherever you want.
MEMORY
{
...
BOB : ORIGIN = 0x123400, length = 0x200
...
}
SECTIONS
{
...
TED : { mydata.o } > BOB
...
}
来源:https://stackoverflow.com/questions/17265950/linking-arbitrary-data-using-gcc-arm-toolchain