Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I link a plain file into my executable? [duplicate]

Some frameworks (Qt, Windows, Gtk...) offer functionality to add resources to your binaries. I wonder if it would be possible to achieve this without the framework, since all that is really needed is

  1. a symbol to contain the resource's address within the binary (data segment)
  2. a symbol to represent the length of the resource
  3. the resource itself

How can this be achieved with the gcc toolchain?

like image 848
xtofl Avatar asked Dec 13 '12 09:12

xtofl


2 Answers

You could do this:

objcopy --input binary \
        --output elf32-i386 \
        --binary-architecture i386 my_file.xml myfile.o

This produces an object file that you can link into your executable. This file will contain these symbols that you'll have to declare in your C code to be able to use them

00000550 D _binary_my_file_xml_end
00000550 A _binary_my_file_xml_size 
00000000 D _binary_my_file_xml_start
like image 179
nos Avatar answered Nov 04 '22 02:11

nos


At its most basic, the equivalent is a char array full of bytes.

On Linux you can use xxd -i <file> to "compile" files into char arrays, then link the arrays into your binary and use the constituent bytes however you please.

Here's an example from my own code's makefile, that creates a "resource file" called templates.h containing a bunch of char arrays representing HTML templates:

templates.h:
    @echo "#ifndef REDACTED_TEMPLATES_H" > templates.h
    @echo "#define REDACTED_TEMPLATES_H" >> templates.h
    @echo "// Auto-generated file! Do not modify!" >> templates.h
    @echo "// NB: arrays are not null-terminated" >> templates.h
    @echo "// (anonymous namespace used to force internal linkage)" >> templates.h
    @echo "namespace {" >> templates.h
    @echo "namespace templates {" >> templates.h
    @cd templates;\
    for i in * ;\
    do \
        echo "Compiling $$i...";\
        xxd -i $$i | sed -e 's/ =/ __attribute__((unused)) =/' >> ../templates.h;\
    done;\
    cd ..
    @echo "}" >> templates.h
    @echo "}" >> templates.h
    @echo "#endif" >> templates.h

(see also: How best can I programmatically apply `__attribute__ ((unused))` to these auto-generated objects?)

The result looks a little like:

#ifndef REDACTED_TEMPLATES_H
#define REDACTED_TEMPLATES_H
// Auto-generated file! Do not modify!
// NB: arrays are not null-terminated
// (anonymous namespace used to force internal linkage)
namespace {
namespace templates {
unsigned char alert_email_finished_events_html[] __attribute__((unused)) = {
  0x3c, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73,
  0x3d, 0x22, 0x6e, 0x6f, 0x64, 0x65, 0x2d, 0x69, 0x6e, 0x66, 0x6f, 0x2d,
[..]
  0x7d, 0x7d, 0x0d, 0x0a, 0x3c, 0x2f, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x3e,
  0x0d, 0x0a
};
unsigned int alert_email_finished_events_html_len __attribute__((unused)) = 290;
unsigned char alert_email_finished_events_list_html[] __attribute__((unused)) = {
  0x3c, 0x74, 0x72, 0x20, 0x63, 0x6c, 0x61, 0x73, 0x73, 0x3d, 0x22, 0x73,
  0x65, 0x70, 0x61, 0x72, 0x61, 0x74, 0x65, 0x2d, 0x70, 0x72, 0x65, 0x76,
[..]
  0x73, 0x74, 0x7d, 0x7d, 0x0d, 0x0a
};
unsigned int alert_email_finished_events_list_html_len __attribute__((unused)) = 42;
}
}
#endif

Note that this particular example is optimal when using the resource in only one Translation Unit, but the general approach can be adapted to suit your needs.

like image 38
Lightness Races in Orbit Avatar answered Nov 04 '22 02:11

Lightness Races in Orbit