我正在开发一个大型项目,涉及编写Perl脚本来转换汇编文件,我正在尝试确定转换后汇编文件的样子,以及编译它们的过程。我一直无法找到一个简单的例子来工作。我从一个简单的程序开始,fib.c。我编译了它,然后添加了一个名为跳板的部分。
.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
我使用这些命令进一步编译:
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
我遇到问题的部分是GNU链接器脚本。我希望能够将跳板部分放在特定的内存地址。这是脚本:
OUTPUT_FORMAT(elf32-i386)
ENTRY(main)
SB_START = 0x08148508;
SECTIONS
{
. = SB_START;
.springboard : { *(.springboard) }
}
我已经坚持了一段时间,并尝试了一些不同的东西,我对链接器脚本很新,所以也许这对你们中的一些人来说很容易。
使用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
然后使用脚本:
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
我希望了解更多关于我可以使用链接器脚本做什么以及如何做到这一点。我已经阅读了其他问题和教程,但我仍然很困惑。我不完全理解所有部分是什么以及它们应该去哪里,我想我会从简单的东西开始并添加一个,但我可能会更详细地了解它以使其工作。有关如何修复链接器脚本的任何想法?关于这个问题我还需要了解什么?谢谢!
在Ubuntu机器上工作,我只专注于32位程序。
答案 0 :(得分:1)
您确实参考了GNU linker manual?第3章确实解释了链接器脚本。但是,它不会赢得任何最佳手册奖。 :)
您看到的部分是各种数据(.data,.bss,.rodata)和代码(.text,.init,.fini)部分。更多细节here。也可以尝试使用Google搜索部分名称。
答案 1 :(得分:1)
问题在于行ENTRY(main)
。这表明程序将从那时开始。
Argc和Argv由crt1.o设置,如下所述:How to correctly use a simple linker script? Executable gets SIGKILL when run
这意味着我们根本不需要入口点。如果我们把它作为我们的入口点,那么参数将无法正确设置。 crt1.o也将调用main。链接器脚本现在看起来像这样:
OUTPUT_FORMAT(elf32-i386)
SECTIONS
{
. = 0x08148508;
.springboard : { *(.springboard) }
}