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:
- You get text out, so it can be in version control and patches sensibly
- 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
Std::Vector::Resize() Vs. Std::Vector::Reserve()
Variadic Template Pack Expansion
In C++ Books, Array Bound Must Be Constant Expression, But Why the Following Code Works
Difference Between Private and Protected Members of C++ Classes
Windows Threading: _Beginthread VS _Beginthreadex VS Createthread C++
Alternative to Itoa() For Converting Integer to String C++
How to Get Main Window Handle from Process Id
Regular Expression to Detect Semi-Colon Terminated C++ For & While Loops
What Does Casting to 'Void' Really Do
How to Use Cout ≪≪ Myclass
How to Terminate a Thread in C++11
Can Someone Explain This Template Code That Gives Me the Size of an Array
Does C++ Support 'Finally' Blocks? (And What's This 'Raii' I Keep Hearing About)
How to Call C++ Function from C
What Are the Differences Between C-Like, Constructor, and Uniform Initialization
Multithreading Program Stuck in Optimized Mode But Runs Normally in -O0