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/