如何使用链接描述文件指定特定部分的内存地址?

时间:2014-01-07 02:13:36

标签: c assembly ld

我正在开发一个大型项目,涉及编写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位程序。

2 个答案:

答案 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) }
}