I'm using objcopy on bash (ubuntu linux) and im trying to copy 2 sections from an ELF file using the folowing commend:
objcopy -j .section1 -j .section2
The problem is the objcopy is adding some padding between the sections. Is there a way (a flag?) that can stop objcopy from padding the sections?
the sections are placed one after the other in the file so there is no need for any kind of padding....
Solved!
The problem was that the sections was one after the other but not at the same segmant.
One was in a W E segment and one was in a R W segmant.
And thats why objcopy messed up.
Related
I am new to linux programming and learning it from The Linux Programming Interface by Michael Kerrisk.
I have to compile my first program that has dependencies.
Directory structure:
--linux-programs
|--seek_io.c
|--lib
|--tlpi_hdr.h
|--error_functions.h
|--error_functions.c
|--get_num.h
|--ename.c.inc
I want to compile seek_io.c program with dependencies in the lib directory, so that I can see how the program works.
I tried a few things, absolutely clueless on how they work following this stackoverflow answer. I get all sorts of errors as I am an absolute beginner to Linux programming, not to programming, linux OS and C.
Trials:
gcc -I ./lib/ -c ./lib/error_functions.c and then gcc -o seek_io.c ./error_function.o gives error:
/usr/lib/gcc/x86_64-linux-gnu/crt1.o: In function _start:
(.text+0x20): undefined reference to main
collect2: error: ld returned 1 exit status
After this run, on ls I find that my seek_io.c is not listed.
Basically the author of the book says for tlpi_hdr.h file:
This header file includes various other header files used by many of the example programs, defines a Boolean data type, and defines macros for calculating the minimum and maximum of two numeric values. Using this header file allows us to make the example programs a bit shorter.
Link to codes for files mentioned above:
tlpi_hdr.h
error_functions.h
error_functions.c
get_num.h
get_num.c
seek_io.c
The problem is with your second gcc command, where you're using the -o file to specify the output file where to store the resulting executable file, but passing it the name of the C source file seek_io.c instead...
gcc -o seek_io.c ./error_function.o
This means link file error_function.o and store the executable in seek_io.c. This fails because there is no main function, which is needed for a standalone executable, so your C source file is not overwritten by the failing link command.
You can fix this easily by passing the -o option a proper output file name, which in the case (of this link command) should be the name of the executable that you want to create, such as seek_io:
gcc -o seek_io seek_io.c ./error_function.o
(But this will fail without a -I ./lib/, since seek_io.c includes tlpi_hdr.h which is in that directory. If you add it to that command, it should work.)
You can also decide to split the compile and link steps in two separate steps (the command above will both compile seek_io.c into an object file and then link the two object files into an executable) with:
$ gcc -I ./lib/ -c ./lib/error_functions.c
$ gcc -I ./lib/ -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
One final nitpick is that for the -I flag to specify the directories where to search for the include files, the more common usage has no space between the flag itself and the directory name, so you'll most commonly see -I./lib or even -Ilib.
$ gcc -Ilib -c ./lib/error_functions.c
$ gcc -Ilib -c seek_io.c
$ gcc -o seek_io seek_io.o error_function.o
As an example the following will set RUNPATH
matthewh#ORAC:~/dev/test$ g++ test.cpp -ldl -Wl,-rpath,\$ORIGIN
matthewh#ORAC:~/dev/test$ objdump -x a.out | grep RUN
RUNPATH $ORIGIN
However, as a more complex example I'm trying to set this for a library that is compiled with a makefile generated with configure.
I run
export LDFLAGS=-Wl,-rpath,\$ORIGIN
./configure
make
objdump -x library.so | grep RUN
RUNPATH RIGIN
Obviously Make is expanding $O instead of putting a literal $O in the output.
How do I overcome this? I've tried escaping it but it's presenting strange output into runpath.
Ok, Specifically I'm attempting to compile ilmbase-2.2.1 from OpenEXR and set the RUNPATH. It's more complicated than a single Makefile as it's using recursive Make!
The top level Makefile ends up setting the variable LDFLAGS=
I've tried manually editing that to be $$ORIGIN as suggested in other places but still, it comes through as -Wl,-rpath,RIGIN
Now I'm a bit stuck. Short of editing it after the path is set by rewriting it with some kind of ELF editor which is ugly.
Oh wow. This seems to work.
./configure LDFLAGS='-Wl,-rpath,\$$ORIGIN'
The magic \$$ vs just $$
What's the backslash mean in gnu make then?
I am very very new to this, I have elf file input.out and need to create hex executable from it. I am using objcopy to create executable in intel hex format as follows
objcopy -O ihex input.out out.hex
by this out.hex contains data from all sections (.interp, .note.ABI-tag etc), but i am not sure if all of it is required for executable. Is just .text section enough for creating executable hex so can i just use as below or any more sections are required
objcopy -j.text -O ihex input.out out.hex
Also if there any good reference to understand this in detail, I couldn't find much by Goggling. Probably I don't know what to search.
It could work with
objcopy -O ihex input.elf output.hex
Add the -S will strip useless sections.
I mean whether gcc can insert some source code version infor into ELF binary as section or something similar. I do not want to change my source file, but add some info with gcc option in Makefile.
If you don't mind changing your source file just once, add something like this:
const volatile static char version[] = VERSION;
and compile with:
gcc -c -DVERSION='"1.2.3"'
The volatile keeps gcc from removing the string at higher optimization levels.
As written, this won't compile if you forget the -D option, which may be either good or bad depending on your requirements.
You can emit your version info into a text file, then turn that text file into an object file which you then statically link into your executable.
The first step is simple but you have to write some code: a script or something to write your version info in any format you like as a plain text file. Then write a makefile rule to produce say version.o from version.txt, using objcopy. Now you'll have an object file with two useful symbols defined in it: the beginning and end of the textual version info. Add that generated object to your executable, and you'll be able to access the version two ways: by running strings on the binary, or by writing code in the application to print the version string (you'll need to declare the start and end symbols as variables in some header file).
Even if you don't have access to your source anymore, you can link the object with this option:
gcc -Wl,--defsym,VERSION_1_2_3=0 prog.o -o prog
You can check it with hexdump -C prog | less and look for VERSION
Add this to your makefile and be sure to always know when a program was compiled:
BUILD = $(shell date +"%Y%m%d_%H%M%S")
LDLIBS = -Wl,--defsym,BUILD_$(BUILD)=0
With the GNU linker ld You can use
--version-script=version-scriptfile
Read more about the command-line options at:
Using LD, the GNU linker - Options
Read more about creating version scripts at:
Using LD, the GNU linker - Version Script
Let me warn you though, that it is not for the weak-hearted!
What's the best tool for converting PE binaries to ELF binaries?
Following is a brief motivation for this question:
Suppose I have a simple C program.
I compiled it using gcc for linux(this gives ELF), and using 'i586-mingw32msvc-gcc' for Windows(this gives a PE binary).
I want to analyze these two binaries for similarities, using Bitblaze's static analysis tool - vine(http://bitblaze.cs.berkeley.edu/vine.html)
Now vine doesn't have a good support for PE binaries, so I wanted to convert PE->ELF, and then carry on with my comparison/analysis.
Since all the analysis has to run on Linux, I would prefer a utility/tool that runs on Linux.
Thanks
It is possible to rebuild an EXE as an ELF binary, but the resulting binary will segfault very soon after loading, due to the missing operating system.
Here's one method of doing it.
Summary
Dump the section headers of the EXE file.
Extract the raw section data from the EXE.
Encapsulate the raw section data in GNU linker script snippets.
Write a linker script to build an ELF binary, including those scripts from the previous step.
Run ld with the linker script to produce the ELF file.
Run the new program, and watch it segfault as it's not running on Windows (and it tries to call functions in the Import Address Table, which doesn't exist).
Detailed Example
Dump the section headers of the EXE file. I'm using objdump from the mingw cross compiler package to do this.
$ i686-pc-mingw32-objdump -h trek.exe
trek.exe: file format pei-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 AUTO 00172600 00401000 00401000 00000400 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .idata 00001400 00574000 00574000 00172a00 2**2
CONTENTS, ALLOC, LOAD, DATA
2 DGROUP 0002b600 00576000 00576000 00173e00 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .bss 000e7800 005a2000 005a2000 00000000 2**2
ALLOC
4 .reloc 00013000 0068a000 0068a000 0019f400 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .rsrc 00000a00 0069d000 0069d000 001b2400 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
Use dd (or a hex editor) to extract the raw section data from the EXE. Here, I'm just going to copy the code and data sections (named AUTO and DGROUP in this example). You may want to copy additional sections though.
$ dd bs=512 skip=2 count=2963 if=trek.exe of=code.bin
$ dd bs=512 skip=2975 count=347 if=trek.exe of=data.bin
Note, I've converted the file offsets and section sizes from hex to decimal to use as skip and count, but I'm using a block size of 512 bytes in dd to speed up the process (example: 0x0400 = 1024 bytes = 2 blocks # 512 bytes).
Encapsulate the raw section data in GNU ld linker scripts snippets (using the BYTE directive). This will be used to populate the sections.
cat code.bin | hexdump -v -e '"BYTE(0x" 1/1 "%02X" ")\n"' >code.ld
cat data.bin | hexdump -v -e '"BYTE(0x" 1/1 "%02X" ")\n"' >data.ld
Write a linker script to build an ELF binary, including those scripts from the previous step. Note I've also set aside space for the uninitialized data (.bss) section.
start = 0x516DE8;
ENTRY(start)
OUTPUT_FORMAT("elf32-i386")
SECTIONS {
.text 0x401000 :
{
INCLUDE "code.ld";
}
.data 0x576000 :
{
INCLUDE "data.ld";
}
.bss 0x5A2000 :
{
. = . + 0x0E7800;
}
}
Run the linker script with GNU ld to produce the ELF file. Note I have to use an emulation mode elf_i386 since I'm using 64-bit Linux, otherwise a 64-bit ELF would be produced.
$ ld -o elf_trek -m elf_i386 elf_trek.ld
ld: warning: elf_trek.ld contains output sections; did you forget -T?
$ file elf_trek
elf_trek: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV),
statically linked, not stripped
Run the new program, and watch it segfault as it's not running on Windows.
$ gdb elf_trek
(gdb) run
Starting program: /home/quasar/src/games/botf/elf_trek
Program received signal SIGSEGV, Segmentation fault.
0x0051d8e6 in ?? ()
(gdb) bt
\#0 0x0051d8e6 in ?? ()
\#1 0x00000000 in ?? ()
(gdb) x/i $eip
=> 0x51d8e6: sub (%edx),%eax
(gdb) quit
IDA Pro output for that location:
0051D8DB ; size_t stackavail(void)
0051D8DB proc stackavail near
0051D8DB push edx
0051D8DC call [ds:off_5A0588]
0051D8E2 mov edx, eax
0051D8E4 mov eax, esp
0051D8E6 sub eax, [edx]
0051D8E8 pop edx
0051D8E9 retn
0051D8E9 endp stackavail
For porting binaries to Linux, this is kind of pointless, given the Wine project.
For situations like the OP's, it may be appropriate.
I've found a simpler way to do this. Use the strip command.
Example
strip -O elf32-i386 -o myprogram.elf myprogram.exe
The -O elf32-i386 has it write out the file in that format.
To see supported formats run
strip --info
I am using the strip command from mxe, which on my system is actually named /opt/mxe/usr/bin/i686-w64-mingw32.static-strip.
I don't know whether this totally fits your needs, but is it an option for you to cross-compile with your MinGW version of gcc?
I mean do say: does it suit your needs to have i586-mingw32msvc-gcc compile direct to ELF format binaries (instead of the PEs you're currently getting). A description of how to do things in the other direction can be found here - I imagine it will be a little hacky but entirely possible to make this work for you in the other direction (I must admit I haven't tried it).