
Heap analysis tooling for dlmalloc
libdlmalloc ist ein Python-Skript, das für die Verwendung mit GDB entwickelt wurde und zur Analyse des Doug-Lea-Allokators, auch bekannt als dlmalloc, verwendet werden kann. Es unterstützt derzeit dlmalloc-Versionen 2.8.x. Beachten Sie, dass einige Teile auch unabhängig von GDB verwendet werden können, beispielsweise für die Offline-Analyse von geschnapptem Heap-Speicher.
libdlmalloc wurde von anderen GDB-Python-Skripten zur Analyse von Heaps inspiriert, wie libtalloc, unmask_jemalloc und libheap. Einige grundlegende Funktionen sind nahezu identisch mit diesen Projekten.
libdlmalloc wurde überwiegend auf 32-Bit- und 64-Bit-Cisco-ASA-Geräten getestet, die dlmalloc 2.8.3 verwenden. Es sollte mit anderen 2.8.x-Versionen funktionieren, jedoch wird es aufgrund erheblicher Unterschiede nicht mit früheren Versionen wie <= 2.7.x funktionieren.
Wenn Sie libdlmalloc erfolgreich mit einer bestimmten 2.8.x-Version oder einem bestimmten Gerät getestet haben, teilen Sie dies bitte den Autoren mit, und wir werden die Dokumente aktualisieren.
Das Skript benötigt lediglich eine relativ moderne Version von GDB mit Python3-Unterstützung. Wir haben hauptsächlich mit Python3 getestet, daher erwarten wir, dass es derzeit mit Python2.7 Probleme geben wird.
Wenn Sie die GDB-Befehle verwenden möchten, können Sie Folgendes verwenden:``` (gdb) source libdlmalloc_28x.py
Ein Großteil der Kernlogik ist in die Klasse `dl_helper` ausgelagert, die es dir ermöglicht, libdlmalloc direkt zu importieren und auf bestimmte wichtige Strukturen außerhalb einer GDB-Sitzung zuzugreifen. Dies ist nützlich, wenn du Offline-Chunk-/Heap-Snapshots analysieren möchtest.
# Verwendung
Der Großteil der Funktionalität ist an den Ansatz in unmask_jemalloc und libtalloc angelehnt, bei dem ein separater GDB-Befehl bereitgestellt wird. Allerdings verwenden wir auch eine ganze Reihe von Schaltern.
Um eine vollständige Liste der derzeit unterstützten Befehle zu sehen, kannst du den Befehl `dlhelp` verwenden:
## dlhelp
Dies ist die Hauptfunktion, um die verfügbaren Befehle anzuzeigen. Jeder der Befehle unterstützt die Option `-h`, mit der du ausführlichere Anweisungen zur Verwendung erhalten kannst.```
(gdb) dlhelp
[libdlmalloc] dlmalloc commands for gdb
[libdlmalloc] dlchunk : show one or more chunks metadata and contents
[libdlmalloc] dlmstate : print mstate structure information. caches address after first use
[libdlmalloc] dlcallback : register a callback or query/modify callback status
[libdlmalloc] dlhelp : this help message
[libdlmalloc] NOTE: Pass -h to any of these commands for more extensive usage. Eg: dlchunk -h
dlchunk kann Ihnen eine Zusammenfassung eines Chunks liefern oder ausführlichere
Informationen zu jedem Feld. Sie können es auch verwenden, um Informationen über
mehrere Chunks aufzulisten, Chunks zu durchsuchen usw. Die Verwendung von dlchunk ist unten zu sehen:```
(gdb) dlchunk -h
[libdlmalloc] usage: dlchunk [-v] [-f] [-x] [-c ]
[libdlmalloc] a dlmalloc chunk header
[libdlmalloc] -v use verbose output (multiples for more verbosity)
[libdlmalloc] -f use explicitly, rather than be smart
[libdlmalloc] -x hexdump the chunk contents
[libdlmalloc] -m max bytes to dump with -x
[libdlmalloc] -c number of chunks to print
[libdlmalloc] -s search pattern when print chunks
[libdlmalloc] --depth depth to search inside chunk
[libdlmalloc] -d debug and force printing stuff
[libdlmalloc] Flag legend: C=CINUSE, P=PINUSE
Die grundlegende Ausgabe sieht so aus:```
(gdb) dlchunk 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP
Wie Sie sehen können, möchten Sie ihm die Adresse der tatsächlichen dlmalloc-Metadaten
selbst geben. Für eine ausführlichere Ausgabe können Sie -v verwenden.```
(gdb) dlchunk -v 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
Sie können auch mehrere benachbarte Chunks auflisten, indem Sie den Schalter `-c <count>` verwenden.```
(gdb) dlchunk -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP
0xacff5ac8 M sz:0x00270 fl:CP
(gdb) dlchunk -v -c 2 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
--
struct malloc_chunk @ 0xacff5ac8 {
prev_foot = 0x8140d4d0
size = 0x270 (CINUSE|PINUSE)
-x ausgeben und festlegen, wie viele Bytes
Sie mit -m ausgeben möchten.```
(gdb) dlchunk -v -x -m 16 -c 2 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
0x10 bytes of chunk data:
0xacff59d8: 0xa11c0123 0x000000cc 0x00000000 0x00000000struct malloc_chunk @ 0xacff5ac8 { prev_foot = 0x8140d4d0 size = 0x270 (CINUSE|PINUSE) 0x10 bytes of chunk data: 0xacff5ad0: 0xa11c0123 0x00000244 0x00000000 0x00000000
Sie können auch innerhalb der Chunks suchen. Suchen wir in 2 Chunks nach dem Wert `0x00000244`, der, wie wir oben sehen, nur im zweiten Chunk vorkommt.```
(gdb) dlchunk -s 0x00000244 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [NO MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
Alle Übereinstimmungen innerhalb der Anzahl der durchsuchten Chunks werden angezeigt. Suchen wir nach 0xa11c01123, von dem wir oben gesehen haben, dass es in beiden Chunks vorhanden ist:```
(gdb) dlchunk -s 0xa11c0123 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
## dlmstate
Der Befehl dlmstate kann zur Analyse der `mstate`-Struktur verwendet werden, die
zur Verwaltung eines diskreten dlmalloc-Heaps dient (auch mspace genannt, wenn mit `MSPACES` kompiliert wird). Sie
können die Verwendung des Befehls mit dem Schalter `-h` anzeigen.```
(gdb) dlmstate -h
[libdlmalloc] usage: dlmstate [-v] [-f] [-x] [-c <count>] <addr>
[libdlmalloc] <addr> a mstate struct addr. Optional if mstate cached
[libdlmalloc] -v use verbose output (multiples for more verbosity)
[libdlmalloc] -c print bin counts
[libdlmalloc] --depth how deep to count each bin (default 10)
[libdlmalloc] NOTE: Last defined mstate will be cached for future use
Wenn Sie die Adresse kennen, die das mstate enthält und die normalerweise der erste Chunk im ersten malloc-Segment ist, können Sie sie an dlmstate übergeben:``` (gdb) dlmstate 0xa8400008 struct dl_mstate @ 0xa8400008 { smallmap = 0b000000000000010000011111111100 treemap = 0b000000000000000000000000000111 dvsize = 0x0 topsize = 0x2ebdf040 least_addr = 0xa8400000 dv = 0x0 top = 0xad020f90 trim_check = 0x200000 magic = 0x2900d4d8 smallbin[00] (sz 0x0) = 0xa840002c, 0xa840002c [EMPTY] smallbin[01] (sz 0x8) = 0xa8400034, 0xa8400034 [EMPTY] smallbin[02] (sz 0x10) = 0xacbf7ad0, 0xa88647f0 smallbin[03] (sz 0x18) = 0xa95059b8, 0xa9689a20 smallbin[04] (sz 0x20) = 0xac79a028, 0xa87206f8 smallbin[05] (sz 0x28) = 0xacff0120, 0xa948a0f8 smallbin[06] (sz 0x30) = 0xac4e4af8, 0xacb56878 smallbin[07] (sz 0x38) = 0xacfe3880, 0xacfe0df0 smallbin[08] (sz 0x40) = 0xa9509b28, 0xa9509b28 smallbin[09] (sz 0x48) = 0xa8a1dc80, 0xa8a1dc80 smallbin[10] (sz 0x50) = 0xac782cb0, 0xac782cb0 smallbin[11] (sz 0x58) = 0xacbf7a88, 0xacbf7a88 [EMPTY] smallbin[12] (sz 0x60) = 0xac782c00, 0xac782c00 [EMPTY] smallbin[13] (sz 0x68) = 0xacbf7a78, 0xacbf7a78 [EMPTY] smallbin[14] (sz 0x70) = 0xa89b9650, 0xa89b9650 [EMPTY] smallbin[15] (sz 0x78) = 0xac789828, 0xac789828 [EMPTY] smallbin[16] (sz 0x80) = 0xa89b9738, 0xa94af740 smallbin[17] (sz 0x88) = 0xac4e5700, 0xac4e5700 [EMPTY] smallbin[18] (sz 0x90) = 0xac788030, 0xac788030 [EMPTY] smallbin[19] (sz 0x98) = 0xac782bc8, 0xac782bc8 [EMPTY] smallbin[20] (sz 0xa0) = 0xa89b9718, 0xa89b9718 [EMPTY] smallbin[21] (sz 0xa8) = 0xa8a1dc20, 0xa8a1dc20 [EMPTY] smallbin[22] (sz 0xb0) = 0xac782af8, 0xac782af8 [EMPTY] smallbin[23] (sz 0xb8) = 0xac789ed0, 0xac789ed0 [EMPTY] smallbin[24] (sz 0xc0) = 0xacbf7a20, 0xacbf7a20 [EMPTY] smallbin[25] (sz 0xc8) = 0xac789940, 0xac789940 [EMPTY] smallbin[26] (sz 0xd0) = 0xac789eb8, 0xac789eb8 [EMPTY] smallbin[27] (sz 0xd8) = 0xa94af6e8, 0xa94af6e8 [EMPTY] smallbin[28] (sz 0xe0) = 0xacbf78e8, 0xacbf78e8 [EMPTY] smallbin[29] (sz 0xe8) = 0xac4e4e68, 0xac4e4e68 [EMPTY] smallbin[30] (sz 0xf0) = 0xac4e5780, 0xac4e5780 [EMPTY] smallbin[31] (sz 0xf8) = 0xac7880b0, 0xac7880b0 [EMPTY] treebin[00] (sz 0x180) = 0xac783cb0 treebin[01] (sz 0x200) = 0xac789dc0 treebin[02] (sz 0x300) = 0xa883db48 treebin[03] (sz 0x400) = 0x0 [EMPTY] treebin[04] (sz 0x600) = 0x0 [EMPTY] treebin[05] (sz 0x800) = 0x0 [EMPTY] treebin[06] (sz 0xc00) = 0x0 [EMPTY] treebin[07] (sz 0x1000) = 0x0 [EMPTY] treebin[08] (sz 0x1800) = 0x0 [EMPTY] treebin[09] (sz 0x2000) = 0x0 [EMPTY] treebin[10] (sz 0x3000) = 0x0 [EMPTY] treebin[11] (sz 0x4000) = 0x0 [EMPTY] treebin[12] (sz 0x6000) = 0x0 [EMPTY] treebin[13] (sz 0x8000) = 0x0 [EMPTY] treebin[14] (sz 0xc000) = 0x0 [EMPTY] treebin[15] (sz 0x10000) = 0x0 [EMPTY] treebin[16] (sz 0x18000) = 0x0 [EMPTY] treebin[17] (sz 0x20000) = 0x0 [EMPTY] treebin[18] (sz 0x30000) = 0x0 [EMPTY] treebin[19] (sz 0x40000) = 0x0 [EMPTY] treebin[20] (sz 0x60000) = 0x0 [EMPTY] treebin[21] (sz 0x80000) = 0x0 [EMPTY] treebin[22] (sz 0xc0000) = 0x0 [EMPTY] treebin[23] (sz 0x100000) = 0x0 [EMPTY] treebin[24] (sz 0x180000) = 0x0 [EMPTY] treebin[25] (sz 0x200000) = 0x0 [EMPTY] treebin[26] (sz 0x300000) = 0x0 [EMPTY] treebin[27] (sz 0x400000) = 0x0 [EMPTY] treebin[28] (sz 0x600000) = 0x0 [EMPTY] treebin[29] (sz 0x800000) = 0x0 [EMPTY] treebin[30] (sz 0xc00000) = 0x0 [EMPTY] treebin[31] (sz 0xffffffff) = 0x0 [EMPTY] footprint = 0x33800000 max_footprint = 0x33800000 mflags = 0x7 mutex = 0x0,0x0,0x0,0x0,0xa8400000, seg = struct malloc_segment @ 0xa84001d4 { base = 0xa8400000 size = 0x33800000 next = 0x0 sflags = 0x8
Um die Ausgabe auf langsameren Geräten zu beschleunigen, cachen wir die zuletzt
gelesenen mstate-Daten. Wenn du also einfach dlmstate erneut ausführst, siehst
du die zuvor ausgegebene Ausgabe (die natürlich veraltet sein kann).```
(gdb) dlmstate
[libdlmalloc] Using cached mstate
struct dl_mstate @ 0xa8400008 {
smallmap = 0b000000000000010000011111111100
treemap = 0b000000000000000000000000000111
dvsize = 0x0
topsize = 0x2ebdf040
least_addr = 0xa8400000
dv = 0x0
top = 0xad020f90
trim_check = 0x200000
magic = 0x2900d4d8
smallbin[00] (sz 0x0) = 0xa840002c, 0xa840002c [EMPTY]
smallbin[01] (sz 0x8) = 0xa8400034, 0xa8400034 [EMPTY]
smallbin[02] (sz 0x10) = 0xacbf7ad0, 0xa88647f0
smallbin[03] (sz 0x18) = 0xa95059b8, 0xa9689a20
[...]
Der Schalter -c kann verwendet werden, um die Anzahl der Chunks in einem bestimmten Bin zu zählen. Beachten
Sie, dass dies recht langsam sein kann, wenn Sie über eine serielle Leitung debuggen. Deshalb bieten
wir auch die Option --depth an, um zu begrenzen, wie viele Bin-Einträge gezählt werden. Standardmäßig
ist die Tiefe auf 10 gesetzt:```
(gdb) dlmstate -c
[libdlmalloc] Using cached mstate
smallbin[00] (sz 0x0) = 0xa840002c, 0xa840002c [EMPTY] smallbin[01] (sz 0x8) = 0xa8400034, 0xa8400034 [EMPTY] smallbin[02] (sz 0x10) = 0xacbf7ad0, 0xa88647f0 [10+] smallbin[03] (sz 0x18) = 0xa95059b8, 0xa9689a20 [10+] smallbin[04] (sz 0x20) = 0xac79a028, 0xa87206f8 [10+] smallbin[05] (sz 0x28) = 0xacff0120, 0xa948a0f8 [10+] smallbin[06] (sz 0x30) = 0xac4e4af8, 0xacb56878 [10+] smallbin[07] (sz 0x38) = 0xacfe3880, 0xacfe0df0 [10] smallbin[08] (sz 0x40) = 0xa9509b28, 0xa9509b28 [2] smallbin[09] (sz 0x48) = 0xa8a1dc80, 0xa8a1dc80 [2] smallbin[10] (sz 0x50) = 0xac782cb0, 0xac782cb0 [2] [...]
Wie gezeigt wird die Anzahl in Klammern rechts neben dem Bin-Inhalt angezeigt.
Wir verwenden die mstate-Bitmap, um zuerst zu testen, ob ein Bin leer ist. Daher kann es vorkommen, dass Sie gelegentlich Bin-Einträge sehen, die gültige Zeiger auf den Heap haben, aber als `[EMPTY]` markiert sind. Diese Zeiger sind an diesem Punkt nur veraltet.
## dlcallback
Wir unterstützen das Konzept von pluginübergreifenden Callbacks. Sie können eine Callback-Funktion in einem bestimmten Modul registrieren, und diese Funktion wird mit einem dict aufgerufen, das eine Reihe von Informationen über den Zustand des jeweils betrachteten Objekts enthält.
Der Callback wird aufgerufen, wenn sowohl dlchunk als auch dlmstate mit der Verarbeitung ihrer Argumente fertig sind.
Die Verwendung kann mit dem `-h`-Schalter eingesehen werden:```
(gdb) dlcallback -h
[libdlmalloc] usage: dlcallback <option>
[libdlmalloc] disable temporarily disable the registered callback
[libdlmalloc] enable enable the registered callback
[libdlmalloc] status check if a callback is registered
[libdlmalloc] clear forget the registered callback
[libdlmalloc] register <name> <module> use a global function <name> as callback from <module>
[libdlmalloc] ex: register mpcallback libmempool/libmempool
Um diese Funktionalität zu demonstrieren, verwenden wir einen Callback, den wir für ein separates GDB-Plugin namens libmempool entwickelt haben,``` (gdb) dlcallback register mpcallback libmempool/libmempool [libmempool] loaded [libdlmalloc] mpcallback registered as callback (gdb) dlcallback status [libdlmalloc] a callback is registered and enabled
Wenn wir nun einen Befehl wie dlchunk verwenden, können wir einige zusätzliche Anmerkungen sehen:```
(gdb) dlchunk 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP alloc_pc:0x08262b45,-
(gdb) dlchunk -v 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
struct mp_header @ 0xacff59d8 {
mh_magic = 0xa11c0123
mh_len = 0xcc
mh_refcount = 0x0
mh_unused = 0x0
mh_fd_link = 0xa9515ed0 (OK)
mh_bk_link = 0xa84005c4 (-)
alloc_pc = 0x8262b45 (-)
free_pc = 0x0 (-)
Ähnlich können wir deutlich mehr Daten sehen, die an den Standard-dlmalloc-mstate angehängt sind, der von dlmstate angezeigt wird:``` (gdb) dlmstate [libdlmalloc] Using cached mstate struct dl_mstate @ 0xa8400008 { smallmap = 0b000000000000010000011111111100 treemap = 0b000000000000000000000000000111 dvsize = 0x0 topsize = 0x2ebdf040 least_addr = 0xa8400000 dv = 0x0 top = 0xad020f90 trim_check = 0x200000 magic = 0x2900d4d8 smallbin[00] (sz 0x0) = 0xa840002c, 0xa840002c [EMPTY] smallbin[01] (sz 0x8) = 0xa8400034, 0xa8400034 [EMPTY] smallbin[02] (sz 0x10) = 0xacbf7ad0, 0xa88647f0 smallbin[03] (sz 0x18) = 0xa95059b8, 0xa9689a20 smallbin[04] (sz 0x20) = 0xac79a028, 0xa87206f8 smallbin[05] (sz 0x28) = 0xacff0120, 0xa948a0f8 smallbin[06] (sz 0x30) = 0xac4e4af8, 0xacb56878 smallbin[07] (sz 0x38) = 0xacfe3880, 0xacfe0df0 smallbin[08] (sz 0x40) = 0xa9509b28, 0xa9509b28 smallbin[09] (sz 0x48) = 0xa8a1dc80, 0xa8a1dc80 smallbin[10] (sz 0x50) = 0xac782cb0, 0xac782cb0 smallbin[11] (sz 0x58) = 0xacbf7a88, 0xacbf7a88 [EMPTY] smallbin[12] (sz 0x60) = 0xac782c00, 0xac782c00 [EMPTY] smallbin[13] (sz 0x68) = 0xacbf7a78, 0xacbf7a78 [EMPTY] smallbin[14] (sz 0x70) = 0xa89b9650, 0xa89b9650 [EMPTY] smallbin[15] (sz 0x78) = 0xac789828, 0xac789828 [EMPTY] smallbin[16] (sz 0x80) = 0xa89b9738, 0xa94af740 smallbin[17] (sz 0x88) = 0xac4e5700, 0xac4e5700 [EMPTY] smallbin[18] (sz 0x90) = 0xac788030, 0xac788030 [EMPTY] smallbin[19] (sz 0x98) = 0xac782bc8, 0xac782bc8 [EMPTY] smallbin[20] (sz 0xa0) = 0xa89b9718, 0xa89b9718 [EMPTY] smallbin[21] (sz 0xa8) = 0xa8a1dc20, 0xa8a1dc20 [EMPTY] smallbin[22] (sz 0xb0) = 0xac782af8, 0xac782af8 [EMPTY] smallbin[23] (sz 0xb8) = 0xac789ed0, 0xac789ed0 [EMPTY] smallbin[24] (sz 0xc0) = 0xacbf7a20, 0xacbf7a20 [EMPTY] smallbin[25] (sz 0xc8) = 0xac789940, 0xac789940 [EMPTY] smallbin[26] (sz 0xd0) = 0xac789eb8, 0xac789eb8 [EMPTY] smallbin[27] (sz 0xd8) = 0xa94af6e8, 0xa94af6e8 [EMPTY] smallbin[28] (sz 0xe0) = 0xacbf78e8, 0xacbf78e8 [EMPTY] smallbin[29] (sz 0xe8) = 0xac4e4e68, 0xac4e4e68 [EMPTY] smallbin[30] (sz 0xf0) = 0xac4e5780, 0xac4e5780 [EMPTY] smallbin[31] (sz 0xf8) = 0xac7880b0, 0xac7880b0 [EMPTY] treebin[00] (sz 0x180) = 0xac783cb0 treebin[01] (sz 0x200) = 0xac789dc0 treebin[02] (sz 0x300) = 0xa883db48 treebin[03] (sz 0x400) = 0x0 [EMPTY] treebin[04] (sz 0x600) = 0x0 [EMPTY] treebin[05] (sz 0x800) = 0x0 [EMPTY] treebin[06] (sz 0xc00) = 0x0 [EMPTY] treebin[07] (sz 0x1000) = 0x0 [EMPTY] treebin[08] (sz 0x1800) = 0x0 [EMPTY] treebin[09] (sz 0x2000) = 0x0 [EMPTY] treebin[10] (sz 0x3000) = 0x0 [EMPTY] treebin[11] (sz 0x4000) = 0x0 [EMPTY] treebin[12] (sz 0x6000) = 0x0 [EMPTY] treebin[13] (sz 0x8000) = 0x0 [EMPTY] treebin[14] (sz 0xc000) = 0x0 [EMPTY] treebin[15] (sz 0x10000) = 0x0 [EMPTY] treebin[16] (sz 0x18000) = 0x0 [EMPTY] treebin[17] (sz 0x20000) = 0x0 [EMPTY] treebin[18] (sz 0x30000) = 0x0 [EMPTY] treebin[19] (sz 0x40000) = 0x0 [EMPTY] treebin[20] (sz 0x60000) = 0x0 [EMPTY] treebin[21] (sz 0x80000) = 0x0 [EMPTY] treebin[22] (sz 0xc0000) = 0x0 [EMPTY] treebin[23] (sz 0x100000) = 0x0 [EMPTY] treebin[24] (sz 0x180000) = 0x0 [EMPTY] treebin[25] (sz 0x200000) = 0x0 [EMPTY] treebin[26] (sz 0x300000) = 0x0 [EMPTY] treebin[27] (sz 0x400000) = 0x0 [EMPTY] treebin[28] (sz 0x600000) = 0x0 [EMPTY] treebin[29] (sz 0x800000) = 0x0 [EMPTY] treebin[30] (sz 0xc00000) = 0x0 [EMPTY] treebin[31] (sz 0xffffffff) = 0x0 [EMPTY] footprint = 0x33800000 max_footprint = 0x33800000 mflags = 0x7 mutex = 0x0,0x0,0x0,0x0,0xa8400000, seg = struct malloc_segment @ 0xa84001d4 { base = 0xa8400000 size = 0x33800000 next = 0x0 sflags = 0x8 struct mp_mstate @ 0xa84001e4 { mp_smallbin[00] - sz: 0x00000000 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[01] - sz: 0x00000008 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[02] - sz: 0x00000010 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[03] - sz: 0x00000018 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[04] - sz: 0x00000020 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[05] - sz: 0x00000028 cnt: 0x0000, mh_fd_link: 0x0 mp_smallbin[06] - sz: 0x00000030 cnt: 0x0213, mh_fd_link: 0xacfdf800 mp_smallbin[07] - sz: 0x00000038 cnt: 0x0cb3, mh_fd_link: 0xaae0ff70 mp_smallbin[08] - sz: 0x00000040 cnt: 0x1c99, mh_fd_link: 0xac4e4b30 mp_smallbin[09] - sz: 0x00000048 cnt: 0x027b, mh_fd_link: 0xaae0fe30 mp_smallbin[10] - sz: 0x00000050 cnt: 0x0415, mh_fd_link: 0xac782c68 mp_smallbin[11] - sz: 0x00000058 cnt: 0x012d, mh_fd_link: 0xac799fd8 mp_smallbin[12] - sz: 0x00000060 cnt: 0x0125, mh_fd_link: 0xacbf7a78 mp_smallbin[13] - sz: 0x00000068 cnt: 0x0a06, mh_fd_link: 0xac789b78 mp_smallbin[14] - sz: 0x00000070 cnt: 0x003e, mh_fd_link: 0xa9515fc8 mp_smallbin[15] - sz: 0x00000078 cnt: 0x0074, mh_fd_link: 0xac789830 mp_smallbin[16] - sz: 0x00000080 cnt: 0x0124, mh_fd_link: 0xac7827a0 mp_smallbin[17] - sz: 0x00000088 cnt: 0x0016, mh_fd_link: 0xac799f50 mp_smallbin[18] - sz: 0x00000090 cnt: 0x0025, mh_fd_link: 0xac784e58 mp_smallbin[19] - sz: 0x00000098 cnt: 0x004e, mh_fd_link: 0xac4e56f8 mp_smallbin[20] - sz: 0x000000a0 cnt: 0x01c8, mh_fd_link: 0xacfefbf0 mp_smallbin[21] - sz: 0x000000a8 cnt: 0x0189, mh_fd_link: 0xacff05e0 mp_smallbin[22] - sz: 0x000000b0 cnt: 0x00e9, mh_fd_link: 0xacbf79c8 mp_smallbin[23] - sz: 0x000000b8 cnt: 0x0165, mh_fd_link: 0xac96be20 mp_smallbin[24] - sz: 0x000000c0 cnt: 0x0017, mh_fd_link: 0xac789a50 mp_smallbin[25] - sz: 0x000000c8 cnt: 0x001a, mh_fd_link: 0xacb4d998 mp_smallbin[26] - sz: 0x000000d0 cnt: 0x004d, mh_fd_link: 0xa9519150 mp_smallbin[27] - sz: 0x000000d8 cnt: 0x0024, mh_fd_link: 0xacbf78f0 mp_smallbin[28] - sz: 0x000000e0 cnt: 0x002c, mh_fd_link: 0xacff49d8 mp_smallbin[29] - sz: 0x000000e8 cnt: 0x0014, mh_fd_link: 0xa89b9658 mp_smallbin[30] - sz: 0x000000f0 cnt: 0x0008, mh_fd_link: 0xacfde720 mp_smallbin[31] - sz: 0x000000f8 cnt: 0x0044, mh_fd_link: 0xacff59d8 mp_treebin[00] - sz: 0x00000180 cnt: 0x0190, mh_fd_link: 0xacb48318 mp_treebin[01] - sz: 0x00000200 cnt: 0x0134, mh_fd_link: 0xa95059d8 mp_treebin[02] - sz: 0x00000300 cnt: 0x01ac, mh_fd_link: 0xad01cd38 mp_treebin[03] - sz: 0x00000400 cnt: 0x004e, mh_fd_link: 0xacffbac8 mp_treebin[04] - sz: 0x00000600 cnt: 0x0073, mh_fd_link: 0xac4e4fa0 mp_treebin[05] - sz: 0x00000800 cnt: 0x0030, mh_fd_link: 0xacfebe20 mp_treebin[06] - sz: 0x00000c00 cnt: 0x0277, mh_fd_link: 0xac7887e8 mp_treebin[07] - sz: 0x00001000 cnt: 0x004f, mh_fd_link: 0xa9507570 mp_treebin[08] - sz: 0x00001800 cnt: 0x0041, mh_fd_link: 0xac784fa8 mp_treebin[09] - sz: 0x00002000 cnt: 0x0010, mh_fd_link: 0xac74f248 mp_treebin[10] - sz: 0x00003000 cnt: 0x0024, mh_fd_link: 0xac796020 mp_treebin[11] - sz: 0x00004000 cnt: 0x0028, mh_fd_link: 0xacf9a3e0 mp_treebin[12] - sz: 0x00006000 cnt: 0x009a, mh_fd_link: 0xad01cf68 mp_treebin[13] - sz: 0x00008000 cnt: 0x000b, mh_fd_link: 0xacae3978 mp_treebin[14] - sz: 0x0000c000 cnt: 0x0027, mh_fd_link: 0xad014678 mp_treebin[15] - sz: 0x00010000 cnt: 0x000b, mh_fd_link: 0xacab7098 mp_treebin[16] - sz: 0x00018000 cnt: 0x0062, mh_fd_link: 0xacafa7c8 mp_treebin[17] - sz: 0x00020000 cnt: 0x0007, mh_fd_link: 0xac2cda88 mp_treebin[18] - sz: 0x00030000 cnt: 0x0012, mh_fd_link: 0xac800720 mp_treebin[19] - sz: 0x00040000 cnt: 0x000a, mh_fd_link: 0xac6e21e0 mp_treebin[20] - sz: 0x00060000 cnt: 0x0006, mh_fd_link: 0xaa5b0f28 mp_treebin[21] - sz: 0x00080000 cnt: 0x0004, mh_fd_link: 0xacf152e8 mp_treebin[22] - sz: 0x000c0000 cnt: 0x000e, mh_fd_link: 0xaac896f0 mp_treebin[23] - sz: 0x00100000 cnt: 0x0000, mh_fd_link: 0x0 mp_treebin[24] - sz: 0x00180000 cnt: 0x0004, mh_fd_link: 0xa934b730 mp_treebin[25] - sz: 0x00200000 cnt: 0x0001, mh_fd_link: 0xaa6d6cc8 mp_treebin[26] - sz: 0x00300000 cnt: 0x0003, mh_fd_link: 0xacc1feb0 mp_treebin[27] - sz: 0x00400000 cnt: 0x0001, mh_fd_link: 0xa8f39370 mp_treebin[28] - sz: 0x00600000 cnt: 0x0000, mh_fd_link: 0x0 mp_treebin[29] - sz: 0x00800000 cnt: 0x0001, mh_fd_link: 0xa9689a40 mp_treebin[30] - sz: 0x00c00000 cnt: 0x0001, mh_fd_link: 0xaae41208 mp_treebin[31] - sz: 0xffffffff cnt: 0x0001, mh_fd_link: 0xab641738 [UNSORTED]
## Callback-Dict
Wir schicken derzeit einfach eine Menge Informationen von libdlmalloc an die Callback-Funktion, und sie kann entscheiden, was sie mit den Informationen tun möchte. Wir liefern mehr Informationen, als die meisten Callbacks benötigen. Außerdem ist zu erwarten, dass der Callback wahrscheinlich wissen muss, welches Plugin den Callback auslöst, um zu bestimmen, welche zusätzlichen Informationen er anzeigen wird. Auf der anderen Seite muss das Plugin (in diesem Fall libdlmalloc), das den Callback aufruft, derzeit nichts darüber wissen (oder sich darum kümmern), was dieser externe Callback-Anbieter tut.
Ein Beispiel für einige der Daten, die wir an die Callback-Funktion übergeben, ist:
* `caller`: Name des aufrufenden gdb-Befehls oder der aufrufenden Funktion
* `allocator`: zugrunde liegender Allokator, der die von uns gesendete Chunk-Adresse verwaltet
* `addr`: Adresse des Chunk-Inhalts nach den Metadaten des Kern-Allokators
* `hdr_sz`: Größe des Metadaten-Headers des Kern-Allokators
* `chunksz`: Größe des Chunks gemäß dem Metadaten-Header des Kern-Allokators
* `min_hdr_sz`: die minimal mögliche Headergröße für diesen Kern-Allokator
* `data_size`: Größe der Daten an der Adresse `addr`
* `inuse`: ob ein Chunk laut Kern-Allokator in Benutzung ist
* `chunk_info`: ob die aufrufende Bibliothek Chunk-Informationen ausgibt oder nicht
* `size_sz`: Die berechnete Größe eines `size_t`-Datentyps auf der Debug-Plattform
# Zukünftige Entwicklung
Wir werden die Funktionalität von libdlmalloc wahrscheinlich erweitern, wenn wir sie benötigen oder im Rahmen künftiger Cisco-ASA-Forschung. Derzeit geplante Ergänzungen sind:
- Die Debug-Engine-Logik so abstrahieren, dass sie den neueren Designs von libheap oder shadow ähnelt
- `dlsearch` schreiben, das alle msegments durchläuft und nach einem Wert sucht.
- Eine dlchunk-Option für einen freien Chunk, die es ermöglicht, den Bin durch Verfolgen der Verkettung zu finden und so die zugehörige Basisadresse von `mstate` abzuleiten
# Anmerkungen zu dlmalloc
## dlmalloc vs. ptmalloc
Der ptmalloc-Allokator, der Teil von glibc ist, wurde wiederholt von dlmalloc abgespalten. Die folgende Tabelle zeigt die Beziehung der Versionen:
| dlmalloc | ptmalloc | Arten von Bins |
| -------------- | --------- | ---------------------------- |
| dlmalloc 2.5.x | N/A | bins |
| dlmalloc 2.6.x | ptmalloc | smallbins/bins |
| dlmalloc 2.7.x | ptmalloc2 | fastbins/smallbins/largebins |
| dlmalloc 2.8.x | ptmalloc3 | smallbins/treebins |
## Lesestoff
dlmalloc 2.8.x unterscheidet sich in vielerlei Hinsicht von früheren dlmalloc-Versionen, insbesondere durch die Verwendung einer Baumstruktur für große Zuweisungen. Die beste Dokumentation ist der [Quellcode](http://g.oswego.edu/pub/misc/). Für einen guten Hintergrund zu den Unterschieden zwischen ptmalloc2 und ptmalloc3 (was dlmalloc 2.7.x vs. 2.8.x entspricht) siehe den Phrack-67-Artikel [The House Of Lore: Reloaded](http://phrack.org/issues/67/8.html) von blackngel.
# Kontakt
Wir würden uns über Feedback zu diesem Tool freuen und nehmen auch gerne Pull Requests an.
* Aaron Adams
* Email: `aaron<dot>adams<at>nccgroup<dot>trust`
* Twitter: @fidgetingbits
* Cedric Halbronn
* Email: `cedric<dot>halbronn<at>nccgroup<dot>trust`
* Twitter: @saidelike