The other day I found a really slick way of adding arbitrary data to an .o (object) file with ‘ld’. It is probably easiest to show the setup, then explain it.
test.data
Hello, World
extra.h
extern const char _binary_test_data_start[];
extern const char _binary_test_data_end[];
extra.c
#include "extra.h"
/* this C file when compiled to an object will include the data found in test.data */
main.c
#include "extra.h"
void print_str(const char *ptr, int length);
int main()
{
int size = _binary_test_data_end - _binary_test_data_start;
print_str(_binary_test_data_start, size);
return 0;
}
Compilation Steps
# gcc extra.c -c
# ld -b binary -r -o extra.o test.data
# gcc extra.o main.c -o out
note: print_str prints character by character to a specified length
note2: _binary_test_data_size is exported, but I haven’t been able to figure out how to use it yet.
LD creates a new ELF segment within the extra.o object file. readelf and objdump will give quite a bit of useful information regarding the segments that will eventually get linked into the executable
# objdump -t extra.o
extra.o: file format elf32-i386 SYMBOL TABLE: 00000000 l d .data 00000000 00000000 l d *ABS* 00000000 00000000 l d *ABS* 00000000 00000000 l d *ABS* 00000000 0000000c g .data 00000000 _binary_test_data_end 0000000c g *ABS* 00000000 _binary_test_data_size 00000000 g .data 00000000 _binary_test_data_start
The start of the test.data file will be located in the variable ‘_binary_test_data_start’ and similary the end will be ‘_binary_test_data_end’.
This might be useful for embedding cryptographic signatures, or maybe game data files.
_binary_test_data_size is an absolute symbol, and can be accessed with declarations like the following (not portable, as it converts pointer to int):
extern void _binary_test_data_size;
printf(“Size %ldn”,(unsigned long)&_binary_test_data_size);
I’m sure someone more familiar with GCC and GNU binutils can get you a better way to extract the value 🙂
Thanks Simon for that tip.