
Heap analysis tooling for dlmalloc
libdlmalloc est un script python conçu pour être utilisé avec GDB afin d'analyser l'allocateur de Doug Lea, également connu sous le nom de dlmalloc. Il prend actuellement en charge les versions 2.8.x de dlmalloc. Notez que certaines parties peuvent également être utilisées indépendamment de GDB, par exemple pour effectuer une analyse hors ligne de mémoire de tas instantanée.
libdlmalloc s'est inspiré d'autres scripts python gdb pour l'analyse des tas, comme libtalloc, unmask_jemalloc et libheap. Certaines fonctionnalités de base sont presque identiques à celles de ces projets.
libdlmalloc a été testé principalement sur des appareils Cisco ASA 32 bits et 64 bits qui utilisent dlmalloc 2.8.3. Il devrait fonctionner avec d'autres versions 2.8.x, mais en raison de différences significatives, il ne fonctionnera pas avec les versions antérieures, comme <= 2.7.x.
Si vous testez avec succès libdlmalloc sur une version 2.8.x spécifique ou sur un appareil spécifique, veuillez informer les auteurs et nous mettrons à jour les documents.
Le script nécessite simplement une version relativement récente de GDB avec le support de python3. Nous avons principalement testé sur python3, donc nous nous attendons à ce qu'il échoue sur python2.7 pour le moment.
Si vous souhaitez utiliser les commandes gdb, vous pouvez utiliser :``` (gdb) source libdlmalloc_28x.py
Une grande partie de la logique centrale est extraite dans la classe `dl_helper`, qui permet
d'importer directement libdlmalloc et d'accéder à certaines structures importantes
en dehors d'une session GDB. Cela est utile si vous souhaitez analyser des
instantanés hors ligne de chunks/tas.
# Utilisation
La plupart des fonctionnalités sont modélisées d'après l'approche d'unmask_jemalloc et
libtalloc, où une commande GDB distincte est fournie. Cependant, nous utilisons également un
bon nombre d'options.
Pour voir la liste complète des commandes actuellement prises en charge, vous pouvez utiliser la commande
`dlhelp` :
## dlhelp
C'est la fonction principale pour afficher les commandes disponibles. Chacune des commandes
prend en charge l'option `-h` qui permet d'obtenir des instructions d'utilisation
plus détaillées.```
(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 peut vous fournir un résumé d'un chunk, ou des informations plus
détaillées sur chaque champ. Vous pouvez également l'utiliser pour lister des informations sur
plusieurs chunks, rechercher des chunks, etc. L'utilisation de dlchunk est indiquée ci-dessous :```
(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
La sortie de base ressemble à ceci :```
(gdb) dlchunk 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP
Comme vous pouvez le voir, vous voulez lui donner l'adresse des véritables métadonnées dlmalloc elles-mêmes. Pour obtenir une sortie plus détaillée, vous pouvez utiliser -v.```
(gdb) dlchunk -v 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
Vous pouvez également lister plusieurs chunks adjacents en utilisant l'option `-c <count>`.```
(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 et contrôler le nombre d'octets que vous souhaitez extraire avec -m.```
(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
Vous pouvez également rechercher dans les chunks. Cherchons dans 2 chunks la valeur `0x00000244`, que nous voyons ci-dessus n'être présente que dans le deuxième chunk.```
(gdb) dlchunk -s 0x00000244 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [NO MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
Toutes les correspondances dans le nombre de blocs recherchés seront affichées. Cherchons
0xa11c01123, qui, comme nous l'avons vu ci-dessus, est présent dans les deux blocs :```
(gdb) dlchunk -s 0xa11c0123 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
## dlmstate
La commande dlmstate peut être utilisée pour analyser la structure `mstate` utilisée pour
gérer un tas dlmalloc discret (également appelé mspace si compilé avec `MSPACES`). Vous
pouvez consulter l'utilisation de la commande avec l'option `-h`.```
(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
Si vous connaissez l'adresse contenant la mstate, qui est généralement le premier chunk à l'intérieur du premier asegment malloc, vous pouvez la passer à dlmstate :``` (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
Pour accélérer la sortie sur les appareils plus lents, nous mettons en cache les dernières données mstate que nous
lisons. Donc, si vous exécutez à nouveau dlmstate, vous verrez la sortie précédemment
affichée (qui peut bien sûr être périmée).```
(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
[...]
Le commutateur -c peut être utilisé pour compter le nombre de morceaux dans un bin donné. Notez que cela peut être assez lent si vous déboguez sur une ligne série, c'est pourquoi nous fournissons également l'option --depth pour limiter le nombre d'entrées de bin qui seront comptées. Par défaut, la profondeur est fixée à 10 :```
(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] [...]
Comme illustré, le compte est affiché entre parenthèses à droite du contenu du bin.
Nous utilisons le bitmap mstate pour d'abord tester si un bin est vide, donc vous pouvez vous attendre à voir occasionnellement des entrées de bin qui ont des pointeurs valides vers le tas, mais qui sont marquées `[EMPTY]`. Ces pointeurs sont simplement obsolètes à ce stade.
## dlcallback
Nous prenons en charge le concept de callbacks inter-plugins. Vous pouvez enregistrer une fonction de callback dans un module spécifié et cette fonction sera appelée avec un dict contenant un tas d'informations sur l'état de ce qui est examiné. Le callback est appelé lorsque dlchunk et dlmstate ont fini de faire ce qu'ils font avec leurs arguments.
L'utilisation peut être consultée avec l'option `-h` :```
(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
Pour démontrer cette fonctionnalité, nous utiliserons un callback que nous avons développé pour un plugin GDB séparé appelé libmempool,``` (gdb) dlcallback register mpcallback libmempool/libmempool [libmempool] loaded [libdlmalloc] mpcallback registered as callback (gdb) dlcallback status [libdlmalloc] a callback is registered and enabled
Maintenant, lorsque nous utilisons une commande comme dlchunk, nous pouvons voir une annotation supplémentaire :```
(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 (-)
De même, nous pouvons voir nettement plus de données ajoutées au mstate par défaut de dlmalloc affiché par dlmstate:``` (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]
## Dictionnaire de callback
Actuellement, nous déversons beaucoup d'informations depuis libdlmalloc vers la fonction de callback, et celle-ci peut choisir d'en faire ce qu'elle veut. Nous fournissons plus d'informations que la plupart des callbacks n'en auront besoin. On s'attend également à ce que la callback doive probablement être consciente du plugin qui émet la callback, afin de lui indiquer quelles informations supplémentaires elle affichera. En contrepartie, le plugin (libdlmalloc dans ce cas) qui appelle la callback n'a actuellement pas besoin de savoir (ni de se soucier) de quoi que ce soit que fait ce fournisseur externe de callback.
Voici un exemple de certaines des données que nous fournissons à la fonction de callback :
* `caller` : nom de la commande ou fonction gdb appelante
* `allocator` : allocateur sous-jacent qui gère l'adresse du chunk que nous envoyons
* `addr` : adresse du contenu du chunk après les métadonnées de l'allocateur principal
* `hdr_sz` : taille de l'en-tête de métadonnées de l'allocateur principal
* `chunksz` : taille du chunk selon l'en-tête de métadonnées de l'allocateur principal
* `min_hdr_sz` : taille d'en-tête minimale possible pour cet allocateur principal
* `data_size` : taille des données à l'adresse `addr`
* `inuse` : indique si un chunk est en cours d'utilisation selon l'allocateur principal
* `chunk_info` : indique si la bibliothèque appelante imprime ou non les informations du chunk
* `size_sz` : taille calculée d'un type de données `size_t` sur la plateforme déboguée
## Développement futur
Nous ajouterons probablement des fonctionnalités à libdlmalloc au besoin ou lors de futures recherches sur Cisco ASA. Les ajouts prévus à l'heure actuelle sont :
- Extraire la logique du moteur de débogage pour se rapprocher des conceptions plus récentes de libheap ou de shadow
- Écrire `dlsearch`, qui parcourt tous les msegments à la recherche d'une valeur.
- Une option dlchunk pour un chunk libre qui permet de trouver le bin en parcourant les liens, et ainsi d'inférer l'adresse de base du `mstate` associé
## Notes sur dlmalloc
## dlmalloc vs ptmalloc
L'allocateur ptmalloc, qui fait partie de glibc, a été régulièrement forké à partir de dlmalloc. Le tableau suivant montre la relation entre les versions :
| dlmalloc | ptmalloc | Types de 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 |
## Lectures
dlmalloc 2.8.x diffère de nombreuses manières des versions antérieures de dlmalloc, notamment en raison de l'utilisation d'une structure en arbre pour les grosses allocations. La meilleure documentation est le [code source](http://g.oswego.edu/pub/misc/). Pour un bon contexte sur les différences entre ptmalloc2 et ptmalloc3 (ce qui correspond à dlmalloc 2.7.x vs 2.8.x), voir l'article de blackngel dans Phrack 67, [The House Of Lore: Reloaded](http://phrack.org/issues/67/8.html).
## Contact
Nous serions ravis d'avoir des retours sur cet outil et nous acceptons volontiers les pull requests.
* Aaron Adams
* Email: `aaron<dot>adams<at>nccgroup<dot>trust`
* Twitter: @fidgetingbits
* Cedric Halbronn
* Email: `cedric<dot>halbronn<at>nccgroup<dot>trust`
* Twitter: @saidelike