dwarf_type.c (14764B)
1 /* dwarf_type.c — type DIE → KitDwarfType resolution. 2 * 3 * Builds KitDwarfType records on demand from DW_TAG_base_type, 4 * DW_TAG_pointer_type, DW_TAG_array_type, struct/union/enum, typedef, 5 * and qualifier-types (const/volatile/restrict transparent to inner). 6 */ 7 8 #include <kit/dwarf.h> 9 #include <stddef.h> 10 #include <stdint.h> 11 #include <string.h> 12 13 #include "core/core.h" 14 #include "core/heap.h" 15 #include "core/util.h" 16 #include "debug/dwarf_internal.h" 17 18 static KitDwarfType* type_cache_get(KitDebugInfo* d, u32 die_offset) { 19 u32 i; 20 for (i = 0; i < d->ntypes; ++i) { 21 if (d->types_off[i] == die_offset) return d->types_by_off[i]; 22 } 23 return NULL; 24 } 25 26 static void type_cache_put(KitDebugInfo* d, u32 die_offset, KitDwarfType* t) { 27 if (d->ntypes == d->types_cap) { 28 u32 ncap = d->types_cap ? d->types_cap * 2 : 16; 29 KitDwarfType** na = (KitDwarfType**)d->h->realloc( 30 d->h, d->types_by_off, d->types_cap * sizeof(*d->types_by_off), 31 ncap * sizeof(*d->types_by_off), _Alignof(KitDwarfType*)); 32 u32* no = 33 (u32*)d->h->realloc(d->h, d->types_off, d->types_cap * sizeof(u32), 34 ncap * sizeof(u32), _Alignof(u32)); 35 if (!na || !no) return; 36 d->types_by_off = na; 37 d->types_off = no; 38 d->types_cap = ncap; 39 } 40 d->types_by_off[d->ntypes] = t; 41 d->types_off[d->ntypes] = die_offset; 42 d->ntypes++; 43 } 44 45 static KitDwarfType* type_alloc(KitDebugInfo* d) { 46 KitDwarfType* t = 47 (KitDwarfType*)d->h->alloc(d->h, sizeof(*t), _Alignof(KitDwarfType)); 48 if (!t) return NULL; 49 memset(t, 0, sizeof(*t)); 50 t->name = ""; 51 return t; 52 } 53 54 KitDwarfType* dw_void_type(KitDebugInfo* d) { 55 KitDwarfType* t = type_cache_get(d, 0); 56 if (t) return t; 57 t = type_alloc(d); 58 if (!t) return NULL; 59 t->kind = DTK_VOID; 60 type_cache_put(d, 0, t); 61 return t; 62 } 63 64 /* Walk struct/union children for fields, or enum children for values. */ 65 static void walk_struct_fields(KitDebugInfo* d, DwCu* cu, u32* off, 66 KitDwarfType* t) { 67 DwField* fields = NULL; 68 u32 nfields = 0, cap = 0; 69 for (;;) { 70 DwDie die; 71 if (!dw_read_die(d, cu, off, &die)) break; 72 if (die.abbrev->tag == DW_TAG_member) { 73 DieAttrPack p; 74 dw_die_pack(d, cu, &die, &p, off); /* decodes attrs and advances off */ 75 if (nfields == cap) { 76 u32 ncap = cap ? cap * 2 : 4; 77 DwField* na = 78 (DwField*)d->h->realloc(d->h, fields, cap * sizeof(*fields), 79 ncap * sizeof(*fields), _Alignof(DwField)); 80 if (!na) break; 81 fields = na; 82 cap = ncap; 83 } 84 fields[nfields].name = p.name ? p.name : ""; 85 fields[nfields].byte_offset = p.has_byte_offset ? p.byte_offset : 0; 86 fields[nfields].bit_offset = p.has_bit_offset ? p.bit_offset : 0; 87 fields[nfields].bit_size = p.has_bit_size ? p.bit_size : 0; 88 fields[nfields].type = 89 p.has_type 90 ? dw_type_from_die(d, (u32)(cu - d->cus), p.type_die_offset) 91 : dw_void_type(d); 92 nfields++; 93 if (die.abbrev->has_children) { 94 for (;;) { 95 DwDie c; 96 if (!dw_read_die(d, cu, off, &c)) break; 97 dw_skip_die_subtree(d, cu, &c, off); 98 } 99 } 100 } else { 101 dw_skip_die_subtree(d, cu, &die, off); 102 } 103 } 104 t->fields = fields; 105 t->nfields = nfields; 106 } 107 108 static void walk_enum_values(KitDebugInfo* d, DwCu* cu, u32* off, 109 KitDwarfType* t) { 110 DwEnumVal* evs = NULL; 111 u32 nev = 0, cap = 0; 112 for (;;) { 113 DwDie die; 114 if (!dw_read_die(d, cu, off, &die)) break; 115 if (die.abbrev->tag == DW_TAG_enumerator) { 116 DieAttrPack p; 117 dw_die_pack(d, cu, &die, &p, off); /* decodes attrs and advances off */ 118 if (nev == cap) { 119 u32 ncap = cap ? cap * 2 : 4; 120 DwEnumVal* na = 121 (DwEnumVal*)d->h->realloc(d->h, evs, cap * sizeof(*evs), 122 ncap * sizeof(*evs), _Alignof(DwEnumVal)); 123 if (!na) break; 124 evs = na; 125 cap = ncap; 126 } 127 evs[nev].name = p.name ? p.name : ""; 128 evs[nev].value = p.has_const_value ? p.const_value : 0; 129 nev++; 130 if (die.abbrev->has_children) { 131 for (;;) { 132 DwDie c; 133 if (!dw_read_die(d, cu, off, &c)) break; 134 dw_skip_die_subtree(d, cu, &c, off); 135 } 136 } 137 } else { 138 dw_skip_die_subtree(d, cu, &die, off); 139 } 140 } 141 t->evals = evs; 142 t->nevals = nev; 143 } 144 145 /* For DW_TAG_array_type: child DW_TAG_subrange_type carries upper_bound / 146 * count. */ 147 static void walk_array_subrange(KitDebugInfo* d, DwCu* cu, u32* off, 148 KitDwarfType* t) { 149 for (;;) { 150 DwDie die; 151 if (!dw_read_die(d, cu, off, &die)) break; 152 if (die.abbrev->tag == DW_TAG_subrange_type) { 153 DieAttrPack p; 154 dw_die_pack(d, cu, &die, &p, off); /* decodes attrs and advances off */ 155 if (p.has_array_count) t->element_count = p.array_count; 156 if (die.abbrev->has_children) { 157 for (;;) { 158 DwDie c; 159 if (!dw_read_die(d, cu, off, &c)) break; 160 dw_skip_die_subtree(d, cu, &c, off); 161 } 162 } 163 } else { 164 dw_skip_die_subtree(d, cu, &die, off); 165 } 166 } 167 } 168 169 KitDwarfType* dw_type_from_die(KitDebugInfo* d, u32 cu_idx, u32 die_offset) { 170 DwCu* cu; 171 DwDie die; 172 u32 off; 173 KitDwarfType* t; 174 DieAttrPack p; 175 if (die_offset == 0) return dw_void_type(d); 176 t = type_cache_get(d, die_offset); 177 if (t) return t; 178 /* Resolve CU containing the DIE. */ 179 cu = dw_cu_at_die_offset(d, die_offset); 180 if (!cu) { 181 if (cu_idx < d->ncus) 182 cu = &d->cus[cu_idx]; 183 else 184 return dw_void_type(d); 185 } 186 off = die_offset; 187 if (!dw_read_die(d, cu, &off, &die)) return dw_void_type(d); 188 if (!die.abbrev) return dw_void_type(d); 189 /* Decode attrs and advance `off` to the first child DIE. */ 190 dw_die_pack(d, cu, &die, &p, &off); 191 /* Allocate before recursing — break cycles by interning early. */ 192 t = type_alloc(d); 193 if (!t) return dw_void_type(d); 194 t->die_offset = die_offset; 195 type_cache_put(d, die_offset, t); 196 197 switch (die.abbrev->tag) { 198 case DW_TAG_base_type: 199 t->kind = DTK_BASE; 200 t->name = p.name ? p.name : ""; 201 t->byte_size = p.byte_size; 202 t->base_encoding = p.base_encoding; 203 break; 204 case DW_TAG_pointer_type: 205 case DW_TAG_reference_type: 206 t->kind = DTK_PTR; 207 t->byte_size = p.has_byte_size ? p.byte_size : 8; 208 t->name = ""; 209 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 210 p.type_die_offset) 211 : dw_void_type(d); 212 break; 213 case DW_TAG_typedef: 214 t->kind = DTK_TYPEDEF; 215 t->name = p.name ? p.name : ""; 216 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 217 p.type_die_offset) 218 : dw_void_type(d); 219 if (t->inner) t->byte_size = t->inner->byte_size; 220 break; 221 case DW_TAG_const_type: 222 case DW_TAG_volatile_type: 223 case DW_TAG_restrict_type: 224 t->kind = (die.abbrev->tag == DW_TAG_const_type) ? DTK_CONST 225 : (die.abbrev->tag == DW_TAG_volatile_type) ? DTK_VOLATILE 226 : DTK_RESTRICT; 227 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 228 p.type_die_offset) 229 : dw_void_type(d); 230 if (t->inner) { 231 t->byte_size = t->inner->byte_size; 232 t->name = t->inner->name; 233 } 234 break; 235 case DW_TAG_array_type: 236 t->kind = DTK_ARRAY; 237 t->name = ""; 238 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 239 p.type_die_offset) 240 : dw_void_type(d); 241 if (die.abbrev->has_children) { 242 /* `off` already sits at the first child (attrs decoded above). */ 243 u32 cur = off; 244 walk_array_subrange(d, cu, &cur, t); 245 } 246 if (t->inner && t->element_count) 247 t->byte_size = t->inner->byte_size * t->element_count; 248 break; 249 case DW_TAG_structure_type: 250 case DW_TAG_class_type: 251 t->kind = DTK_STRUCT; 252 t->name = p.name ? p.name : ""; 253 t->byte_size = p.byte_size; 254 if (die.abbrev->has_children) { 255 u32 cur = off; 256 walk_struct_fields(d, cu, &cur, t); 257 } 258 break; 259 case DW_TAG_union_type: 260 t->kind = DTK_UNION; 261 t->name = p.name ? p.name : ""; 262 t->byte_size = p.byte_size; 263 if (die.abbrev->has_children) { 264 u32 cur = off; 265 walk_struct_fields(d, cu, &cur, t); 266 } 267 break; 268 case DW_TAG_enumeration_type: 269 t->kind = DTK_ENUM; 270 t->name = p.name ? p.name : ""; 271 t->byte_size = p.byte_size; 272 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 273 p.type_die_offset) 274 : dw_void_type(d); 275 if (die.abbrev->has_children) { 276 u32 cur = off; 277 walk_enum_values(d, cu, &cur, t); 278 } 279 break; 280 case DW_TAG_subroutine_type: 281 t->kind = DTK_FUNC; 282 t->name = ""; 283 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 284 p.type_die_offset) 285 : dw_void_type(d); 286 break; 287 default: 288 t->kind = DTK_VOID; 289 break; 290 } 291 return t; 292 } 293 294 /* ---- public type-info accessors -------------------------------------- */ 295 296 static KitDwarfTypeKind map_kind(const KitDwarfType* t) { 297 if (!t) return KIT_DT_VOID; 298 switch (t->kind) { 299 case DTK_VOID: 300 return KIT_DT_VOID; 301 case DTK_PTR: 302 return KIT_DT_PTR; 303 case DTK_ARRAY: 304 return KIT_DT_ARRAY; 305 case DTK_STRUCT: 306 return KIT_DT_STRUCT; 307 case DTK_UNION: 308 return KIT_DT_UNION; 309 case DTK_ENUM: 310 return KIT_DT_ENUM; 311 case DTK_TYPEDEF: 312 return KIT_DT_TYPEDEF; 313 case DTK_FUNC: 314 return KIT_DT_FUNC; 315 case DTK_CONST: 316 case DTK_VOLATILE: 317 case DTK_RESTRICT: 318 return t->inner ? map_kind(t->inner) : KIT_DT_VOID; 319 case DTK_BASE: 320 switch (t->base_encoding) { 321 case DW_ATE_boolean: 322 return KIT_DT_BOOL; 323 case DW_ATE_float: 324 case DW_ATE_complex_float: 325 return KIT_DT_FLOAT; 326 case DW_ATE_signed_char: 327 return KIT_DT_CHAR; 328 case DW_ATE_unsigned_char: 329 return KIT_DT_CHAR; 330 case DW_ATE_unsigned: 331 case DW_ATE_address: 332 case DW_ATE_UTF: 333 return KIT_DT_UINT; 334 case DW_ATE_signed: 335 return KIT_DT_SINT; 336 default: 337 return KIT_DT_UINT; 338 } 339 } 340 return KIT_DT_VOID; 341 } 342 343 KitDwarfTypeInfo kit_dwarf_type_info(const KitDwarfType* t) { 344 KitDwarfTypeInfo info; 345 memset(&info, 0, sizeof(info)); 346 info.name = KIT_SLICE_NULL; 347 if (!t) { 348 info.kind = KIT_DT_VOID; 349 return info; 350 } 351 info.kind = map_kind(t); 352 info.byte_size = t->byte_size; 353 info.name = t->name ? kit_slice_cstr(t->name) : KIT_SLICE_NULL; 354 info.element_count = t->element_count; 355 /* For TYPEDEF/PTR/ARRAY: expose inner. For BASE_CHAR map signedness. */ 356 switch (t->kind) { 357 case DTK_BASE: 358 if (t->base_encoding == DW_ATE_signed_char) 359 info.kind = KIT_DT_SINT; 360 else if (t->base_encoding == DW_ATE_unsigned_char) 361 info.kind = KIT_DT_UINT; 362 break; 363 case DTK_PTR: 364 case DTK_ARRAY: 365 case DTK_TYPEDEF: 366 case DTK_FUNC: 367 info.inner = t->inner; 368 break; 369 case DTK_CONST: 370 case DTK_VOLATILE: 371 case DTK_RESTRICT: 372 /* Transparent: report inner directly. */ 373 if (t->inner) { 374 return kit_dwarf_type_info(t->inner); 375 } 376 break; 377 default: 378 break; 379 } 380 return info; 381 } 382 383 /* Field iterator. */ 384 struct KitDwarfFieldIter { 385 KitDebugInfo* d; 386 const KitDwarfType* t; 387 u32 idx; 388 }; 389 390 KitStatus kit_dwarf_field_iter_new(KitDebugInfo* d, const KitDwarfType* t, 391 KitDwarfFieldIter** out) { 392 KitDwarfFieldIter* it; 393 if (!out) return KIT_INVALID; 394 *out = NULL; 395 if (!d || !t) return KIT_INVALID; 396 it = (KitDwarfFieldIter*)d->h->alloc(d->h, sizeof(*it), 397 _Alignof(KitDwarfFieldIter)); 398 if (!it) return KIT_NOMEM; 399 it->d = d; 400 /* Look through typedef / qualifiers to the underlying aggregate. */ 401 while (t && (t->kind == DTK_TYPEDEF || t->kind == DTK_CONST || 402 t->kind == DTK_VOLATILE || t->kind == DTK_RESTRICT)) 403 t = t->inner; 404 it->t = t; 405 it->idx = 0; 406 *out = it; 407 return KIT_OK; 408 } 409 410 KitIterResult kit_dwarf_field_iter_next(KitDwarfFieldIter* it, 411 KitDwarfField* out) { 412 const KitDwarfType* t; 413 if (!it || !out) return KIT_ITER_ERROR; 414 if (!it->t) return KIT_ITER_END; 415 t = it->t; 416 if (t->kind != DTK_STRUCT && t->kind != DTK_UNION) return KIT_ITER_END; 417 if (it->idx >= t->nfields) return KIT_ITER_END; 418 { 419 DwField* f = &t->fields[it->idx++]; 420 out->name = f->name ? kit_slice_cstr(f->name) : KIT_SLICE_NULL; 421 out->byte_offset = f->byte_offset; 422 out->bit_offset = f->bit_offset; 423 out->bit_size = f->bit_size; 424 out->type = f->type; 425 } 426 return KIT_ITER_ITEM; 427 } 428 429 void kit_dwarf_field_iter_free(KitDwarfFieldIter* it) { 430 if (!it) return; 431 it->d->h->free(it->d->h, it, sizeof(*it)); 432 } 433 434 struct KitDwarfEnumIter { 435 KitDebugInfo* d; 436 const KitDwarfType* t; 437 u32 idx; 438 }; 439 440 KitStatus kit_dwarf_enum_iter_new(KitDebugInfo* d, const KitDwarfType* t, 441 KitDwarfEnumIter** out) { 442 KitDwarfEnumIter* it; 443 if (!out) return KIT_INVALID; 444 *out = NULL; 445 if (!d || !t) return KIT_INVALID; 446 it = (KitDwarfEnumIter*)d->h->alloc(d->h, sizeof(*it), 447 _Alignof(KitDwarfEnumIter)); 448 if (!it) return KIT_NOMEM; 449 it->d = d; 450 while (t && (t->kind == DTK_TYPEDEF || t->kind == DTK_CONST || 451 t->kind == DTK_VOLATILE || t->kind == DTK_RESTRICT)) 452 t = t->inner; 453 it->t = t; 454 it->idx = 0; 455 *out = it; 456 return KIT_OK; 457 } 458 459 KitIterResult kit_dwarf_enum_iter_next(KitDwarfEnumIter* it, 460 KitDwarfEnumVal* out) { 461 const KitDwarfType* t; 462 if (!it || !out) return KIT_ITER_ERROR; 463 if (!it->t) return KIT_ITER_END; 464 t = it->t; 465 if (t->kind != DTK_ENUM) return KIT_ITER_END; 466 if (it->idx >= t->nevals) return KIT_ITER_END; 467 out->name = t->evals[it->idx].name ? kit_slice_cstr(t->evals[it->idx].name) 468 : KIT_SLICE_NULL; 469 out->value = t->evals[it->idx].value; 470 it->idx++; 471 return KIT_ITER_ITEM; 472 } 473 474 void kit_dwarf_enum_iter_free(KitDwarfEnumIter* it) { 475 if (!it) return; 476 it->d->h->free(it->d->h, it, sizeof(*it)); 477 }