
Ferramenta de análise de heap para dlmalloc
libdlmalloc é um script Python projetado para uso com GDB que pode ser usado para analisar o alocador de Doug Lea, também conhecido como dlmalloc. Atualmente suporta versões 2.8.x do dlmalloc. Observe que algumas partes também podem ser usadas independentemente do GDB, por exemplo, para fazer análise offline de alguma memória de heap capturada em snapshot.
libdlmalloc foi inspirado por outros scripts Python do gdb para análise de heaps, como libtalloc, unmask_jemalloc e libheap. Algumas funcionalidades básicas são quase idênticas a esses projetos.
libdlmalloc foi testado predominantemente em dispositivos Cisco ASA de 32 e 64 bits que usam dlmalloc 2.8.3. Deve funcionar com outras versões 2.8.x, porém, devido a diferenças significativas, não funcionará em versões anteriores, como <= 2.7.x.
Se você testar o libdlmalloc com sucesso em alguma versão específica 2.8.x ou em algum dispositivo específico, por favor informe os autores e atualizaremos os documentos.
O script apenas requer uma versão relativamente moderna do GDB com suporte a python3. Testamos principalmente em python3, então esperamos que ele quebre no python2.7 no momento.
Se você quiser usar os comandos do gdb, você pode usar:``` (gdb) source libdlmalloc_28x.py
Grande parte da lógica central é separada na classe `dl_helper`, o que permite
importar diretamente o libdlmalloc e acessar certas estruturas importantes fora
de uma sessão GDB. Isso é útil se você quiser analisar snapshots offline de
chunks/heap.
# Uso
A maior parte da funcionalidade é modelada com base na abordagem em unmask_jemalloc e
libtalloc, onde um comando GDB separado é fornecido. Embora também usemos um
bom número de opções.
Para ver uma lista completa dos comandos atualmente suportados, você pode usar o
comando `dlhelp`:
## dlhelp
Esta é a função principal para visualizar os comandos disponíveis. Cada um dos comandos
suporta a opção `-h`, que permite obter instruções de uso mais detalhadas.```
(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 pode fornecer um resumo de um chunk, ou informações mais detalhadas
de cada campo. Você também pode usá-lo para listar informações sobre
vários chunks, pesquisar chunks, etc. O uso do dlchunk pode ser visto abaixo:```
(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
A saída básica é assim:```
(gdb) dlchunk 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP
Como você pode ver, você quer dar a ele o endereço dos metadados reais do dlmalloc
em si. Para obter uma saída mais detalhada, você pode usar -v.```
(gdb) dlchunk -v 0xacff59d0
struct malloc_chunk @ 0xacff59d0 {
prev_foot = 0x8140d4d0
size = 0xf8 (CINUSE|PINUSE)
Você também pode listar vários blocos adjacentes usando a opção `-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 e controlar quantos bytes você deseja despejar com -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
Você também pode pesquisar dentro dos chunks. Vamos pesquisar 2 chunks pelo valor `0x00000244`, que vimos acima estar apenas no segundo chunk.```
(gdb) dlchunk -s 0x00000244 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [NO MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
Todas as correspondências dentro do número de blocos pesquisados serão mostradas. Vamos pesquisar
por 0xa11c01123, que vimos acima estar presente em ambos os blocos:```
(gdb) dlchunk -s 0xa11c0123 -c 2 0xacff59d0
0xacff59d0 M sz:0x000f8 fl:CP [MATCH]
0xacff5ac8 M sz:0x00270 fl:CP [MATCH]
## dlmstate