456 pág.


DisciplinaLinux714 materiais1.843 seguidores
Pré-visualização50 páginas
Address of pHeapVar after malloc is 0x8049998
sbrk( 0 ) value after malloc is 0x806b000
My maps file after the malloc call is:
08048000-08049000 r-xp 00000000 03:08 130260 /home/dbehman/book/src/
08049000-0804a000 rw-p 00000000 03:08 130260 /home/dbehman/book/src/
0804a000-0806b000 rwxp 00000000 00:00 0
40000000-40018000 r-xp 00000000 03:08 6664 /lib/
40018000-40019000 rw-p 00017000 03:08 6664 /lib/
40019000-4001b000 rw-p 00000000 00:00 0
40028000-40154000 r-xp 00000000 03:08 6661 /lib/i686/
40154000-40159000 rw-p 0012c000 03:08 6661 /lib/i686/
40159000-4015b000 rw-p 00000000 00:00 0
bfffe000-c0000000 rwxp fffff000 00:00 0
When examining this output, it may seem that a contradiction exists as to
where the bss section actually exists. I\u2019ve written that it exists in the heap
segment, but the preceding output shows that the address of the bss variable
lives in data segment (that is, 0x8049948 lies within the address range 0x08049000-
0x0804a000). The reason for this is that there is unused space at the end of the
data segment, due to the small size of the example and the small number of
global variables declared, so the bss segment appears in the data segment to
limit wasted space. This fact in no way changes its properties.
993.2 Process Information
The next important thing to note from this output is that before the malloc
call, the heapseg executable only had two entries in the maps file. This meant
that there was no heap at that particular point in time. After the malloc call,
we now see the third line, which represents the heap segment. Next we see
that after the malloc call, the brk pointer is now pointing to the end of the
range reported in the maps file, 0x0806b000. Now you may be a bit confused
because the brk pointer moved from 0x08049948 to 0x0806b000 which is a total
of 136888 bytes. This is an awful lot more than the 1024 that we requested, so
what happened? Malloc is smart enough to know that it\u2019s quite likely that
more heap memory will be required by the program in the future so rather
than continuously calling the expensive brk() system call to move the pointer
for every malloc call, it asks for a much larger chunk of memory than
immediately needed. This way, when malloc is called again to get a relatively
small chunk of memory, brk() need not be called again, and malloc can just
return some of this extra memory. Doing this provides a huge performance
boost, especially if the program requests many small chunks of memory via
malloc calls. Mapped Base / Shared Libraries Continuing our examination
of the maps file, the next point of interest is what\u2019s commonly referred to as
the mapped base address, which defines where the shared libraries for an
executable get loaded. In standard kernel source code (as downloaded from, the mapped base address is a hardcoded location defined as
TASK_UNMAPPED_BASE in each architecture\u2019s processor.h header file. For
example, in the 2.6.0 kernel source code, the file, include/asm-i386/processor.h,
contains the definition:
/* This decides where the kernel will search for a free chunk of vm
* space during mmap's.
Resolving the definitions of PAGE_ALIGN and TASK_SIZE, this equates to
0x40000000. Note that some distributions such as SuSE include a patch that
allows this value to be dynamically modified. See the discussion on the /proc/
<pid>/mapped_base file in this chapter. Continuing our examination of the
mapped base, let\u2019s look at the maps file for bash again:
08048000-080b6000 r-xp 00000000 03:08 10667 /bin/bash
080b6000-080b9000 rw-p 0006e000 03:08 10667 /bin/bash
080b9000-08101000 rwxp 00000000 00:00 0
40000000-40018000 r-xp 00000000 03:08 6664 /lib/
40018000-40019000 rw-p 00017000 03:08 6664 /lib/
40019000-4001a000 rw-p 00000000 00:00 0
100 The /proc Filesystem Chap. 3
4001a000-4001b000 r--p 00000000 03:08 8598 /usr/lib/locale/
4001b000-4001c000 r--p 00000000 03:08 9920 /usr/lib/locale/
4001c000-4001d000 r--p 00000000 03:08 9917 /usr/lib/locale/
4001d000-4001e000 r--p 00000000 03:08 9921 /usr/lib/locale/
4001e000-4001f000 r--p 00000000 03:08 9918 /usr/lib/locale/
4001f000-40020000 r--p 00000000 03:08 9939 /usr/lib/locale/
40020000-40021000 r--p 00000000 03:08 9953 /usr/lib/
40021000-40022000 r--p 00000000 03:08 9919 /usr/lib/locale/
40022000-40028000 r--p 00000000 03:08 10057 /usr/lib/locale/
40028000-40050000 r-xp 00000000 03:08 10434 /lib/
40050000-40054000 rw-p 00028000 03:08 10434 /lib/
40054000-40055000 rw-p 00000000 00:00 0
40055000-4005b000 r-xp 00000000 03:08 10432 /lib/
4005b000-4005c000 rw-p 00005000 03:08 10432 /lib/
4005c000-40096000 r-xp 00000000 03:08 6788 /lib/
40096000-400a1000 rw-p 00039000 03:08 6788 /lib/
400a1000-400a2000 rw-p 00000000 00:00 0
400a2000-400a4000 r-xp 00000000 03:08 6673 /lib/
400a4000-400a5000 rw-p 00002000 03:08 6673 /lib/
400a5000-401d1000 r-xp 00000000 03:08 6661 /lib/i686/
401d1000-401d6000 rw-p 0012c000 03:08 6661 /lib/i686/
401d6000-401d9000 rw-p 00000000 00:00 0
401d9000-401da000 r--p 00000000 03:08 8600 /usr/lib/locale/
401da000-401db000 r--p 00000000 03:08 9952 /usr/lib/locale/
401db000-40207000 r--p 00000000 03:08 10056 /usr/lib/locale/
40207000-4020d000 r--s 00000000 03:08 8051 /usr/lib/gconv/
4020d000-4020f000 r-xp 00000000 03:08 8002 /usr/lib/gconv/
4020f000-40210000 rw-p 00001000 03:08 8002 /usr/lib/gconv/
40210000-40212000 rw-p 00000000 00:00 0
bfffa000-c0000000 rwxp ffffb000 00:00 0
Note the line:
40000000-40018000 r-xp 00000000 03:08 6664 /lib/
This shows us that /lib/ was the first shared library to be loaded
when this process began. /lib/ is the linker itself, so this makes perfect
sense and in fact is the case in all executables that dynamically link in shared
libraries. Basically what happens is that when creating an executable that
will link in one or more shared libraries, the linker is implicitly linked into the
executable as well. Because the linker is responsible for resolving all external
symbols in the linked shared libraries, it must be mapped into memory first,
which is why it will always be the first shared library to show up in the maps
After the linker, all shared libraries that an executable depends upon
will appear in the maps file. You can check to see what an executable needs
without running it and looking at the maps file by running the ldd command
as shown here:
penguin> ldd /bin/bash => /lib/ (0x40028000) => /lib/ (0x40055000) => /lib/ (0x4005c000) => /lib/ (0x400a2000) => /lib/i686/ (0x400a5000)
 /lib/ => /lib/ (0x40000000)
You can now correlate the list of libraries and their addresses to Figure 3.1
and see what they look like in the maps file.
3.2 Process Information
Note: ldd is actually a script that does many things, but the main
thing it does is it sets the LD_TRACE_LOADED_OBJECTS environment
variable to non-NULL. Try the following sequence of commands and see
what happens:
Note: Be sure to do an unset