- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个小的 c 代码文件(function.c):
int function()
{
return 0x1234abce;
}
gcc function.c -c -m32 -o file.o -ffreestanding # This gives you the object file
ld -o function.bin -m elf_i386 -Ttext 0x0 --oformat binary function.o
function.o: In function `function':
function.c:(.text+0x9): undefined reference to `_GLOBAL_OFFSET_TABLE_'
最佳答案
您需要-fno-pie
; default (in most modern distros) is -fpie
: generate code for a position-independent executable .这是一个独立于 -pie
的代码生成选项。链接器选项(默认情况下 gcc 也会通过),并且独立于 -ffreestanding
. -fpie -ffreestanding
意味着您想要一个使用 GOT 的独立 PIE,这就是 GCC 的目标。-fpie
仅在 64 位代码中花费一点速度(其中 RIP 相对寻址是可能的),但对于 32 位代码来说非常糟糕;编译器在其中一个整数寄存器中获得指向 GOT 的指针(占用 8 个寄存器中的另一个),并使用 [reg + disp32]
访问相对于该地址的静态数据。寻址模式,如 [eax + foo@GOTOFF]
禁用优化,gcc -fpie -m32
在寄存器 中生成 GOT 的地址即使该函数不访问任何静态数据。如果您查看编译器输出(在您正在编译的机器上使用 gcc -S
而不是 -c
),您会看到这一点。
On Godbolt我们可以使用 -m32 -fpie
提供与配置了 --enable-default-pie
的 GCC 相同的效果:
# gcc9.2 -O0 -m32 -fpie
function():
push ebp
mov ebp, esp # frame pointer
call __x86.get_pc_thunk.ax
add eax, OFFSET FLAT:_GLOBAL_OFFSET_TABLE_ # EAX points to the GOT
mov eax, 305441742 # overwrite with the return value
pop ebp
ret
__x86.get_pc_thunk.ax: # this is the helper function gcc calls
mov eax, DWORD PTR [esp]
ret
call
之后的指令地址.
.ax
name 表示在 EAX 中返回。现代 GCC 可以选择任何寄存器;传统上,32 位 PIC 基址寄存器始终是 EBX,但现代 GCC 在避免额外保存/恢复 EBX 时选择了一个 call-clobbered 寄存器。
call +0; pop eax
会更有效率,并且在每个调用站点只增加 1 个字节。您可能认为这会使返回地址预测器堆栈失衡,但实际上
call +0
在大多数 CPU 上都是特殊情况,不会这样做。
http://blog.stuffedcow.net/2018/04/ras-microbenchmarks/#call0 . (
call +0
表示 rel32 = 0,因此它调用下一条指令。不过,NASM 不是这样解释该语法的。)
-O0
处也是如此。 .但它使用
call +0
;
pop %eax
:
https://godbolt.org/z/GFY9Ht
关于c - 在 gcc 32 位代码中未定义的对 `_GLOBAL_OFFSET_TABLE_' 的引用,用于一个简单的函数,独立的操作系统,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59070109/
我正在使用 Rust 开发操作系统,尝试链接时遇到以下错误: undefined reference to '_GLOBAL_OFFSET_TABLE_' 据我所知,这是由调用另一个 Rust 函数引
我想在我的程序中获取 _GLOBAL_OFFSET_TABLE_ 的地址。一种方法是使用 nm Linux 中的命令,可能会将输出重定向到一个文件并解析该文件以获取 _GLOBAL_OFFSET_TA
这就是问题所在: 当我使用 ld 在 C 中链接脚本时,当我在 ld 中生成 elf32-i386 文件作为输出格式,并将其作为 OUTPUT_FORMAT() 放在 ld 脚本中时,我没有任何错误,
我有一个小的 c 代码文件(function.c): int function() { return 0x1234abce; } 我使用的是 64 位机器。但是,我想写一个小的 32 位操作系
我是一名优秀的程序员,十分优秀!