Writing an x86 bootloader (binary size inflated) - linux

I'm making my best effort at following this tutorial as my first bit of ever actually writing assembly. Start small, right? ;)
Anyway... here's what I've got.
[patrick#manifold-arch Assembly]$ cat loader.s
.code16 # we're operating in 16bit real mode
.global begin # make the begin tag globally accessible
begin: # traditionally called _start, but who cares?
jmp begin # infinite loop!
.fill 510-(.-begin), 1, 0 # pad with zeroes till 510 bytes
Cool.
[patrick#manifold-arch Assembly]$ as -o loader.o loader.s
[patrick#manifold-arch Assembly]$ ld -o loader.bin loader.o --oformat binary -e begin --nmagic
[patrick#manifold-arch Assembly]$ ls -lh
total 12K
-rwxr-xr-x 1 patrick patrick 558 Mar 10 11:17 loader.bin
-rw-r--r-- 1 patrick patrick 1.3K Mar 10 11:16 loader.o
-rw-r--r-- 1 patrick patrick 288 Mar 10 10:49 loader.s
First, I was getting 4k files, so I rifled around until I discovered --nmagic. Problem solved. Kind of. My .o file is consistently smaller amusingly enough. But, when I slap the -n flag onto ld, I still wind up with an extra 48 bytes in file size.
[patrick#manifold-arch Assembly]$ objdump -D -Matt,i386 -b binary -m i386 -ls loader.bin
loader.bin: file format binary
Contents of section .data:
0000 04000000 20000000 05000000 474e5500 .... .......GNU.
0010 020001c0 04000000 00000000 00000000 ................
0020 010001c0 04000000 01000000 00000000 ................
0030 ebfe0000 00000000 00000000 00000000 ................
0040 00000000 00000000 00000000 00000000 ................
0050 00000000 00000000 00000000 00000000 ................
0060 00000000 00000000 00000000 00000000 ................
0070 00000000 00000000 00000000 00000000 ................
0080 00000000 00000000 00000000 00000000 ................
0090 00000000 00000000 00000000 00000000 ................
00a0 00000000 00000000 00000000 00000000 ................
00b0 00000000 00000000 00000000 00000000 ................
00c0 00000000 00000000 00000000 00000000 ................
00d0 00000000 00000000 00000000 00000000 ................
00e0 00000000 00000000 00000000 00000000 ................
00f0 00000000 00000000 00000000 00000000 ................
0100 00000000 00000000 00000000 00000000 ................
0110 00000000 00000000 00000000 00000000 ................
0120 00000000 00000000 00000000 00000000 ................
0130 00000000 00000000 00000000 00000000 ................
0140 00000000 00000000 00000000 00000000 ................
0150 00000000 00000000 00000000 00000000 ................
0160 00000000 00000000 00000000 00000000 ................
0170 00000000 00000000 00000000 00000000 ................
0180 00000000 00000000 00000000 00000000 ................
0190 00000000 00000000 00000000 00000000 ................
01a0 00000000 00000000 00000000 00000000 ................
01b0 00000000 00000000 00000000 00000000 ................
01c0 00000000 00000000 00000000 00000000 ................
01d0 00000000 00000000 00000000 00000000 ................
01e0 00000000 00000000 00000000 00000000 ................
01f0 00000000 00000000 00000000 00000000 ................
0200 00000000 00000000 00000000 00000000 ................
0210 00000000 00000000 00000000 00000000 ................
0220 00000000 00000000 00000000 0000 ..............
Disassembly of section .data:
00000000 <.data>:
0: 04 00 add $0x0,%al
2: 00 00 add %al,(%eax)
4: 20 00 and %al,(%eax)
6: 00 00 add %al,(%eax)
8: 05 00 00 00 47 add $0x47000000,%eax
d: 4e dec %esi
e: 55 push %ebp
f: 00 02 add %al,(%edx)
11: 00 01 add %al,(%ecx)
13: c0 04 00 00 rolb $0x0,(%eax,%eax,1)
...
1f: 00 01 add %al,(%ecx)
21: 00 01 add %al,(%ecx)
23: c0 04 00 00 rolb $0x0,(%eax,%eax,1)
27: 00 01 add %al,(%ecx)
29: 00 00 add %al,(%eax)
2b: 00 00 add %al,(%eax)
2d: 00 00 add %al,(%eax)
2f: 00 eb add %ch,%bl
31: fe 00 incb (%eax)
...
I see the zeroes from 13 to 1f, but that only accounts for 12 bytes, yes? It seems like that block shouldn't be there at all, but it still doesn't account for everything that I'm getting as extra.
And when I remove the padding, instead of ending up with a 4 byte binary like the author does, I wind up with a 50 byte binary.
I'm clearly doing something wrong, and it's probably just a flag or something. So I've got two questions: one, what am I doing wrong? And two: why does the author get such different outcomes (particularly regarding page alignment) than I do? The article's from 2018, so surely those commands weren't run on a 32-bit machine? I dunno. All I know is I need a hand. =)
Thanks in advance, and as always.

Related

Why /proc/net/tcp inode field is zero?

I'm trying to map which socket belong to which process, and to do that, i'm parsing /proc/net/tcp file. But sometime, the inode field is zero. What does that mean?
Example output from /proc/net/tcp:
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
6: 0100007F:2EE1 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 54791 1 0000000000000000 100 0 0 10 0
7: 0100007F:5F04 00000000:0000 0A 00000000:00000000 00:00000000 00000000 130 0 56323 1 0000000000000000 100 0 0 10 0
8: 00000000:0386 00000000:0000 0A 00000000:00000000 00:00000000 00000000 0 0 50586 1 0000000000000000 100 0 0 10 0
9: 0100007F:19C8 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 4831553 1 0000000000000000 100 0 0 10 0
10: 0100007F:61A9 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 56521 1 0000000000000000 100 0 0 10 0
11: 00000000:93D0 00000000:0000 0A 00000000:00000000 00:00000000 00000000 1000 0 56765 1 0000000000000000 100 0 0 10 0
12: 0100007F:B4C4 0100007F:19C8 06 00000000:00000000 03:00000BC1 00000000 0 0 0 3 0000000000000000
13: 0100007F:B462 0100007F:19C8 06 00000000:00000000 03:00000582 00000000 0 0 0 3 0000000000000000
14: 0100007F:B538 0100007F:19C8 06 00000000:00000000 03:000012CA 00000000 0 0 0 3 0000000000000000
15: 0100007F:B51C 0100007F:19C8 06 00000000:00000000 03:00001139 00000000 0 0 0 3 0000000000000000

The size limitation of .bss/.data section in Linux kernel

I just added a 56,212 byte array (declare, not dynamically allocate) to one of device driver (driver is built-in) in Linux 2.6.15 at ARM platform, and always get kernel panic after issue the commands related to process ID (e.g. ps or top) even if that device driver is not running.
Here is the backtrace,
[<c009be04>] (pid_revalidate+0x0/0xa8) from [<c007b934>] (do_lookup+0x18c/0x1b8)
r5 = C5CA9F70 r4 = 00000000
[<c007b7a8>] (do_lookup+0x0/0x1b8) from [<c007c380>] (__link_path_walk+0x8b8/0xd78)
[<c007bac8>] (__link_path_walk+0x0/0xd78) from [<c007c8c4>] (link_path_walk+0x84/0x134)
[<c007c840>] (link_path_walk+0x0/0x134) from [<c007cb10>] (path_lookup+0x19c/0x1a8)
r7 = C48E1000 r6 = 00000000 r5 = C487E000 r4 = C487FF14
[<c007c974>] (path_lookup+0x0/0x1a8) from [<c007cc08>] (__path_lookup_intent_open+0x4c/0x8c)
r7 = 00000001 r6 = C487FF14 r5 = C48E1000 r4 = 00000001
[<c007cbbc>] (__path_lookup_intent_open+0x0/0x8c) from [<c007cc64>] (path_lookup_open+0x1c/0x20)
r7 = 00000005 r6 = 00000004 r5 = C487FF14 r4 = 00000000
[<c007cc48>] (path_lookup_open+0x0/0x20) from [<c007d45c>] (open_namei+0x7c/0x67c)
[<c007d3e0>] (open_namei+0x0/0x67c) from [<c006d28c>] (filp_open+0x2c/0x48)
[<c006d260>] (filp_open+0x0/0x48) from [<c006d55c>] (do_sys_open+0x44/0xd0)
r5 = 00000000 r4 = 00000000
[<c006d518>] (do_sys_open+0x0/0xd0) from [<c006d5f8>] (sys_open+0x10/0x14)
[<c006d5e8>] (sys_open+0x0/0x14) from [<c0020e00>] (ret_fast_syscall+0x0/0x2c)
If I decrease the volume of array to 56,208 bytes, everything is OK.
The "readelf" result of 56,208 bytes array (OK case)
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .init PROGBITS c0008000 008000 018000 00 WAX 0 0 32
[ 2] .text PROGBITS c0020000 020000 24c7f4 00 AX 0 0 32
[ 3] .text.init PROGBITS c026c7f4 26c7f4 000078 00 AX 0 0 4
[ 4] .pci_fixup PROGBITS c026c86c 30a700 000000 00 W 0 0 1
[ 5] .rio_route PROGBITS c026c86c 30a700 000000 00 W 0 0 1
[ 6] __ksymtab PROGBITS c026c86c 26c86c 004458 00 A 0 0 4
[ 7] __ksymtab_gpl PROGBITS c0270cc4 270cc4 000898 00 A 0 0 4
[ 8] __kcrctab PROGBITS c027155c 30a700 000000 00 W 0 0 1
[ 9] __kcrctab_gpl PROGBITS c027155c 30a700 000000 00 W 0 0 1
[10] __ksymtab_strings PROGBITS c027155c 27155c 00b288 00 A 0 0 4
[11] __param PROGBITS c027c7e4 27c7e4 000618 00 A 0 0 4
[12] .data PROGBITS c027e000 27e000 08c6f0 00 WA 0 0 32
[13] .bss NOBITS c030a700 30a700 0248e8 00 WA 0 0 32
[14] .comment PROGBITS 00000000 30a700 0028c8 00 0 0 1
[15] .shstrtab STRTAB 00000000 30cfc8 0000a0 00 0 0 1
[16] .symtab SYMTAB 00000000 30d338 07aa50 10 17 25869 4
[17] .strtab STRTAB 00000000 387d88 057629 00 0 0 1
The "readelf" result of 56,212 bytes array (NG case)
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .init PROGBITS c0008000 008000 018000 00 WAX 0 0 32
[ 2] .text PROGBITS c0020000 020000 24c7f4 00 AX 0 0 32
[ 3] .text.init PROGBITS c026c7f4 26c7f4 000078 00 AX 0 0 4
[ 4] .pci_fixup PROGBITS c026c86c 30a700 000000 00 W 0 0 1
[ 5] .rio_route PROGBITS c026c86c 30a700 000000 00 W 0 0 1
[ 6] __ksymtab PROGBITS c026c86c 26c86c 004458 00 A 0 0 4
[ 7] __ksymtab_gpl PROGBITS c0270cc4 270cc4 000898 00 A 0 0 4
[ 8] __kcrctab PROGBITS c027155c 30a700 000000 00 W 0 0 1
[ 9] __kcrctab_gpl PROGBITS c027155c 30a700 000000 00 W 0 0 1
[10] __ksymtab_strings PROGBITS c027155c 27155c 00b288 00 A 0 0 4
[11] __param PROGBITS c027c7e4 27c7e4 000618 00 A 0 0 4
[12] .data PROGBITS c027e000 27e000 08c6f0 00 WA 0 0 32
[13] .bss NOBITS c030a700 30a700 024908 00 WA 0 0 32
[14] .comment PROGBITS 00000000 30a700 0028c8 00 0 0 1
[15] .shstrtab STRTAB 00000000 30cfc8 0000a0 00 0 0 1
[16] .symtab SYMTAB 00000000 30d338 07aa50 10 17 25869 4
[17] .strtab STRTAB 00000000 387d88 057629 00 0 0 1
The differences between two cases is just the size of .bss. (OK case is 248e8; NG case is 24908)
I was wondering whether I have violated some rules in Linux kernel, or I am debugging in the wrong way?

Segfault when running cross-compiled HelloWorld to armv5te on a board with CPU arm926ej-s

I have a board that has this CPU:
# uname -a
Linux gw-9167 4.4.24 #1 Thu Mar 28 17:52:19 UTC 2019 armv5tejl GNU/Linux
# cat /proc/cpuinfo
processor : 0
model name : ARM926EJ-S rev 5 (v5l)
BogoMIPS : 226.09
Features : swp half fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 5
Hardware : Freescale MXS (Device Tree)
Revision : 0000
Serial : 0000000000000000
I'm trying to cross-compile a simple Rust hello world to it:
[0] [05:56:25] ~/r/gw-test HEAD > /bin/cat .cargo/config
[target.armv5te-unknown-linux-gnueabi]
linker = "arm-none-eabi-gcc"
[target.armv5te-unknown-linux-musleabi]
linker = "arm-none-eabi-gcc"
[0] [05:56:34] ~/r/gw-test HEAD > env RUSTFLAGS="-C target-cpu=arm926ej-s" cargo build --target=armv5te-unknown-linux-musleabi --release
Compiling gw-test v0.1.0 (/home/cecile/repos/gw-test)
Finished release [optimized] target(s) in 0.28s
[0] [05:56:51] ~/r/gw-test HEAD > qemu-arm -L /usr/arm-linux-gnueabi -cpu arm926 target/armv5te-unknown-linux-musleabi/release/gw-test
Hello, world!
When I run it on the board itself, it segfaults immediately:
[0] [05:57:09] ~/r/gw-test HEAD > scp ......
gw-test 100% 1781KB 906.4KB/s 00:01
[0] [05:58:27] ~/r/gw-test HEAD > ssh ...... /tmp/gw-test
Segmentation fault
[139] [05:58:47] ~/r/gw-test HEAD > ssh ..... strace /tmp/gw-test
execve("/tmp/gw-test", ["/tmp/gw-test"], [/* 9 vars */]) = -1 EINVAL (Invalid argument)
--- SIGSEGV {si_signo=SIGSEGV, si_code=SI_KERNEL, si_addr=0} ---
+++ killed by SIGSEGV +++
Segmentation fault
What is the content of your main.rs?
Nothing! It's just the default hello world generated by Cargo
EINVAL An ELF executable had more than one PT_INTERP segment (i.e., tried to name more than one interpreter).
Now that's really weird because I also read in the doc: "If the executable is a dynamically linked ELF executable, the interpreter named in the PT_INTERP segment is used to load the needed shared libraries." and I have compiled with musl. It should be static (at least it says it is when I run ldd from the host machine on it).
Try to attach a debugger, either directly via gdb or remotely by using gdbserver.
I understand. I will try to see how to do it remotely as you suggested.
It seems like an error from strace and not from your process.
It makes sense.
What happens when you run it without strace? Is there a core dump?
It's in the log I already shared.
[0] [05:58:27] ~/r/gw-test HEAD > ssh ...... /tmp/gw-test
Segmentation fault
You are using arm-none-eabi-gcc, which is not targetting any operating system. Check readelf --headers ~/r/gw-test and compare it with a binary that does work, like /bin/cat or something.
Here is the output of readelf --headers on the binary I made and on cat:
[0] [08:11:23] ~ > cd ~/repos/gw-test/
[0] [08:15:26] ~/r/gw-test HEAD > ls
Cargo.lock Cargo.toml gw.json lib-root resources src target
[0] [08:15:27] ~/r/gw-test HEAD > readelf --headers target/armv5te-unknown-linux-musleabi/release/gw-test
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0x8278
Start of program headers: 52 (bytes into file)
Start of section headers: 1822748 (bytes into file)
Flags: 0x5000200, Version5 EABI, soft-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 5
Size of section headers: 40 (bytes)
Number of section headers: 27
Section header string table index: 26
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .init PROGBITS 00008000 008000 00000c 00 AX 0 0 4
[ 2] .text PROGBITS 00008010 008010 0281b8 00 AX 0 0 8
[ 3] .fini PROGBITS 000301c8 0301c8 00000c 00 AX 0 0 4
[ 4] .rodata PROGBITS 000301e0 0301e0 005174 00 A 0 0 16
[ 5] .ARM.extab PROGBITS 00035354 035354 000bf4 00 A 0 0 4
[ 6] .ARM.exidx ARM_EXIDX 00035f48 035f48 0009e8 00 AL 2 0 4
[ 7] .tdata PROGBITS 00046930 036930 000018 00 WAT 0 0 8
[ 8] .tbss NOBITS 00046948 036948 000034 00 WAT 0 0 8
[ 9] .data.rel.ro PROGBITS 00046948 036948 000f98 00 WA 0 0 8
[10] .got PROGBITS 000478e0 0378e0 0000cc 04 WA 0 0 4
[11] .data PROGBITS 000479b0 0379b0 0000bc 00 WA 0 0 8
[12] .bss NOBITS 00047a70 037a6c 000a78 00 WA 0 0 8
[13] .comment PROGBITS 00000000 037a6c 00003b 01 MS 0 0 1
[14] .debug_aranges PROGBITS 00000000 037aa8 0012f0 00 0 0 8
[15] .debug_info PROGBITS 00000000 038d98 07d9b8 00 0 0 1
[16] .debug_abbrev PROGBITS 00000000 0b6750 00a574 00 0 0 1
[17] .debug_line PROGBITS 00000000 0c0cc4 04e271 00 0 0 1
[18] .debug_frame PROGBITS 00000000 10ef38 0101f4 00 0 0 4
[19] .debug_str PROGBITS 00000000 11f12c 02bc3f 01 MS 0 0 1
[20] .debug_loc PROGBITS 00000000 14ad6b 015230 00 0 0 1
[21] .debug_macinfo PROGBITS 00000000 15ff9b 000007 00 0 0 1
[22] .debug_ranges PROGBITS 00000000 15ffa8 033418 00 0 0 8
[23] .ARM.attributes ARM_ATTRIBUTES 00000000 1933c0 000031 00 0 0 1
[24] .symtab SYMTAB 00000000 1933f4 01e590 10 25 7245 4
[25] .strtab STRTAB 00000000 1b1984 00b595 00 0 0 1
[26] .shstrtab STRTAB 00000000 1bcf19 000103 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x035f48 0x00035f48 0x00035f48 0x009e8 0x009e8 R 0x4
LOAD 0x000000 0x00000000 0x00000000 0x36930 0x36930 R E 0x10000
LOAD 0x036930 0x00046930 0x00046930 0x0113c 0x01bb8 RW 0x10000
TLS 0x036930 0x00046930 0x00046930 0x00018 0x0004c R 0x8
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
Section to Segment mapping:
Segment Sections...
00 .ARM.exidx
01 .init .text .fini .rodata .ARM.extab .ARM.exidx
02 .tdata .data.rel.ro .got .data .bss
03 .tdata .tbss
04
[127] [08:19:01] ~/r/gw-test HEAD > scp -r -i ~/Downloads/hub_keys/sshKeys/0200000100009167 root#gw-9167.lan:/bin/cat ./
cat 100% 651KB 581.0KB/s 00:01
[0] [08:19:18] ~/r/gw-test HEAD > stat cat
File: cat
Size: 666788 Blocks: 1304 IO Block: 4096 regular file
Device: 18h/24d Inode: 4034474 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 1000/ cecile) Gid: ( 1000/ cecile)
Access: 2019-04-07 10:19:17.131861726 +0200
Modify: 2019-04-07 10:19:18.251842664 +0200
Change: 2019-04-07 10:19:18.251842664 +0200
Birth: 2019-04-07 10:19:17.131861726 +0200
[0] [08:19:22] ~/r/gw-test HEAD > readelf --headers cat
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xc914
Start of program headers: 52 (bytes into file)
Start of section headers: 665748 (bytes into file)
Flags: 0x5000002, Version5 EABI, <unknown>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 26
Section header string table index: 25
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 00008134 000134 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00008148 000148 000020 00 A 0 0 4
[ 3] .hash HASH 00008168 000168 000990 04 A 4 0 4
[ 4] .dynsym DYNSYM 00008af8 000af8 0015b0 10 A 5 1 4
[ 5] .dynstr STRTAB 0000a0a8 0020a8 000b33 00 A 0 0 1
[ 6] .gnu.version VERSYM 0000abdc 002bdc 0002b6 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 0000ae94 002e94 000020 00 A 5 1 4
[ 8] .rel.dyn REL 0000aeb4 002eb4 000050 08 A 4 0 4
[ 9] .rel.plt REL 0000af04 002f04 000a60 08 A 4 11 4
[10] .init PROGBITS 0000b964 003964 00000c 00 AX 0 0 4
[11] .plt PROGBITS 0000b970 003970 000fa4 04 AX 0 0 4
[12] .text PROGBITS 0000c914 004914 07dcd8 00 AX 0 0 4
[13] .fini PROGBITS 0008a5ec 0825ec 000008 00 AX 0 0 4
[14] .rodata PROGBITS 0008a5f8 0825f8 01f208 00 A 0 0 8
[15] .ARM.exidx ARM_EXIDX 000a9800 0a1800 000008 00 AL 12 0 4
[16] .eh_frame PROGBITS 000a9808 0a1808 000004 00 A 0 0 4
[17] .init_array INIT_ARRAY 000b2000 0a2000 000004 00 WA 0 0 4
[18] .fini_array FINI_ARRAY 000b2004 0a2004 000004 00 WA 0 0 4
[19] .jcr PROGBITS 000b2008 0a2008 000004 00 WA 0 0 4
[20] .dynamic DYNAMIC 000b200c 0a200c 0000e8 08 WA 5 0 4
[21] .got PROGBITS 000b20f4 0a20f4 000544 04 WA 0 0 4
[22] .data PROGBITS 000b2638 0a2638 00014e 00 WA 0 0 4
[23] .bss NOBITS 000b2788 0a2786 0022c0 00 WA 0 0 8
[24] .ARM.attributes ARM_ATTRIBUTES 00000000 0a2786 000034 00 0 0 1
[25] .shstrtab STRTAB 00000000 0a27ba 0000da 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x0a1800 0x000a9800 0x000a9800 0x00008 0x00008 R 0x4
PHDR 0x000034 0x00008034 0x00008034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x00008134 0x00008134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.3]
LOAD 0x000000 0x00008000 0x00008000 0xa180c 0xa180c R E 0x8000
LOAD 0x0a2000 0x000b2000 0x000b2000 0x00786 0x02a48 RW 0x8000
DYNAMIC 0x0a200c 0x000b200c 0x000b200c 0x000e8 0x000e8 RW 0x4
NOTE 0x000148 0x00008148 0x00008148 0x00020 0x00020 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .ARM.exidx
01
02 .interp
03 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .ARM.exidx .eh_frame
04 .init_array .fini_array .jcr .dynamic .got .data .bss
05 .dynamic
06 .note.ABI-tag
07
[0] [08:19:32] ~/r/gw-test HEAD > /usr/arm-none-eabi/bin/readelf --headers cat
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: EXEC (Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xc914
Start of program headers: 52 (bytes into file)
Start of section headers: 665748 (bytes into file)
Flags: 0x5000002, Version5 EABI, <unknown>
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 8
Size of section headers: 40 (bytes)
Number of section headers: 26
Section header string table index: 25
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .interp PROGBITS 00008134 000134 000013 00 A 0 0 1
[ 2] .note.ABI-tag NOTE 00008148 000148 000020 00 A 0 0 4
[ 3] .hash HASH 00008168 000168 000990 04 A 4 0 4
[ 4] .dynsym DYNSYM 00008af8 000af8 0015b0 10 A 5 1 4
[ 5] .dynstr STRTAB 0000a0a8 0020a8 000b33 00 A 0 0 1
[ 6] .gnu.version VERSYM 0000abdc 002bdc 0002b6 02 A 4 0 2
[ 7] .gnu.version_r VERNEED 0000ae94 002e94 000020 00 A 5 1 4
[ 8] .rel.dyn REL 0000aeb4 002eb4 000050 08 A 4 0 4
[ 9] .rel.plt REL 0000af04 002f04 000a60 08 A 4 11 4
[10] .init PROGBITS 0000b964 003964 00000c 00 AX 0 0 4
[11] .plt PROGBITS 0000b970 003970 000fa4 04 AX 0 0 4
[12] .text PROGBITS 0000c914 004914 07dcd8 00 AX 0 0 4
[13] .fini PROGBITS 0008a5ec 0825ec 000008 00 AX 0 0 4
[14] .rodata PROGBITS 0008a5f8 0825f8 01f208 00 A 0 0 8
[15] .ARM.exidx ARM_EXIDX 000a9800 0a1800 000008 00 AL 12 0 4
[16] .eh_frame PROGBITS 000a9808 0a1808 000004 00 A 0 0 4
[17] .init_array INIT_ARRAY 000b2000 0a2000 000004 00 WA 0 0 4
[18] .fini_array FINI_ARRAY 000b2004 0a2004 000004 00 WA 0 0 4
[19] .jcr PROGBITS 000b2008 0a2008 000004 00 WA 0 0 4
[20] .dynamic DYNAMIC 000b200c 0a200c 0000e8 08 WA 5 0 4
[21] .got PROGBITS 000b20f4 0a20f4 000544 04 WA 0 0 4
[22] .data PROGBITS 000b2638 0a2638 00014e 00 WA 0 0 4
[23] .bss NOBITS 000b2788 0a2786 0022c0 00 WA 0 0 8
[24] .ARM.attributes ARM_ATTRIBUTES 00000000 0a2786 000034 00 0 0 1
[25] .shstrtab STRTAB 00000000 0a27ba 0000da 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
y (purecode), p (processor specific)
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
EXIDX 0x0a1800 0x000a9800 0x000a9800 0x00008 0x00008 R 0x4
PHDR 0x000034 0x00008034 0x00008034 0x00100 0x00100 R E 0x4
INTERP 0x000134 0x00008134 0x00008134 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.3]
LOAD 0x000000 0x00008000 0x00008000 0xa180c 0xa180c R E 0x8000
LOAD 0x0a2000 0x000b2000 0x000b2000 0x00786 0x02a48 RW 0x8000
DYNAMIC 0x0a200c 0x000b200c 0x000b200c 0x000e8 0x000e8 RW 0x4
NOTE 0x000148 0x00008148 0x00008148 0x00020 0x00020 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4
Section to Segment mapping:
Segment Sections...
00 .ARM.exidx
01
02 .interp
03 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .text .fini .rodata .ARM.exidx .eh_frame
04 .init_array .fini_array .jcr .dynamic .got .data .bss
05 .dynamic
06 .note.ABI-tag
07
Solution:
I made this Dockerfile:
FROM buildpack-deps:xenial
RUN dpkg --add-architecture i386 && \
apt-get update && \
apt-get install -y --no-install-recommends \
apt-utils build-essential sudo libssl-dev \
subversion wget cpio python unzip rsync bc libncurses-dev \
libc6:i386 libncurses5:i386 libstdc++6:i386 ca-certificates \
ant ant-optional bison curl flex fusesmb
COPY ./dp-mgw-toolchain_1.6_i386.deb ./
RUN dpkg -i dp-mgw-toolchain_1.6_i386.deb
RUN curl https://sh.rustup.rs -sSf | bash -s -- -y
RUN echo '. ~/.cargo/env' >> ~/.bashrc
RUN . ~/.cargo/env && \
rustup target add armv5te-unknown-linux-musleabi
ENV PATH=/opt/develco-products/buildroot-toolchain-multigateway-1.6/host/usr/bin:$PATH
ENV RUSTFLAGS="-C target-cpu=arm926ej-s"
RUN cargo build --target=armv5te-unknown-linux-musleabi --release
The deb file is actually the toolchain provided by the manufacturer. Now I'm using the correct linker and it runs properly on the board.
My first bet are incompatible ABI. Your binary:
0x5000200, Version5 EABI, soft-float ABI
Binaries from your board:
0x5000002, Version5 EABI, <unknown>
Next bet, your binary has many sections missing, so it looks like linker issue. Your QEMU environment isn't identical to that used on your target, but I'd expect your QEMU runs bare metal binary. These cannot run under Linux as would not have direct access to hardware & peripherals.
You need to setup your linker to link ELF compatible with environment on your board. I don't have experience with Freescale but looking at any project that cross compiles for this board should lead you to proper linker invocation.

ELF standard and relocation offset computation

I am struggling in understanding how a linker perform relocation. According on the ELF manual (Relocation section, pag 27) a relocation of type R_386_PC32 is performed by calculating the quantity S + A - P (see ELF manual at page 29).
Now, consider the following ELF header:
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: REL (Relocatable file)
Machine: Intel 80386
Version: 0x1
Entry point address: 0x0
Start of program headers: 0 (bytes into file)
Start of section headers: 560 (bytes into file)
Flags: 0x0
Size of this header: 52 (bytes)
Size of program headers: 0 (bytes)
Number of program headers: 0
Size of section headers: 40 (bytes)
Number of section headers: 13
Section header string table index: 10
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[ 0] NULL 00000000 000000 000000 00 0 0 0
[ 1] .text PROGBITS 00000000 000034 000038 00 AX 0 0 1
[ 2] .rel.text REL 00000000 0001b8 000010 08 I 11 1 4
[ 3] .data PROGBITS 00000000 00006c 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 00006c 000000 00 WA 0 0 1
[ 5] .rodata PROGBITS 00000000 00006c 00000f 00 A 0 0 1
[ 6] .comment PROGBITS 00000000 00007b 000035 01 MS 0 0 1
[ 7] .note.GNU-stack PROGBITS 00000000 0000b0 000000 00 0 0 1
[ 8] .eh_frame PROGBITS 00000000 0000b0 000044 00 A 0 0 4
[ 9] .rel.eh_frame REL 00000000 0001c8 000008 08 I 11 8 4
[10] .shstrtab STRTAB 00000000 0001d0 00005f 00 0 0 1
[11] .symtab SYMTAB 00000000 0000f4 0000b0 10 12 9 4
[12] .strtab STRTAB 00000000 0001a4 000013 00 0 0 1
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings)
I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
O (extra OS processing required) o (OS specific), p (processor specific)
There are no section groups in this file.
There are no program headers in this file.
Relocation section '.rel.text' at offset 0x1b8 contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000001f 00000501 R_386_32 00000000 .rodata
00000024 00000a02 R_386_PC32 00000000 printf
Relocation section '.rel.eh_frame' at offset 0x1c8 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
00000020 00000202 R_386_PC32 00000000 .text
The decoding of unwind sections for machine type Intel 80386 is not currently supported.
Symbol table '.symtab' contains 11 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS asd.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 0 SECTION LOCAL DEFAULT 5
6: 00000000 0 SECTION LOCAL DEFAULT 7
7: 00000000 0 SECTION LOCAL DEFAULT 8
8: 00000000 0 SECTION LOCAL DEFAULT 6
9: 00000000 56 FUNC GLOBAL DEFAULT 1 main
10: 00000000 0 NOTYPE GLOBAL DEFAULT UND printf
No version information found in this file.
and the relative relocatable file:
asd.o: file format elf32-i386
Disassembly of section .text:
00000000 <main>:
0: 8d 4c 24 04 lea 0x4(%esp),%ecx
4: 83 e4 f0 and $0xfffffff0,%esp
7: ff 71 fc pushl -0x4(%ecx)
a: 55 push %ebp
b: 89 e5 mov %esp,%ebp
d: 51 push %ecx
e: 83 ec 14 sub $0x14,%esp
11: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
18: 83 ec 08 sub $0x8,%esp
1b: ff 75 f4 pushl -0xc(%ebp)
1e: 68 00 00 00 00 push $0x0
23: e8 fc ff ff ff call 24 <main+0x24>
28: 83 c4 10 add $0x10,%esp
2b: b8 00 00 00 00 mov $0x0,%eax
30: 8b 4d fc mov -0x4(%ebp),%ecx
33: c9 leave
34: 8d 61 fc lea -0x4(%ecx),%esp
37: c3 ret
Given that the symbol printf has type R_386_PC32, the new offset has to be calculated as S + A - P. According the sym table S is equal to 0. The quantity A, according the ELF manual, is implicit in the location to be modified, therefore should be equal to 0xfffffffc (little endianess) and finally P should be r_offset, thus 0x24. It follows that the new offset should be equal to 0xffffffD8.
Instead, after linking the above program, I obtain:
0804840b <main>:
804840b: 8d 4c 24 04 lea 0x4(%esp),%ecx
804840f: 83 e4 f0 and $0xfffffff0,%esp
8048412: ff 71 fc pushl -0x4(%ecx)
8048415: 55 push %ebp
8048416: 89 e5 mov %esp,%ebp
8048418: 51 push %ecx
8048419: 83 ec 14 sub $0x14,%esp
804841c: c7 45 f4 00 00 00 00 movl $0x0,-0xc(%ebp)
8048423: 83 ec 08 sub $0x8,%esp
8048426: ff 75 f4 pushl -0xc(%ebp)
8048429: 68 d0 84 04 08 push $0x80484d0
804842e: e8 ad fe ff ff call 80482e0 <printf#plt>
8048433: 83 c4 10 add $0x10,%esp
8048436: b8 00 00 00 00 mov $0x0,%eax
804843b: 8b 4d fc mov -0x4(%ebp),%ecx
804843e: c9 leave
804843f: 8d 61 fc lea -0x4(%ecx),%esp
8048442: c3 ret
8048443: 66 90 xchg %ax,%ax
8048445: 66 90 xchg %ax,%ax
8048447: 66 90 xchg %ax,%ax
8048449: 66 90 xchg %ax,%ax
804844b: 66 90 xchg %ax,%ax
804844d: 66 90 xchg %ax,%ax
804844f: 90 nop
My question is: how is calculated the value actually stored in the final executable file as argument of the printf call(i.e., 0xfffffead)?
Except printf isn't in your object file, it's undefined. So yes, the specification is correct, it is going to be that address, but from your dump that address is not yet known. PS: also applies to your .rodata relocation.
– Jester

Why two audio files exported the same way have different checksums?

I originally asked this question on Signal Processing but it was off topic. So, here it goes!
I tried to export a recording from Audacity twice, each time with the same parameters and tags. The resulting files had different checksums. So I opened up an diffed the two files (as binary).
My first try was a wav file containing a 32 bit float PCM. Only 3 bits were different in the whole file.
0000003c: 01000000 01001001 01110000 01010111 01001100 11100111 #IpWL.
became
0000003c: 01000111 01001001 01110000 01010111 01001100 11100111 GIpWL.
My first question is: what are these three bits used for?
Then I tried this same procedure with flac files. I will not paste it here because it would be too long, but what happened is that at the beginning of the file, there were only a few differences here and there, but the farther in the file I got the more it was apparent that the files were different.
Why is that? Isn't the flac compression algorithm deterministic?
Finally I took a wav file containing a 16 bit signed PCM and converted it to a 16 bit signed flac file, and then back to wav. The file I obtained is very similar to the original but it seems data is offseted by 33 bytes, as you can see from these samples of the files:
Original file:
00000294: 11111110 11111111 11111111 11111111 11111101 11111111 ......
0000029a: 11111011 11111111 11111100 11111111 11111110 11111111 ......
000002a0: 00000000 00000000 11111011 11111111 00000000 00000000 ......
000002a6: 00000001 00000000 00000010 00000000 00000001 00000000 ......
000002ac: 11111101 11111111 11111110 11111111 11111100 11111111 ......
000002b2: 11111100 11111111 11111101 11111111 11111101 11111111 ......
000002b8: 00000001 00000000 00000010 00000000 11111100 11111111 ......
000002be: 11111100 11111111 11111011 11111111 11111010 11111111 ......
000002c4: 00000010 00000000 00000010 00000000 00000000 00000000 ......
New File:
000002b2: 00000011 00000000 00000011 00000000 11111110 11111111 ......
000002b8: 11111111 11111111 11111101 11111111 11111011 11111111 ......
000002be: 11111100 11111111 11111110 11111111 00000000 00000000 ......
000002c4: 11111011 11111111 00000000 00000000 00000001 00000000 ......
000002ca: 00000010 00000000 00000001 00000000 11111101 11111111 ......
000002d0: 11111110 11111111 11111100 11111111 11111100 11111111 ......
000002d6: 11111101 11111111 11111101 11111111 00000001 00000000 ......
000002dc: 00000010 00000000 11111100 11111111 11111100 11111111 ......
000002e2: 11111011 11111111 11111010 11111111 00000010 00000000 ......
Why?

Resources