分类: C语言基础2012-12-06 23:16 2174人阅读 评论(0) 收藏 举报

found a good example to demostrate the memory layout and its stack info of a user-mode process, only that this example is for Linux. But it is still worth taking a look at it.

C source file is quite simple:

  1. void func(int x, int y)
  2. {
  3. int a;
  4. int b[3];
  5. /* no other auto variable */
  6. }
  7. void main()
  8. {
  9. func(72,73);
  10. }

Memory layout is as below. I will talk about the stack in the next session.

The diagram below shows the memory layout of a typical C’s process. The process load segments (corresponding to ” text ” and ” data ” in the diagram) at the process’s base address. The main stack is located just below and grows downwards. Any additional threads that are created will have their own stacks, located below the main stack. Each of the stack frames is separated by a guard page to detect stack overflows among stacks frame. The heap is located above the process and grows upwards.

In the middle of the process’s address space, there is a region is reserved for shared objects.  When a new process is created, the process manager first maps the two segments from the executable into memory. It then decodes the program’s ELF header. If the program header indicates that the executable was linked against a shared library, the process manager will extract the name of the dynamic interpreter from the program header. The dynamic interpreter points to a shared library that contains the runtime linker code. The process manager will load this shared library in memory and will then pass control to the runtime linker code in this library.

Ref:
http://www.cs.uleth.ca/~holzmann/C/system/memorylayout.pdf

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow1c.html

Stack Frame

Stack is one important segment of the process’s memory layout. It is a dynamic memory buffer portion used to store data implicitly normally during the run time.

The stack segment is where local (automatic) variables are allocated.  In C program, local variables are all variables declared inside the opening left curly brace of a function body including the main() or other left curly brace that aren’t defined as static.  The data is popped up or pushed into the stack following the Last In First Out (LIFO) rule.  The stack holds local variables, temporary information/data, function parameters, return address and the like.  When a function is called, a stack frame (or a procedure activation record) is created and PUSHed onto the top of the stack. This stack frame contains information such as the address from which the function was called and where to jump back to when the function is finished (return address), parameters, local variables, and any other information needed by the invoked function. The order of the information may vary by system and compiler.  When a function returns, the stack frame is POPped from the stack. Typically the stack grows downward, meaning that items deeper in the call chain are at numerically lower addresses and toward the heap.

Stack frame constructed during the function call for memory allocation implicitly.

A typical layout of a stack frame is shown below although it may be organized differently in different operating systems:
*Function parameters.
*Function’s return address.
*Frame pointer.
*Exception Handler frame.
*Locally declared variables.
*Buffer
*Callee save registers

As an example in Windows/Intel, typically, when the function call takes place, data elements are stored on the stack in the following way:
1. The function parameters are pushed on the stack before the function is called.  The parameters are pushed from right to left.
2. The function return address is placed on the stack by the x86 CALL instruction, which stores the current value of the EIP register.
3. Then, the frame pointer that is the previous value of the EBP register is placed on the stack.
4. If a function includes try/catch or any other exception handling construct such as SEH (Structured Exception Handling – Microsoft implementation), the compiler will include exception handling information on the stack.
5. Next, the locally declared variables.
6. Then the buffers are allocated for temporary data storage.
7. Finally, the callee save registers such as ESI, EDI, and EBX are stored if they are used at any point during the functions execution.  For Linux/Intel, this step comes after step no. 4.

There are two CPU registers that are important for the functioning of the stack which hold information that is necessary when calling data residing in the memory. Their names areESP and EBP in 32 bits system.
The ESP (Extended Stack Pointer) holds the top stack address.  TheEBP (Extended Base Pointer) points to the bottom of the current stack frame.

ESP points to the top of the stack (lower numerical address); it is often convenient to have a stack frame pointer (FP) which holds an address that point to a fixed location within a frame.  Looking at the stack frame, local variables could be referenced by giving their offsets from ESP.  However , as data are pushed onto the stack and popped off the stack, these offsets change, so the reference of the local variables is not consistent.  Consequently, many compilers use another register, generally called Frame Pointer (FP), for referencing both local variables and parameters because their distances from FP do not change with PUSHes and POPs.  On Intel CPUs,EBP (Extended Base Pointer) is used for this purpose.
Because the way stack grows, actual parameters have positive offsets and local variables have negative offsets from FP as shown below.  Let examine the following simple C program.

  1. #include <stdio.h>
  2. int MyFunc(int parameter1, char parameter2)
  3. {
  4. int local1 = 9;
  5. char local2 = ’Z';
  6. return 0;
  7. }
  8. int main(int argc, char *argv[])
  9. {
  10. MyFunc(7, ’8′);
  11. return 0;
  12. }

And the memory layout will look something like this:

Each time a new function is called, the old value of EBP is the first to be pushed onto the stack and then the new value of ESP is moved to EBP. This new value of ESP held by EBP becomes the reference base to local variables that are needed to retrieve the stack section allocated for the new function call. As mentioned before, a stack grows downward to lower memory address. The stack pointer (ESP) points to the last address on the stack not the next free available address after the top of the stack.

The first thing a function must do when called is to save the previous EBP (so it can be restored by copying into the EIP at function exit later).  Then it copies ESP into EBP to create the new stack frame pointer, and advances ESP to reserve space for the local variables.  This code is called the procedure prolog .  Upon function exit, the stack must be cleaned up again, something called theprocedure epilog .

Using a very simple C program skeleton, the following tries to figure out function calls and stack frames construction/destruction.

  1. #include <stdio.h>
  2. int a();
  3. int b();
  4. int c();
  5. int a()
  6. {
  7. b();
  8. c();
  9. return 0;
  10. }
  11. int b()
  12. {
  13. return 0;
  14. }
  15. int c()
  16. {
  17. return 0;
  18. }
  19. int main()
  20. {
  21. a();
  22. return 0;
  23. }

By taking the stack area only, the following is what happen when the above program is run.

By referring the previous program example and above figure, when a program begins execution in the function main(), stack frame is created, space is allocated on the stack for all variables declared within main().  Then, when main()  calls a function, a(), new stack frame is created for the variables in a() at the top of the main() stack.  Any parameters passed by main() to a() are stored on the stack.  If a() were to call any additional functions such as b() and c(), new stack frames would be allocated at the new top of the stack.  Notice that the order of the execution happened in the sequence.  When c(), b() and a() return, storage for their local variables are de-allocated, the stack frames are destroyed and the top of the stack returns to the previous condition.  The order of the execution is in the reverse.  As can be seen, the memory allocated in the stack area is used and reused during program execution.  It should be clear that memory allocated in this area will contain garbage values left over from previous usage.

Ref:

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow1c.html

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2.html

http://www.tenouk.com/Bufferoverflowc/Bufferoverflow2a.html

参考链接:http://dralu.com/?p=153

Memory Layout (Virtual address space of a C process)的更多相关文章

  1. ARM64 Linux kernel virtual address space

    墙外通道:http://thinkiii.blogspot.com/2014/02/arm64-linux-kernel-virtual-address-space.html Now let's ta ...

  2. ARM32 Linux kernel virtual address space

    http://thinkiii.blogspot.jp/2014/02/arm32-linux-kernel-virtual-address-space.html   The 32-bit ARM C ...

  3. Method of address space layout randomization for windows operating systems

    A system and method for address space layout randomization ("ASLR") for a Windows operatin ...

  4. Method for address space layout randomization in execute-in-place code

    The present application relates generally to laying out address space for execute-in-place code and, ...

  5. Virtual address cache memory, processor and multiprocessor

    An embodiment provides a virtual address cache memory including: a TLB virtual page memory configure ...

  6. Multiple address space mapping technique for shared memory wherein a processor operates a fault handling routine upon a translator miss

    Virtual addresses from multiple address spaces are translated to real addresses in main memory by ge ...

  7. Memory Layout of C Programs

    Memory Layout of C Programs   A typical memory representation of C program consists of following sec ...

  8. System and method for critical address space protection in a hypervisor environment

    A system and method in one embodiment includes modules for detecting an access attempt to a critical ...

  9. Memory Layout for Multiple and Virtual Inheritance

    Memory Layout for Multiple and Virtual Inheritance(By Edsko de Vries, January 2006)Warning. This art ...

随机推荐

  1. Spring事务管理之声明式事务管理-基于注解的方式

    © 版权声明:本文为博主原创文章,转载请注明出处 案例 - 利用Spring的声明式事务(TransactionProxyFactoryBean)管理模拟转账过程 数据库准备 -- 创建表 CREAT ...

  2. hdu 3172 Virtual Friends(并查集,字典树)

    题意:人与人交友构成关系网,两个人交友,相当于两个朋友圈的合并,问每个出两人,他们目前所在的关系网中的人数. 分析:用并查集,其实就是求每个集合当前的人数.对于人名的处理用到了字典树. 注意:1.题目 ...

  3. Apache安全和强化的十三个技巧

    Apache是一个很受欢迎的web服务器软件,其安全性对于网站的安全运营可谓生死攸关.下面介绍一些可帮助管理员在Linux上配置Apache确保其安全的方法和技巧. 本文假设你知道这些基本知识: 文档 ...

  4. 安装wamp后 异常Exception Exception in module wampmanager.exe at 000F15A0

    系统环境:Windows 2008 R2 64bit 安装环境:wampserver2.4-x64 按照正常windows安装程序,完成WAMP Server程序安装,安装完成启动WAMP Serve ...

  5. 4.关于QT中的QFile文件操作,QBuffer,Label上加入QPixmap,QByteArray和QString之间的差别,QTextStream和QDataStream的差别,QT内存映射(

     新建项目13IO 13IO.pro HEADERS += \ MyWidget.h SOURCES += \ MyWidget.cpp QT += gui widgets network CON ...

  6. 从外置U盘中拷文件到Linux(挂载)

    第一步: 将U盘插入电脑,在Linux系统中会有反应,类似sda.sdb……,然后去/dev目录查看是否有这个文件 第二步: 新建一个目录:/mnt/mine 第三步: 将u盘挂载到/mnt/mine ...

  7. 如何通过git客户端上传项目到github上

    参考地址: 1.http://1ke.co/course/194 2.https://github.com/wohugb/git-reference/blob/master/Git-on-the-Se ...

  8. poj 3468 Splay 树

    大二上的时候.写过一个AVL的操作演示,今天一看Splay.发现和AVL事实上一样,加上线段树的基础,懒惰标记什么都知道.学起来轻松很多哦 我參考的模板来自这里  http://blog.csdn.n ...

  9. 贝塞尔曲线与CAShapeLayer的关系以及Stroke动画

    1.贝塞尔曲线与CAShapeLayer的关系    1.1CAShapeLayer须要一个形状才干生效,贝塞尔曲线能够创建基于矢量的路径.进而能够给CAShapeLayer提供路径,路径会闭环.   ...

  10. 将非递减有序排列(L L1)归并为一个新的线性表L2 线性表L2中的元素仍按值非递减

    #include "stdio.h"#include "stdlib.h"#include "function.h"void main(){ ...