Excuse the ads! We need some help to keep our site up.
malloc()에서 메모리 영역과 메모리 관리 부분을 arena라고 합니다.
프로세스에 할당된 Heap 영역(non-mmapped )입니다.
static struct malloc_state main_arena = { .mutex = _LIBC_LOCK_INITIALIZER, .next = &main_arena, .attached_threads = 1 }; |
struct malloc_state { /* Serialize access. */ mutex_t mutex; /* Flags (formerly in max_fast). */ int flags; /* Fastbins */ mfastbinptr fastbinsY[NFASTBINS]; /* Base of the topmost chunk -- not otherwise kept in a bin */ mchunkptr top; /* The remainder from the most recent split of a small request */ mchunkptr last_remainder; /* Normal bins packed as described above */ mchunkptr bins[NBINS * 2 - 2]; /* Bitmap of bins */ unsigned int binmap[BINMAPSIZE]; /* Linked list */ struct malloc_state *next; /* Linked list for free arenas. Access to this field is serialized by free_list_lock in arena.c. */ struct malloc_state *next_free; /* Number of threads attached to this arena. 0 if the arena is on the free list. Access to this field is serialized by free_list_lock in arena.c. */ INTERNAL_SIZE_T attached_threads; /* Memory allocated from the system in this arena. */ INTERNAL_SIZE_T system_mem; INTERNAL_SIZE_T max_system_mem; }; |
gdb-peda$ p main_arena $1 = { mutex = 0x0, flags = 0x1, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x602070, last_remainder = 0x0, bins = {0x7ffff7dd37b8 <main_arena+88>, 0x7ffff7dd37b8 <main_arena+88>, 0x7ffff7dd37c8 <main_arena+104>, 0x7ffff7dd37c8 <main_arena+104>, 0x7ffff7dd37d8 <main_arena+120>, 0x7ffff7dd37d8 <main_arena+120>, 0x7ffff7dd37e8 <main_arena+136>, 0x7ffff7dd37e8 <main_arena+136>, 0x7ffff7dd37f8 <main_arena+152>, 0x7ffff7dd37f8 <main_arena+152>, 0x7ffff7dd3808 <main_arena+168>, 0x7ffff7dd3808 <main_arena+168>, 0x7ffff7dd3818 <main_arena+184>, 0x7ffff7dd3818 <main_arena+184>, 0x7ffff7dd3828 <main_arena+200>, 0x7ffff7dd3828 <main_arena+200>, 0x7ffff7dd3838 <main_arena+216>, 0x7ffff7dd3838 <main_arena+216>, 0x7ffff7dd3848 <main_arena+232>, 0x7ffff7dd3848 <main_arena+232>, 0x7ffff7dd3858 <main_arena+248>, 0x7ffff7dd3858 <main_arena+248>, 0x7ffff7dd3868 <main_arena+264>, 0x7ffff7dd3868 <main_arena+264>, 0x7ffff7dd3878 <main_arena+280>, 0x7ffff7dd3878 <main_arena+280>, 0x7ffff7dd3888 <main_arena+296>, 0x7ffff7dd3888 <main_arena+296>, 0x7ffff7dd3898 <main_arena+312>, 0x7ffff7dd3898 <main_arena+312>, 0x7ffff7dd38a8 <main_arena+328>, 0x7ffff7dd38a8 <main_arena+328>, 0x7ffff7dd38b8 <main_arena+344>, 0x7ffff7dd38b8 <main_arena+344>, 0x7ffff7dd38c8 <main_arena+360>, 0x7ffff7dd38c8 <main_arena+360>, 0x7ffff7dd38d8 <main_arena+376>, 0x7ffff7dd38d8 <main_arena+376>, 0x7ffff7dd38e8 <main_arena+392>, 0x7ffff7dd38e8 <main_arena+392>, 0x7ffff7dd38f8 <main_arena+408>, 0x7ffff7dd38f8 <main_arena+408>, 0x7ffff7dd3908 <main_arena+424>, 0x7ffff7dd3908 <main_arena+424>, 0x7ffff7dd3918 <main_arena+440>, 0x7ffff7dd3918 <main_arena+440>, 0x7ffff7dd3928 <main_arena+456>, 0x7ffff7dd3928 <main_arena+456>, 0x7ffff7dd3938 <main_arena+472>, 0x7ffff7dd3938 <main_arena+472>, 0x7ffff7dd3948 <main_arena+488>, 0x7ffff7dd3948 <main_arena+488>, 0x7ffff7dd3958 <main_arena+504>, 0x7ffff7dd3958 <main_arena+504>, 0x7ffff7dd3968 <main_arena+520>, 0x7ffff7dd3968 <main_arena+520>, 0x7ffff7dd3978 <main_arena+536>, 0x7ffff7dd3978 <main_arena+536>, 0x7ffff7dd3988 <main_arena+552>, 0x7ffff7dd3988 <main_arena+552>, 0x7ffff7dd3998 <main_arena+568>, 0x7ffff7dd3998 <main_arena+568>, 0x7ffff7dd39a8 <main_arena+584>, 0x7ffff7dd39a8 <main_arena+584>, 0x7ffff7dd39b8 <main_arena+600>, 0x7ffff7dd39b8 <main_arena+600>, 0x7ffff7dd39c8 <main_arena+616>, 0x7ffff7dd39c8 <main_arena+616>, 0x7ffff7dd39d8 <main_arena+632>, 0x7ffff7dd39d8 <main_arena+632>, 0x7ffff7dd39e8 <main_arena+648>, 0x7ffff7dd39e8 <main_arena+648>, 0x7ffff7dd39f8 <main_arena+664>, 0x7ffff7dd39f8 <main_arena+664>, 0x7ffff7dd3a08 <main_arena+680>, 0x7ffff7dd3a08 <main_arena+680>, 0x7ffff7dd3a18 <main_arena+696>, 0x7ffff7dd3a18 <main_arena+696>, 0x7ffff7dd3a28 <main_arena+712>, 0x7ffff7dd3a28 <main_arena+712>, 0x7ffff7dd3a38 <main_arena+728>, 0x7ffff7dd3a38 <main_arena+728>, 0x7ffff7dd3a48 <main_arena+744>, 0x7ffff7dd3a48 <main_arena+744>, 0x7ffff7dd3a58 <main_arena+760>, 0x7ffff7dd3a58 <main_arena+760>, 0x7ffff7dd3a68 <main_arena+776>, 0x7ffff7dd3a68 <main_arena+776>, 0x7ffff7dd3a78 <main_arena+792>, 0x7ffff7dd3a78 <main_arena+792>, 0x7ffff7dd3a88 <main_arena+808>, 0x7ffff7dd3a88 <main_arena+808>, 0x7ffff7dd3a98 <main_arena+824>, 0x7ffff7dd3a98 <main_arena+824>, 0x7ffff7dd3aa8 <main_arena+840>, 0x7ffff7dd3aa8 <main_arena+840>, 0x7ffff7dd3ab8 <main_arena+856>, 0x7ffff7dd3ab8 <main_arena+856>, 0x7ffff7dd3ac8 <main_arena+872>, 0x7ffff7dd3ac8 <main_arena+872>, 0x7ffff7dd3ad8 <main_arena+888>, 0x7ffff7dd3ad8 <main_arena+888>, 0x7ffff7dd3ae8 <main_arena+904>, 0x7ffff7dd3ae8 <main_arena+904>, 0x7ffff7dd3af8 <main_arena+920>, 0x7ffff7dd3af8 <main_arena+920>, 0x7ffff7dd3b08 <main_arena+936>, 0x7ffff7dd3b08 <main_arena+936>, 0x7ffff7dd3b18 <main_arena+952>, 0x7ffff7dd3b18 <main_arena+952>, 0x7ffff7dd3b28 <main_arena+968>, 0x7ffff7dd3b28 <main_arena+968>, 0x7ffff7dd3b38 <main_arena+984>, 0x7ffff7dd3b38 <main_arena+984>, 0x7ffff7dd3b48 <main_arena+1000>, 0x7ffff7dd3b48 <main_arena+1000>, 0x7ffff7dd3b58 <main_arena+1016>, 0x7ffff7dd3b58 <main_arena+1016>, 0x7ffff7dd3b68 <main_arena+1032>, 0x7ffff7dd3b68 <main_arena+1032>, 0x7ffff7dd3b78 <main_arena+1048>, 0x7ffff7dd3b78 <main_arena+1048>, 0x7ffff7dd3b88 <main_arena+1064>, 0x7ffff7dd3b88 <main_arena+1064>, 0x7ffff7dd3b98 <main_arena+1080>, 0x7ffff7dd3b98 <main_arena+1080>, 0x7ffff7dd3ba8 <main_arena+1096>, 0x7ffff7dd3ba8 <main_arena+1096>, 0x7ffff7dd3bb8 <main_arena+1112>, 0x7ffff7dd3bb8 <main_arena+1112>, 0x7ffff7dd3bc8 <main_arena+1128>, 0x7ffff7dd3bc8 <main_arena+1128>, 0x7ffff7dd3bd8 <main_arena+1144>, 0x7ffff7dd3bd8 <main_arena+1144>, 0x7ffff7dd3be8 <main_arena+1160>, 0x7ffff7dd3be8 <main_arena+1160>, 0x7ffff7dd3bf8 <main_arena+1176>, 0x7ffff7dd3bf8 <main_arena+1176>, 0x7ffff7dd3c08 <main_arena+1192>, 0x7ffff7dd3c08 <main_arena+1192>, 0x7ffff7dd3c18 <main_arena+1208>, 0x7ffff7dd3c18 <main_arena+1208>, 0x7ffff7dd3c28 <main_arena+1224>, 0x7ffff7dd3c28 <main_arena+1224>, 0x7ffff7dd3c38 <main_arena+1240>, 0x7ffff7dd3c38 <main_arena+1240>, 0x7ffff7dd3c48 <main_arena+1256>, 0x7ffff7dd3c48 <main_arena+1256>, 0x7ffff7dd3c58 <main_arena+1272>, 0x7ffff7dd3c58 <main_arena+1272>, 0x7ffff7dd3c68 <main_arena+1288>, 0x7ffff7dd3c68 <main_arena+1288>, 0x7ffff7dd3c78 <main_arena+1304>, 0x7ffff7dd3c78 <main_arena+1304>, 0x7ffff7dd3c88 <main_arena+1320>, 0x7ffff7dd3c88 <main_arena+1320>, 0x7ffff7dd3c98 <main_arena+1336>, 0x7ffff7dd3c98 <main_arena+1336>, 0x7ffff7dd3ca8 <main_arena+1352>, 0x7ffff7dd3ca8 <main_arena+1352>, 0x7ffff7dd3cb8 <main_arena+1368>, 0x7ffff7dd3cb8 <main_arena+1368>, 0x7ffff7dd3cc8 <main_arena+1384>, 0x7ffff7dd3cc8 <main_arena+1384>, 0x7ffff7dd3cd8 <main_arena+1400>, 0x7ffff7dd3cd8 <main_arena+1400>, 0x7ffff7dd3ce8 <main_arena+1416>, 0x7ffff7dd3ce8 <main_arena+1416>, 0x7ffff7dd3cf8 <main_arena+1432>, 0x7ffff7dd3cf8 <main_arena+1432>, 0x7ffff7dd3d08 <main_arena+1448>, 0x7ffff7dd3d08 <main_arena+1448>, 0x7ffff7dd3d18 <main_arena+1464>, 0x7ffff7dd3d18 <main_arena+1464>, 0x7ffff7dd3d28 <main_arena+1480>, 0x7ffff7dd3d28 <main_arena+1480>, 0x7ffff7dd3d38 <main_arena+1496>, 0x7ffff7dd3d38 <main_arena+1496>, 0x7ffff7dd3d48 <main_arena+1512>, 0x7ffff7dd3d48 <main_arena+1512>, 0x7ffff7dd3d58 <main_arena+1528>, 0x7ffff7dd3d58 <main_arena+1528>, 0x7ffff7dd3d68 <main_arena+1544>, 0x7ffff7dd3d68 <main_arena+1544>, 0x7ffff7dd3d78 <main_arena+1560>, 0x7ffff7dd3d78 <main_arena+1560>, 0x7ffff7dd3d88 <main_arena+1576>, 0x7ffff7dd3d88 <main_arena+1576>, 0x7ffff7dd3d98 <main_arena+1592>, 0x7ffff7dd3d98 <main_arena+1592>, 0x7ffff7dd3da8 <main_arena+1608>, 0x7ffff7dd3da8 <main_arena+1608>, 0x7ffff7dd3db8 <main_arena+1624>, 0x7ffff7dd3db8 <main_arena+1624>, 0x7ffff7dd3dc8 <main_arena+1640>, 0x7ffff7dd3dc8 <main_arena+1640>, 0x7ffff7dd3dd8 <main_arena+1656>, 0x7ffff7dd3dd8 <main_arena+1656>, 0x7ffff7dd3de8 <main_arena+1672>, 0x7ffff7dd3de8 <main_arena+1672>...}, binmap = {0x0, 0x0, 0x0, 0x0}, next = 0x7ffff7dd3760 <main_arena>, next_free = 0x0, system_mem = 0x21000, max_system_mem = 0x21000 } gdb-peda$ |
/* ----------------------- Chunk representations ----------------------- */ /* This struct declaration is misleading (but accurate and necessary). It declares a "view" into memory allowing access to necessary fields at known offsets from a given base. See explanation below. */ struct malloc_chunk { INTERNAL_SIZE_T prev_size; /* Size of previous chunk (if free). */ INTERNAL_SIZE_T size; /* Size in bytes, including overhead. */ struct malloc_chunk* fd; /* double links -- used only if free. */ struct malloc_chunk* bk; /* Only used for large blocks: pointer to next larger size. */ struct malloc_chunk* fd_nextsize; /* double links -- used only if free. */ struct malloc_chunk* bk_nextsize; }; |
|
prev_size |
|
---|---|
size |
|
#include <stdio.h> #include <stdlib.h> void main(){ char *heap = malloc(8); printf("Heap Addr : %p\n",heap); free(heap); } |
다음과 같은 방법으로 Allocated chunk의 구조를 확인할 수 있습니다.
해당 Chunk 앞에 해제된 Chunk가 없기 때문에 prev_size 영역은 비워져있습니다.
size는 다음과 같은 값을 더한 값이 저장되어 있습니다.
Allocated chunk의 header 정보를 저장하는 공간 - 16byte
사용자가 요청한 Heap 공간의 크기 - 8 byte
Next chunk 정보를 저장할 공간 - 8 byte
lazenca0x0@ubuntu:~/Documents/def$ gcc -o allocated allocated.c lazenca0x0@ubuntu:~/Documents/def$ gdb ./allocated gdb-peda$ disassemble main Dump of assembler code for function main: 0x00000000004005bd <+0>: push rbp 0x00000000004005be <+1>: mov rbp,rsp 0x00000000004005c1 <+4>: sub rsp,0x10 0x00000000004005c5 <+8>: mov edi,0x8 0x00000000004005ca <+13>: call 0x4004c0 <malloc@plt> 0x00000000004005cf <+18>: mov QWORD PTR [rbp-0x8],rax 0x00000000004005d3 <+22>: mov rax,QWORD PTR [rbp-0x8] 0x00000000004005d7 <+26>: mov rsi,rax 0x00000000004005da <+29>: mov edi,0x400684 0x00000000004005df <+34>: mov eax,0x0 0x00000000004005e4 <+39>: call 0x400490 <printf@plt> 0x00000000004005e9 <+44>: mov rax,QWORD PTR [rbp-0x8] 0x00000000004005ed <+48>: mov rdi,rax 0x00000000004005f0 <+51>: call 0x400480 <free@plt> 0x00000000004005f5 <+56>: leave 0x00000000004005f6 <+57>: ret End of assembler dump. gdb-peda$ b *0x00000000004005cf Breakpoint 1 at 0x4005cf gdb-peda$ r Starting program: /home/lazenca0x0/Documents/def/allocated Breakpoint 1, 0x00000000004005cf in main () gdb-peda$ heap heapbase : 0x602000 gdb-peda$ x/10gx 0x602000 0x602000: 0x0000000000000000 0x0000000000000021 0x602010: 0x0000000000000000 0x0000000000000000 0x602020: 0x0000000000000000 0x0000000000020fe1 0x602030: 0x0000000000000000 0x0000000000000000 0x602040: 0x0000000000000000 0x0000000000000000 gdb-peda$ |
|
prev_size |
|
---|---|
size |
|
fd(Forward pointer) |
|
bk(Backward pointer) |
|
#include <stdio.h> #include <stdlib.h> void main(){ char *heap1 = malloc(128); char *tmp2 = malloc(8); char *heap2 = malloc(128); char *tmp3 = malloc(8); char *heap3 = malloc(128); char *tmp1 = malloc(8); printf("Free chunk : %p\n",heap2); free(heap1); free(heap2); free(heap3); getchar(); } |
Free chunk의 header 정보를 저장하는 공간 - 16byte
해제된 Heap 공간의 크기 - 128 byte
"PREV_INUSE" flag 설정 - 1 byte
lazenca0x0@ubuntu:~/Documents/def$ gcc -o freechunk freechunk.c lazenca0x0@ubuntu:~/Documents/def$ gdb ./freechunk gdb-peda$ r Starting program: /home/lazenca0x0/Documents/def/unsorted Free chunk : 0x6020c0 ^C Program received signal SIGINT, Interrupt. gdb-peda$ x/4gx 0x6020c0 - 0x10 0x6020b0: 0x0000000000000000 0x0000000000000091 0x6020c0: 0x0000000000602000 0x0000000000602160 gdb-peda$ |
|
|
Bin 정보는 "malloc_state" 구조체에서 관리됩니다.
FastbinsY : "Fast bin"을 관리합니다.
Bins : "Unsorted bin", "Small bin", "Large bin"을 관리 합니다.
총 126개의 bin을 관리 합니다.
Bins의 구성은 다음과 같습니다.
Index 1 : Unsorted bin
Index 2 ~ 63 : Small bin
Index 64 ~ 126 : Large bin
해당 bin은 속도 향상을 위해 single-linked list로 구성됩니다.
gdb-peda$ p global_max_fast $2 = 0x80 gdb-peda$ |
#include <stdio.h> #include <stdlib.h> void main(){ char *heap = malloc(16); char *heap1 = malloc(32); char *heap2 = malloc(48); char *heap3 = malloc(64); char *heap4 = malloc(80); char *heap5 = malloc(96); char *heap6 = malloc(112); printf("Heap Addr : %p\n",heap); printf("Heap Addr : %p\n",heap1); printf("Heap Addr : %p\n",heap2); printf("Heap Addr : %p\n",heap3); printf("Heap Addr : %p\n",heap4); printf("Heap Addr : %p\n",heap5); printf("Heap Addr : %p\n",heap6); free(heap); free(heap1); free(heap2); free(heap3); free(heap4); free(heap5); free(heap6); getchar(); } |
lazenca0x0@ubuntu:~/Documents/def$ gcc -o fastbin fastbin.c lazenca0x0@ubuntu:~/Documents/def$ gdb ./fastbin gdb-peda$ r Starting program: /home/lazenca0x0/Documents/def/fastbin Heap Addr : 0x602010 Heap Addr : 0x602030 Heap Addr : 0x602060 Heap Addr : 0x6020a0 Heap Addr : 0x6020f0 Heap Addr : 0x602150 Heap Addr : 0x6021c0 ^C Program received signal SIGINT, Interrupt. gdb-peda$ p main_arena $1 = { mutex = 0x0, flags = 0x0, fastbinsY = {0x602000, 0x602020, 0x602050, 0x602090, 0x6020e0, 0x602140, 0x6021b0, 0x0, 0x0, 0x0}, top = 0x602230, last_remainder = 0x0, bins = {0x7ffff7dd37b8 <main_arena+88>, 0x7ffff7dd37b8 <main_arena+88>, ... |
#include <stdio.h> #include <stdlib.h> void main(){ char *heap = malloc(8); char *heap2 = malloc(128); char *heap3 = malloc(8); free(heap2); getchar(); } |
free()가 호출 후에 bins의 1번째 Index 영역(0x7ffff7dd37c8,0x7ffff7dd37d0)에 해제된 heap영역의 주소 값이 저장되었습니다.
lazenca0x0@ubuntu:~/Documents/def$ gcc -o unsorted unsorted.c lazenca0x0@ubuntu:~/Documents/def$ gdb ./unsorted gdb-peda$ disassemble main Dump of assembler code for function main: 0x00000000004005bd <+0>: push rbp 0x00000000004005be <+1>: mov rbp,rsp 0x00000000004005c1 <+4>: sub rsp,0x20 0x00000000004005c5 <+8>: mov edi,0x8 0x00000000004005ca <+13>: call 0x4004c0 <malloc@plt> 0x00000000004005cf <+18>: mov QWORD PTR [rbp-0x18],rax 0x00000000004005d3 <+22>: mov edi,0x80 0x00000000004005d8 <+27>: call 0x4004c0 <malloc@plt> 0x00000000004005dd <+32>: mov QWORD PTR [rbp-0x10],rax 0x00000000004005e1 <+36>: mov edi,0x8 0x00000000004005e6 <+41>: call 0x4004c0 <malloc@plt> 0x00000000004005eb <+46>: mov QWORD PTR [rbp-0x8],rax 0x00000000004005ef <+50>: mov rax,QWORD PTR [rbp-0x10] 0x00000000004005f3 <+54>: mov rdi,rax 0x00000000004005f6 <+57>: call 0x400480 <free@plt> 0x00000000004005fb <+62>: call 0x4004a0 <getchar@plt> 0x0000000000400600 <+67>: leave 0x0000000000400601 <+68>: ret End of assembler dump. gdb-peda$ b *0x00000000004005f6 Breakpoint 1 at 0x4005f6 gdb-peda$ r Starting program: /home/lazenca0x0/Documents/def/unsorted Breakpoint 1, 0x00000000004005f6 in main () gdb-peda$ p main_arena $2 = { mutex = 0x0, flags = 0x1, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x6020d0, last_remainder = 0x0, bins = {0x7ffff7dd37b8 <main_arena+88>, 0x7ffff7dd37b8 <main_arena+88>, 0x7ffff7dd37c8 <main_arena+104>, 0x7ffff7dd37c8 ... } gdb-peda$ ni 0x00000000004005fb in main () gdb-peda$ p main_arena $3 = { mutex = 0x0, flags = 0x1, fastbinsY = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, top = 0x6020d0, last_remainder = 0x0, bins = {0x602020, 0x602020, 0x7ffff7dd37c8 <main_arena+104>, 0x7ffff7dd37c8 <main_arena+104>, 0x7ffff7dd37d8 ... } |
Excuse the ads! We need some help to keep our site up.