understand process memory map in linux
I am trying to understand the basic of linux process memory layout and i got this program:
#include <stdio.h> // standard io
#include <stdlib.h> // C standard library
#include <pthread.h> // threading
#include <unistd.h> // unix standard library
#include <sys/types.h> // system types for linux
// getchar basically is like "read"
// it prompts the user for input
// in this case, the input is thrown away
// which makes similar to a "pause" continuation primitive
// but a pause that is resolved through user input, which we promptly throw away!
void * thread_func (void * arg) {
printf("Before malloc in thread 1n");
getchar();
char * addr = (char *) malloc(1000);
printf("After malloc and before free in thread 1n");
getchar();
free(addr);
printf("After free in thread 1n");
getchar();
}
int main () {
char * addr;
printf("Welcome to per thread arena example::%dn", getpid());
printf("Before malloc in the main threadn");
getchar();
addr = (char *) malloc(1000);
printf("After malloc and before free in main threadn");
getchar();
free(addr);
printf("After free in main threadn");
getchar();
// pointer to the thread 1
pthread_t thread_1;
// pthread_* functions return 0 upon succeeding, and other numbers upon failing
int pthread_status;
pthread_status = pthread_create(&thread_1, NULL, thread_func, NULL);
if (pthread_status != 0) {
printf("Thread creation errorn");
return -1;
}
// returned status code from thread_1
void * thread_1_status;
pthread_status = pthread_join(thread_1, &thread_1_status);
if (pthread_status != 0) {
printf("Thread join errorn");
return -1;
}
return 0;
}
When I started the program, the content in /proc/<pid>/maps
is:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these memory regions?
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
...
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
Then I press enter a few times after running the program. After it prints "Before malloc in thread 1". The memory layout looks like below:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00632000-00653000 rw-p 00000000 00:00 0 [heap]
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these two regions?
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
After it prints "After malloc and before free in thread 1", it creates another two regions below:
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
What are the purposes of these two regions?
linux memory memory-management x86-64 glibc
add a comment |
I am trying to understand the basic of linux process memory layout and i got this program:
#include <stdio.h> // standard io
#include <stdlib.h> // C standard library
#include <pthread.h> // threading
#include <unistd.h> // unix standard library
#include <sys/types.h> // system types for linux
// getchar basically is like "read"
// it prompts the user for input
// in this case, the input is thrown away
// which makes similar to a "pause" continuation primitive
// but a pause that is resolved through user input, which we promptly throw away!
void * thread_func (void * arg) {
printf("Before malloc in thread 1n");
getchar();
char * addr = (char *) malloc(1000);
printf("After malloc and before free in thread 1n");
getchar();
free(addr);
printf("After free in thread 1n");
getchar();
}
int main () {
char * addr;
printf("Welcome to per thread arena example::%dn", getpid());
printf("Before malloc in the main threadn");
getchar();
addr = (char *) malloc(1000);
printf("After malloc and before free in main threadn");
getchar();
free(addr);
printf("After free in main threadn");
getchar();
// pointer to the thread 1
pthread_t thread_1;
// pthread_* functions return 0 upon succeeding, and other numbers upon failing
int pthread_status;
pthread_status = pthread_create(&thread_1, NULL, thread_func, NULL);
if (pthread_status != 0) {
printf("Thread creation errorn");
return -1;
}
// returned status code from thread_1
void * thread_1_status;
pthread_status = pthread_join(thread_1, &thread_1_status);
if (pthread_status != 0) {
printf("Thread join errorn");
return -1;
}
return 0;
}
When I started the program, the content in /proc/<pid>/maps
is:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these memory regions?
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
...
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
Then I press enter a few times after running the program. After it prints "Before malloc in thread 1". The memory layout looks like below:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00632000-00653000 rw-p 00000000 00:00 0 [heap]
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these two regions?
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
After it prints "After malloc and before free in thread 1", it creates another two regions below:
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
What are the purposes of these two regions?
linux memory memory-management x86-64 glibc
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent anmmap(NULL, ...)
from randomly choosing it.
– Peter Cordes
Nov 24 '18 at 6:25
add a comment |
I am trying to understand the basic of linux process memory layout and i got this program:
#include <stdio.h> // standard io
#include <stdlib.h> // C standard library
#include <pthread.h> // threading
#include <unistd.h> // unix standard library
#include <sys/types.h> // system types for linux
// getchar basically is like "read"
// it prompts the user for input
// in this case, the input is thrown away
// which makes similar to a "pause" continuation primitive
// but a pause that is resolved through user input, which we promptly throw away!
void * thread_func (void * arg) {
printf("Before malloc in thread 1n");
getchar();
char * addr = (char *) malloc(1000);
printf("After malloc and before free in thread 1n");
getchar();
free(addr);
printf("After free in thread 1n");
getchar();
}
int main () {
char * addr;
printf("Welcome to per thread arena example::%dn", getpid());
printf("Before malloc in the main threadn");
getchar();
addr = (char *) malloc(1000);
printf("After malloc and before free in main threadn");
getchar();
free(addr);
printf("After free in main threadn");
getchar();
// pointer to the thread 1
pthread_t thread_1;
// pthread_* functions return 0 upon succeeding, and other numbers upon failing
int pthread_status;
pthread_status = pthread_create(&thread_1, NULL, thread_func, NULL);
if (pthread_status != 0) {
printf("Thread creation errorn");
return -1;
}
// returned status code from thread_1
void * thread_1_status;
pthread_status = pthread_join(thread_1, &thread_1_status);
if (pthread_status != 0) {
printf("Thread join errorn");
return -1;
}
return 0;
}
When I started the program, the content in /proc/<pid>/maps
is:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these memory regions?
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
...
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
Then I press enter a few times after running the program. After it prints "Before malloc in thread 1". The memory layout looks like below:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00632000-00653000 rw-p 00000000 00:00 0 [heap]
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these two regions?
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
After it prints "After malloc and before free in thread 1", it creates another two regions below:
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
What are the purposes of these two regions?
linux memory memory-management x86-64 glibc
I am trying to understand the basic of linux process memory layout and i got this program:
#include <stdio.h> // standard io
#include <stdlib.h> // C standard library
#include <pthread.h> // threading
#include <unistd.h> // unix standard library
#include <sys/types.h> // system types for linux
// getchar basically is like "read"
// it prompts the user for input
// in this case, the input is thrown away
// which makes similar to a "pause" continuation primitive
// but a pause that is resolved through user input, which we promptly throw away!
void * thread_func (void * arg) {
printf("Before malloc in thread 1n");
getchar();
char * addr = (char *) malloc(1000);
printf("After malloc and before free in thread 1n");
getchar();
free(addr);
printf("After free in thread 1n");
getchar();
}
int main () {
char * addr;
printf("Welcome to per thread arena example::%dn", getpid());
printf("Before malloc in the main threadn");
getchar();
addr = (char *) malloc(1000);
printf("After malloc and before free in main threadn");
getchar();
free(addr);
printf("After free in main threadn");
getchar();
// pointer to the thread 1
pthread_t thread_1;
// pthread_* functions return 0 upon succeeding, and other numbers upon failing
int pthread_status;
pthread_status = pthread_create(&thread_1, NULL, thread_func, NULL);
if (pthread_status != 0) {
printf("Thread creation errorn");
return -1;
}
// returned status code from thread_1
void * thread_1_status;
pthread_status = pthread_join(thread_1, &thread_1_status);
if (pthread_status != 0) {
printf("Thread join errorn");
return -1;
}
return 0;
}
When I started the program, the content in /proc/<pid>/maps
is:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these memory regions?
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
...
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
Then I press enter a few times after running the program. After it prints "Before malloc in thread 1". The memory layout looks like below:
00400000-00401000 r-xp 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00600000-00601000 r--p 00000000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00601000-00602000 rw-p 00001000 08:01 1323314 /home/oscp/xg/c/memory_layout/a.out
00632000-00653000 rw-p 00000000 00:00 0 [heap]
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37697000-7fcc3769c000 rw-p 00000000 00:00 0
7fcc3769c000-7fcc376b5000 r-xp 00000000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc376b5000-7fcc378b4000 ---p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b4000-7fcc378b5000 r--p 00018000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b5000-7fcc378b6000 rw-p 00019000 08:01 1053877 /lib/x86_64-linux-gnu/libpthread-2.19.so
7fcc378b6000-7fcc378ba000 rw-p 00000000 00:00 0
7fcc378ba000-7fcc378dd000 r-xp 00000000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
7fcc37adc000-7fcc37add000 r--p 00022000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37add000-7fcc37ade000 rw-p 00023000 08:01 1053733 /lib/x86_64-linux-gnu/ld-2.19.so
7fcc37ade000-7fcc37adf000 rw-p 00000000 00:00 0
7ffdc1cff000-7ffdc1d20000 rw-p 00000000 00:00 0 [stack]
7ffdc1dd8000-7ffdc1ddb000 r--p 00000000 00:00 0 [vvar]
7ffdc1ddb000-7ffdc1ddd000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
What are the purposes of these two regions?
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
After it prints "After malloc and before free in thread 1", it creates another two regions below:
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
What are the purposes of these two regions?
linux memory memory-management x86-64 glibc
linux memory memory-management x86-64 glibc
edited Nov 24 '18 at 6:27
Peter Cordes
126k18189325
126k18189325
asked Nov 24 '18 at 6:03
drdotdrdot
1,08442240
1,08442240
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent anmmap(NULL, ...)
from randomly choosing it.
– Peter Cordes
Nov 24 '18 at 6:25
add a comment |
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent anmmap(NULL, ...)
from randomly choosing it.
– Peter Cordes
Nov 24 '18 at 6:25
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent an
mmap(NULL, ...)
from randomly choosing it.– Peter Cordes
Nov 24 '18 at 6:25
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent an
mmap(NULL, ...)
from randomly choosing it.– Peter Cordes
Nov 24 '18 at 6:25
add a comment |
1 Answer
1
active
oldest
votes
Your question covers many completely different things, so the answer will be long.
The first question is the meaning of
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
in
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
This inaccessible memory region is a gap between adjacent ELF segments of the library (which is supposed to occupy the contiguous chunk of memory). The ---p
protection mode forbids using this gap for occasional memory allocation. If you strace(1)
the process when it loads the library, you may see something like this:
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0) = 0x7f9673d8f000
mprotect(0x7f9673db1000, 1671168, PROT_NONE) = 0
mmap(0x7f9673db1000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x22000) = 0x7f9673db1000
mmap(0x7f9673efc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x16d000) = 0x7f9673efc000
mmap(0x7f9673f49000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x1b9000) = 0x7f9673f49000
The first mmap()
maps the first ELF segment into the memory but reserves the space for whole library. This is done to allow the kernel to choose the location for the library on its discretion. To protect any possible gaps between segments mprotect(..., PROT_NONE)
is called; then all remaining segments are mapped into the memory using mmap()
- this also changes the protection mode of the appropriate memory pages from ---p
to whatever mode the segment requires. You may have some fun by taking a look at how it actually works. If you want to verify how this ---p
gap is formed during the loading, you may also use readelf(1)
with library's binary and do some hexadecimal math with segments' locations and alignments, collating the results with the output of strace
.
The second question are the following anonymous mappings:
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
This looks like a thread stack for thread 1
. The second mapping is the stack itself (372d7000
- 36ad7000
= 800000
= 8 MiB, which is a default stack size limit in many distros, which, in turn, is a default stack size for pthread
), and the first one is a stack guard page. This page with mode ---p
protects the stack from overflowing, and triggers the segfault when the overflow happens (because of a write to this write-protected page).
Note: in older Linux kernels, the thread stacks were annotated with [stack:TID]
names in maps
file, but this feature was removed, so I cannot guarantee that this mapping is really a thread stack (though it looks like). However, you may use strace
to find the exact thread's stack location from child_stack
argument of clone()
syscall and compare with this mapping.
Going on. The third question is
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
Well, this is what malloc()
in thread 1
did to allocate the memory you have requested. In short, the whole region 7fcc30000000-7fcc34000000
is a heap, from which allocations are done. The rw-p
interval 7fcc30000000-7fcc30021000
, allocated from this heap, will grow as you will request more and more memory with malloc()
. When this heap will deplete, new one will be requested using mmap()
.
As you probably noticed, I don't have an explanation for the following mappings in your question:
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
I can't recognize those guys quickly and not sure that these are ordinary allocations. Probably this needs separate investigation, as this topic is already too long.
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (catch syscall mmap
and then see who is caller).
– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with[heap]
. You may do 1000malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not bymmap()
syscall, but bybrk()
. You may be interested in reading some stuff about how glibc'smalloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.
– Danila Kiver
Nov 25 '18 at 23:28
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53455603%2funderstand-process-memory-map-in-linux%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
Your question covers many completely different things, so the answer will be long.
The first question is the meaning of
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
in
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
This inaccessible memory region is a gap between adjacent ELF segments of the library (which is supposed to occupy the contiguous chunk of memory). The ---p
protection mode forbids using this gap for occasional memory allocation. If you strace(1)
the process when it loads the library, you may see something like this:
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0) = 0x7f9673d8f000
mprotect(0x7f9673db1000, 1671168, PROT_NONE) = 0
mmap(0x7f9673db1000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x22000) = 0x7f9673db1000
mmap(0x7f9673efc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x16d000) = 0x7f9673efc000
mmap(0x7f9673f49000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x1b9000) = 0x7f9673f49000
The first mmap()
maps the first ELF segment into the memory but reserves the space for whole library. This is done to allow the kernel to choose the location for the library on its discretion. To protect any possible gaps between segments mprotect(..., PROT_NONE)
is called; then all remaining segments are mapped into the memory using mmap()
- this also changes the protection mode of the appropriate memory pages from ---p
to whatever mode the segment requires. You may have some fun by taking a look at how it actually works. If you want to verify how this ---p
gap is formed during the loading, you may also use readelf(1)
with library's binary and do some hexadecimal math with segments' locations and alignments, collating the results with the output of strace
.
The second question are the following anonymous mappings:
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
This looks like a thread stack for thread 1
. The second mapping is the stack itself (372d7000
- 36ad7000
= 800000
= 8 MiB, which is a default stack size limit in many distros, which, in turn, is a default stack size for pthread
), and the first one is a stack guard page. This page with mode ---p
protects the stack from overflowing, and triggers the segfault when the overflow happens (because of a write to this write-protected page).
Note: in older Linux kernels, the thread stacks were annotated with [stack:TID]
names in maps
file, but this feature was removed, so I cannot guarantee that this mapping is really a thread stack (though it looks like). However, you may use strace
to find the exact thread's stack location from child_stack
argument of clone()
syscall and compare with this mapping.
Going on. The third question is
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
Well, this is what malloc()
in thread 1
did to allocate the memory you have requested. In short, the whole region 7fcc30000000-7fcc34000000
is a heap, from which allocations are done. The rw-p
interval 7fcc30000000-7fcc30021000
, allocated from this heap, will grow as you will request more and more memory with malloc()
. When this heap will deplete, new one will be requested using mmap()
.
As you probably noticed, I don't have an explanation for the following mappings in your question:
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
I can't recognize those guys quickly and not sure that these are ordinary allocations. Probably this needs separate investigation, as this topic is already too long.
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (catch syscall mmap
and then see who is caller).
– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with[heap]
. You may do 1000malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not bymmap()
syscall, but bybrk()
. You may be interested in reading some stuff about how glibc'smalloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.
– Danila Kiver
Nov 25 '18 at 23:28
add a comment |
Your question covers many completely different things, so the answer will be long.
The first question is the meaning of
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
in
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
This inaccessible memory region is a gap between adjacent ELF segments of the library (which is supposed to occupy the contiguous chunk of memory). The ---p
protection mode forbids using this gap for occasional memory allocation. If you strace(1)
the process when it loads the library, you may see something like this:
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0) = 0x7f9673d8f000
mprotect(0x7f9673db1000, 1671168, PROT_NONE) = 0
mmap(0x7f9673db1000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x22000) = 0x7f9673db1000
mmap(0x7f9673efc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x16d000) = 0x7f9673efc000
mmap(0x7f9673f49000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x1b9000) = 0x7f9673f49000
The first mmap()
maps the first ELF segment into the memory but reserves the space for whole library. This is done to allow the kernel to choose the location for the library on its discretion. To protect any possible gaps between segments mprotect(..., PROT_NONE)
is called; then all remaining segments are mapped into the memory using mmap()
- this also changes the protection mode of the appropriate memory pages from ---p
to whatever mode the segment requires. You may have some fun by taking a look at how it actually works. If you want to verify how this ---p
gap is formed during the loading, you may also use readelf(1)
with library's binary and do some hexadecimal math with segments' locations and alignments, collating the results with the output of strace
.
The second question are the following anonymous mappings:
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
This looks like a thread stack for thread 1
. The second mapping is the stack itself (372d7000
- 36ad7000
= 800000
= 8 MiB, which is a default stack size limit in many distros, which, in turn, is a default stack size for pthread
), and the first one is a stack guard page. This page with mode ---p
protects the stack from overflowing, and triggers the segfault when the overflow happens (because of a write to this write-protected page).
Note: in older Linux kernels, the thread stacks were annotated with [stack:TID]
names in maps
file, but this feature was removed, so I cannot guarantee that this mapping is really a thread stack (though it looks like). However, you may use strace
to find the exact thread's stack location from child_stack
argument of clone()
syscall and compare with this mapping.
Going on. The third question is
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
Well, this is what malloc()
in thread 1
did to allocate the memory you have requested. In short, the whole region 7fcc30000000-7fcc34000000
is a heap, from which allocations are done. The rw-p
interval 7fcc30000000-7fcc30021000
, allocated from this heap, will grow as you will request more and more memory with malloc()
. When this heap will deplete, new one will be requested using mmap()
.
As you probably noticed, I don't have an explanation for the following mappings in your question:
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
I can't recognize those guys quickly and not sure that these are ordinary allocations. Probably this needs separate investigation, as this topic is already too long.
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (catch syscall mmap
and then see who is caller).
– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with[heap]
. You may do 1000malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not bymmap()
syscall, but bybrk()
. You may be interested in reading some stuff about how glibc'smalloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.
– Danila Kiver
Nov 25 '18 at 23:28
add a comment |
Your question covers many completely different things, so the answer will be long.
The first question is the meaning of
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
in
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
This inaccessible memory region is a gap between adjacent ELF segments of the library (which is supposed to occupy the contiguous chunk of memory). The ---p
protection mode forbids using this gap for occasional memory allocation. If you strace(1)
the process when it loads the library, you may see something like this:
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0) = 0x7f9673d8f000
mprotect(0x7f9673db1000, 1671168, PROT_NONE) = 0
mmap(0x7f9673db1000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x22000) = 0x7f9673db1000
mmap(0x7f9673efc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x16d000) = 0x7f9673efc000
mmap(0x7f9673f49000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x1b9000) = 0x7f9673f49000
The first mmap()
maps the first ELF segment into the memory but reserves the space for whole library. This is done to allow the kernel to choose the location for the library on its discretion. To protect any possible gaps between segments mprotect(..., PROT_NONE)
is called; then all remaining segments are mapped into the memory using mmap()
- this also changes the protection mode of the appropriate memory pages from ---p
to whatever mode the segment requires. You may have some fun by taking a look at how it actually works. If you want to verify how this ---p
gap is formed during the loading, you may also use readelf(1)
with library's binary and do some hexadecimal math with segments' locations and alignments, collating the results with the output of strace
.
The second question are the following anonymous mappings:
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
This looks like a thread stack for thread 1
. The second mapping is the stack itself (372d7000
- 36ad7000
= 800000
= 8 MiB, which is a default stack size limit in many distros, which, in turn, is a default stack size for pthread
), and the first one is a stack guard page. This page with mode ---p
protects the stack from overflowing, and triggers the segfault when the overflow happens (because of a write to this write-protected page).
Note: in older Linux kernels, the thread stacks were annotated with [stack:TID]
names in maps
file, but this feature was removed, so I cannot guarantee that this mapping is really a thread stack (though it looks like). However, you may use strace
to find the exact thread's stack location from child_stack
argument of clone()
syscall and compare with this mapping.
Going on. The third question is
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
Well, this is what malloc()
in thread 1
did to allocate the memory you have requested. In short, the whole region 7fcc30000000-7fcc34000000
is a heap, from which allocations are done. The rw-p
interval 7fcc30000000-7fcc30021000
, allocated from this heap, will grow as you will request more and more memory with malloc()
. When this heap will deplete, new one will be requested using mmap()
.
As you probably noticed, I don't have an explanation for the following mappings in your question:
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
I can't recognize those guys quickly and not sure that these are ordinary allocations. Probably this needs separate investigation, as this topic is already too long.
Your question covers many completely different things, so the answer will be long.
The first question is the meaning of
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
in
7fcc372d7000-7fcc37491000 r-xp 00000000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37491000-7fcc37691000 ---p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37691000-7fcc37695000 r--p 001ba000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
7fcc37695000-7fcc37697000 rw-p 001be000 08:01 1053757 /lib/x86_64-linux-gnu/libc-2.19.so
This inaccessible memory region is a gap between adjacent ELF segments of the library (which is supposed to occupy the contiguous chunk of memory). The ---p
protection mode forbids using this gap for occasional memory allocation. If you strace(1)
the process when it loads the library, you may see something like this:
mmap(NULL, 1848896, PROT_READ, MAP_PRIVATE|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0) = 0x7f9673d8f000
mprotect(0x7f9673db1000, 1671168, PROT_NONE) = 0
mmap(0x7f9673db1000, 1355776, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x22000) = 0x7f9673db1000
mmap(0x7f9673efc000, 311296, PROT_READ, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x16d000) = 0x7f9673efc000
mmap(0x7f9673f49000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3</usr/lib/libc-2.28.so>, 0x1b9000) = 0x7f9673f49000
The first mmap()
maps the first ELF segment into the memory but reserves the space for whole library. This is done to allow the kernel to choose the location for the library on its discretion. To protect any possible gaps between segments mprotect(..., PROT_NONE)
is called; then all remaining segments are mapped into the memory using mmap()
- this also changes the protection mode of the appropriate memory pages from ---p
to whatever mode the segment requires. You may have some fun by taking a look at how it actually works. If you want to verify how this ---p
gap is formed during the loading, you may also use readelf(1)
with library's binary and do some hexadecimal math with segments' locations and alignments, collating the results with the output of strace
.
The second question are the following anonymous mappings:
7fcc36ad6000-7fcc36ad7000 ---p 00000000 00:00 0
7fcc36ad7000-7fcc372d7000 rw-p 00000000 00:00 0
This looks like a thread stack for thread 1
. The second mapping is the stack itself (372d7000
- 36ad7000
= 800000
= 8 MiB, which is a default stack size limit in many distros, which, in turn, is a default stack size for pthread
), and the first one is a stack guard page. This page with mode ---p
protects the stack from overflowing, and triggers the segfault when the overflow happens (because of a write to this write-protected page).
Note: in older Linux kernels, the thread stacks were annotated with [stack:TID]
names in maps
file, but this feature was removed, so I cannot guarantee that this mapping is really a thread stack (though it looks like). However, you may use strace
to find the exact thread's stack location from child_stack
argument of clone()
syscall and compare with this mapping.
Going on. The third question is
7fcc30000000-7fcc30021000 rw-p 00000000 00:00 0
7fcc30021000-7fcc34000000 ---p 00000000 00:00 0
Well, this is what malloc()
in thread 1
did to allocate the memory you have requested. In short, the whole region 7fcc30000000-7fcc34000000
is a heap, from which allocations are done. The rw-p
interval 7fcc30000000-7fcc30021000
, allocated from this heap, will grow as you will request more and more memory with malloc()
. When this heap will deplete, new one will be requested using mmap()
.
As you probably noticed, I don't have an explanation for the following mappings in your question:
7fcc37abe000-7fcc37ac1000 rw-p 00000000 00:00 0
7fcc37ad8000-7fcc37adc000 rw-p 00000000 00:00 0
I can't recognize those guys quickly and not sure that these are ordinary allocations. Probably this needs separate investigation, as this topic is already too long.
edited Nov 25 '18 at 4:40
answered Nov 25 '18 at 3:38
Danila KiverDanila Kiver
397212
397212
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (catch syscall mmap
and then see who is caller).
– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with[heap]
. You may do 1000malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not bymmap()
syscall, but bybrk()
. You may be interested in reading some stuff about how glibc'smalloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.
– Danila Kiver
Nov 25 '18 at 23:28
add a comment |
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (catch syscall mmap
and then see who is caller).
– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with[heap]
. You may do 1000malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not bymmap()
syscall, but bybrk()
. You may be interested in reading some stuff about how glibc'smalloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.
– Danila Kiver
Nov 25 '18 at 23:28
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
That might be TLS maybe?
– o11c
Nov 25 '18 at 4:47
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (
catch syscall mmap
and then see who is caller).– Danila Kiver
Nov 25 '18 at 10:39
There are few more small anon mappings pretty similar to these two, so I can't prove the purpose of each particular one of them and say "this one is definitely a TLS". It would be better to check each of them with debugger individually to be sure (
catch syscall mmap
and then see who is caller).– Danila Kiver
Nov 25 '18 at 10:39
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
Regarding the answer to the third question, if you see the malloc in the main thread, you will find the malloc does not generate a protected region. i.e., press "enter" until it prints "After malloc and before free in main thread". Why is that?
– drdot
Nov 25 '18 at 23:18
The main thread here uses the region marked with
[heap]
. You may do 1000 malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not by mmap()
syscall, but by brk()
. You may be interested in reading some stuff about how glibc's malloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.– Danila Kiver
Nov 25 '18 at 23:28
The main thread here uses the region marked with
[heap]
. You may do 1000 malloc()
s of 100k chunks and you will see this region growing. This region is a bit special for historical reason and resized not by mmap()
syscall, but by brk()
. You may be interested in reading some stuff about how glibc's malloc()
works, e.g. sourceware.org/glibc/wiki/MallocInternals.– Danila Kiver
Nov 25 '18 at 23:28
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53455603%2funderstand-process-memory-map-in-linux%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
The mappings with no permissions might be some kind of "guard" page, and/or reserving the virtual address space for future growth (to prevent an
mmap(NULL, ...)
from randomly choosing it.– Peter Cordes
Nov 24 '18 at 6:25