Linux 静态elf映像设置的段%fs在哪里?

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

我正在试图弄清楚%fs寄存器是如何初始化的 手动创建elf图像时

我想运行的简单代码段是:

        .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;
}