Linux 什么是程序集中的 %gs

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9249315/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 04:32:17  来源:igfitidea点击:

What is %gs in Assembly

linuxassemblyx86

提问by Alex F

void return_input (void)
{ 
   char array[30]; 

   gets (array); 
   printf("%s\n", array); 
}

After compiling it in gcc, this function is converted to the following Assembly code:

在gcc中编译后,这个函数被转换成如下汇编代码:

push   %ebp
mov    %esp,%ebp
sub    
mov    %gs:0x14,%eax
xor    %gs:0x14,%eax
x28,%esp mov %gs:0x14,%eax mov %eax,-0x4(%ebp) xor %eax,%eax lea -0x22(%ebp),%eax mov %eax,(%esp) call 0x8048374 lea -0x22(%ebp),%eax mov %eax,(%esp) call 0x80483a4 mov -0x4(%ebp),%eax xor %gs:0x14,%eax je 0x80484ac call 0x8048394 leave ret

I don't understand two lines:

我不明白两行:

cc -c -mpreferred-stack-boundary=2 -ggdb file.c

What is %gs, and what exactly these two lines do?

什么是 %gs,这两行到底是做什么的?

This is compilation command:

这是编译命令:

mov    %gs:0x14,%eax
xor    %gs:0x14,%eax

采纳答案by Necrolis

GS is a segment register, its use in linux can be read up on here(its basically used for per process data).

GS 是一个段寄存器,它在 linux 中的使用可以在这里读取(它基本上用于每个进程的数据)。

##代码##

this code is used to validate that the stack hasn't exploded or been corupted, using a canary value stored at GS+0x14, see this.

此代码用于验证堆栈没有爆炸或损坏,使用存储在 GS+0x14 的金丝雀值,请参阅

回答by Sergey Benner

ES, FS, GS: Extra Segment Registers Can be used as extra segment registers; also used in special instructions that span segments (like string copies). taken from here

ES、FS、GS:Extra Segment Registers 可以作为额外的段寄存器使用;也用于跨段的特殊指令(如字符串副本)。取自这里

http://www.hep.wisc.edu/~pinghc/x86AssmTutorial.htm

http://www.hep.wisc.edu/~pinghc/x86AssmTutorial.htm



hope it helps

希望能帮助到你

回答by dig

In the AT&T style assembly languages, the percent sigil generally indicates a register. In x86 family processors from 386 onwards, GS is one of the so-called segment registers. However, in protected mode environments segment registers work as selector registers.

在 AT&T 风格的汇编语言中,百分比符号通常表示一个寄存器。在 386 以后的 x86 系列处理器中,GS 是所谓的段寄存器之一。然而,在保护模式环境中,段寄存器作为选择器寄存器工作。

A virtual memory selector represents its own mapping of virtual address space together with its own access regime. In practical terms, %gs:0x14can be thought of as a reference into an array whose origin is held in %gs (albeit the CPU does a bit of extra dereferencing). On modern GNU/Linux systems, %gsis usually used to point at the thread-local storage region. In the code you're asking about, however, only one item of the TLS matters —?the stack canary.

虚拟内存选择器代表它自己的虚拟地址空间映射以及它自己的访问机制。实际上,%gs:0x14可以将其视为对原点保存在 %gs 中的数组的引用(尽管 CPU 做了一些额外的解引用)。在现代 GNU/Linux 系统上,%gs通常用于指向线程本地存储区域。然而,在您询问的代码中,只有一项 TLS 很重要——堆栈金丝雀。

The idea is to attempt to detect a buffer overflow error by placing a random but constant value — it's called a stack canaryin memory of the canaries coal miners used to employ to signal increase in levels of poisonous gases by dying — into the stack before gets()gets called, above its stack frame, and check whether it is still there after gets()will have returned. gets()has no business overwriting this part of the stack — it is outside its own stack frame, and it is not given a pointer to it —, so if the stack canary has died, something has gone wrong in a dangerous way. (C as a programming environment happens to be particularly prone to this kind of wrong-goings, and security researchers have learnt to exploit many of them over the last twenty years or so. Also, gets()happens to be a function that is inherently at risk to overflow its target buffer.) You have not offered addresses with your code, but 0x80484ac is likely the address of leave, and the call 0x8048394which is executed in case of mismatch (that is, jumped over by je 0x80484acin case of match), is probably a call to __stack_chk_fail(), provided by libc to handle the stack corruption by fleeing the metaphorical poisonous mine.

我们的想法是试图通过将一个随机的,但恒定的值来检测缓冲区溢出错误-它被称为堆金丝雀通过死在有毒有害气体的含量用于聘请到信号增加金丝雀矿工的记忆-入堆栈之前gets()得到调用,在其堆栈帧上方,并检查它是否仍然存在,之后gets()将返回。 gets()没有覆盖堆栈的这一部分的业务——它在自己的堆栈框架之外,并且没有指向它——所以如果堆栈金丝雀已经死了,那么某些地方就会以危险的方式出错。(C 作为一种编程环境,碰巧特别容易出现这种错误,在过去的二十年左右的时间里,安全研究人员已经学会了利用其中的许多错误。此外,gets()碰巧是一个本质上存在溢出其目标缓冲区风险的函数。)您没有为您的代码提供地址,但 0x80484ac 可能是 的地址leave,并且在call 0x8048394不匹配的情况下执行(即跳过je 0x80484ac在匹配的情况下),可能是对 的调用__stack_chk_fail(),由 libc 提供,以通过逃离隐喻的有毒矿井来处理堆栈损坏。

The reason the canonical value of the stack canary is kept in the thread-local storage is that this way, every thread can have its own stack canary. Stacks themselves are normally not shared between threads, so it is natural to also not share the canary value.

堆栈金丝雀的规范值保存在线程本地存储中的原因是这样,每个线程都可以拥有自己的堆栈金丝雀。堆栈本身通常不在线程之间共享,因此也不共享 canary 值是很自然的。