For some sections of an ELF file, '.dynstr' for example, the offset which is written in the structure of the section header table is something that "readelf -a" does not report. For example the offset is "0x0245" but readelf reports "0x0300" as the offset of the section. I can confirm that the offset returned by "readelf" is wrong using a HexEditor. For the first few sections what readelf is reporting as their corresponding offset is correct, but some point downward all the offsets are wrong. Does any body know why the reported offsets are different from what is written in the file? Or is this a bug related to readelf?
Note: By using "objdump -h" I can also confirm that the offsets reported by readelf are wrong
Note2: Some offsets returned by 'readelf' are even bigger than the file size.
This is as output example or readelf:
Section Headers:
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[ 0] NULL 0000000000000000 00000000
0000000000000000 0000000000000000 0 0 0
[ 1] .interp PROGBITS 0000000000400200 00000200
000000000000001c 0000000000000000 A 0 0 1
[ 2] .note.ABI-tag NOTE 000000000040021c 0000021c
0000000000000020 0000000000000000 A 0 0 4
[ 3] .note.gnu.build-i NOTE 000000000040023c 0000023c
0000000000000024 0000000000000000 A 0 0 4
[ 4] .gnu.hash GNU_HASH 0000000000400260 00000260
000000000000001c 0000000000000000 A 5 0 8
[ 5] .dynsym DYNSYM 0000000000400280 00000280
0000000000000120 0000000000000018 A 6 1 8
>> [ 6] .dynstr STRTAB 00000000004003a0 000003a0 <<< 0x3a0 is wrong
0000000000000084 0000000000000000 A 0 0 1
This is 'objdump -h' output :
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 0000001c 0000000000400200 0000000000400200 00000200 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 000000000040021c 000000000040021c 0000021c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 000000000040023c 000000000040023c 0000023c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .gnu.hash 0000001c 0000000000400260 0000000000400260 00000260 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynsym 00000048 0000000000400280 0000000000400280 00000280 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynstr 00000038 00000000004002c8 00000000004002c8 000002c8 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version 00000006 0000000000400300 0000000000400300 00000300 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version_r 00000020 0000000000400308 0000000000400308 00000308 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rela.dyn 00000018 0000000000400328 0000000000400328 00000328 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rela.plt 00000030 0000000000400340 0000000000400340 00000340 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .init 0000001a 0000000000400370 0000000000400370 00000370 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .plt 00000030 0000000000400390 0000000000400390 00000390 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .text 00000182 00000000004003c0 00000000004003c0 000003c0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 00000009 0000000000400544 0000000000400544 00000544 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00000004 0000000000400550 0000000000400550 00000550 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame_hdr 00000034 0000000000400554 0000000000400554 00000554 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .eh_frame 000000f4 0000000000400588 0000000000400588 00000588 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .init_array 00000008 0000000000600680 0000000000600680 00000680 2**3
CONTENTS, ALLOC, LOAD, DATA
18 .fini_array 00000008 0000000000600688 0000000000600688 00000688 2**3
CONTENTS, ALLOC, LOAD, DATA
19 .jcr 00000008 0000000000600690 0000000000600690 00000690 2**3
CONTENTS, ALLOC, LOAD, DATA
20 .dynamic 000001d0 0000000000600698 0000000000600698 00000698 2**3
CONTENTS, ALLOC, LOAD, DATA
21 .got 00000008 0000000000600868 0000000000600868 00000868 2**3
CONTENTS, ALLOC, LOAD, DATA
22 .got.plt 00000028 0000000000600870 0000000000600870 00000870 2**3
CONTENTS, ALLOC, LOAD, DATA
23 .data 00000014 0000000000600898 0000000000600898 00000898 2**3
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00000004 00000000006008ac 00000000006008ac 000008ac 2**0
ALLOC
25 .comment 00000039 0000000000000000 0000000000000000 000008ac 2**0
CONTENTS, READONLY
Related
readelf output of the object file:
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS fp16.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 NOTYPE LOCAL DEFAULT 1 $t
6: 00000001 194 FUNC LOCAL DEFAULT 1 __gnu_f2h_internal
7: 00000010 0 NOTYPE LOCAL DEFAULT 5 $d
8: 00000000 0 SECTION LOCAL DEFAULT 5
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 000000c5 78 FUNC GLOBAL HIDDEN 1 __gnu_h2f_internal
11: 00000115 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_ieee
12: 00000119 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_ieee
13: 0000011d 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_alternative
14: 00000121 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_alternative
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 000124 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00058c 000010 08 9 1 4
[ 3] .data PROGBITS 00000000 000158 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000158 000000 00 WA 0 0 1
[ 5] .debug_frame PROGBITS 00000000 000158 00008c 00 0 0 4
[ 6] .rel.debug_frame REL 00000000 00059c 000060 08 9 5 4
[ 7] .ARM.attributes ARM_ATTRIBUTES 00000000 0001e4 00002f 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 000213 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 00041c 0000f0 10 10 10 4
[10] .strtab STRTAB 00000000 00050c 00007e 00 0 0 1
Relocation section '.rel.text' at offset 0x58c contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000011a 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
00000122 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
Relocation section '.rel.debug_frame' at offset 0x59c contains 12 entries:
Offset Info Type Sym.Value Sym. Name
00000014 00000802 R_ARM_ABS32 00000000 .debug_frame
00000018 00000202 R_ARM_ABS32 00000000 .text
00000040 00000802 R_ARM_ABS32 00000000 .debug_frame
00000044 00000202 R_ARM_ABS32 00000000 .text
00000050 00000802 R_ARM_ABS32 00000000 .debug_frame
00000054 00000202 R_ARM_ABS32 00000000 .text
00000060 00000802 R_ARM_ABS32 00000000 .debug_frame
00000064 00000202 R_ARM_ABS32 00000000 .text
00000070 00000802 R_ARM_ABS32 00000000 .debug_frame
00000074 00000202 R_ARM_ABS32 00000000 .text
00000080 00000802 R_ARM_ABS32 00000000 .debug_frame
00000084 00000202 R_ARM_ABS32 00000000 .text
.text section structure as I understand it:
.text section has size of 0x124
0x0: unknown byte
0x1-0xC3: __gnu_f2h_internal
0xC3-0xC5: two unknown bytes between those functions (btw what are those?)
0xC5-0x113: __gnu_h2f_internal
0x113-0x115: two unknown bytes between those functions
0x115-0x119: __gnu_f2h_ieee
0x119-0x11D: __gnu_h2f_ieee
0x11D-0x121: __gnu_f2h_alternative
0x121-0x125: __gnu_h2f_alternative // section is only 0x124, what happened to the missing byte?
Notice that the section size is 0x124 and the last function end in 0x125, what happend to the missing byte?
Thanks.
Technically, your "missing byte" is the one right there at 0x0.
Note that you're looking at the value of the symbol, i.e. the runtime function address (this would be a lot clearer if your .text section VMA wasn't 0). Since they're Thumb functions, the addresses have bit 0 set such that the processor will switch to Thumb mode when calling them; the actual locations of those instructions are still halfword-aligned, i.e. 0x0, 0xc4, 0x114, etc. since they couldn't be executed otherwise (you'd take a fault for a misaligned PC). Strip off bit 0 as per what the ARM
ELF spec says about STT_FUNC symbols to get the actual VMA of the instruction corresponding to that symbol, then subtract the start of the section and you should have the same relative offset as within the object file itself.
<offset in section> = (<symbol value> & ~1) - <section VMA>
The extra halfword padding after some functions just ensures each symbol is word-aligned - there are probably various reasons for this, but the first one that comes to mind is that the adr instruction wouldn't work properly if they weren't.
readelf output of the object file:
Symbol table '.symtab' contains 15 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS fp16.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 NOTYPE LOCAL DEFAULT 1 $t
6: 00000001 194 FUNC LOCAL DEFAULT 1 __gnu_f2h_internal
7: 00000010 0 NOTYPE LOCAL DEFAULT 5 $d
8: 00000000 0 SECTION LOCAL DEFAULT 5
9: 00000000 0 SECTION LOCAL DEFAULT 7
10: 000000c5 78 FUNC GLOBAL HIDDEN 1 __gnu_h2f_internal
11: 00000115 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_ieee
12: 00000119 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_ieee
13: 0000011d 4 FUNC GLOBAL HIDDEN 1 __gnu_f2h_alternative
14: 00000121 4 FUNC GLOBAL HIDDEN 1 __gnu_h2f_alternative
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 000124 00 AX 0 0 4
[ 2] .rel.text REL 00000000 00058c 000010 08 9 1 4
[ 3] .data PROGBITS 00000000 000158 000000 00 WA 0 0 1
[ 4] .bss NOBITS 00000000 000158 000000 00 WA 0 0 1
[ 5] .debug_frame PROGBITS 00000000 000158 00008c 00 0 0 4
[ 6] .rel.debug_frame REL 00000000 00059c 000060 08 9 5 4
[ 7] .ARM.attributes ARM_ATTRIBUTES 00000000 0001e4 00002f 00 0 0 1
[ 8] .shstrtab STRTAB 00000000 000213 000051 00 0 0 1
[ 9] .symtab SYMTAB 00000000 00041c 0000f0 10 10 10 4
[10] .strtab STRTAB 00000000 00050c 00007e 00 0 0 1
Relocation section '.rel.text' at offset 0x58c contains 2 entries:
Offset Info Type Sym.Value Sym. Name
0000011a 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
00000122 00000a66 R_ARM_THM_JUMP11 000000c5 __gnu_h2f_internal
Relocation section '.rel.debug_frame' at offset 0x59c contains 12 entries:
Offset Info Type Sym.Value Sym. Name
00000014 00000802 R_ARM_ABS32 00000000 .debug_frame
00000018 00000202 R_ARM_ABS32 00000000 .text
00000040 00000802 R_ARM_ABS32 00000000 .debug_frame
00000044 00000202 R_ARM_ABS32 00000000 .text
00000050 00000802 R_ARM_ABS32 00000000 .debug_frame
00000054 00000202 R_ARM_ABS32 00000000 .text
00000060 00000802 R_ARM_ABS32 00000000 .debug_frame
00000064 00000202 R_ARM_ABS32 00000000 .text
00000070 00000802 R_ARM_ABS32 00000000 .debug_frame
00000074 00000202 R_ARM_ABS32 00000000 .text
00000080 00000802 R_ARM_ABS32 00000000 .debug_frame
00000084 00000202 R_ARM_ABS32 00000000 .text
.text section structure as I understand it:
.text section has size of 0x124
0x0: unknown byte
0x1-0xC3: __gnu_f2h_internal
0xC3-0xC5: two unknown bytes between those functions (btw what are those?)
0xC5-0x113: __gnu_h2f_internal
0x113-0x115: two unknown bytes between those functions
0x115-0x119: __gnu_f2h_ieee
0x119-0x11D: __gnu_h2f_ieee
0x11D-0x121: __gnu_f2h_alternative
0x121-0x125: __gnu_h2f_alternative // section is only 0x124, what happened to the missing byte?
Notice that the section size is 0x124 and the last function end in 0x125, what happend to the missing byte?
Thanks.
Technically, your "missing byte" is the one right there at 0x0.
Note that you're looking at the value of the symbol, i.e. the runtime function address (this would be a lot clearer if your .text section VMA wasn't 0). Since they're Thumb functions, the addresses have bit 0 set such that the processor will switch to Thumb mode when calling them; the actual locations of those instructions are still halfword-aligned, i.e. 0x0, 0xc4, 0x114, etc. since they couldn't be executed otherwise (you'd take a fault for a misaligned PC). Strip off bit 0 as per what the ARM
ELF spec says about STT_FUNC symbols to get the actual VMA of the instruction corresponding to that symbol, then subtract the start of the section and you should have the same relative offset as within the object file itself.
<offset in section> = (<symbol value> & ~1) - <section VMA>
The extra halfword padding after some functions just ensures each symbol is word-aligned - there are probably various reasons for this, but the first one that comes to mind is that the adr instruction wouldn't work properly if they weren't.
So, I am trying to learn ARM assembly and basically what I want to do is turn on the LEDs of my BeagleBone Black using pure assembly. I know how to program in C very well, but I am new to ARM assembly if that makes any difference.
Basically I am just trying to modify a character in a string, but it doesn't seem to be working. Maybe it is because I do not fully understand the memory management instructions.
When I run the code it gives me a segmentation fault.
Here is my code:
.syntax unified
.global main
main:
push {ip, lr}
mov r0, beagle_bone_0
mov r1, #0x65
strb r1, [r0]
ldr r0, =beagle_bone_0
bl printf
pop {ip, pc}
beagle_bone_0:
.asciz "/sys/class/leds/beaglebone:green:usr0/brightness"
objdump -x output:
helloworld: file format elf32-littlearm
helloworld
architecture: arm, flags 0x00000112:
EXEC_P, HAS_SYMS, D_PAGED
start address 0x00008325
Program Header:
0x70000001 off 0x00000444 vaddr 0x00008444 paddr 0x00008444 align 2**2
filesz 0x00000008 memsz 0x00000008 flags r--
PHDR off 0x00000034 vaddr 0x00008034 paddr 0x00008034 align 2**2
filesz 0x00000100 memsz 0x00000100 flags r-x
INTERP off 0x00000134 vaddr 0x00008134 paddr 0x00008134 align 2**0
filesz 0x00000019 memsz 0x00000019 flags r--
LOAD off 0x00000000 vaddr 0x00008000 paddr 0x00008000 align 2**15
filesz 0x00000450 memsz 0x00000450 flags r-x
LOAD off 0x00000450 vaddr 0x00010450 paddr 0x00010450 align 2**15
filesz 0x00000124 memsz 0x00000128 flags rw-
DYNAMIC off 0x0000045c vaddr 0x0001045c paddr 0x0001045c align 2**2
filesz 0x000000f0 memsz 0x000000f0 flags rw-
NOTE off 0x00000150 vaddr 0x00008150 paddr 0x00008150 align 2**2
filesz 0x00000044 memsz 0x00000044 flags r--
STACK off 0x00000000 vaddr 0x00000000 paddr 0x00000000 align 2**2
filesz 0x00000000 memsz 0x00000000 flags rwx
Dynamic Section:
NEEDED libc.so.6
INIT 0x000082d1
FINI 0x00008439
INIT_ARRAY 0x00010450
INIT_ARRAYSZ 0x00000004
FINI_ARRAY 0x00010454
FINI_ARRAYSZ 0x00000004
HASH 0x00008194
GNU_HASH 0x000081bc
STRTAB 0x00008238
SYMTAB 0x000081e8
STRSZ 0x00000043
SYMENT 0x00000010
DEBUG 0x00000000
PLTGOT 0x0001054c
PLTRELSZ 0x00000020
PLTREL 0x00000011
JMPREL 0x000082b0
REL 0x000082a8
RELSZ 0x00000008
RELENT 0x00000008
VERNEED 0x00008288
VERNEEDNUM 0x00000001
VERSYM 0x0000827c
Version References:
required from libc.so.6:
0x0d696914 0x00 02 GLIBC_2.4
private flags = 5000002: [Version5 EABI] [has entry point]
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000019 00008134 00008134 00000134 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 00008150 00008150 00000150 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .note.gnu.build-id 00000024 00008170 00008170 00000170 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .hash 00000028 00008194 00008194 00000194 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .gnu.hash 0000002c 000081bc 000081bc 000001bc 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .dynsym 00000050 000081e8 000081e8 000001e8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .dynstr 00000043 00008238 00008238 00000238 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .gnu.version 0000000a 0000827c 0000827c 0000027c 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .gnu.version_r 00000020 00008288 00008288 00000288 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .rel.dyn 00000008 000082a8 000082a8 000002a8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
10 .rel.plt 00000020 000082b0 000082b0 000002b0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
11 .init 0000000a 000082d0 000082d0 000002d0 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .plt 00000048 000082dc 000082dc 000002dc 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .text 00000114 00008324 00008324 00000324 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .fini 00000006 00008438 00008438 00000438 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
15 .rodata 00000004 00008440 00008440 00000440 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .ARM.exidx 00000008 00008444 00008444 00000444 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
17 .eh_frame 00000004 0000844c 0000844c 0000044c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
18 .init_array 00000004 00010450 00010450 00000450 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .fini_array 00000004 00010454 00010454 00000454 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .jcr 00000004 00010458 00010458 00000458 2**2
CONTENTS, ALLOC, LOAD, DATA
21 .dynamic 000000f0 0001045c 0001045c 0000045c 2**2
CONTENTS, ALLOC, LOAD, DATA
22 .got 00000020 0001054c 0001054c 0000054c 2**2
CONTENTS, ALLOC, LOAD, DATA
23 .data 00000008 0001056c 0001056c 0000056c 2**2
CONTENTS, ALLOC, LOAD, DATA
24 .bss 00000004 00010574 00010574 00000574 2**0
ALLOC
25 .comment 0000001d 00000000 00000000 00000574 2**0
CONTENTS, READONLY
26 .ARM.attributes 00000031 00000000 00000000 00000591 2**0
CONTENTS, READONLY
SYMBOL TABLE:
00008134 l d .interp 00000000 .interp
00008150 l d .note.ABI-tag 00000000 .note.ABI-tag
00008170 l d .note.gnu.build-id 00000000 .note.gnu.build-id
00008194 l d .hash 00000000 .hash
000081bc l d .gnu.hash 00000000 .gnu.hash
000081e8 l d .dynsym 00000000 .dynsym
00008238 l d .dynstr 00000000 .dynstr
0000827c l d .gnu.version 00000000 .gnu.version
00008288 l d .gnu.version_r 00000000 .gnu.version_r
000082a8 l d .rel.dyn 00000000 .rel.dyn
000082b0 l d .rel.plt 00000000 .rel.plt
000082d0 l d .init 00000000 .init
000082dc l d .plt 00000000 .plt
00008324 l d .text 00000000 .text
00008438 l d .fini 00000000 .fini
00008440 l d .rodata 00000000 .rodata
00008444 l d .ARM.exidx 00000000 .ARM.exidx
0000844c l d .eh_frame 00000000 .eh_frame
00010450 l d .init_array 00000000 .init_array
00010454 l d .fini_array 00000000 .fini_array
00010458 l d .jcr 00000000 .jcr
0001045c l d .dynamic 00000000 .dynamic
0001054c l d .got 00000000 .got
0001056c l d .data 00000000 .data
00010574 l d .bss 00000000 .bss
00000000 l d .comment 00000000 .comment
00000000 l d .ARM.attributes 00000000 .ARM.attributes
0000835c l F .text 00000000 call_gmon_start
00000000 l df *ABS* 00000000 crtstuff.c
00010458 l O .jcr 00000000 __JCR_LIST__
00008374 l F .text 00000000 __do_global_dtors_aux
00010574 l O .bss 00000001 completed.5637
00010454 l O .fini_array 00000000 __do_global_dtors_aux_fini_array_entry
00008384 l F .text 00000000 frame_dummy
00010450 l O .init_array 00000000 __frame_dummy_init_array_entry
000083b8 l .text 00000000 beagle_bone_0
00000000 l df *ABS* 00000000 crtstuff.c
0000844c l O .eh_frame 00000000 __FRAME_END__
00010458 l O .jcr 00000000 __JCR_END__
00010454 l .init_array 00000000 __init_array_end
0001045c l O .dynamic 00000000 _DYNAMIC
00010450 l .init_array 00000000 __init_array_start
0001054c l O .got 00000000 _GLOBAL_OFFSET_TABLE_
00008434 g F .text 00000002 __libc_csu_fini
0001056c w .data 00000000 data_start
000082f0 F *UND* 00000000 printf##GLIBC_2.4
00010574 g *ABS* 00000000 __bss_start__
00010578 g *ABS* 00000000 _bss_end__
00010574 g *ABS* 00000000 _edata
00008438 g F .fini 00000000 _fini
00010578 g *ABS* 00000000 __bss_end__
0001056c g .data 00000000 __data_start
000082fc F *UND* 00000000 __libc_start_main##GLIBC_2.4
00000000 w *UND* 00000000 __gmon_start__
00010570 g O .data 00000000 .hidden __dso_handle
00008440 g O .rodata 00000004 _IO_stdin_used
000083f0 g F .text 00000044 __libc_csu_init
00010578 g *ABS* 00000000 _end
00008324 g F .text 00000000 _start
00010578 g *ABS* 00000000 __end__
00010574 g *ABS* 00000000 __bss_start
0000839c g .text 00000000 main
00000000 w *UND* 00000000 _Jv_RegisterClasses
00008318 F *UND* 00000000 abort##GLIBC_2.4
000082d0 g F .init 00000000 _init
The answer to my question was actually really simple. Since ldr r0, =beagle_bone_0 loads the address of beagle_bone_0 into register 0 I can just manipulate beagle_bone_0 with that address.
Working test code:
.syntax unified
.data
beagle_bone_0: .ascii "Hello, world\n"
.text
.global main
main:
push {ip, lr}
ldr r0, =beagle_bone_0
mov r1, #0x65
strb r1, [r0]
bl printf
pop {ip, pc}
I ran and debugged your code. The line mov r0, beagle_bone_0 didn't even compile (on my compiler, at least). You want to load in r0 the address of beagle_bone. For this, you should use the adr pseudo-instruction, that is translated by the compiler in a pc-relative move (something like mov r0, [pc, #8]. You cannot use it this way. Probably your compiler translated it into something different.
So, to fix it, just replace the line mov r0, beagle_bone_0 by adr r0, beagle_bone_0.
Also the string was in the .text section which we cannot edit. So, I put beagle_bone_0 in the .data section.
I've been having trouble getting this code to work.
test $0x10000000, %esp
jz .ERROR
ret
If it jumps to .ERROR, the code just exits. Otherwise the output prints as normal.
When I use test $0x0000000, %esp it quits as I would expect.
These are my sections:
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048114 08048114 00000114 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048128 08048128 00000128 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 00000038 08048148 08048148 00000148 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000090 08048180 08048180 00000180 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 00000064 08048210 08048210 00000210 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 00000012 08048274 08048274 00000274 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000020 08048288 08048288 00000288 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.dyn 00000010 080482a8 080482a8 000002a8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 00000030 080482b8 080482b8 000002b8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 00000024 080482e8 080482e8 000002e8 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 00000070 08048310 08048310 00000310 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00000188 08048380 08048380 00000380 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .springboard 00000023 08048508 08048508 00000508 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 00000015 0804852c 0804852c 0000052c 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00000024 08048544 08048544 00000544 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame 000000e0 08048568 08048568 00000568 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .dynamic 000000c8 08049648 08049648 00000648 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .got 00000004 08049710 08049710 00000710 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .got.plt 00000024 08049714 08049714 00000714 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .data 00000004 08049738 08049738 00000738 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .bss 00000004 0804973c 0804973c 0000073c 2**2
ALLOC
21 .comment 0000002a 00000000 00000000 0000073c 2**0
CONTENTS, READONLY
Maybe I don't understand this yet, but should %esp be equal to addresses in that range?
I can move the .springboard section to 0x10000000 if I link it with my linker script. The return goes to the springboard section. So my thought was that it shouldn't work here, but if I link it with my script and the springboard section is moved, then it will work. Why is it working in both cases?
I'm guessing the test is returning a non-zero value but I don't understand why.
No, esp is a stack pointer, so it should point to some address inside stack. Your program doesn't seem to provide any stack section, so I guess the OS allocates the stack.
Well, if you are about to return from a function, dword ptr [esp] (but not esp) should indeed contain an address from the sections above, as this should be an address of the next instruction to be executed after the function call.
I'm working on a big project that involves writing a Perl script to transform assembly files and I'm trying to determine what the assembly files will look like after the transformation, and what the process is to compile them. I've been having trouble getting a simple example to work. I'm starting with a simple program, fib.c. I compiled it, and then added a section called the springboard.
.file "fib.c"
.text
.globl fib
.type fib, #function
fib:
.LFB0:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
pushl %ebx
subl $20, %esp
cmpl $0, 8(%ebp)
jne .L2
.cfi_offset 3, -12
movl $1, %eax
jmp .SB1
.LBL1:
jmp .L3
.L2:
cmpl $1, 8(%ebp)
jne .L4
movl $1, %eax
jmp .SB2
.LBL2:
jmp .L3
.L4:
movl 8(%ebp), %eax
subl $1, %eax
movl %eax, (%esp)
call fib
movl %eax, %ebx
movl 8(%ebp), %eax
subl $2, %eax
movl %eax, (%esp)
call fib
addl %ebx, %eax
.L3:
addl $20, %esp
popl %ebx
.cfi_restore 3
popl %ebp
.cfi_def_cfa 4, 4
.cfi_restore 5
ret
.cfi_endproc
.LFE0:
.size fib, .-fib
.section .rodata
.LC0:
.string "Usage: fib <n>\n"
.LC1:
.string "f(%d) = %d\n"
.text
.globl main
.type main, #function
main:
.LFB1:
.cfi_startproc
pushl %ebp
.cfi_def_cfa_offset 8
.cfi_offset 5, -8
movl %esp, %ebp
.cfi_def_cfa_register 5
andl $-16, %esp
subl $32, %esp
cmpl $2, 8(%ebp)
je .L6
movl stderr, %eax
movl %eax, %edx
movl $.LC0, %eax
movl %edx, 12(%esp)
movl $15, 8(%esp)
movl $1, 4(%esp)
movl %eax, (%esp)
call fwrite
movl $1, (%esp)
call exit
.L6:
movl 12(%ebp), %eax
addl $4, %eax
movl (%eax), %eax
movl %eax, (%esp)
call atoi
movl %eax, 24(%esp)
movl 24(%esp), %eax
movl %eax, (%esp)
call fib
movl %eax, 28(%esp)
movl $.LC1, %eax
movl 28(%esp), %edx
movl %edx, 8(%esp)
movl 24(%esp), %edx
movl %edx, 4(%esp)
movl %eax, (%esp)
call printf
movl $0, (%esp)
call exit
.cfi_endproc
.LFE1:
.size main, .-main
.section .springboard,"ax",#progbits
.SB2:
jmp .LBL2
.SB1:
jmp .LBL1
.LFE2:
.size .springboard, .-.springboard
.ident "GCC: (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3"
.section .note.GNU-stack,"",#progbits
I used these commands to compile it further:
as -o fib.o fib.S -32
ld -melf_i386 -o fib -dynamic-linker /lib/ld-linux.so.2 /usr/lib32/crt1.o /usr/lib32/crti.o fib.o -lc /usr/lib32/crtn.o script.ld
The part I'm having trouble with is the GNU linker script. I want to be able to put the springboard section at a specific memory address. Here's the script:
OUTPUT_FORMAT(elf32-i386)
ENTRY(main)
SB_START = 0x08148508;
SECTIONS
{
. = SB_START;
.springboard : { *(.springboard) }
}
I've been stuck on this for a while and tried a few different things and I'm very new to linker scripts so maybe this will be easy for some of you.
Looking at the sections without the linker script using objdump -x fib
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048114 08048114 00000114 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048128 08048128 00000128 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 00000038 08048148 08048148 00000148 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000090 08048180 08048180 00000180 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 00000064 08048210 08048210 00000210 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 00000012 08048274 08048274 00000274 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000020 08048288 08048288 00000288 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.dyn 00000010 080482a8 080482a8 000002a8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 00000030 080482b8 080482b8 000002b8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 00000024 080482e8 080482e8 000002e8 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 00000070 08048310 08048310 00000310 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00000188 08048380 08048380 00000380 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .springboard 0000000a 08048508 08048508 00000508 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .fini 00000015 08048514 08048514 00000514 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
14 .rodata 00000024 0804852c 0804852c 0000052c 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame 000000e0 08048550 08048550 00000550 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
16 .dynamic 000000c8 08049630 08049630 00000630 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .got 00000004 080496f8 080496f8 000006f8 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .got.plt 00000024 080496fc 080496fc 000006fc 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .data 00000004 08049720 08049720 00000720 2**2
CONTENTS, ALLOC, LOAD, DATA
20 .bss 00000004 08049724 08049724 00000724 2**2
ALLOC
21 .comment 0000002a 00000000 00000000 00000724 2**0
CONTENTS, READONLY
And then with the script:
Sections:
Idx Name Size VMA LMA File off Algn
0 .interp 00000013 08048134 08048134 00000134 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
1 .note.ABI-tag 00000020 08048148 08048148 00000148 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .hash 00000038 08048168 08048168 00000168 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
3 .dynsym 00000090 080481a0 080481a0 000001a0 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
4 .dynstr 00000064 08048230 08048230 00000230 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
5 .gnu.version 00000012 08048294 08048294 00000294 2**1
CONTENTS, ALLOC, LOAD, READONLY, DATA
6 .gnu.version_r 00000020 080482a8 080482a8 000002a8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
7 .rel.dyn 00000010 080482c8 080482c8 000002c8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
8 .rel.plt 00000030 080482d8 080482d8 000002d8 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
9 .init 00000024 08048308 08048308 00000308 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
10 .plt 00000070 08048330 08048330 00000330 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
11 .text 00000188 080483a0 080483a0 000003a0 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
12 .fini 00000015 08048528 08048528 00000528 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
13 .rodata 00000024 08048540 08048540 00000540 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .eh_frame 000000e0 08048564 08048564 00000564 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .dynamic 000000c8 08049644 08049644 00000644 2**2
CONTENTS, ALLOC, LOAD, DATA
16 .got 00000004 0804970c 0804970c 0000070c 2**2
CONTENTS, ALLOC, LOAD, DATA
17 .got.plt 00000024 08049710 08049710 00000710 2**2
CONTENTS, ALLOC, LOAD, DATA
18 .data 00000004 08049734 08049734 00000734 2**2
CONTENTS, ALLOC, LOAD, DATA
19 .bss 00000004 08049738 08049738 00000738 2**2
ALLOC
20 .comment 0000002a 00000000 00000000 00001512 2**0
CONTENTS, READONLY
21 .springboard 0000000a 08148508 08148508 00001508 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
I would love to learn more about what I can do with linker scripts and how do to it. I've read other questions and tutorials but am still pretty confused. I don't fully understand what all the sections are and where they should go, I thought I'd start with something simple and add one, but I might to understand things in more detail to get it to work. Any idea on how to fix my linker script? What else do I need to know about this subject? Thanks!
Working on an Ubuntu machine and I'm only focused on 32-bit programs.
You did refer to GNU linker manual? Chapter 3 does explain linker scripts. It's won't win any awards for best manuals, though. :)
The sections you see are various data (.data, .bss, .rodata) and code (.text, .init, .fini) sections. More details here. Also try googling up section names.
The problem was the line ENTRY(main). That indicates the program will start at that point.
Argc and Argv get set up by crt1.o, as explained here: How to correctly use a simple linker script? Executable gets SIGKILL when run
That means we don't need an entry point at all. And if we put that as our entry point, the arguments won't get set up correctly. crt1.o will also call into main. The linker script now looks like this:
OUTPUT_FORMAT(elf32-i386)
SECTIONS
{
. = 0x08148508;
.springboard : { *(.springboard) }
}