#ifndef R2_HEAP_GLIBC_H #define R2_HEAP_GLIBC_H #ifdef __cplusplus extern "C" { #endif R_LIB_VERSION_HEADER(r_heap_glibc); #ifndef R_PRINTF_YA #define R_PRINTF_YA // XXX dupe with jemalloc #define PRINTF_A(color, fmt , ...) r_cons_gprintf (color fmt Color_RESET, __VA_ARGS__) #define PRINTF_YA(fmt, ...) PRINTF_A ("%s", fmt, pal->addr, __VA_ARGS__) #define PRINTF_GA(fmt, ...) PRINTF_A ("%s", fmt, pal->args, __VA_ARGS__) #define PRINTF_BA(fmt, ...) PRINTF_A ("%s", fmt, pal->num, __VA_ARGS__) #define PRINTF_RA(fmt, ...) PRINTF_A ("%s", fmt, pal->invalid, __VA_ARGS__) #define PRINT_A(color, msg) r_cons_gprint (color msg Color_RESET) #define PRINT_YA(msg) r_cons_gprintf ("%s" msg Color_RESET, pal->addr) #define PRINT_GA(msg) r_cons_gprintf ("%s" msg Color_RESET, pal->args) #define PRINT_BA(msg) r_cons_gprintf ("%s" msg Color_RESET, pal->num) #define PRINT_RA(msg) r_cons_gprintf ("%s" msg Color_RESET, pal->invalid) #endif #define PREV_INUSE 0x1 #define IS_MMAPPED 0x2 #define NON_MAIN_ARENA 0x4 #define NBINS 128 #define NSMALLBINS 64 #define NFASTBINS 10 #define BINMAPSHIFT 5 #define SZ (core->dbg->bits == 64 ? 8 : 4) #define FASTBIN_IDX_TO_SIZE(i) ((SZ * 4) + (SZ * 2) * (i - 1)) #define BITSPERMAP (1U << BINMAPSHIFT) #define BINMAPSIZE (NBINS / BITSPERMAP) #define MAX(a,b) (((a)>(b))?(a):(b)) #define NPAD -6 #define TCACHE_MAX_BINS 64 #define TCACHE_FILL_COUNT 7 #define TCACHE_NEW_VERSION 230 #define MMAP_ALIGN_32 0x14 #define MMAP_ALIGN_64 0x18 #define MMAP_OFFSET 0x8 #define HDR_SZ_32 0x8 #define HDR_SZ_64 0x10 #define TC_HDR_SZ 0x10 #define TC_SZ_32 0x0 #define TC_SZ_64 0x10 // Introduced with glibc 2.32 #define PROTECT_PTR(pos, ptr) \ ((__typeof (ptr)) ((((size_t) pos) >> 12) ^ ((size_t) ptr))) #define largebin_index_32(size) \ (((((ut32)(size)) >> 6) <= 38)? 56 + (((ut32)(size)) >> 6): \ ((((ut32)(size)) >> 9) <= 20)? 91 + (((ut32)(size)) >> 9): \ ((((ut32)(size)) >> 12) <= 10)? 110 + (((ut32)(size)) >> 12): \ ((((ut32)(size)) >> 15) <= 4)? 119 + (((ut32)(size)) >> 15): \ ((((ut32)(size)) >> 18) <= 2)? 124 + (((ut32)(size)) >> 18): \ 126) #define largebin_index_32_big(size) \ (((((ut32)(size)) >> 6) <= 45)? 49 + (((ut32)(size)) >> 6): \ ((((ut32)(size)) >> 9) <= 20)? 91 + (((ut32)(size)) >> 9): \ ((((ut32)(size)) >> 12) <= 10)? 110 + (((ut32)(size)) >> 12): \ ((((ut32)(size)) >> 15) <= 4)? 119 + (((ut32)(size)) >> 15): \ ((((ut32)(size)) >> 18) <= 2)? 124 + (((ut32)(size)) >> 18): \ 126) #define largebin_index_64(size) \ (((((ut32)(size)) >> 6) <= 48)? 48 + (((ut32)(size)) >> 6): \ ((((ut32)(size)) >> 9) <= 20)? 91 + (((ut32)(size)) >> 9): \ ((((ut32)(size)) >> 12) <= 10)? 110 + (((ut32)(size)) >> 12): \ ((((ut32)(size)) >> 15) <= 4)? 119 + (((ut32)(size)) >> 15): \ ((((ut32)(size)) >> 18) <= 2)? 124 + (((ut32)(size)) >> 18): \ 126) #define largebin_index(size) \ (SZ == 8 ? largebin_index_64 (size) : largebin_index_32 (size)) /* Not works 32 bit on 64 emulation #define largebin_index(size) \ (SZ == 8 ? largebin_index_64 (size) \ : MALLOC_ALIGNMENT == 16 ? largebin_index_32_big (size) \ : largebin_index_32 (size)) */ typedef struct r_malloc_chunk_64 { ut64 prev_size; /* Size of previous chunk (if free). */ ut64 size; /* Size in bytes, including overhead. */ ut64 fd; /* double links -- used only if free. */ ut64 bk; /* Only used for large blocks: pointer to next larger size. */ ut64 fd_nextsize; /* double links -- used only if free. */ ut64 bk_nextsize; } RHeapChunk_64; typedef struct r_malloc_chunk_32 { ut32 prev_size; /* Size of previous chunk (if free). */ ut32 size; /* Size in bytes, including overhead. */ ut32 fd; /* double links -- used only if free. */ ut32 bk; /* Only used for large blocks: pointer to next larger size. */ ut32 fd_nextsize; /* double links -- used only if free. */ ut32 bk_nextsize; } RHeapChunk_32; /* typedef RHeapChunk64 *mfastbinptr64; typedef RHeapChunk64 *mchunkptr64; typedef RHeapChunk32 *mfastbinptr32; typedef RHeapChunk32 *mchunkptr32; */ // 2.23 > GLIBC_VERSION >= 2.12 // https://github.com/bminor/glibc/blob/glibc-2.12/malloc/malloc.c#L2362-L2400 typedef struct r_malloc_state_212_32 { int mutex; int flags; ut32 fastbinsY[NFASTBINS]; ut32 top; ut32 last_remainder; ut32 bins[NBINS * 2 - 2]; unsigned int binmap[BINMAPSIZE]; ut32 next; ut32 next_free; ut32 system_mem; ut32 max_system_mem; } RHeap_MallocState_212_32; typedef struct r_malloc_state_212_64 { int mutex; int flags; ut64 fastbinsY[NFASTBINS]; ut64 top; ut64 last_remainder; ut64 bins[NBINS * 2 - 2]; unsigned int binmap[BINMAPSIZE]; ut64 next; ut64 next_free; ut64 system_mem; ut64 max_system_mem; } RHeap_MallocState_212_64; // 2.27 > GLIBC_VERSION >= 2.23 // https://github.com/bminor/glibc/blob/1c9a5c270d8b66f30dcfaf1cb2d6cf39d3e18369/malloc/malloc.c#L1678-L1716 typedef struct r_malloc_state_223_32 { int mutex; /* serialized access */ int flags; /* flags */ ut32 fastbinsY[NFASTBINS]; /* array of fastchunks */ ut32 top; /* top chunk's base addr */ ut32 last_remainder; /* remainder top chunk's addr */ ut32 bins[NBINS * 2 - 2]; /* array of remainder free chunks */ unsigned int binmap[BINMAPSIZE]; /* bitmap of bins */ ut32 next; /* double linked list of chunks */ ut32 next_free; /* double linked list of free chunks */ unsigned int attached_threads; /* threads attached */ ut32 system_mem; /* current allocated memory of current arena */ ut32 max_system_mem; /* maximum system memory */ } RHeap_MallocState_223_32; typedef struct r_malloc_state_223_64 { int mutex; /* serialized access */ int flags; /* flags */ ut64 fastbinsY[NFASTBINS]; /* array of fastchunks */ ut64 top; /* top chunk's base addr */ ut64 last_remainder; /* remainder top chunk's addr */ ut64 bins[NBINS * 2 - 2]; /* array of remainder free chunks */ unsigned int binmap[BINMAPSIZE]; /* bitmap of bins */ ut64 next; /* double linked list of chunks */ ut64 next_free; /* double linked list of free chunks */ unsigned int attached_threads; /* threads attached */ ut64 system_mem; /* current allocated memory of current arena */ ut64 max_system_mem; /* maximum system memory */ } RHeap_MallocState_223_64; typedef struct r_tcache_perthread_struct_32 { ut16 counts[TCACHE_MAX_BINS]; ut32 entries[TCACHE_MAX_BINS]; } RHeapTcache_32; typedef struct r_tcache_perthread_struct_64 { ut16 counts[TCACHE_MAX_BINS]; ut64 entries[TCACHE_MAX_BINS]; } RHeapTcache_64; typedef struct r_tcache_perthread_struct_pre_230_32 { ut8 counts[TCACHE_MAX_BINS]; ut32 entries[TCACHE_MAX_BINS]; } RHeapTcachePre230_32; typedef struct r_tcache_perthread_struct_pre_230_64 { ut8 counts[TCACHE_MAX_BINS]; ut64 entries[TCACHE_MAX_BINS]; } RHeapTcachePre230_64; typedef enum {NEW, OLD} tcache_type; typedef struct { tcache_type type; union { RHeapTcache_64 *heap_tcache; RHeapTcachePre230_64 *heap_tcache_pre_230; } RHeapTcache; } RTcache_64; typedef struct { tcache_type type; union { RHeapTcache_32 *heap_tcache; RHeapTcachePre230_32 *heap_tcache_pre_230; } RHeapTcache; } RTcache_32; // GLIBC_VERSION >= 2.27 // https://github.com/bminor/glibc/blob/glibc-2.34/malloc/malloc.c#L1831 typedef struct r_malloc_state_227_32 { int mutex; /* serialized access */ int flags; /* flags */ int have_fast_chunks; /* have fast chunks */ ut32 fastbinsY[NFASTBINS]; /* array of fastchunks */ ut32 top; /* top chunk's base addr */ ut32 last_remainder; /* remainder top chunk's addr */ ut32 bins[NBINS * 2 - 2]; /* array of remainder free chunks */ unsigned int binmap[BINMAPSIZE]; /* bitmap of bins */ ut32 next; /* double linked list of chunks */ ut32 next_free; /* double linked list of free chunks */ ut32 attached_threads; /* threads attached */ ut32 system_mem; /* current allocated memory of current arena */ ut32 max_system_mem; /* maximum system memory */ } RHeap_MallocState_227_32; typedef struct r_malloc_state_227_64 { int mutex; /* serialized access */ int flags; /* flags */ int have_fast_chunks; /* have fast chunks */ ut64 fastbinsY[NFASTBINS]; /* array of fastchunks */ ut64 top; /* top chunk's base addr */ ut64 last_remainder; /* remainder top chunk's addr */ ut64 bins[NBINS * 2 - 2]; /* array of remainder free chunks */ unsigned int binmap[BINMAPSIZE]; /* bitmap of bins */ ut64 next; /* double linked list of chunks */ ut64 next_free; /* double linked list of free chunks */ ut64 attached_threads; /* threads attached */ ut64 system_mem; /* current allocated memory of current arena */ ut64 max_system_mem; /* maximum system memory */ } RHeap_MallocState_227_64; typedef struct r_malloc_state { int mutex; /* serialized access */ int flags; /* flags */ unsigned int binmap[BINMAPSIZE]; /* bitmap of bins */ /*tcache*/ int have_fast_chunks; /* have fast chunks */ unsigned int attached_threads; /* threads attached */ /*32 bits members*/ ut32 fastbinsY_32[NFASTBINS]; /* array of fastchunks */ ut32 top_32; /* top chunk's base addr */ ut32 last_remainder_32; /* remainder top chunk's addr */ ut32 bins_32[NBINS * 2 - 2]; /* array of remainder free chunks */ ut32 next_32; /* double linked list of chunks */ ut32 next_free_32; /* double linked list of free chunks */ ut32 system_mem_32; /* current allocated memory of current arena */ ut32 max_system_mem_32; /* maximum system memory */ /*64 bits members */ ut64 fastbinsY_64[NFASTBINS]; /* array of fastchunks */ ut64 top_64; /* top chunk's base addr */ ut64 last_remainder_64; /* remainder top chunk's addr */ ut64 bins_64[NBINS * 2 - 2]; /* array of remainder free chunks */ ut64 next_64; /* double linked list of chunks */ ut64 next_free_64; /* double linked list of free chunks */ ut64 system_mem_64; /* current allocated memory of current arena */ ut64 max_system_mem_64; /* maximum system memory */ } MallocState; typedef struct r_heap_info_32 { ut32 ar_ptr; /* Arena for this heap. */ ut32 prev; /* Previous heap. */ ut32 size; /* Current size in bytes. */ ut32 mprotect_size; /* Size in bytes that has been mprotected PROT_READ|PROT_WRITE. */ /* Make sure the following data is properly aligned, particularly that sizeof (heap_info) + 2 * SZ is a multiple of MALLOC_ALIGNMENT. */ /* char pad[NPAD * SZ & MALLOC_ALIGN_MASK]; */ } RHeapInfo_32; typedef struct r_heap_info_64 { ut64 ar_ptr; /* Arena for this heap. */ ut64 prev; /* Previous heap. */ ut64 size; /* Current size in bytes. */ ut64 mprotect_size; /* Size in bytes that has been mprotected PROT_READ|PROT_WRITE. */ /* Make sure the following data is properly aligned, particularly that sizeof (heap_info) + 2 * SZ is a multiple of MALLOC_ALIGNMENT. */ /* char pad[NPAD * SZ & MALLOC_ALIGN_MASK]; */ } RHeapInfo_64; typedef struct _section_content_32 { ut32 size; ut8 *buf; } section_content_32; typedef struct _section_content_64 { ut64 size; ut8 *buf; } section_content_64; #ifdef __cplusplus } #endif #endif