Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

It is quite easy to embed binary resources into PE images (EXE, DLL) via Windows API (refer to http://msdn.microsoft.com/en-us/library/ms648008(v=VS.85).aspx).

Is there any similar standard API in Linux?

or maybe some kind of de-facto approach to resource embedding?

The goal is to embed some static binary and/or textual data into executable, e.g. pictures, HTMLs, etc.. so that program binary distribution is as simple as making one file copy? (assuming all library dependencies are ok)

Update:

following bdk's suggestion, I've tried solution described in Embedding binary blobs using gcc mingw and it worked for me. Though, there were some issues that are worth mentioning: my project (in Code::Blocks) consists of a number of C++ files and adding binary data into any of corresponding object files rendered them useless breaking the build - objdump -x would show that most of the symbols have gone after embedding (and I didn't find how to fix it). To overcome this issue I added an empty dummy .cpp file into the project with the only purpose of providing an object file to play with and wrote the following custom build step for that file which did the job nicely (example uses Code::Blocks macros):

$compiler $options $includes -c $file -o $object
ld -Ur -b binary -o $object <binary payload path>
like image 267
Andrey Avatar asked Mar 29 '11 22:03

Andrey


4 Answers

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)

like image 132
Simon Edlund Avatar answered Nov 13 '22 13:11

Simon Edlund


objcopy --add-section allows you to add an arbitrary file as a section in an ELF executable. (objcopy man page). However this is only half a solution, as I have not yet found a way to access this data from inside a C Program other than by loading and parsing the ELF Binary using an ELF Library.

Edit Additional Information:

If you have a compiled program called MyProgram and a resource file MyResource.dat which you want embedded into MyProgram, you can use the objcopy command like this:

objcopy MyProgram --add-section MyResource=MyResource.dat

Now if you look at your program using the command objdump -x MyProgram

You will see a section called MyResource which contains the contents of MyResource.dat. The file is now embedded inside of your executable.

The trick now, is how do you access the data from inside your program. My instinct tells me that the loader should place the file into memory somewhere and you should be able to get a pointer to it, however I'm not sure how to do that simply. Ideally I'd want to be able to dlopen my exeutable and dlsym the section, but that doesn't work because its a section and not a symbol.

The only alternative I know of to access the section from inside the program is to use the libelf library or something similar which is a little like using a sledgehammer to tap in a nail. You can use it in your application to load itself as an ELF Resource and retrieve the sections. Documentation is sparse, but here's an example

http://em386.blogspot.com/2007/03/quick-libelf-guide.html

I'd love if someone could chime in with an easier way to access the data from --add-section.

Edit 2 In My research I encoutered this question: Embedding binary blobs using gcc mingw

Which should work for gcc as well as mingw and shows a way to use ld instead of objcopy to add the data and be able to access it as a symbol. Looks promising

like image 42
bdk Avatar answered Nov 13 '22 13:11

bdk


Sure. Try something like Bin2Hex converter. Convert the binary data into a C++ char array, and then embed it into your code as a constant variable.

like image 4
littleadv Avatar answered Nov 13 '22 14:11

littleadv


how about makeself

it will make a tar archive from a directory where all your program,resources files into an executable shell file. And when the user run the executable file, it will extract the files and run an arbitrary command (could be the program main executable). There's a drawback, that every time user launch the executable, it will takes time to load/extract the files first, before launching the real program.

like image 1
technomage Avatar answered Nov 13 '22 13:11

technomage