本文介绍了asm x86 中变量声明的顺序?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这里是一段代码:

int main()
{

  char buffer[64];
  int check;
...

如你所见,check被声明为AFTERbuffer,所以在栈中,我们必须有check> ABOVE buffer 是否在堆栈中?

As you can see, check is declared AFTER buffer, so in the stack, we must have check ABOVE buffer in the stack right?

但是,当我用 gdb 反汇编 (x86) 它时,这就是我得到的:

However, when I disassembly (x86) it with gdb, this is what I got :

--> check0xbffff4f8

--> buffer0xbffff4b8

我的问题:局部变量在堆栈中是否有特定的顺序?

另外,我要告诉你,我在另一台电脑上也试过同样的事情(x86也是,同样的gcc编译选项,但不同的gdb版本和linux distrib),而且顺序不一样......:S

Also, I have to tell you that I tried the same thing on another computer (x86 too, same gcc compilation options, but different gdb version and linux distrib), and the order is not the same...:S

谢谢!

PS:如果你想了解更多细节,请看截图:(左边是电脑1,右边是电脑2)

PS: if you want more details, please see the screenshot : (left with computer 1 and right with computer 2)

推荐答案

gcc 中有 -fstack-protect 用于重新排序堆栈变量,在某些 Linux 操作系统变体中默认启用近 10 年,尤其是Ubuntu、Redhat、gentoo.自 gcc 4.8.3 ("4.9 及更高版本启用 -fstack-protector-strong.")

There is -fstack-protect in gcc to reorder stack variables, turned on by default in some Linux OS variant for almost 10 years, especially Ubuntu, Redhat, gentoo. Also default since gcc 4.8.3 ("4.9 and later enable -fstack-protector-strong.")

关于 gcc 默认值的 Ubuntu 页面:https://wiki.ubuntu.com/ToolChain/CompilerFlags

Ubuntu page about gcc defaults: https://wiki.ubuntu.com/ToolChain/CompilerFlags

工具链中特定于 Ubuntu 的默认编译器标志,用于帮助为 Ubuntu 提供额外的安全功能....默认标志 ​​-fstack-protector ... 首先在 Ubuntu 6.10 中启用.

关于堆栈保护的 Ubuntu 页面 https://wiki.ubuntu.com/GccSsp

Ubuntu page about stack protection https://wiki.ubuntu.com/GccSsp

gcc 4.1 现在带有 SSP,这是一项很好的技术,可以减轻许多缓冲区溢出的可利用性.... SSP 提供了一种通过 (1) 重新排序堆栈变量 来阻止此类漏洞的可利用性的技术 ... RedHat 和 gentoo 默认使用 SSP 多年

这种重新排序需要对函数的所有局部变量进行多次 O(n^2) 遍历,这会使长函数的编译速度变慢,例如为什么编译超过 100,000 行的 std::vector::push_back 需要很长时间?"- https://stackoverflow.com/a/14034393/196561

This reordering requires several O(n^2) walks on all local variables of function which will make compilation slower for long functions, for example "Why does compiling over 100,000 lines of std::vector::push_back take a long time?" - https://stackoverflow.com/a/14034393/196561

在启用 -fstack-protect 时强制延迟分配(有时需要重新排序所有堆栈变量)... cfgexpand.c

969 /* A subroutine of expand_one_var.  VAR is a variable that will be
970    allocated to the local stack frame.  Return true if we wish to
971    add VAR to STACK_VARS so that it will be coalesced with other
972    variables.  Return false to allocate VAR immediately.
973
974    This function is used to reduce the number of variables considered
975    for coalescing, which reduces the size of the quadratic problem.  */
976
977 static bool
978 defer_stack_allocation (tree var, bool toplevel)
980   /* If stack protection is enabled, *all* stack variables must be deferred,
981      so that we can re-order the strings to the top of the frame.  */

因此,gcc 将对所有堆栈变量重新排序,并且字符串将位于框架的顶部.尝试使用 -fno-stack-protector 选项来禁用.

So, gcc will reorder all stack variables, and strings will be at top of the frame. Try -fno-stack-protector option to disable.

像往常一样,gcc 的作者不会在公共文档中记录 -fstack-protect 如何工作 https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html:

As usual, gcc's author don't document how -fstack-protect works in public documentation https://gcc.gnu.org/onlinedocs/gcc/Instrumentation-Options.html:

-fstack-protector发出额外的代码来检查缓冲区溢出,例如堆栈粉碎攻击.这是通过向具有易受攻击对象的函数添加保护变量来完成的.这包括调用 alloca 的函数,以及缓冲区大于 8 字节的函数.守卫在进入函数时初始化,然后在函数退出时检查.如果防护检查失败,则会打印错误消息并退出程序.

-fstack-protector-all-fstack-protector 类似,只是所有函数都受到保护.

-fstack-protector-all Like -fstack-protector except that all functions are protected.

-fstack-protector-strong-fstack-protector 类似,但包括要保护的附加函数 — 那些具有本地数组定义或具有对本地帧地址的引用的函数.

-fstack-protector-strong Like -fstack-protector but includes additional functions to be protected — those that have local array definitions, or have references to local frame addresses.

-fstack-protector-explicit类似于 -fstack-protector 但只保护那些具有 stack_protect 属性的函数.

-fstack-protector-explicit Like -fstack-protector but only protects those functions which have the stack_protect attribute.

我看到的唯一的array-before-locals 文档是真实的、最好的文档:源代码

And the only documentation of array-before-locals I see is the real, best documentation: source code

https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1526 - expand_used_vars()

1533          if (has_protected_decls)
1534            {
1535              /* Phase 1 contains only character arrays.  */
1536              expand_stack_vars (stack_protect_decl_phase_1);
1537
1538              /* Phase 2 contains other kinds of arrays.  */
1539              if (flag_stack_protect == 2)
1540                expand_stack_vars (stack_protect_decl_phase_2);
1541            }
1542
1543          expand_stack_vars (NULL);

阶段 1 和阶段 2 变量由 stack_protect_decl_phase() https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?修订版=175029&view=markup#l1235

phase 1 and phase 2 vars are separated by stack_protect_decl_phase() https://gcc.gnu.org/viewcvs/gcc/branches/gcc-4_6-branch/gcc/cfgexpand.c?revision=175029&view=markup#l1235

1235    /* Return nonzero if DECL should be segregated into the "vulnerable" upper
1236       part of the local stack frame.  Remember if we ever return nonzero for
1237       any variable in this function.  The return value is the phase number in
1238       which the variable should be allocated.  */
1239
1240    static int
1241    stack_protect_decl_phase (tree decl)
 ...
1243      unsigned int bits = stack_protect_classify_type (TREE_TYPE (decl));
 ...
1249      if (flag_stack_protect == 2)
1250        {
1251          if ((bits & (SPCT_HAS_SMALL_CHAR_ARRAY | SPCT_HAS_LARGE_CHAR_ARRAY))
1252              && !(bits & SPCT_HAS_AGGREGATE))
1253            ret = 1;
1254          else if (bits & SPCT_HAS_ARRAY)
1255            ret = 2;
1256        }

stack_protect_classify_type 将返回位 HAS_ARRAYHAS_*_CHAR_ARRAY 仅用于字符数组(字符、无符号字符和有符号字符)

stack_protect_classify_type will return bits HAS_ARRAY with HAS_*_CHAR_ARRAY only for arrays of char (both char, unsigned char and signed char)

这篇关于asm x86 中变量声明的顺序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-20 10:42
查看更多