Andrew Egeler
Learning how things work.

I Compiled Static Data Files Into My Final Binary

TL;DR: Why find and load data files at runtime, when you could be building them directly into the final executable and have the the OS automatically mmap them?

Lets say I'm writing a small application, and this application needs a couple of read-only static data or resource files. I could write some code to install the resource files into an appropriate location, find them when the program starts, and then read the files in at runtime. However, if I'm writing it in a language that uses ld to create the final executable binary, I can just build the static files directly into the resulting executable and just use them as read-only memory buffers.

There are a couple of different ways to do this - I'm going to use the assembler approach, as it's efficient and lets me easily define my own symbol names.

Assuming I have a resource.dat file that I want to include and use in my program, I can write a small static.s assembly file which will compile to an object file containing the resource file and symbols pointing to it:

    .section .rodata

    .global dat_resource
    .type   dat_resource, @object
    .align  4
    .incbin "resource.dat"
    .global dat_resource_size
    .type   dat_resource_size, @object
    .align  4
    .int    dat_resource_end - dat_resource

Once compiled (with gcc -c static.s for example), it will simply be a .o file that can be linked into the final executable.

To use this data, you can simply reference the symbols from the object file. In C++, it looks like this (note the extern "C" - the symbols in static.s have C linkage and don't go through the C++ name mangling process):

extern "C" {
    extern char const dat_resource[];
    extern unsigned const dat_resource_size;

With those declarations in scope, you can use dat_resource as a pre-populated memory buffer containing the data from resource.dat - and you didn't have to do any runtime work or write any file handling code to do it.