AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / user-11588863

pikafan_8080's questions

Martin Hope
pikafan_8080
Asked: 2023-10-06 20:16:12 +0800 CST

如何使用GNU Assembler (GAS)从相应的.s文件创建手写的ELF文件

  • 7

介绍

我正在尝试了解ELF文件,并对它们进行一些实验。目前,我正在遵循此处的教程,该教程是关于创建一个仅以代码 42 退出的小型 32 位ELF文件。本教程使用NASM和ld来创建ELF文件。但是,我想使用GNU Assembler (GAS)创建 64 位ELF文件(而不是 32 位),因为我对它有点熟悉(但不是使用它的专家!)

我目前陷入了教程的部分,他们ELF从头开始创建文件 - 这涉及编写ELF标头和程序标头。由于 32 位和 64 位ELF文件略有不同(例如,在 ELF 标头大小方面),我的.s文件版本如下:

.intel_syntax noprefix
ehdr:
        .byte 0x7F
        .byte 0x45 # E
        .byte 0x4c # L
        .byte 0x46 # F
        .byte 0x02 # 64 bit ; CLASS
        .byte 0x01 # lsb ; DATA
        .byte 0x01 # ; VERSION
        .byte 0x00 # None/Sytem V ; OS ABI
        .8byte 0x0 # ABI VERSION + PADDING

        .2byte 0x02 # ET_EXEC ; E_TYPE
        .2byte 0x3E # AMD64 ; E_MACHINE
        .4byte 0x01 # 1 ; E_VERSION
        .8byte _start # ; E_ENTRY
        .8byte phdr - ehdr # offset into program header ; E_PHOFF
        .8byte 0x00 # offset into section header ; E_SHOFF
        .4byte 0x00 # flag ; E_FLAGS
        .2byte ehdrsize # ELF header size ; E_EHSIZE
        .2byte phdrsize # Program header size ; E_PHSIZE
        .2byte 0x01 # Number of program headers ; E_PHNUM
        .2byte 0x00 # Section header size ; E_SHENTSIZE
        .2byte 0x00 # Number of section headers ; E_SHNUM
        .2byte 0x00 # Section header string table index ; E_SHSTRNDX

DECLARE_ELF_HEADER_SIZE:
.set ehdrsize,  DECLARE_ELF_HEADER_SIZE - ehdr

phdr:
        .4byte 0x01 # PT_LOAD ; P_TYPE
        .4byte 0x00 # located at offset 0??? ; P_OFFSET
        .8byte ehdr # ; P_VADDR
        .8byte ehdr # ; P_PADDR
        .8byte filesize # ; P_FILESIZE
        .8byte filesize # ; P_MEMSZ
        .8byte 5 # R-X ; P_FLAGS
        .8byte 0x1000 # P_ALIGN

DECLARE_PHEADER_SIZE:
.set phdrsize, DECLARE_PHEADER_SIZE - phdr

_start:
        mov eax, 60
        mov edi, 42
        syscall

DECLARE_FILE_SIZE:
.set filesize, DECLARE_FILE_SIZE - ehdr

有关 ELF 文件头的更多信息可以通过查看此处的相应源代码来找到。由于我仍在学习ELF文件,上面的代码可能不正确(如果您发现任何错误,请告诉我!)

问题

假设上面的代码是正确的,我想将上面的.s文件转换成一个ELF文件。为此,本教程使用以下命令:

$ nasm -f bin -o a.out tiny.asm

但是,我无法找到我应该使用 GAS 的相应命令来创建相应的文件ELF,这就是我面临的问题。

我尝试过的...

我尝试过各种方法。我将在下面列出它们:

  1. SO上有一个类似的问题,可以在这里找到。该方法使用以下2条命令来获取对应的ELF文件:
$ as --64 -o test.o test.s 
$ ld -Ttext 200000 --oformat binary -o test.bin test.o

.s对我编写的文件运行相同的命令,我确实得到了一个 ELF 文件,以及以下警告:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000200000

运行生成的 ELF 文件会出现分段错误,并以代码 139 退出。生成的文件的标ELF头如下(通过运行获得readelf -h <output ELF file>):

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x200078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           0 (bytes)
  Number of section headers:         0
  Section header string table index: 0
readelf: Error: the segment's file size is larger than its memory size

我相信发生了分段错误,因为它很可能是不正确的(错误消息中Entry Point address也暗示了这一点)。ld

  1. 在这种方法中,我修改了命令:
$ as --64 -o test.o test.s 
$ ld -Ttext 200000 --oformat binary -o test.bin test.o

到

$ as --64 -o test.o test.s (same as before) 
$ ld -nmagic -s test.o (changed)

这也会创建一个 ELF 文件,但同样会出现以下警告:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400078

这再次暗示我们将遇到分段错误,新ELF文件确实就是这种情况。该文件的 ELF 标头是:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x400078
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           64 (bytes)
  Number of section headers:         0
  Section header string table index: 0

没有运气!

  1. 从给出的警告来看ld,看起来我们可能想要.global _start在我们的.s文件中添加。.s下面是也包含此行的新文件:
.intel_syntax noprefix
.global _start   # Added here
ehdr:
        .byte 0x7F
        .byte 0x45 # E
        .byte 0x4c # L
        .byte 0x46 # F
        .byte 0x02 # 64 bit ; CLASS
        .byte 0x01 # lsb ; DATA
        .byte 0x01 # ; VERSION
        .byte 0x00 # None/Sytem V ; OS ABI
        .8byte 0x0 # ABI VERSION + PADDING

        .2byte 0x02 # ET_EXEC ; E_TYPE
        .2byte 0x3E # AMD64 ; E_MACHINE
        .4byte 0x01 # 1 ; E_VERSION
        .8byte _start # ; E_ENTRY
        .8byte phdr - ehdr # offset into program header ; E_PHOFF
        .8byte 0x00 # offset into section header ; E_SHOFF
        .4byte 0x00 # flag ; E_FLAGS
        .2byte ehdrsize # ELF header size ; E_EHSIZE
        .2byte phdrsize # Program header size ; E_PHSIZE
        .2byte 0x01 # Number of program headers ; E_PHNUM
        .2byte 0x00 # Section header size ; E_SHENTSIZE
        .2byte 0x00 # Number of section headers ; E_SHNUM
        .2byte 0x00 # Section header string table index ; E_SHSTRNDX

DECLARE_ELF_HEADER_SIZE:
.set ehdrsize,  DECLARE_ELF_HEADER_SIZE - ehdr

phdr:
        .4byte 0x01 # PT_LOAD ; P_TYPE
        .4byte 0x00 # located at offset 0??? ; P_OFFSET
        .8byte ehdr # ; P_VADDR
        .8byte ehdr # ; P_PADDR
        .8byte filesize # ; P_FILESIZE
        .8byte filesize # ; P_MEMSZ
        .8byte 5 # R-X ; P_FLAGS
        .8byte 0x1000 # P_ALIGN

DECLARE_PHEADER_SIZE:
.set phdrsize, DECLARE_PHEADER_SIZE - phdr

_start:
        mov eax, 60
        mov edi, 42
        syscall

DECLARE_FILE_SIZE:
.set filesize, DECLARE_FILE_SIZE - ehdr

再次,我们使用以下命令为上述代码创建 ELF 文件:

$ as --64 -o test.o test.s 
$ ld -nmagic -s test.o 

这次,我们没有收到任何错误,并且 ELF 文件执行了它应该执行的操作(即以代码 42 退出)。该文件的 ELF 标头是:

ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x4000f0
  Start of program headers:          64 (bytes into file)
  Start of section headers:          0 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         1
  Size of section headers:           64 (bytes)
  Number of section headers:         0
  Section header string table index: 0

问题解决了,嗯?

不幸的是,我不这么认为。深入研究二进制文件发现它没有ELF使用我们在文件中编写的手写标头.s:

gef➤  search-pattern 'ELF'
[+] Searching 'ELF' in memory
[+] In '/home/VM/Desktop/Experiments/ELF/a.out'(0x400000-0x401000), permission=r-x
  0x400001 - 0x400004  →   "ELF[...]"
  0x400079 - 0x40007c  →   "ELF[...]"

哎呀,看起来ld(或者as,我不确定!)创建了自己的ELF标头(从有 2 个位置包含字符串这一事实可以明显看出。ELF根据我的理解,ELF字符串 at0x400001是由 ( 贡献的ld)或as),其中的内容0x400079是我包含在.s文件中的内容。

然而,这违背了从头开始编写 ELF 文件的初衷,包括ELF头文件和程序头文件!我也确信我之前列出的方法 1 和方法 2 中存在此问题,但由于它们无论如何都因分段错误而退出,因此我没有在这些方法中突出显示此问题。

现在,我不知道该怎么做,所以我非常感谢任何帮助ELF正确构建文件的帮助!

多谢!

assembly
  • 1 个回答
  • 30 Views

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve