27

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>
Community
  • 1
  • 1
Andrey
  • 4,216
  • 1
  • 23
  • 31
  • @noloader He's asking about Linux, .exe is for Windows. You should pay more attention :) – sashoalm Jan 30 '14 at 14:45
  • @sashoalm - The linked question had nothing to do with Windows PE's. I changed the title of the linked question so that ".exe" -> "executable". That should clear it up for folks. – jww Jan 30 '14 at 15:46

4 Answers4

37

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)

Simon Edlund
  • 605
  • 6
  • 5
8

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

Community
  • 1
  • 1
bdk
  • 4,769
  • 29
  • 33
  • can you not add the section into a .o file and then create a relocation symbol. This should then allow linking from another C or C++ file – doron Mar 29 '11 at 23:12
  • this seems to be quite close to what I wanted, could you please elaborate a bit? and what `ELF library`, is it something guaranteed to be on modern Linux'es? maybe you can add some references? – Andrey Mar 29 '11 at 23:23
  • @Andrey- Sure, I've edited my answer to tell you as much as I know. – bdk Mar 29 '11 at 23:50
  • 1
    you rock! thanks a lot for going the extra mile by improving your answer and adding all those important details. Solution from your "Edit 2" worked for me. – Andrey Mar 30 '11 at 20:00
  • 1
    You can add the options `--set-section-flags MyResource=alloc,load --change-section-address MyResource=
    ` to the objcopy command to get the linker to load the MyResource section at a fixed address. Figuring out a reasonable address to use can be tricky.
    – Chris Dodd May 21 '12 at 21:46
  • 1
    http://www.linuxjournal.com/content/embedding-file-executable-aka-hello-world-version-5967 – hookenz Nov 10 '15 at 23:07
4

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.

littleadv
  • 20,100
  • 2
  • 36
  • 50
  • thanks for the link, I've seen this solution before (it was used to represent icons in Motif). But I don't like it - it introduces `perl` into my build process and, even worse, it brings some hexmare into the code. Still, it's a workaround, so +1 – Andrey Mar 29 '11 at 22:53
  • @Andrey, frankly, you can easily implement a script like that without `perl`, even using just `bash`, if you really want. Check it out [here](http://code.google.com/p/dsharingu/source/browse/trunk/work/bin2hex.sh). Re the hexmare - ignore it, as you would ignore the binary data file content. Just put it in a separate `.h` file, and add the script to your build process, and you're done. Basically that's what the MSVC does with their resources, as well. – littleadv Mar 29 '11 at 23:11
  • 2
    I use `xxd -i` for this. – Andrew Domaszek Sep 23 '14 at 23:46
1

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.

technomage
  • 525
  • 4
  • 14