debug_abbrev.c (3118B)
1 /* Abbrev pool: dedup by (tag, has_children, attr-list). 2 * 3 * Linear search dedup. Abbrev pools for our DIE shapes top out in the low 4 * tens; not worth a hashmap. Codes are 1-based in DWARF. */ 5 6 #include <string.h> 7 8 #include "core/buf.h" 9 #include "core/core.h" 10 #include "core/heap.h" 11 #include "core/vec.h" 12 #include "debug/debug_internal.h" 13 14 void abbrev_init(DebugAbbrevPool* p, Heap* h) { 15 (void)h; 16 p->items = NULL; 17 p->n = 0; 18 p->cap = 0; 19 } 20 21 /* Teardown frees the per-abbrev attr arrays, which requires a heap — so the 22 * sole entry point is abbrev_fini_heap below. Callers (debug.c) hold the 23 * heap that abbrev_init received and pass it back here. */ 24 static void abbrev_free_attrs(DebugAbbrevPool* p, Heap* h) { 25 u32 i; 26 for (i = 0; i < p->n; ++i) { 27 if (p->items[i].attrs) { 28 h->free(h, p->items[i].attrs, 29 sizeof(DebugAbbrevAttr) * p->items[i].nattrs); 30 p->items[i].attrs = NULL; 31 p->items[i].nattrs = 0; 32 } 33 } 34 if (p->items) { 35 h->free(h, p->items, sizeof(*p->items) * p->cap); 36 p->items = NULL; 37 p->n = 0; 38 p->cap = 0; 39 } 40 } 41 42 /* Public-ish helper: debug.c will call this at fini time. We expose a 43 * thin wrapper that simply forwards. */ 44 void abbrev_fini_heap(DebugAbbrevPool* p, Heap* h); 45 void abbrev_fini_heap(DebugAbbrevPool* p, Heap* h) { abbrev_free_attrs(p, h); } 46 47 static int attr_eq(const DebugAbbrevAttr* a, const DebugAbbrevAttr* b, u32 n) { 48 u32 i; 49 for (i = 0; i < n; ++i) { 50 if (a[i].attr != b[i].attr) return 0; 51 if (a[i].form != b[i].form) return 0; 52 if (a[i].implicit_const != b[i].implicit_const) return 0; 53 } 54 return 1; 55 } 56 57 u32 abbrev_intern(DebugAbbrevPool* p, Heap* h, u16 tag, u8 has_children, 58 const DebugAbbrevAttr* attrs, u32 nattrs) { 59 u32 i; 60 DebugAbbrev* slot; 61 for (i = 0; i < p->n; ++i) { 62 DebugAbbrev* it = &p->items[i]; 63 if (it->tag == tag && it->has_children == has_children && 64 it->nattrs == nattrs && attr_eq(it->attrs, attrs, nattrs)) { 65 return it->code; 66 } 67 } 68 if (VEC_GROW(h, p->items, p->cap, p->n + 1)) return 0; 69 slot = &p->items[p->n]; 70 slot->code = p->n + 1; 71 slot->tag = tag; 72 slot->has_children = has_children; 73 slot->pad = 0; 74 slot->nattrs = nattrs; 75 if (nattrs) { 76 slot->attrs = (DebugAbbrevAttr*)h->alloc( 77 h, sizeof(DebugAbbrevAttr) * nattrs, _Alignof(DebugAbbrevAttr)); 78 if (!slot->attrs) return 0; 79 memcpy(slot->attrs, attrs, sizeof(DebugAbbrevAttr) * nattrs); 80 } else { 81 slot->attrs = NULL; 82 } 83 p->n++; 84 return slot->code; 85 } 86 87 void abbrev_encode(const DebugAbbrevPool* p, Buf* out) { 88 u32 i, j; 89 for (i = 0; i < p->n; ++i) { 90 const DebugAbbrev* a = &p->items[i]; 91 form_uleb(out, a->code); 92 form_uleb(out, a->tag); 93 form_u8(out, a->has_children); 94 for (j = 0; j < a->nattrs; ++j) { 95 form_uleb(out, a->attrs[j].attr); 96 form_uleb(out, a->attrs[j].form); 97 /* DW_FORM_implicit_const carries a sleb here, but we never use it. */ 98 } 99 /* (0,0) terminator for attr list */ 100 form_uleb(out, 0); 101 form_uleb(out, 0); 102 } 103 /* code 0 terminates the abbrev table */ 104 form_uleb(out, 0); 105 }