Very Late Assignments with LD

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.