скомпилировать картинку в линукс


Предыдущая | Следующая

скомпилировать картинку в линукс
https://stackoverflow.com/questions/5479691/is-there-any-standard-way-of-embedding-resources-into-linux-executable-image

 

25

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>
c++ linux embedded-resource
se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" style="margin: 0px; padding: 0px 4px 2px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 13px; vertical-align: baseline; box-sizing: inherit; color: rgb(132, 141, 149); text-decoration: none; cursor: pointer; display: inline-block;">shareimprove this question
edited May 23 '17 at 12:25
Community♦
111 silver badge
asked Mar 29 '11 at 22:27
 
  •  
    @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 Answers

activeoldestvotes
30

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)

se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" style="margin: 0px; padding: 0px 4px 2px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 13px; vertical-align: baseline; box-sizing: inherit; color: rgb(132, 141, 149); text-decoration: none; cursor: pointer; display: inline-block;">shareimprove this answer
answered May 21 '12 at 21:28
 
  •  
    Very nice method. Thank you. Any idea how portable this is across various platforms supported by GCC? – 0xC0000022L Jul 16 '12 at 16:08
  • 1
    It should be portable, this is the way the linux kernel uses to add a initramfs filesystem to an image. – Simon Edlund Jun 5 '13 at 19:20
  •  
    This should be the accepted answer. The one thing I would make more explicit is that a file named "blob.bin" should exist, and its contents are what is embedded. – Todd Freed Oct 4 '16 at 0:59
7

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

se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" style="margin: 0px; padding: 0px 4px 2px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 13px; vertical-align: baseline; box-sizing: inherit; color: rgb(132, 141, 149); text-decoration: none; cursor: pointer; display: inline-block;">shareimprove this answer
edited May 23 '17 at 12:10
Community♦
111 silver badge
answered Mar 29 '11 at 23:06
 
  •  
    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 
  • 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=<address> 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
    linuxjournal.com/content/… – Matt 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.

se-share-sheet#willShow s-popover:shown->se-share-sheet#didShow" style="margin: 0px; padding: 0px 4px 2px; border: 0px; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit; font-family: inherit; font-size: 13px; vertical-align: baseline; box-sizing: inherit; color: rgb(132, 141, 149); text-decoration: none; cursor: pointer; display: inline-block;">shareimprove this answer
answered Mar 29 '11 at 22:46
 
  •  
    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. 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
  • 1
    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.