如何以及何时构建堆栈框架? [英] How and when are stack frames built?

查看:124
本文介绍了如何以及何时构建堆栈框架?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在阅读有关在Linux下利用内存漏洞的信息,我发现很难找到有关何时确定堆栈框架布局的任何信息.换句话说,它是在编译时,程序执行之前确定的还是在调用函数时构建的?操作系统之间的布局是否有所不同?

I am currently reading about exploiting memory vulnerabilities under Linux and I found it hard to find any information on when the layout of stack frames is decided. In other words, is it something determined at the compile time, before the program's execution or are those built when a function is being called? Does the layout differ between operating systems?

推荐答案

我怀疑您通常或容易地找到有关堆栈框架设计方式的文档化答案.正如其他人所观察到的,记录在案的是该设计过程的结果,通常没有很多相关的基本原理,我同意这将是非常有趣的.

I doubt you will generally or easily find an documented answer to how stack frames were designed. As others have observed, what gets documented is the result of that design process, often without a lot of associated rationale which I agree would be pretty interesting.

每个堆栈框架布局的设计都可能是由人们为特定的处理器体系结构甚至可能是特定的OS设计一个编译器或一组可互操作的编译器.这将受到以下子程序的影响:需要从调用程序访问信息的子例程(参数?词法作用域?),什么指令集效果良好(很多寄存器?容易推入参数?),编译器的优缺点等.例如,随着他们的编译器和x86的发展,这种设计在过去的几十年中进行了几次.它们在x86-32上的约定与x86-64上的约定确实不同.您可以从记录的结果中猜测其基本原理,有时会有些提示,但并非总是如此.

Each design of a stack frame layout comes from presumably people designing a compiler or a set of interoperable compilers for a particular processor architecture and maybe even for the particular OS. This will be influenced by what subroutine needs to access information from callers (arguments? lexical scopes?), what the instruction set does well (lots of registers? easy to push arguments?), strengths or weaknesses of the compilers, etc. Microsoft, as an example, did this design several times over decades, as their compilers and the x86 evolved; their conventions for the x86-32 are really different than they are for x86-64. You can guess at the rationale from the documented result and sometimes there are hints, but not always.

为我公司在x86上运行的并行编程语言设计了堆栈框架",我可以给您一些想法.

I can give you some ideas, having designed "stack frames" for my company's parallel programming language that runs on an x86.

  • 因为语言是并行的,所以堆栈帧是堆分配的(通过极其快速的线程本地块分配器分配),而不是堆栈分配的;因此,堆栈框架"并不是一个正确的术语,我们称它们为激活记录". (在本讨论中,我将继续称它们为堆栈框架").该方案支持并行编程,其中一个函数可以派生多个并行子计算,每个子计算都需要自己的堆栈框架;他们显然不能共享一个堆栈.这意味着每个堆栈帧都必须包含指向前一帧的显式指针,以使被调用者能够返回.因此,堆栈帧中有一个低偏移量的插槽,用于容纳调用者堆栈帧指针.同样,有一个插槽可容纳调用者的堆栈指针.使用这两个插槽代替x86调用约定传统上使用的传统PUSH EBP/LEAESP.k[ESP].
  • 词汇范围界定要求每个被调用者都可以访问父母的词汇范围.这是通过在堆栈帧中放置一组低偏移点来保存经典的显示"(指向包含范围的指针的集合),并将指向ECX中调用者显示的指针传递给被调用者来实现的.被调用方复制了父级显示所需的内容,如果被调用方不是叶子过程,则可能会增加.
  • CPU的寄存器数量有限,这意味着您无法在寄存器中传递所有参数,甚至无法传递其中的许多参数.我们选择在EAX中传递一个32位参数,在EDX中传递第二个参数,或者在EAX/EDX中传递一个64位参数.通过将参数推入堆栈并简单地调用子例程来传递更大的参数列表.被调用者希望访问参数.我们选择在堆栈帧中以低偏移量分配2个插槽以容纳EAX/EDX.
  • 与单线程代码不同,每个PARLANSE堆栈框架表示一个函数,该函数可能具有大量静态定义的并行计算.因此,堆栈帧包含一个粒"(并行线程)上下文块的集合",这些上下文块具有关联的固定大小的堆栈,每个堆栈均由其ESP寄存器访问.该方案允许编译器完成分配空间和设置并行粒度的大部分工作,从而最大程度地减少了创建颗粒"的时间,进而允许更小的计算有效地并行运行.关于每个谷物控制模块的内容有很多细节,在这里不值得解释.重点是堆栈框架设计中有很多细节.

我的观点是,堆栈框架设计的基本原理是由计算机体系结构和应该支持的编程语言的目标驱动的.诸如此类的基本原理并未出现在许多文档中,是的,这使得查找起来非常困难.

My point is the rationale for stack frame design is driven by the machine architecture and the goal of the programming language it is supposed to support. Rationale such as the above doesn't appear in many documents, and yes, that makes it pretty hard to find.

考虑到堆栈框架的设计,一种语言的编译器随后会为正在编译的特定子例程在框架内分配空间.

Given a stack frame design, the compiler for a language then allocates space within the frame, for a particular subroutine being compiled.

这篇关于如何以及何时构建堆栈框架?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆