Linux 静态elf映像设置的段%fs在哪里?
我正在试图弄清楚%fs寄存器是如何初始化的 手动创建elf图像时 我想运行的简单代码段是:Linux 静态elf映像设置的段%fs在哪里?,linux,gcc,linker,glibc,elf,Linux,Gcc,Linker,Glibc,Elf,我正在试图弄清楚%fs寄存器是如何初始化的 手动创建elf图像时 我想运行的简单代码段是: .text nop movq %fs:0x28, %rax; 1: jmp 1b 应在%fs段中的偏移量0x28处读取。通常这是堆栈金丝雀的存储位置。因为我是手工创建elf映像的,%fs段根本不是由我的代码设置的,所以预期会失败(?) 以下是我如何创建elf图像: 0000000000000000 <.text>: 0: 9
.text
nop
movq %fs:0x28, %rax;
1: jmp 1b
应在%fs段中的偏移量0x28处读取。通常这是堆栈金丝雀的存储位置。因为我是手工创建elf映像的,%fs段根本不是由我的代码设置的,所以预期会失败(?)
以下是我如何创建elf图像:
0000000000000000 <.text>:
0: 90 nop
1: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax
8: 00 00
a: eb fe jmp 0xa
然后我转换为elf:
ld -b binary -r -o raw.elf r2.bin
objcopy --rename-section .data=.text --set-section-flags .data=alloc,code,load raw.elf
此时,raw.elf
包含我的指令。然后我链接到
ld-T raw.ld-o out.elf-M--verbose
其中raw.ld是:
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64")
OUTPUT_ARCH(i386:x86-64)
ENTRY(_entry)
PHDRS {
phdr4000000 PT_LOAD;
}
SECTIONS
{
_entry = 0x4000000;
.text 0x4000000 : { raw.elf (.text) } :phdr4000000
}
我现在可以使用gdb启动out.elf:
gdb --args out.elf
并将断点设置为0x4000000:
(gdb)break *0x4000000
(gdb)run
第一个nop
可以通过stepi
步进,但是堆栈金丝雀读取mov%fs:0x28,%rax
segfults
我想这是意料之中的,因为操作系统可能没有设置%fs。
对于一个简单的m.c:int main(){return 0;}
使用gcc--static m.c-om
编译的程序,我可以从%fs读取。添加:
long can()
{
long v = 0;
__asm__("movq %%fs:0x28, %0;"
: "=r"(val)::);
return v;
}
允许我读取%fs-尽管我怀疑%fs:28是否已设置,因为ld.so未运行(它是静态映像)
问题:
有人能指出在c运行时为静态图像设置%fs的位置吗?在使用%fs
段前缀之前,需要使用ARCH\u SET\u fs
参数调用。您必须将备份存储分配到某个位置(brk
、mmap
,或堆栈中其他未使用的部分)
glibc在csu/libc tls.c
中的\u libc\u setup\u tls
中为静态链接的二进制文件执行此操作,隐藏在tls\u INIT\u TP
宏后面
long can()
{
long v = 0;
__asm__("movq %%fs:0x28, %0;"
: "=r"(val)::);
return v;
}