Embedding Resources in Executable Using Gcc

Embedding resources in executable using GCC

There are a couple possibilities:

  • use ld's capability to turn any file into an object (Embedding binary blobs using gcc mingw):

    ld -r -b binary -o binary.o foo.bar  # then link in binary.o
  • use a bin2c/bin2h utility to turn any file into an array of bytes (Embed image in code, without using resource section or external images)


Update: Here's a more complete example of how to use data bound into the executable using ld -r -b binary:

#include <stdio.h>

// a file named foo.bar with some example text is 'imported' into
// an object file using the following command:
//
// ld -r -b binary -o foo.bar.o foo.bar
//
// That creates an bject file named "foo.bar.o" with the following
// symbols:
//
// _binary_foo_bar_start
// _binary_foo_bar_end
// _binary_foo_bar_size
//
// Note that the symbols are addresses (so for example, to get the
// size value, you have to get the address of the _binary_foo_bar_size
// symbol).
//
// In my example, foo.bar is a simple text file, and this program will
// dump the contents of that file which has been linked in by specifying
// foo.bar.o as an object file input to the linker when the progrma is built

extern char _binary_foo_bar_start[];
extern char _binary_foo_bar_end[];

int main(void)
{
printf( "address of start: %p\n", &_binary_foo_bar_start);
printf( "address of end: %p\n", &_binary_foo_bar_end);

for (char* p = _binary_foo_bar_start; p != _binary_foo_bar_end; ++p) {
putchar( *p);
}

return 0;
}

Update 2 - Getting the resource size: I could not read the _binary_foo_bar_size correctly. At runtime, gdb shows me the right size of the text resource by using display (unsigned int)&_binary_foo_bar_size. But assigning this to a variable gave always a wrong value. I could solve this issue the following way:

unsigned int iSize =  (unsigned int)(&_binary_foo_bar_end - &_binary_foo_bar_start)

It is a workaround, but it works good and is not too ugly.

Embedding resources into executable using GCC on Arm?

I suppose I cannot reuse the same myv2.o?

You can't that; file is an ELF 64bit x86_64 ABI object file, you need it for your target architecture

Do I have to regenerate the file on Arm

no, there's no reason ld needs to run on an ARM machine,

using ld from an appropriate Arm toolchain?

exactly, just replace ld with your correctly targeting linker, e.g. arm-none-eabi-ld if this is for baremetal. Again, this is normal cross-development: no need to run on the target architecture, just build for the target architecture.

C/C++ with GCC: Statically add resource files to executable/library

With imagemagick:

convert file.png data.h

Gives something like:

/*
data.h (PNM).
*/
static unsigned char
MagickImage[] =
{
0x50, 0x36, 0x0A, 0x23, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x20,
0x77, 0x69, 0x74, 0x68, 0x20, 0x47, 0x49, 0x4D, 0x50, 0x0A, 0x32, 0x37,
0x37, 0x20, 0x31, 0x36, 0x32, 0x0A, 0x32, 0x35, 0x35, 0x0A, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,

....

For compatibility with other code you can then use either fmemopen to get a "regular" FILE * object, or alternatively std::stringstream to make an iostream. std::stringstream is not great for this though and you can of course just use a pointer anywhere you can use an iterator.

If you're using this with automake don't forget to set BUILT_SOURCES appropriately.

The nice thing about doing it this way is:

  1. You get text out, so it can be in version control and patches sensibly
  2. It is portable and well defined on every platform

Is there any standard way of embedding resources into Linux executable image?

Make yourself an assembler file, blob.S:

    .global blob
.global blob_size
.section .rodata
blob:
.incbin "blob.bin"
1:
blob_size:
.int 1b - blob

Compile with gcc -c blob.S -o blob.o
The blob can now be accessed from within your C program with:

extern uint8_t blob[];
extern int blob_size;

Using a bin2c converter usually works fine, but if the blob is large, the incbin solution is much faster, and uses much less memory (compile time)

Linux: update embedded resource from executable

Nothing special and nothing hard at all. I'll give you correct sequence below, but first let me to correct slightly your embedding method. Lets not use objcopy explicitly, lets use GNU LD instead to got correct entry inside ELF file.

Lets begin. This is test-emb.c file:

#include <stdio.h>

extern unsigned char data[] asm("_binary_data_txt_start");

int
main (void)
{
fprintf(stderr, "%u, %u, %u\n", data[0] - '0', data[1] - '0', data[2] - '0');
return 0;
}

This is resource called data.txt

12345678

This is another resource called newdata.txt

98765432

Now compile and link:

$ gcc test-emb.c -c -m32
$ gcc -o test-emb test-emb.o -Wl,--format=binary -Wl,data.txt -Wl,--format=default -m32

Try:

$ ./test-emb 
1, 2, 3

Now start dancing. Step one: determine logical and physical address of data section:

$ readelf -S test-emb | grep "\.data" | awk '{print $4}'
080496b8

$ readelf -S test-emb | grep "\.data" | awk '{print $5}'
0006b8

Step two: start and size fo binary data:

$ readelf -s test-emb | grep _binary_data_txt_start | awk '{print $2}'
080496c0

$readelf -s test-emb | grep _binary_data_txt_size | awk '{print $2}'
00000009

Step three: doing math. We do need: find offset of binary data in data, and convert it to physical starting point:

$ echo $((0x080496c0 - 0x080496b8))
8
echo $((0x0006b8 + 8))
1728

Step four: actual replacement (count value is binary data size, taht is 9):

cat newdata.txt | dd of=test-emb bs=1 seek=1728 count=9 conv=notrunc

Now check again:

$ ./test-emb 
9, 8, 7

Everything works. You may easily fold this method into script, not harder in use, that UpdateResource under Windows, but I want to give you understanding of how things are going on.

Embed resources (eg, shader code; images) into executable/library with CMake

One of the easiest ways to do this is to include a small, portable C program in your build that reads the resource and generates a C file that contains the length of the resource data and the actual resource data as an array of constant character literals. This will be entirely platform independent, but should only be used for resources that are reasonably small. For larger resources, you probably don't want to embed the files in your program.

For resource "foo", the generated C file "foo.c" would contain:

const char foo[] = { /* bytes of resource foo */ };
const size_t foo_len = sizeof(foo);

To access the resource from C++, you declare the following two symbols in either a header or the cpp file where they're used:

extern "C" const char foo[];
extern "C" const size_t foo_len;

To generate foo.c in the build, you need a target for the C program (call it embedfile.c), and you need to use the ADD_CUSTOM_COMMAND command to call this program:

add_executable(embedfile embedfile.c)

add_custom_command(
OUTPUT foo.c
COMMAND embedfile foo foo.rsrc
DEPENDS foo.rsrc)

Then, include foo.c on the source list of a target that requires the "foo" resource. You now have access to the bytes of "foo".

The program embedfile.c is:

#include <stdlib.h>
#include <stdio.h>

FILE* open_or_exit(const char* fname, const char* mode)
{
FILE* f = fopen(fname, mode);
if (f == NULL) {
perror(fname);
exit(EXIT_FAILURE);
}
return f;
}

int main(int argc, char** argv)
{
if (argc < 3) {
fprintf(stderr, "USAGE: %s {sym} {rsrc}\n\n"
" Creates {sym}.c from the contents of {rsrc}\n",
argv[0]);
return EXIT_FAILURE;
}

const char* sym = argv[1];
FILE* in = open_or_exit(argv[2], "r");

char symfile[256];
snprintf(symfile, sizeof(symfile), "%s.c", sym);

FILE* out = open_or_exit(symfile,"w");
fprintf(out, "#include <stdlib.h>\n");
fprintf(out, "const char %s[] = {\n", sym);

unsigned char buf[256];
size_t nread = 0;
size_t linecount = 0;
do {
nread = fread(buf, 1, sizeof(buf), in);
size_t i;
for (i=0; i < nread; i++) {
fprintf(out, "0x%02x, ", buf[i]);
if (++linecount == 10) { fprintf(out, "\n"); linecount = 0; }
}
} while (nread > 0);
if (linecount > 0) fprintf(out, "\n");
fprintf(out, "};\n");
fprintf(out, "const size_t %s_len = sizeof(%s);\n\n",sym,sym);

fclose(in);
fclose(out);

return EXIT_SUCCESS;
}

How to embed a file into an executable?

A portable way is to define a function like

typedef unsigned char Byte;

Byte const* pngFileData()
{
static Byte const data =
{
// Byte data generated by a helper program.
};
return data;
}

Then all you have to do is to write a little helper program that reads the PNG file as binary and generates the C++ curly braces initializer text. Edit: @awoodland has pointed out in comment to the question, that ImageMagick has such a little helper program…

Of course, for a Windows-specific program, instead use the ordinary Windows resource scheme.

Cheers & hth.,

Embedding binary blobs using gcc mingw

In your C program remove the leading underscore:

#include <stdlib.h>
#include <stdio.h>

extern char binary_input_txt_start[];

int main (int argc, char *argv[])
{
char *p;
p = binary_input_txt_start;

return 0;
}

C compilers often (always?) seem to prepend an underscore to extern names. I'm not entirely sure why that is - I assume that there's some truth to this wikipedia article's claim that

It was common practice for C compilers to prepend a leading underscore to all external scope program identifiers to avert clashes with contributions from runtime language support

But it strikes me that if underscores were prepended to all externs, then you're not really partitioning the namespace very much. Anyway, that's a question for another day, and the fact is that the underscores do get added.



Related Topics



Leave a reply



Submit