I have installed all cross compile packages on my ubuntu system so far but am having a problem and need some help.
Linux 2.6.28.7 #1 CST 2012 armv5tejl unknown
$ cat /proc/cpuinfo
Processor : ARM926EJ-S rev 5 (v5l)
BogoMIPS : 199.47
Features : swp half fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 5
Hardware : ServerEngines PILOT3
Revision : 0000
Serial : 0000000000000000
user#ubuntu:~/code$ arm-linux-gnueabi-readelf -h xxx.bin
ELF Header:
Magic: 7f 45 4c 46 01 01 01 61 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: ARM
ABI Version: 0
Type: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xa27c
Start of program headers: 52 (bytes into file)
Start of section headers: 128752 (bytes into file)
Flags: 0x2, GNU EABI, <unknown>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 25
Section header string table index: 24
This is the target machine I need to cross compile for. What flags should I use when compiling?
arm-linux-gnueabi-gcc simple.c -march=armv5 -static -o simplev5
arm-linux-gnueabi-gcc simple.c -mcpu=arm926ej-s -static -o simple926
when I run the simplev5 or simple926, show:
Segmentation fault
follow #Steven P advice, I checked the file format, as follows:
user#ubuntu:~/code$ file simplev5
simplev5: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=f0607da1d809a7d98636d76ee0e538fc828e3b65, not stripped
user#ubuntu:~/code$ file simple926
simple926: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=ed1e6fdade02c0d2c985a503dafb6efadd13522f, not stripped
You most likely have the right compilation or you would get an error about Invalid Format. You can confirm you have the proper file format by using:
file simple926
Try a simpler program:
int main() { return 123; }
Then you can check the result code when you run it to confirm it did something.
./simple926
echo $?
To solve your segmentation fault, you probably need to get out gdb and examine the stack (backtrace).
Related
I have cross-compiled the paho.mqtt.c to the so file and copy them to my lib directory in the workspace. I use the nm and readelf to check it, nothing goes wrong. But I can't use make to compile the sample client.c
$ readelf -h libpaho-mqtt3c.so
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: ARM
Version: 0x1
Entry point address: 0x2a50
Start of program headers: 52 (bytes into file)
Start of section headers: 168104 (bytes into file)
Flags: 0x5000202, Version5 EABI, soft-float ABI, <unknown>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 4
Size of section headers: 40 (bytes)
Number of section headers: 31
Section header string table index: 28
$ nm libpaho-mqtt3c.so
00004c44 t MQTTClient_cleanSession
00004acc t MQTTClient_closeSession
000061d0 T MQTTClient_connect
00006234 T MQTTClient_connect5
000062e4 t MQTTClient_connectAll
000058c0 t MQTTClient_connectURI
0000503c t MQTTClient_connectURIVersion
000033b4 T MQTTClient_create
00002db8 T MQTTClient_createWithOptions
000086a0 t MQTTClient_cycle
00003aac t MQTTClient_deliverMessage
00003608 T MQTTClient_destroy
00006be8 T MQTTClient_disconnect
$ make
[ 50%] Linking C executable ../bin/pub
arm-openwrt-linux-uclibcgnueabi-gcc: warning: environment variable 'STAGING_DIR' not defined
arm-openwrt-linux-uclibcgnueabi-gcc: warning: environment variable 'STAGING_DIR' not defined
CMakeFiles/pub.dir/src/pub.c.o: In function `main':
pub.c:(.text+0x78): undefined reference to `MQTTClient_create'
pub.c:(.text+0x9c): undefined reference to `MQTTClient_connect'
pub.c:(.text+0x100): undefined reference to `MQTTClient_publishMessage'
pub.c:(.text+0x140): undefined reference to `MQTTClient_waitForCompletion'
pub.c:(.text+0x168): undefined reference to `MQTTClient_disconnect'
pub.c:(.text+0x174): undefined reference to `MQTTClient_destroy'
collect2: error: ld returned 1 exit status
make[2]: *** [CMakeFiles/pub.dir/build.make:85: ../bin/pub] Error 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/pub.dir/all] Error 2
make: *** [Makefile:84: all] Error 2
here's my CMakeLists
cmake_minimum_required(VERSION 3.16)
project(CPE LANGUAGES C)
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_C_COMPILER ${PROJECT_SOURCE_DIR}/toolchain/bin/arm-openwrt-linux-uclibcgnueabi-gcc)
set(CMAKE_CXX_COMPILER ${PROJECT_SOURCE_DIR}/toolchain/bin/arm-openwrt-linux-uclibcgnueabi-g++)
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)
include_directories(${PROJECT_SOURCE_DIR}/include)
# aux_source_directory(./src SRC_LIST)
set(SRC_LIST ${PROJECT_SOURCE_DIR}/src/pub.c)
find_library(LIB ${PROJECT_SOURCE_DIR}/lib)
add_executable(pub ${SRC_LIST})
target_link_libraries(pub ${LIB})
- find_library(LIB ${PROJECT_SOURCE_DIR}/lib)
+ find_library(LIB paho-mqtt3c ${PROJECT_SOURCE_DIR}/lib)
Given only access to a standalone ELF program I want to be able to call a function within the program from my own program.
Let's say the below code is main.c
#include <stdio.h>
extern int mystery(int a,int b);
int main() {
int a = 0;
int b = 1;
printf("mystery(a,b) = %d\n",mystery(a,b));
return 0;
}
The function mystery exists in some elf file not_my_program.
What I'm trying to do is something along the lines of
gcc main.c not_my_program
However this gives me an undefined reference error to mystery . I've looked for methods
on forums and found that converting this elf file into a shared object file is not possible. I've also looked into compiling main.c into a relocatable object file with
gcc -c main.c
and then using ld to link the elf with main.o but I could not figure out how to do it. The elf is 32 bit but I've omitted the -m32 flag. If the flag is different for ld please let me know. Any help would be very much appreciated.
edit:
output of readelf -h not_my_program
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Shared object file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x10e0
Start of program headers: 52 (bytes into file)
Start of section headers: 15116 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 11
Size of section headers: 40 (bytes)
Number of section headers: 30
Section header string table index: 29
This hacky way worked with a very simple case.
[ aquila ~ ] $ cat 1.c
int func (int a) { return a * (a-1) ; }
int main(int argc) { return func (argc) ; }
[ aquila ~ ] $ cc 1.c
[ aquila ~ ] $ ./a.out ; echo $?
0
[ aquila ~ ] $ readelf -s a.out | grep func
43: 0000000000400487 19 FUNC GLOBAL DEFAULT 11 func
[ aquila ~ ] $ cat 2.c
#include <stdlib.h>
static __attribute__((constructor)) void main() {
int (*func)() = (int (*)())0x0000000000400487;
exit(func(3));
}
[ aquila ~ ] $ cc -fPIC -shared 2.c -o a.so
[ aquila ~ ] $ LD_PRELOAD=./a.so ./a.out ; echo $?
6
The caller in 2.c is made into a constructor with an exit so that the main program's main() is not called, in an attempt to limit the execution of the code other than the caller and func() itself. The return value being 6 instead of 0 shows both that the call worked and that the main program's main() did not get called.
Given only access to a standalone ELF program I want to be able to call a function within the program from my own program
It sounds like you have an XY problem.
While what you desire is technically possible, the difficulty of doing this is approximately 1000x of what you have tried so far. If you are not prepared to spend a month or two getting this working, you should look for other solutions.
Effectively you would have to write a custom ELF loader to load not_my_program into memory and initialize it, but then call mystery instead of main in it.
Note also that mystery may depend on global data, and that data may be initialized in main, so there is no guarantee that mystery will work at all when called before main.
P.S. Would it be sufficient to call mystery from a debugger? That can be achieved in under 30 seconds.
For some reason I made simple program in C to output binary representation of given input:
int main()
{
char c;
while(read(0,&c,1) > 0)
{
unsigned char cmp = 128;
while(cmp)
{
if(c & cmp)
write(1,"1",1);
else
write(1,"0",1);
cmp >>= 1;
}
}
return 0;
}
After compilation:
$ gcc bindump.c -o bindump
I made simple test to check if program is able to print binary:
$ cat bindump | ./bindump | fold -b100 | nl
Output is following: http://pastebin.com/u7SasKDJ
I suspected the output to look like random series of ones and zeroes. However, output partially seems to be quite more interesting. For example take a look at the output between line 171 and 357. I wonder why there are lots of zeros in compare to other sections of executable ?
My architecture is:
$ lscpu
Architecture: i686
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 4
On-line CPU(s) list: 0-3
Thread(s) per core: 2
Core(s) per socket: 2
Socket(s): 1
Vendor ID: GenuineIntel
CPU family: 6
Model: 28
Stepping: 10
CPU MHz: 1000.000
BogoMIPS: 3325.21
Virtualization: VT-x
L1d cache: 24K
L1i cache: 32K
L2 cache: 512K
When you compile a program into an executable on Linux (and a number of other unix systems), it is written in the ELF format. The ELF format has a number of sections, which you can examine with readelf or objdump:
readelf -a bindump | less
For example, section .text contains CPU instructions, .data global variables, .bss uninitialized global variables (it is actually empty in the ELF file itself, but is created in the main memory when the program is executed), .plt and .got which are jump tables, debugging information, etc.
Btw. it is much more convenient to examine the binary content of files with hexdump:
hexdump -C bindata | less
There you can see that starting with offset 0x850 (approx. line 171 in your dump) there is a lot of zeros, and you can also see the ASCII representation on the right.
Let us look at which sections correspond to the block of your interest between 0x850 and 0x1160 (the field Off – offset in the file is important here):
> readelf -a bindata
...
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
...
[28] .shstrtab STRTAB 00000000 00074c 000106 00 0 0 1
[29] .symtab SYMTAB 00000000 000d2c 000440 10 30 45 4
...
You can examine the content of an individual section with -x:
> readelf -x .symtab bindump | less
0x00000000 00000000 00000000 00000000 00000000 ................
0x00000010 00000000 34810408 00000000 03000100 ....4...........
0x00000020 00000000 48810408 00000000 03000200 ....H...........
0x00000030 00000000 68810408 00000000 03000300 ....h...........
0x00000040 00000000 8c810408 00000000 03000400 ................
0x00000050 00000000 b8810408 00000000 03000500 ................
0x00000060 00000000 d8810408 00000000 03000600 ................
You would see that there are many zeros. The section is composed of 18-byte values (= one line in the -x output) defining symbols. From readelf -a you can see that it has 68 entries, and first 27 of them (excl. the very first one) are of type SECTION:
Symbol table '.symtab' contains 68 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 08048134 0 SECTION LOCAL DEFAULT 1
2: 08048148 0 SECTION LOCAL DEFAULT 2
3: 08048168 0 SECTION LOCAL DEFAULT 3
4: 0804818c 0 SECTION LOCAL DEFAULT 4
...
According to the specification (page 1-18), each entry has the following format:
typedef struct {
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
Without going into too much detail here, I think what matters here is that st_name and st_size are both zeros for these SECTION entries. Both are 32-bit numbers, which means lots of zeros in this particular section.
This is not really a programming question, but however...
A binary normally consists of different sections: code, data, debugging info, etc. Since these sections contents differ by type, I would pretty much expect them to look different.
I.e. the symbol table consists of address offsets in your binary. If I read your lspci correctly, you are on a 32-bit system. That means Each offset has four bytes, and given the size of your program, in most cases two of those bytes will be zero. And there are more effects like this.
You didn't strip your program, that means there's still lots of information (symbol table etc.) present in the binary. Try stripping the binary and have a look at it again.
I m playing with open source which contains the following code
uint32_t addr = htonl(* (uint32_t *)RTA_DATA(rth));
if (htonl(13) == 13) {
// running on big endian system
} else {
// running on little endian system
addr = __builtin_bswap32(addr);
}
It looks like it check if the system is a big endian or little endian with if (htonl(13) == 13). is it correct? and could you please explain why the check this in this way? and why he use 13?
Also the addr = __builtin_bswap32(addr); cause a compilation problem "undefined reference". Are there a solution to fix that? it looks like that function does not exist any more in the new versions of the gcc libs. is it correct?
EDIT:
The toolchain I use is toolchain-i386_gcc-4.1.2_uClibc-0.9.30.1
for the options I used in the compilation:
for the c to object compilation options:
-DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -I. -I/opt/lampp/htdocs/backfire/staging_dir/target-i386_uClibc-0.9.30.1/usr/include -O2 -pipe -march=i486 -funit-at-a-time -fhonour-copts -D_GNU_SOURCE -MT
for the object to binary (linker)
-O2 -pipe -march=i486 -funit-at-a-time -fhonour-copts -D_GNU_SOURCE -L/opt/lampp/htdocs/backfire/staging_dir/target-i386_uClibc-0.9.30.1/usr/lib -L/opt/lampp/htdocs/backfire/staging_dir/target-i386_uClibc-0.9.30.1/lib -L/opt/lampp/htdocs/backfire/staging_dir/toolchain-i386_gcc-4.1.2_uClibc-0.9.30.1/lib -Wl,-rpath-link=/opt/lampp/htdocs/backfire/staging_dir/target-i386_uClibc-0.9.30.1/usr/lib
htonl converts a "host-order" number to network byte order. Host order is whatever endianness you have on the system running the code. Network byte order is big-endian. If host-to-network is big-to-big, that means no change -- which is what 13 -> 13 would verify. On the other hand, if host-to-network is small-to-big, that means you'll get swapping, so the least-significant byte 13 (least because changing it by 1 changes the overall number only by 1) would become most-significant-byte 13 (most because changing that byte by one changes the overall number by the largest amount), and 13 -> (13 << 24).
13 specifically is unimportant. You could use any number, so long as its little-endian representation wasn't the same as its big-endian representation. (0 would be bad, because 0 byte-swapped is still 0. Same for (65536 + 256) as well, because the 32-bit representation is 00 01 01 00 in both big-endian and little-endian.
Note that there are also mixed-endian systems where for the 32-bit number 0x12345678, you'd have bytes not in the order 12 34 56 78 (big-endian) or 78 56 34 12 (little-endian): 34 12 78 56 for one, I believe. These systems aren't common, but they do still exist, and the code here wouldn't handle them correctly.
http://gcc.gnu.org/onlinedocs/gcc-4.2.0/gcc/Other-Builtins.html and http://gcc.gnu.org/onlinedocs/gcc-4.3.0/gcc/Other-Builtins.html suggest __builtin_bswap32 was added in gcc 4.3, so your gcc 4.1.2 toolchain wouldn't have it.
I wish to inject an object file into an existing binary. The method I am attempting is:
Convert a compiled binary into a relocatable object file.
Use gcc/ld to link the relocatable object file with the object file to be embedded.
Given the source:
#include <stdlib.h>
#include <stdio.h>
int main(void)
{
puts("main");
return EXIT_SUCCESS;
}
I compile this to host with the following:
gcc -Wall host.c -o host
I do the conversion to relocatable object file with:
objcopy -B i386 -I binary -O elf64-x86-64 host host.o
I then attempt a link with:
gcc host.o -o host
Ideally, this would relink the relocatable object file back to a binary. This would also give a chance to link in any extra object files. Unfortunately the command gives the following error:
/usr/lib/gcc/x86_64-linux-gnu/4.6.1/../../../x86_64-linux-gnu/crt1.o: In function `_start':
(.text+0x20): undefined reference to `main'
collect2: ld returned 1 exit status
My question is why is this error appearing and how would I go about properly relinking?
Something I tried was to link in another object file at this point which contained a dummy main (because I figured I could manually patch up the entry point later anyway), but what happened was that the new binary seemed to relocate the old code in a weird way with the symbol table completely messed up.
Extra Information
readelf on the binary yields the following:
mike#mike-ubuntu:~/Desktop/inject-obj$ readelf -h host
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400410
Start of program headers: 64 (bytes into file)
Start of section headers: 4424 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 9
Size of section headers: 64 (bytes)
Number of section headers: 30
Section header string table index: 27
And on the relocatable object file:
mike#mike-ubuntu:~/Desktop/inject-obj$ readelf -h host.o
ELF Header:
Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: REL (Relocatable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 8480 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 64 (bytes)
Number of section headers: 5
Section header string table index: 2
Rationale
For those interested, the rationale can be found here.
An executable file that is not PIE is impossible to make relocatable. Relocations have already been performed and the record of those relocations was thrown away. That is, relocating it would require finding all addresses of objects or functions inside the code and data of the binary, but it's impossible to determine whether a sequence of bytes is an address or some other sort of data or code.
There should be a way to do what you originally wanted to do (adding in new code), but the approach you're taking is doomed to failure.