카테고리 없음

C program memory layout

sunshout 2015. 3. 23. 21:38

C program의 일반적 memory layout








objdump

http://www.thegeekstuff.com/2012/09/objdump-examples/


c++ layout 분석 (hello.cc)

#include <stdio.h>


class hello {

    public:

        int a;


        hello();

        ~hello();

        void show();

};


hello::hello() {}

hello::~hello() {}

void hello::show() {

    printf("%d\n", a);

}


int main()

{

    hello *h = new hello();

    return 0;

}



g++ -c hello.cc 컴파일 하면 hello.o 라는 object 파일이 생성된다.

 . nm 을 이용하여 symbol table 을 찾을 수 있다.

 . nm 은 3개의 필드로 구성되어 있다

 -> 첫번째 필드: 심볼값 (table offset 또는 virtual address를 의미)

 -> 두번째 필드: 심볼타입(A,B,C,D,G,I,N,R,S,T,U,V,W,-,?)

 -> 세번째 필드: 심볼이름 (nm에서 -C 옵션을 주면 코딩명으로 나온다)

root@cnode01-m:~/example# nm hello.o -C

0000000000000014 T hello::show()

0000000000000000 T hello::hello()

0000000000000000 T hello::hello()

000000000000000a T hello::~hello()

000000000000000a T hello::~hello()

                 U operator new(unsigned long)

0000000000000039 T main

                 U printf



 . 여기에서 hello(), show(), ~hello() 함수의 심볼타입이 T (Text) 이기 때문에 해당 코드는 Text area에 존재함을 알 수 있다.



new를 통해서 생성한 class 의 object 의 memory layout 분석

#include <vector>

#include <stdio.h>


class A {

    private:

    char a;

    char b;

    char c;

    char d;

    std::vector<char> e;


    public:

    A();

    ~A();

    void show();

};


A::A() {

    a = 'a';

    b = 'b';

    c = 'c';

    d = 'd';

    e.reserve(6);

    e.push_back('e');

    e.push_back('f');

    e.push_back('g');

    e.push_back('h');

    e.push_back('i');

    e.push_back('j');

}

A::~A() {

}


void A::show() {

    int i;

    for(i=0; i != 6; ++i) {

        printf("%c\n", e.at(i));

    }

}


int main(int argc, char** argv)

{

    A *a = new A();

    a->show();

    return 0;

}


gdb를 사용하여 "info proc mappings"를 수행하면 heap, stack 등의 주소 공간을 파악할 수 있다.

 - 현재 heap 은 0x604000 부터 증가하고 있음을 알 수 있다.

 - new A() 를 통해서 생성한 a 는 0x604010 부터 증가함을 알 수 있다.

   . 0x604010 (a->a)

   . 0x604011 (a->b)

   . 0x604012 (a->c)

   . 0x604013 (a->e)

 - 하지만 A 클래스의 vector 변수인 e는 continuous 한 공간이 아닌 0x604018부터 생성되며,

   . 실제 데이터는 0x604040 ~ 0x604046 사이에 존재함을 알 수 있다.

(gdb) info proc mappings

process 11404

Mapped address spaces:


          Start Addr           End Addr       Size     Offset objfile

            0x400000           0x403000     0x3000        0x0 /root/example/vector

            0x602000           0x603000     0x1000     0x2000 /root/example/vector

            0x603000           0x604000     0x1000     0x3000 /root/example/vector

            0x604000           0x625000    0x21000        0x0 [heap]

      0x7ffff71f4000     0x7ffff72f9000   0x105000        0x0 /lib/x86_64-linux-gnu/libm-2.19.so

      0x7ffff72f9000     0x7ffff74f8000   0x1ff000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so

      0x7ffff74f8000     0x7ffff74f9000     0x1000   0x104000 /lib/x86_64-linux-gnu/libm-2.19.so

      0x7ffff74f9000     0x7ffff74fa000     0x1000   0x105000 /lib/x86_64-linux-gnu/libm-2.19.so

      0x7ffff74fa000     0x7ffff76b5000   0x1bb000        0x0 /lib/x86_64-linux-gnu/libc-2.19.so

      0x7ffff76b5000     0x7ffff78b5000   0x200000   0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so

      0x7ffff78b5000     0x7ffff78b9000     0x4000   0x1bb000 /lib/x86_64-linux-gnu/libc-2.19.so

      0x7ffff78b9000     0x7ffff78bb000     0x2000   0x1bf000 /lib/x86_64-linux-gnu/libc-2.19.so

      0x7ffff78bb000     0x7ffff78c0000     0x5000        0x0

      0x7ffff78c0000     0x7ffff78d6000    0x16000        0x0 /lib/x86_64-linux-gnu/libgcc_s.so.1

      0x7ffff78d6000     0x7ffff7ad5000   0x1ff000    0x16000 /lib/x86_64-linux-gnu/libgcc_s.so.1

      0x7ffff7ad5000     0x7ffff7ad6000     0x1000    0x15000 /lib/x86_64-linux-gnu/libgcc_s.so.1

      0x7ffff7ad6000     0x7ffff7bbc000    0xe6000        0x0 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19

      0x7ffff7bbc000     0x7ffff7dbb000   0x1ff000    0xe6000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19

      0x7ffff7dbb000     0x7ffff7dc3000     0x8000    0xe5000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19

      0x7ffff7dc3000     0x7ffff7dc5000     0x2000    0xed000 /usr/lib/x86_64-linux-gnu/libstdc++.so.6.0.19

      0x7ffff7dc5000     0x7ffff7dda000    0x15000        0x0

      0x7ffff7dda000     0x7ffff7dfd000    0x23000        0x0 /lib/x86_64-linux-gnu/ld-2.19.so

      0x7ffff7fe7000     0x7ffff7fec000     0x5000        0x0

      0x7ffff7ff8000     0x7ffff7ffa000     0x2000        0x0

      0x7ffff7ffa000     0x7ffff7ffc000     0x2000        0x0 [vdso]

      0x7ffff7ffc000     0x7ffff7ffd000     0x1000    0x22000 /lib/x86_64-linux-gnu/ld-2.19.so

      0x7ffff7ffd000     0x7ffff7ffe000     0x1000    0x23000 /lib/x86_64-linux-gnu/ld-2.19.so

      0x7ffff7ffe000     0x7ffff7fff000     0x1000        0x0

      0x7ffffffde000     0x7ffffffff000    0x21000        0x0 [stack]

  0xffffffffff600000 0xffffffffff601000     0x1000        0x0 [vsyscall]

(gdb) p a

$1 = (A *) 0x604010

(gdb) p a->e

$2 = {<std::_Vector_base<char, std::allocator<char> >> = {_M_impl = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>},

      _M_start = 0x604040 "efghij", _M_finish = 0x604046 "", _M_end_of_storage = 0x604046 ""}}, <No data fields>}


(gdb) p &a->a

$3 = 0x604010 "abcd"

(gdb) p &a->b

$4 = 0x604011 "bcd"

(gdb) p &a->c

$5 = 0x604012 "cd"

(gdb) p &a->d

$6 = 0x604013 "d" 

(gdb) p &a->e

$7 = (std::vector<char, std::allocator<char> > *) 0x604018



참조:

https://kldp.org/node/68410

Weak symbol 관련 http://www.embedded-bits.co.uk/2008/digging-deeper-into-weak-symbols/