- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个 C 程序的目标文件,它打印 hello world,只是为了这个问题。我试图了解使用 readelf 实用程序或 gdb 或 hexedit(我无法确定哪个工具是正确的)文件中函数“main”的代码从哪里开始。
我知道使用 readelf 会出现符号 _start & main 以及它在虚拟内存中映射的地址。此外,我还知道 .text 部分的大小和指定入口点的 coruse 的大小,即与 text 部分相同的地址。
问题是 - 函数“main”的代码在文件中的哪里开始?我认为这是文本部分的入口点和偏移量,但我如何理解数据、bss、rodata 部分应该在 main 之前运行,并且它出现在 readelf 中的部分文本之后。
此外,我认为我们应该将符号表中直到 main 为止的所有行的大小相加,但我根本不确定它是否正确。
后续的另一个问题是我是否想用 NOP 指令替换 main 函数或在我的目标文件中植入一个 ret 指令。我怎样才能知道可以使用十六进制编辑器执行此操作的偏移量。
最佳答案
那么,让我们一步一步来。
从这个 C 文件开始:
#include <stdio.h>
void printit()
{
puts("Hello world!");
}
int main(void)
{
printit();
return 0;
}
由于注释看起来像是在 x86 上,因此将其编译为 32 位非 PIE 可执行文件,如下所示:
$ gcc -m32 -no-pie -o test test.c
需要 -m32
选项,因为我在 x86-64 机器上工作。如您所知,您可以使用 readelf、objdump 或 nm 获取 main 的虚拟内存地址,例如如下所示:
$ nm test | grep -w main
0804918d T main
显然,804918d
不能是大小仅为 15 kB 的文件中的偏移量。您需要找到虚拟内存地址和文件偏移量之间的映射。在典型的 ELF 文件中,映射包含两次。一次是链接器(因为目标文件也是 ELF 文件)和调试器的详细形式,第二次是内核用于加载程序的压缩形式。详细形式是部分列表,由部分标题组成,您可以像这样查看它(输出被缩短了一点,以使答案更具可读性):
$ readelf --section-headers test
There are 29 section headers, starting at offset 0x3748:
Section Headers:
[Nr] Name Type Addr Off Size ES Flg Lk Inf Al
[...]
[11] .init PROGBITS 08049000 001000 000020 00 AX 0 0 4
[12] .plt PROGBITS 08049020 001020 000030 04 AX 0 0 16
[13] .text PROGBITS 08049050 001050 0001c1 00 AX 0 0 16
[14] .fini PROGBITS 08049214 001214 000014 00 AX 0 0 4
[15] .rodata PROGBITS 0804a000 002000 000015 00 A 0 0 4
[...]
Key to Flags:
W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
L (link order), O (extra OS processing required), G (group), T (TLS),
C (compressed), x (unknown), o (OS specific), E (exclude),
p (processor specific)
在这里您会发现.text
部分从(虚拟)地址08049050
开始,大小为1c1
字节,因此它结束地址08049211
。 main 的地址 804918d
在此范围内,因此您知道 main
是文本部分的成员。如果从 main 的地址中减去文本部分的基址,您会发现 main 占文本部分的 13d
字节。节列表还包含文本节数据开始的文件偏移量。它是 1050
,因此 main 的第一个字节位于偏移量 0x1050 + 0x13d == 0x118d
。
您可以使用程序头进行相同的计算:
$ readelf --program-headers test
[...]
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00160 0x00160 R 0x4
INTERP 0x000194 0x08048194 0x08048194 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x002e8 0x002e8 R 0x1000
LOAD 0x001000 0x08049000 0x08049000 0x00228 0x00228 R E 0x1000
LOAD 0x002000 0x0804a000 0x0804a000 0x0019c 0x0019c R 0x1000
LOAD 0x002f0c 0x0804bf0c 0x0804bf0c 0x00110 0x00114 RW 0x1000
[...]
第二个加载行告诉您,08049000
(VirtAddr) 到 08049228
(VirtAddr + MemSiz) 的区域是可读且可执行的,并从偏移量 1000 加载
在文件中。因此,您可以再次计算出 main 的地址是此加载区域的 18d
字节,因此它必须驻留在可执行文件内的偏移量 0x118d
处。让我们测试一下:
$ ./test
Hello world!
$ echo -ne '\xc3' | dd of=test conv=notrunc bs=1 count=1 seek=$((0x118d))
1+0 records in
1+0 records out
1 byte copied, 0.0116672 s, 0.1 kB/s
$ ./test
$
使用 x86 上 return(near)的操作码 0xc3
覆盖 main 的第一个字节,导致程序不再输出任何内容。
关于c - 函数 "main"的代码在目标文件中的哪里开始?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62088056/
我尝试理解[c代码 -> 汇编]代码 void node::Check( data & _data1, vector& _data2) { -> push ebp -> mov ebp,esp ->
我需要在当前表单(代码)的上下文中运行文本文件中的代码。其中一项要求是让代码创建新控件并将其添加到当前窗体。 例如,在Form1.cs中: using System.Windows.Forms; ..
我有此 C++ 代码并将其转换为 C# (.net Framework 4) 代码。有没有人给我一些关于 malloc、free 和 sprintf 方法的提示? int monate = ee; d
我的网络服务器代码有问题 #include #include #include #include #include #include #include int
给定以下 html 代码,将列表中的第三个元素(即“美丽”一词)以斜体显示的 CSS 代码是什么?当然,我可以给这个元素一个 id 或一个 class,但 html 代码必须保持不变。谢谢
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我试图制作一个宏来避免重复代码和注释。 我试过这个: #define GrowOnPage(any Page, any Component) Component.Width := Page.Surfa
我正在尝试将我的旧 C++ 代码“翻译”成头条新闻所暗示的 C# 代码。问题是我是 C# 中的新手,并不是所有的东西都像 C++ 中那样。在 C++ 中这些解决方案运行良好,但在 C# 中只是不能。我
在 Windows 10 上工作,R 语言的格式化程序似乎没有在 Visual Studio Code 中完成它的工作。我试过R support for Visual Studio Code和 R-T
我正在处理一些报告(计数),我必须获取不同参数的计数。非常简单但乏味。 一个参数的示例查询: qCountsEmployee = ( "select count(*) from %s wher
最近几天我尝试从 d00m 调试网络错误。我开始用尽想法/线索,我希望其他 SO 用户拥有可能有用的宝贵经验。我希望能够提供所有相关信息,但我个人无法控制服务器环境。 整个事情始于用户注意到我们应用程
我有一个 app.js 文件,其中包含如下 dojo amd 模式代码: require(["dojo/dom", ..], function(dom){ dom.byId('someId').i
我对“-gencode”语句中的“code=sm_X”选项有点困惑。 一个例子:NVCC 编译器选项有什么作用 -gencode arch=compute_13,code=sm_13 嵌入库中? 只有
我为我的表格使用 X-editable 框架。 但是我有一些问题。 $(document).ready(function() { $('.access').editable({
我一直在通过本教程学习 flask/python http://blog.miguelgrinberg.com/post/the-flask-mega-tutorial-part-i-hello-wo
我想将 Vim 和 EMACS 用于 CNC、G 代码和 M 代码。 Vim 或 EMACS 是否有任何语法或模式来处理这种类型的代码? 最佳答案 一些快速搜索使我找到了 this vim 和 thi
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 想改进这个问题?更新问题,使其成为 on-topic对于堆栈溢出。 7年前关闭。 Improve this
这个问题在这里已经有了答案: Enabling markdown highlighting in Vim (5 个回答) 6年前关闭。 当我在 Vim 中编辑包含 Markdown 代码的 READM
我正在 Swift3 iOS 中开发视频应用程序。基本上我必须将视频 Assets 和音频与淡入淡出效果合并为一个并将其保存到 iPhone 画廊。为此,我使用以下方法: private func d
pipeline { agent any stages { stage('Build') { steps { e
我是一名优秀的程序员,十分优秀!