Why is .data executable? - linux

According to readelf:
----------------------------------------------------------------------
[Nr] Name Type Address Offset
Size EntSize Flags Link Info Align
[24] .data PROGBITS 0000000000601040 00001040
0000000000000051 0000000000000000 WA 0 0 32
----------------------------------------------------------------------
Section to Segment mapping:
Segment Sections...
00
01
02
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
----------------------------------------------------------------------
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
PHDR
INTERP
LOAD
LOAD 0x0000000000000e10 0x0000000000600e10 0x0000000000600e10
0x0000000000000281 0x0000000000000288 RW 200000
As you can see above .data segment has W (Write) and A (Alloc) permissions and .data is loaded in a LOAD section with R (Read) W (Write).
However, the shellcode in the .data section is executable, according to GDB:
0x601060 <bytecode>: xor rax,rax
=> 0x601063 <bytecode+3>: xor rdi,rdi
And I don't know why. Is this correct? What am I missing?

However, the shellcode in the .data section is executable, according to GDB:
The GDB output does not tell you that the .data section is executable. GDB will happily disassemble any memory you ask it to disassemble.
Try this:
(gdb) set $p = (void (*)(void))&bytecode
(gdb) call $p()
This should result in a SIGSEGV on the first instruction of bytecode, because it in fact is not executable.

Related

Segmentation fault with a variable in SECTION .DATA

I am trying to learn nasm. I want to make a program that prints "Hello, world." n times (in this case 10). I am trying to save the loop register value in a constant so that it is not changed when the body of the loop is executed. When I try to do this I receive a segmentation fault error. I am not sure why this is happening.
My code:
SECTION .DATA
print_str: db 'Hello, world.', 10
print_str_len: equ $-print_str
limit: equ 10
step: dw 1
SECTION .TEXT
GLOBAL _start
_start:
mov eax, 4 ; 'write' system call = 4
mov ebx, 1 ; file descriptor 1 = STDOUT
mov ecx, print_str ; string to write
mov edx, print_str_len ; length of string to write
int 80h ; call the kernel
mov eax, [step] ; moves the step value to eax
inc eax ; Increment
mov [step], eax ; moves the eax value to step
cmp eax, limit ; Compare sil to the limit
jle _start ; Loop while less or equal
exit:
mov eax, 1 ; 'exit' system call
mov ebx, 0 ; exit with error code 0
int 80h ; call the kernel
The result:
Hello, world.
Segmentation fault (core dumped)
The cmd:
nasm -f elf64 file.asm -o file.o
ld file.o -o file
./file
section .DATA is the direct cause of the crash. Lower-case section .data is special, and linked as a read-write (private) mapping of the executable. Section names are case-sensitive.
Upper-case .DATA is not special for nasm or the linker, and it ends up as part of the text segment mapped read+exec without write permission.
Upper-case .TEXT is also weird: by default objdump -drwC -Mintel only disassembles the .text section (to avoid disassembling data as if it were code), so it shows empty output for your executable.
On newer systems, the default for a section name NASM doesn't recognize doesn't include exec permission, so code in .TEXT will segfault. Same as Assembly section .code and .text behave differently
After starting the program under GDB (gdb ./foo, starti), I looked at the process's memory map from another shell.
$ cat /proc/11343/maps
00400000-00401000 r-xp 00000000 00:31 110651257 /tmp/foo
7ffff7ffa000-7ffff7ffd000 r--p 00000000 00:00 0 [vvar]
7ffff7ffd000-7ffff7fff000 r-xp 00000000 00:00 0 [vdso]
7ffffffde000-7ffffffff000 rwxp 00000000 00:00 0 [stack]
As you can see, other than the special VDSO mappings and the stack, there's only the one file-backed mapping, and it has read+exec permission only.
Single-stepping inside GDB, the mov eax,DWORD PTR ds:0x400086 load succeeds, but the mov DWORD PTR ds:0x400086,eax store faults. (See the bottom of the x86 tag wiki for GDB asm tips.)
From readelf -a foo, we can see the ELF program headers that tell the OS's program loader how to map it into memory:
$ readelf -a foo # broken version
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000bf 0x00000000000000bf R 0x200000
Section to Segment mapping:
Segment Sections...
00 .DATA .TEXT
Notice how both .DATA and .TEXT are in the same segment. This is what you'd want for section .rodata (a standard section name where you should put read-only constant data like your string), but it won't work for mutable global variables.
After fixing your asm to use section .data and .text, readelf shows us:
$ readelf -a foo # fixed version
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000400000 0x0000000000400000
0x00000000000000e7 0x00000000000000e7 R E 0x200000
LOAD 0x00000000000000e8 0x00000000006000e8 0x00000000006000e8
0x0000000000000010 0x0000000000000010 RW 0x200000
Section to Segment mapping:
Segment Sections...
00 .text
01 .data
Notice how segment 00 is R + E without W, and the .text section is in there. Segment 01 is RW (read + write) without exec, and the .data section is there.
The LOAD tag means they're mapped into the process's virtual address space. Some section (like debug info) aren't, and are just metadata for other tools. But NASM flags unknown section names as progbits, i.e. loaded, which is why it was able to link and have the load not segfault.
After fixing it to use section .data, your program runs without segfaulting.
The loop runs for one iteration, because the 2 bytes following step: dw 1 are not zero. After the dword load, RAX = 0x2c0001 on my system. (cmp between 0x002c0002 and 0xa makes the LE condition false because it's not less or equal.)
dw means "data word" or "define word". Use dd for a data dword.
BTW, there's no need to keep your loop counter in memory. You're not using RDI, RSI, RBP, or R8..R15 for anything so you could just keep it in a register. Like mov edi, limit before the loop, and dec edi / jnz at the bottom.
But actually you should use the 64-bit syscall ABI if you want to build 64-bit code, not the 32-bit int 0x80 ABI. What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?. Or build 32-bit executables if you're following a guide or tutorial written for that.
Anyway, in that case you'd be able to use ebx as your loop counter, because the syscall ABI uses different args for registers.

Why is there more than one .rodata section being mapped to the LOAD segment, yet only one .rodata output section is specified in the linker script?

Here is my linker script :
ENTRY(__startup)
SECTIONS
{
. = 0x0000;
.text : { *(.text) }
. = . + 0x4000;
.rodata :
{
*(.rodata)
*(.rodata.*)
}
.bss : { *(.bss) }
.data : { *(.data) }
}
Simple Enough. However, when all of the object files get linked together and I look at the segment mapping for the executable I get the following:
Elf file type is EXEC (Executable file)
Entry point 0x0
There are 6 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0xfffff034 0xfffff034 0x000c0 0x000c0 R 0x4
LOAD 0x000000 0xfffff000 0xfffff000 0x000f4 0x000f4 R 0x1000
LOAD 0x001000 0x00000000 0x00000000 0x01a18 0x01a18 R E 0x1000
LOAD 0x002a18 0x00005a18 0x00005a18 0x00038 0x00038 R 0x1000
LOAD 0x002a50 0x00005a50 0x00005a50 0x0010c 0x0010c RW 0x1000
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0
Section to Segment mapping:
Segment Sections...
00
01
02 .text
03 .rodata .rodata
04 .bss .bss .data
05
Doing an objdump on the program also shows two .rodata sections. The system I'm running on is ubuntu 16.0.4 and my compiler is gcc (I'm using LD, the GNU linker).
Does anyone know the reason why two output sections of the same name would be generated by the compilation? And is there a way to force it to one? It's entirely possible that this is more than just a generic question about the command language script, but as I can't show the codebase I'm working with, I still thought it wouldn't hurt to ask the good people on Stack Overflow.
It seems that the default behavior of the LD linker is to allocate different .rodata sections based on whatever alignment is required for the constants that are being stored in read-only memory. For more information refer to here:
what does `.rodata.str1.8` section mean in elf file

How to show the name of header files and src files that are included in C/C++ shared library

For a C/C++ shared library (.so file), how to check all the names of headers and sources that are included in it?
I tried compile the shared library with -g option, and use readelf -Wl, but I can only get something like:
Elf file type is DYN (Shared object file)
Entry point 0x560
There are 7 program headers, starting at offset 64
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x000754 0x000754 R E 0x200000
LOAD 0x000e70 0x0000000000200e70 0x0000000000200e70 0x0001b0 0x0001b8 RW 0x200000
DYNAMIC 0x000e88 0x0000000000200e88 0x0000000000200e88 0x000150 0x000150 RW 0x8
NOTE 0x0001c8 0x00000000000001c8 0x00000000000001c8 0x000024 0x000024 R 0x4
GNU_EH_FRAME 0x0006a8 0x00000000000006a8 0x00000000000006a8 0x000024 0x000024 R 0x4
GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x10
GNU_RELRO 0x000e70 0x0000000000200e70 0x0000000000200e70 0x000190 0x000190 R 0x1
Section to Segment mapping:
Segment Sections...
00 .note.gnu.build-id .gnu.hash .dynsym .dynstr .rela.dyn .init .plt .plt.got .text .fini .eh_frame_hdr .eh_frame
01 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
02 .dynamic
03 .note.gnu.build-id
04 .eh_frame_hdr
05
06 .init_array .fini_array .jcr .dynamic .got
Your .so won't necessarily even have any of this information unless it was explicitly compiled with "-G".
SUGGESTIONS:
How can I know what type of debug info is in an ELF object file?
objdump -g
objdump -W file.elf
How do I best determine if a binary contains STAB or DWARF debug information?
readelf -WS ./a.out | egrep '\.(stab |debug)'
Linux Journal: The ELF Object File Format by Dissection
Playing with gdb. Reverse engineer your way
Debugging formats DWARF and STAB

How shared library finds GOT section?

While I was reading http://eli.thegreenplace.net/2011/11/03/position-independent-code-pic-in-shared-libraries/#id1
question came:
How does PIC shared library after being loaded somewhere in virtual address space of the process knows how to reference external variables?
Here is code of shared library in question:
#include <stdio.h>
extern long var;
void
shara_func(void)
{
printf("%ld\n", var);
}
Produce object code, then shared object(library):
gcc -fPIC -c lib1.c # produce PIC lib1.o
gcc -fPIC -shared lib1.o -o liblib1.so # produce PIC shared library
Disassemble shara_func in shared library:
objdump -d liblib1.so
...
00000000000006d0 <shara_func>:
6d0: 55 push %rbp
6d1: 48 89 e5 mov %rsp,%rbp
6d4: 48 8b 05 fd 08 20 00 mov 0x2008fd(%rip),%rax # 200fd8 <_DYNAMIC+0x1c8>
6db: 48 8b 00 mov (%rax),%rax
6de: 48 89 c6 mov %rax,%rsi
6e1: 48 8d 3d 19 00 00 00 lea 0x19(%rip),%rdi # 701 <_fini+0x9>
6e8: b8 00 00 00 00 mov $0x0,%eax
6ed: e8 be fe ff ff callq 5b0 <printf#plt>
6f2: 90 nop
6f3: 5d pop %rbp
6f4: c3 retq
...
I see that instruction at 0x6d4 address moves some address that is relative to PC to rax, I suppose that is the entry in GOT, GOT referenced relatively from PC to get address of external variable var at runtime(it is resolved at runtime depending where var was loaded).
Then after executing instruction at 0x6db we get external variable's actual content placed in rax, then move value from rax to rsi - second function parameter passed in register.
I was thinking that there is only one GOT in process memory, however,
see that library references GOT? How shared library knows offset to process's GOT when it(PIC library) does not know where in process memory it would be loaded? Or does each shared library has its own GOT that is loaded with her? I would be very glad if you clarify my confusion.
I was thinking that there is only one GOT in process memory, however, see that library references GOT?
We clearly see .got section as part of the library. With readelf we can find what are the sections of the library and how they are loaded:
readelf -e liblib1.so
...
Section Headers:
[21] .got PROGBITS 0000000000200fd0 00000fd0
0000000000000030 0000000000000008 WA 0 0 8
...
Program Headers:
Type Offset VirtAddr PhysAddr
FileSiz MemSiz Flags Align
LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000
0x000000000000078c 0x000000000000078c R E 200000
LOAD 0x0000000000000df8 0x0000000000200df8 0x0000000000200df8
0x0000000000000230 0x0000000000000238 RW 200000
...
Section to Segment mapping:
Segment Sections...
00 ... .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
01 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
02 .dynamic
So, there is section .got, but runtime linker ld-linux.so.2 (registered as interpreter for dynamic ELFs) does not load sections; it loads segments as described by Program header with LOAD type. .got is part of segment 01 LOAD with RW flags. Other library will have own GOT (think about compiling liblib2.so from the similar source, it will not know anything about liblib1.so and will have own GOT); so it is "Global" only for the library; but not to the whole program image in memory after loading.
How shared library knows offset to process's GOT when it(PIC library) does not know where in process memory it would be loaded?
It is done by static linker when it takes several ELF objects and combine them all into one library. Linker will generate .got section and put it to some place with known offset from the library code (pc-relative, rip-relative). It writes instructions to program header, so the relative address is known and it is the only needed address to access own GOT.
When objdump is used with -r / -R flags, it will print information about relocations (static / dynamic) recorded in the ELF file or library; it can be combined with -d flag. lib1.o object had relocation here; no known offset to GOT, mov has all zero:
$ objdump -dr lib1.o
lib1.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <shara_func>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 8b 05 00 00 00 00 mov 0x0(%rip),%rax # b <shara_func+0xb>
7: R_X86_64_REX_GOTPCRELX var-0x4
b: 48 8b 00 mov (%rax),%rax
e: 48 89 c6 mov %rax,%rsi
In library file this was converted to relative address by gcc -shared (it calls ld variant collect2 inside):
$ objdump -d liblib1.so
liblib1.so: file format elf64-x86-64
00000000000006d0 <shara_func>:
6d0: 55 push %rbp
6d1: 48 89 e5 mov %rsp,%rbp
6d4: 48 8b 05 fd 08 20 00 mov 0x2008fd(%rip),%rax # 200fd8 <_DYNAMIC+0x1c8>
And finally, there is dynamic relocation into GOT to put here actual address of var (done by rtld - ld-linux.so.2):
$ objdump -R liblib1.so
liblib1.so: file format elf64-x86-64
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
...
0000000000200fd8 R_X86_64_GLOB_DAT var
Let's use your lib, adding executable with definition, compiling it and running with rtld debugging enabled:
$ cat main.c
long var;
int main(){
shara_func();
return 0;
}
$ gcc main.c -llib1 -L. -o main -Wl,-rpath=`pwd`
$ LD_DEBUG=all ./main 2>&1 |less
...
311: symbol=var; lookup in file=./main [0]
311: binding file /test3/liblib1.so [0] to ./main [0]: normal symbol `var'
So, linker was able to bind relocation for var to the "main" ELF file where it is defined:
$ gdb -q ./main
Reading symbols from ./main...(no debugging symbols found)...done.
(gdb) b main
Breakpoint 1 at 0x4006da
(gdb) r
Starting program: /test3/main
Breakpoint 1, 0x00000000004006da in main ()
(gdb) disassemble shara_func
Dump of assembler code for function shara_func:
0x00007ffff7bd56d0 <+0>: push %rbp
0x00007ffff7bd56d1 <+1>: mov %rsp,%rbp
0x00007ffff7bd56d4 <+4>: mov 0x2008fd(%rip),%rax # 0x7ffff7dd5fd8
0x00007ffff7bd56db <+11>: mov (%rax),%rax
0x00007ffff7bd56de <+14>: mov %rax,%rsi
No changes in mov in your func. rax after func+4 is 0x601040, it is third mapping of ./main according to /proc/$pid/maps:
00601000-00602000 rw-p 00001000 08:07 6691394 /test3/main
And it was loaded from main after this program header (readelf -e ./main)
LOAD 0x0000000000000df0 0x0000000000600df0 0x0000000000600df0
0x0000000000000248 0x0000000000000258 RW 200000
It is part of .bss section:
[26] .bss NOBITS 0000000000601038 00001038
0000000000000010 0000000000000000 WA 0 0 8
After stepping to func+11, we can check value in GOT:
(gdb) b shara_func
(gdb) r
(gdb) si
0x00007ffff7bd56db in shara_func () from /test3/liblib1.so
1: x/i $pc
=> 0x7ffff7bd56db <shara_func+11>: mov (%rax),%rax
(gdb) p $rip+0x2008fd
$6 = (void (*)()) 0x7ffff7dd5fd8
(gdb) x/2x 0x7ffff7dd5fd8
0x7ffff7dd5fd8: 0x00601040 0x00000000
Who did write correct value to this GOT entry?
(gdb) watch *0x7ffff7dd5fd8
Hardware watchpoint 2: *0x7ffff7dd5fd8
(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /test3/main
Hardware watchpoint 2: *0x7ffff7dd5fd8
Old value = <unreadable>
New value = 6295616
0x00007ffff7de36bf in elf_machine_rela (..) at ../sysdeps/x86_64/dl-machine.h:435
(gdb) bt
#0 0x00007ffff7de36bf in elf_machine_rela (...) at ../sysdeps/x86_64/dl-machine.h:435
#1 elf_dynamic_do_Rela (...) at do-rel.h:137
#2 _dl_relocate_object (...) at dl-reloc.c:258
#3 0x00007ffff7ddaf5b in dl_main (...) at rtld.c:2072
#4 0x00007ffff7df0462 in _dl_sysdep_start (start_argptr=start_argptr#entry=0x7fffffffde20,
dl_main=dl_main#entry=0x7ffff7dd89a0 <dl_main>) at ../elf/dl-sysdep.c:249
#5 0x00007ffff7ddbe7a in _dl_start_final (arg=0x7fffffffde20) at rtld.c:307
#6 _dl_start (arg=0x7fffffffde20) at rtld.c:413
#7 0x00007ffff7dd7cc8 in _start () from /lib64/ld-linux-x86-64.so.2
(gdb) x/2x 0x7ffff7dd5fd8
0x7ffff7dd5fd8: 0x00601040 0x00000000
Runtime linker of glibc did (rtld.c), just before calling main - here is the source (bit different version) - http://code.metager.de/source/xref/gnu/glibc/sysdeps/x86_64/dl-machine.h
329 case R_X86_64_GLOB_DAT:
330 case R_X86_64_JUMP_SLOT:
331 *reloc_addr = value + reloc->r_addend;
332 break;
With reverse stepping we can get history of code and old value = 0:
(gdb) b _dl_relocate_object
(gdb) r
(gdb) dis 3
(gdb) target record-full
(gdb) c
(gdb) disp/i $pc
(gdb) rsi
(gdb) rsi
(gdb) rsi
(gdb) x/2x 0x7ffff7dd5fd8
0x7ffff7dd5fd8: 0x00000000 0x00000000
=> 0x7ffff7de36b8 <_dl_relocate_object+1560>: add 0x10(%rbx),%rax
=> 0x7ffff7de36bc <_dl_relocate_object+1564>: mov %rax,(%r10)
=> 0x7ffff7de36bf <_dl_relocate_object+1567>: nop

Can _start be the thumb function?

Help me please with gnu assembler for arm926ejs cpu.
I try to build a simple program(test.S):
.global _start
_start:
mov r0, #2
bx lr
and success build it:
arm-none-linux-gnueabi-as -mthumb -o test.o test.S
arm-none-linux-gnueabi-ld -o test test.o
but when I run the program in the arm target linux environment, I get an error:
./test
Segmentation fault
What am I doing wrong?
Can _start function be the thumb func?
or
It is always arm func?
Can _start be a thumb function (in a Linux user program)?
Yes it can. The steps are not as simple as you may believe.
Please use the .code 16 as described by others. Also look at ARM Script predicate; my answer shows how to detect a thumb binary. The entry symbol must have the traditional _start+1 value or Linux will decide to call your _start in ARM mode.
Also your code is trying to emulate,
int main(void) { return 2; }
The _start symbol must not do this (as per auselen). To do _start to main() in ARM mode you need,
#include <linux/unistd.h>
static inline void exit(int status)
{
asm volatile ("mov r0, %0\n\t"
"mov r7, %1\n\t"
"swi #7\n\t"
: : "r" (status),
"Ir" (__NR_exit)
: "r0", "r7");
}
/* Wrapper for main return code. */
void __attribute__ ((unused)) estart (int argc, char*argv[])
{
int rval = main(argc,argv);
exit(rval);
}
/* Setup arguments for estart [like main()]. */
void __attribute__ ((naked)) _start (void)
{
asm(" sub lr, lr, lr\n" /* Clear the link register. */
" ldr r0, [sp]\n" /* Get argc... */
" add r1, sp, #4\n" /* ... and argv ... */
" b estart\n" /* Let's go! */
);
}
It is good to clear the lr so that stack traces will terminate. You can avoid the argc and argv processing if you want. The start shows how to work with this. The estart is just a wrapper to convert the main() return code to an exit() call.
You need to convert the above assembler to Thumb equivalents. I would suggest using gcc inline assembler. You can convert to pure assembler source if you get inlines to work. However, doing this in 'C' source is probably more practical, unless you are trying to make a very minimal executable.
Helpful gcc arguements are,
-nostartfiles -static -nostdlib -isystem <path to linux user headers>
Add -mthumb and you should have a harness for either mode.
Your problem is you end with
bx lr
and you expect Linux to take over after that. That exact line must be the cause of Segmentation fault.
You can try to create a minimal executable then try to bisect it to see the guts and understand how an executable is expected to behave.
See below for a working example:
.global _start
.thumb_func
_start:
mov r0, #42
mov r7, #1
svc #0
compile with
arm-linux-gnueabihf-as start.s -o start.o && arm-linux-gnueabihf-ld
start.o -o start_test
and dump to see the guts
$ arm-linux-gnueabihf-readelf -a -W start_test
Now you should notice the odd address of _start
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: 0x8055
Start of program headers: 52 (bytes into file)
Start of section headers: 160 (bytes into file)
Flags: 0x5000000, Version5 EABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 1
Size of section headers: 40 (bytes)
Number of section headers: 6
Section header string table index: 3
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 00008054 000054 000006 00 AX 0 0 4
[ 2] .ARM.attributes ARM_ATTRIBUTES 00000000 00005a 000014 00 0 0 1
[ 3] .shstrtab STRTAB 00000000 00006e 000031 00 0 0 1
[ 4] .symtab SYMTAB 00000000 000190 0000e0 10 5 6 4
[ 5] .strtab STRTAB 00000000 000270 000058 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.
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
LOAD 0x000000 0x00008000 0x00008000 0x0005a 0x0005a R E 0x8000
Section to Segment mapping:
Segment Sections...
00 .text
There is no dynamic section in this file.
There are no relocations in this file.
There are no unwind sections in this file.
Symbol table '.symtab' contains 14 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00008054 0 SECTION LOCAL DEFAULT 1
2: 00000000 0 SECTION LOCAL DEFAULT 2
3: 00000000 0 FILE LOCAL DEFAULT ABS start.o
4: 00008054 0 NOTYPE LOCAL DEFAULT 1 $t
5: 00000000 0 FILE LOCAL DEFAULT ABS
6: 0001005a 0 NOTYPE GLOBAL DEFAULT 1 _bss_end__
7: 0001005a 0 NOTYPE GLOBAL DEFAULT 1 __bss_start__
8: 0001005a 0 NOTYPE GLOBAL DEFAULT 1 __bss_end__
9: 00008055 0 FUNC GLOBAL DEFAULT 1 _start
10: 0001005a 0 NOTYPE GLOBAL DEFAULT 1 __bss_start
11: 0001005c 0 NOTYPE GLOBAL DEFAULT 1 __end__
12: 0001005a 0 NOTYPE GLOBAL DEFAULT 1 _edata
13: 0001005c 0 NOTYPE GLOBAL DEFAULT 1 _end
No version information found in this file.
Attribute Section: aeabi
File Attributes
Tag_CPU_arch: v4T
Tag_THUMB_ISA_use: Thumb-1
here answer.
Thanks for all.
http://stuff.mit.edu/afs/sipb/project/egcs/src/egcs/gcc/config/arm/README-interworking
Calls via function pointers should use the BX instruction if the call is made in ARM mode:
.code 32
mov lr, pc
bx rX
This code sequence will not work in Thumb mode however, since the mov instruction will not set the bottom bit of the lr register. Instead a branch-and-link to the _call_via_rX functions should be used instead:
.code 16
bl _call_via_rX
where rX is replaced by the name of the register containing the function address.

Resources