gpt4 book ai didi

linker - 为什么使用 "ld -e"选项无法更改 ELF 入口点 0x8048000?

转载 作者:行者123 更新时间:2023-12-04 02:50:49 26 4
gpt4 key购买 nike

关注 Why is the ELF execution entry point virtual address of the form 0x80xxxxx and not zero 0x0?Why do virtual memory addresses for linux binaries start at 0x8048000? ,为什么我做不到ld使用与 ld -e 不同的入口点?

如果我这样做,我要么得到一个 segmentation fault返回代码为 139,即使对于默认入口点附近的地址也是如此。为什么?

编辑:

我会让问题更具体:

        .text
.globl _start
_start:
movl $0x4,%eax # eax = code for 'write' system call
movl $1,%ebx # ebx = file descriptor to standard output
movl $message,%ecx # ecx = pointer to the message
movl $13,%edx # edx = length of the message
int $0x80 # make the system call
movl $0x0,%ebx # the status returned by 'exit'
movl $0x1,%eax # eax = code for 'exit' system call
int $0x80 # make the system call
.data
.globl message
message:
.string "Hello world\n" # The message as data

如果我用 as program.s -o program.o 编译它然后将其与 ld -N program.o -o program 静态链接, readelf -l program显示 0x0000000000400078VirtAddr文本段和 0x400078作为切入点。运行时,打印“Hello world”。

但是,当我尝试与 ld -N -e0x400082 -Ttext=0x400082 program.o -o program 链接时(将文本段和入口点移动 4 个字节),程序将为 killed .用 readelf -l 检查它现在显示 LOAD 类型的两个不同的标题, 一个在 0x0000000000400082和一个在 0x00000000004000b0 .

当我尝试时 0x400086 ,一切正常,而且只有一个 LOAD部分。
  • 这里发生了什么?
  • 我可以选择哪些内存地址,哪些不能选择,为什么?

  • 谢谢。

    最佳答案

    why cannot I make ld use a different entry point than the default with ld -e



    你肯定可以。这个:
    int foo(int argc, char *argv[]) { return 0; }

    gcc main.c -Wl,-e,foo

    不起作用,因为执行不是从 main 开始的。它始于 _start ,链接自 crt0.o (glibc 的一部分)并安排诸如动态链接之类的事情正确启动。通过重定向 _startfoo ,你已经绕过了所有需要的 glibc 初始化,所以事情不起作用。

    但是如果您不需要动态链接,并且愿意做 glibc 通常为您做的事情,那么您可以随意命名入口点。例子:
    #include <syscall.h>

    int foo()
    {
    syscall(SYS_write, 1, "Hello, world\n", 13);
    syscall(SYS_exit, 0);
    }

    gcc t.c -static -nostartfiles -Wl,-e,foo && ./a.out
    Hello, world

    哦,你这个问题的标题与你的实际问题不符(坏主意(TM))。

    要回答标题中的问题,您肯定可以更改链接可执行文件的地址。默认情况下,您会收到 0x8048000加载地址(仅限 32 位;64 位默认为 0x400000 )。

    您可以轻松地将其更改为例如 0x80000通过添加 -Wl,-Ttext-segment=0x80000到链接线。

    更新:

    However, when I try to link with ld -N -e0x400082 -Ttext=0x400082 program.o -o program (moving text segment and entry point by 4 bytes), the program will be killed.



    好吧,不可能分配 Ttext0x400082不违反 .text部分对齐约束(即 4)。您必须保持 .text 地址在至少 4 字节边界上对齐(或更改 .text 所需的对齐方式)。

    当我将起始地址设置为 0x400078、0x40007c、0x400080、0x400084、...、0x400098 并使用 GNU-ld 2.20.1 时,程序就可以运行了。

    但是,当我使用 binutils 的当前 CVS 快照时,该程序适用于 0x400078、0x40007c、0x400088、0x40008c,并且在 0x400080、0x400084、0x400090、0x404090 处被杀死这可能是链接器中的错误,或者我违反了其他一些约束(虽然我不知道是哪个)。

    此时,如果你真的有兴趣,建议下载binutils源码,构建 ld ,并找出究竟是什么导致它创建两个 PT_LOAD段而不是一个。

    更新 2:

    Force new segment for sections with overlapping LMAs.



    啊!那只是意味着您需要移动 .data挡道。这使得一个有效的可执行文件:
    ld -N -o t t.o -e0x400080 -Ttext=0x400080 -Tdata=0x400180

    关于linker - 为什么使用 "ld -e"选项无法更改 ELF 入口点 0x8048000?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8116648/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com