dwarf_type.c (16006B)
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); 75 /* skip past die's attrs */ 76 { 77 u32 i; 78 for (i = 0; i < die.abbrev->nattrs; ++i) { 79 DwAbbrevAttr* aa = &die.abbrev->attrs[i]; 80 dw_skip_form(d, cu, aa->form, aa->implicit_const, off); 81 } 82 } 83 if (nfields == cap) { 84 u32 ncap = cap ? cap * 2 : 4; 85 DwField* na = 86 (DwField*)d->h->realloc(d->h, fields, cap * sizeof(*fields), 87 ncap * sizeof(*fields), _Alignof(DwField)); 88 if (!na) break; 89 fields = na; 90 cap = ncap; 91 } 92 fields[nfields].name = p.name ? p.name : ""; 93 fields[nfields].byte_offset = p.has_byte_offset ? p.byte_offset : 0; 94 fields[nfields].bit_offset = p.has_bit_offset ? p.bit_offset : 0; 95 fields[nfields].bit_size = p.has_bit_size ? p.bit_size : 0; 96 fields[nfields].type = 97 p.has_type 98 ? dw_type_from_die(d, (u32)(cu - d->cus), p.type_die_offset) 99 : dw_void_type(d); 100 nfields++; 101 if (die.abbrev->has_children) { 102 for (;;) { 103 DwDie c; 104 if (!dw_read_die(d, cu, off, &c)) break; 105 dw_skip_die_subtree(d, cu, &c, off); 106 } 107 } 108 } else { 109 dw_skip_die_subtree(d, cu, &die, off); 110 } 111 } 112 t->fields = fields; 113 t->nfields = nfields; 114 } 115 116 static void walk_enum_values(KitDebugInfo* d, DwCu* cu, u32* off, 117 KitDwarfType* t) { 118 DwEnumVal* evs = NULL; 119 u32 nev = 0, cap = 0; 120 for (;;) { 121 DwDie die; 122 if (!dw_read_die(d, cu, off, &die)) break; 123 if (die.abbrev->tag == DW_TAG_enumerator) { 124 DieAttrPack p; 125 dw_die_pack(d, cu, &die, &p); 126 { 127 u32 i; 128 for (i = 0; i < die.abbrev->nattrs; ++i) { 129 DwAbbrevAttr* aa = &die.abbrev->attrs[i]; 130 dw_skip_form(d, cu, aa->form, aa->implicit_const, off); 131 } 132 } 133 if (nev == cap) { 134 u32 ncap = cap ? cap * 2 : 4; 135 DwEnumVal* na = 136 (DwEnumVal*)d->h->realloc(d->h, evs, cap * sizeof(*evs), 137 ncap * sizeof(*evs), _Alignof(DwEnumVal)); 138 if (!na) break; 139 evs = na; 140 cap = ncap; 141 } 142 evs[nev].name = p.name ? p.name : ""; 143 evs[nev].value = p.has_const_value ? p.const_value : 0; 144 nev++; 145 if (die.abbrev->has_children) { 146 for (;;) { 147 DwDie c; 148 if (!dw_read_die(d, cu, off, &c)) break; 149 dw_skip_die_subtree(d, cu, &c, off); 150 } 151 } 152 } else { 153 dw_skip_die_subtree(d, cu, &die, off); 154 } 155 } 156 t->evals = evs; 157 t->nevals = nev; 158 } 159 160 /* For DW_TAG_array_type: child DW_TAG_subrange_type carries upper_bound / 161 * count. */ 162 static void walk_array_subrange(KitDebugInfo* d, DwCu* cu, u32* off, 163 KitDwarfType* t) { 164 for (;;) { 165 DwDie die; 166 if (!dw_read_die(d, cu, off, &die)) break; 167 if (die.abbrev->tag == DW_TAG_subrange_type) { 168 DieAttrPack p; 169 dw_die_pack(d, cu, &die, &p); 170 { 171 u32 i; 172 for (i = 0; i < die.abbrev->nattrs; ++i) { 173 DwAbbrevAttr* aa = &die.abbrev->attrs[i]; 174 dw_skip_form(d, cu, aa->form, aa->implicit_const, off); 175 } 176 } 177 if (p.has_array_count) t->element_count = p.array_count; 178 if (die.abbrev->has_children) { 179 for (;;) { 180 DwDie c; 181 if (!dw_read_die(d, cu, off, &c)) break; 182 dw_skip_die_subtree(d, cu, &c, off); 183 } 184 } 185 } else { 186 dw_skip_die_subtree(d, cu, &die, off); 187 } 188 } 189 } 190 191 KitDwarfType* dw_type_from_die(KitDebugInfo* d, u32 cu_idx, u32 die_offset) { 192 DwCu* cu; 193 DwDie die; 194 u32 off; 195 KitDwarfType* t; 196 DieAttrPack p; 197 if (die_offset == 0) return dw_void_type(d); 198 t = type_cache_get(d, die_offset); 199 if (t) return t; 200 /* Resolve CU containing the DIE. */ 201 cu = dw_cu_at_die_offset(d, die_offset); 202 if (!cu) { 203 if (cu_idx < d->ncus) 204 cu = &d->cus[cu_idx]; 205 else 206 return dw_void_type(d); 207 } 208 off = die_offset; 209 if (!dw_read_die(d, cu, &off, &die)) return dw_void_type(d); 210 if (!die.abbrev) return dw_void_type(d); 211 dw_die_pack(d, cu, &die, &p); 212 /* Allocate before recursing — break cycles by interning early. */ 213 t = type_alloc(d); 214 if (!t) return dw_void_type(d); 215 t->die_offset = die_offset; 216 type_cache_put(d, die_offset, t); 217 218 switch (die.abbrev->tag) { 219 case DW_TAG_base_type: 220 t->kind = DTK_BASE; 221 t->name = p.name ? p.name : ""; 222 t->byte_size = p.byte_size; 223 t->base_encoding = p.base_encoding; 224 break; 225 case DW_TAG_pointer_type: 226 case DW_TAG_reference_type: 227 t->kind = DTK_PTR; 228 t->byte_size = p.has_byte_size ? p.byte_size : 8; 229 t->name = ""; 230 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 231 p.type_die_offset) 232 : dw_void_type(d); 233 break; 234 case DW_TAG_typedef: 235 t->kind = DTK_TYPEDEF; 236 t->name = p.name ? p.name : ""; 237 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 238 p.type_die_offset) 239 : dw_void_type(d); 240 if (t->inner) t->byte_size = t->inner->byte_size; 241 break; 242 case DW_TAG_const_type: 243 case DW_TAG_volatile_type: 244 case DW_TAG_restrict_type: 245 t->kind = (die.abbrev->tag == DW_TAG_const_type) ? DTK_CONST 246 : (die.abbrev->tag == DW_TAG_volatile_type) ? DTK_VOLATILE 247 : DTK_RESTRICT; 248 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 249 p.type_die_offset) 250 : dw_void_type(d); 251 if (t->inner) { 252 t->byte_size = t->inner->byte_size; 253 t->name = t->inner->name; 254 } 255 break; 256 case DW_TAG_array_type: 257 t->kind = DTK_ARRAY; 258 t->name = ""; 259 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 260 p.type_die_offset) 261 : dw_void_type(d); 262 if (die.abbrev->has_children) { 263 u32 cur = off; 264 /* Skip attrs (already read into p). */ 265 u32 ii; 266 for (ii = 0; ii < die.abbrev->nattrs; ++ii) { 267 DwAbbrevAttr* aa = &die.abbrev->attrs[ii]; 268 dw_skip_form(d, cu, aa->form, aa->implicit_const, &cur); 269 } 270 walk_array_subrange(d, cu, &cur, t); 271 } 272 if (t->inner && t->element_count) 273 t->byte_size = t->inner->byte_size * t->element_count; 274 break; 275 case DW_TAG_structure_type: 276 case DW_TAG_class_type: 277 t->kind = DTK_STRUCT; 278 t->name = p.name ? p.name : ""; 279 t->byte_size = p.byte_size; 280 if (die.abbrev->has_children) { 281 u32 cur = off; 282 u32 ii; 283 for (ii = 0; ii < die.abbrev->nattrs; ++ii) { 284 DwAbbrevAttr* aa = &die.abbrev->attrs[ii]; 285 dw_skip_form(d, cu, aa->form, aa->implicit_const, &cur); 286 } 287 walk_struct_fields(d, cu, &cur, t); 288 } 289 break; 290 case DW_TAG_union_type: 291 t->kind = DTK_UNION; 292 t->name = p.name ? p.name : ""; 293 t->byte_size = p.byte_size; 294 if (die.abbrev->has_children) { 295 u32 cur = off; 296 u32 ii; 297 for (ii = 0; ii < die.abbrev->nattrs; ++ii) { 298 DwAbbrevAttr* aa = &die.abbrev->attrs[ii]; 299 dw_skip_form(d, cu, aa->form, aa->implicit_const, &cur); 300 } 301 walk_struct_fields(d, cu, &cur, t); 302 } 303 break; 304 case DW_TAG_enumeration_type: 305 t->kind = DTK_ENUM; 306 t->name = p.name ? p.name : ""; 307 t->byte_size = p.byte_size; 308 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 309 p.type_die_offset) 310 : dw_void_type(d); 311 if (die.abbrev->has_children) { 312 u32 cur = off; 313 u32 ii; 314 for (ii = 0; ii < die.abbrev->nattrs; ++ii) { 315 DwAbbrevAttr* aa = &die.abbrev->attrs[ii]; 316 dw_skip_form(d, cu, aa->form, aa->implicit_const, &cur); 317 } 318 walk_enum_values(d, cu, &cur, t); 319 } 320 break; 321 case DW_TAG_subroutine_type: 322 t->kind = DTK_FUNC; 323 t->name = ""; 324 t->inner = p.has_type ? dw_type_from_die(d, (u32)(cu - d->cus), 325 p.type_die_offset) 326 : dw_void_type(d); 327 break; 328 default: 329 t->kind = DTK_VOID; 330 break; 331 } 332 return t; 333 } 334 335 /* ---- public type-info accessors -------------------------------------- */ 336 337 static KitDwarfTypeKind map_kind(const KitDwarfType* t) { 338 if (!t) return KIT_DT_VOID; 339 switch (t->kind) { 340 case DTK_VOID: 341 return KIT_DT_VOID; 342 case DTK_PTR: 343 return KIT_DT_PTR; 344 case DTK_ARRAY: 345 return KIT_DT_ARRAY; 346 case DTK_STRUCT: 347 return KIT_DT_STRUCT; 348 case DTK_UNION: 349 return KIT_DT_UNION; 350 case DTK_ENUM: 351 return KIT_DT_ENUM; 352 case DTK_TYPEDEF: 353 return KIT_DT_TYPEDEF; 354 case DTK_FUNC: 355 return KIT_DT_FUNC; 356 case DTK_CONST: 357 case DTK_VOLATILE: 358 case DTK_RESTRICT: 359 return t->inner ? map_kind(t->inner) : KIT_DT_VOID; 360 case DTK_BASE: 361 switch (t->base_encoding) { 362 case DW_ATE_boolean: 363 return KIT_DT_BOOL; 364 case DW_ATE_float: 365 case DW_ATE_complex_float: 366 return KIT_DT_FLOAT; 367 case DW_ATE_signed_char: 368 return KIT_DT_CHAR; 369 case DW_ATE_unsigned_char: 370 return KIT_DT_CHAR; 371 case DW_ATE_unsigned: 372 case DW_ATE_address: 373 case DW_ATE_UTF: 374 return KIT_DT_UINT; 375 case DW_ATE_signed: 376 return KIT_DT_SINT; 377 default: 378 return KIT_DT_UINT; 379 } 380 } 381 return KIT_DT_VOID; 382 } 383 384 KitDwarfTypeInfo kit_dwarf_type_info(const KitDwarfType* t) { 385 KitDwarfTypeInfo info; 386 memset(&info, 0, sizeof(info)); 387 info.name = KIT_SLICE_NULL; 388 if (!t) { 389 info.kind = KIT_DT_VOID; 390 return info; 391 } 392 info.kind = map_kind(t); 393 info.byte_size = t->byte_size; 394 info.name = t->name ? kit_slice_cstr(t->name) : KIT_SLICE_NULL; 395 info.element_count = t->element_count; 396 /* For TYPEDEF/PTR/ARRAY: expose inner. For BASE_CHAR map signedness. */ 397 switch (t->kind) { 398 case DTK_BASE: 399 if (t->base_encoding == DW_ATE_signed_char) 400 info.kind = KIT_DT_SINT; 401 else if (t->base_encoding == DW_ATE_unsigned_char) 402 info.kind = KIT_DT_UINT; 403 break; 404 case DTK_PTR: 405 case DTK_ARRAY: 406 case DTK_TYPEDEF: 407 case DTK_FUNC: 408 info.inner = t->inner; 409 break; 410 case DTK_CONST: 411 case DTK_VOLATILE: 412 case DTK_RESTRICT: 413 /* Transparent: report inner directly. */ 414 if (t->inner) { 415 return kit_dwarf_type_info(t->inner); 416 } 417 break; 418 default: 419 break; 420 } 421 return info; 422 } 423 424 /* Field iterator. */ 425 struct KitDwarfFieldIter { 426 KitDebugInfo* d; 427 const KitDwarfType* t; 428 u32 idx; 429 }; 430 431 KitStatus kit_dwarf_field_iter_new(KitDebugInfo* d, const KitDwarfType* t, 432 KitDwarfFieldIter** out) { 433 KitDwarfFieldIter* it; 434 if (!out) return KIT_INVALID; 435 *out = NULL; 436 if (!d || !t) return KIT_INVALID; 437 it = (KitDwarfFieldIter*)d->h->alloc(d->h, sizeof(*it), 438 _Alignof(KitDwarfFieldIter)); 439 if (!it) return KIT_NOMEM; 440 it->d = d; 441 /* Look through typedef / qualifiers to the underlying aggregate. */ 442 while (t && (t->kind == DTK_TYPEDEF || t->kind == DTK_CONST || 443 t->kind == DTK_VOLATILE || t->kind == DTK_RESTRICT)) 444 t = t->inner; 445 it->t = t; 446 it->idx = 0; 447 *out = it; 448 return KIT_OK; 449 } 450 451 KitIterResult kit_dwarf_field_iter_next(KitDwarfFieldIter* it, 452 KitDwarfField* out) { 453 const KitDwarfType* t; 454 if (!it || !out) return KIT_ITER_ERROR; 455 if (!it->t) return KIT_ITER_END; 456 t = it->t; 457 if (t->kind != DTK_STRUCT && t->kind != DTK_UNION) return KIT_ITER_END; 458 if (it->idx >= t->nfields) return KIT_ITER_END; 459 { 460 DwField* f = &t->fields[it->idx++]; 461 out->name = f->name ? kit_slice_cstr(f->name) : KIT_SLICE_NULL; 462 out->byte_offset = f->byte_offset; 463 out->bit_offset = f->bit_offset; 464 out->bit_size = f->bit_size; 465 out->type = f->type; 466 } 467 return KIT_ITER_ITEM; 468 } 469 470 void kit_dwarf_field_iter_free(KitDwarfFieldIter* it) { 471 if (!it) return; 472 it->d->h->free(it->d->h, it, sizeof(*it)); 473 } 474 475 struct KitDwarfEnumIter { 476 KitDebugInfo* d; 477 const KitDwarfType* t; 478 u32 idx; 479 }; 480 481 KitStatus kit_dwarf_enum_iter_new(KitDebugInfo* d, const KitDwarfType* t, 482 KitDwarfEnumIter** out) { 483 KitDwarfEnumIter* it; 484 if (!out) return KIT_INVALID; 485 *out = NULL; 486 if (!d || !t) return KIT_INVALID; 487 it = (KitDwarfEnumIter*)d->h->alloc(d->h, sizeof(*it), 488 _Alignof(KitDwarfEnumIter)); 489 if (!it) return KIT_NOMEM; 490 it->d = d; 491 while (t && (t->kind == DTK_TYPEDEF || t->kind == DTK_CONST || 492 t->kind == DTK_VOLATILE || t->kind == DTK_RESTRICT)) 493 t = t->inner; 494 it->t = t; 495 it->idx = 0; 496 *out = it; 497 return KIT_OK; 498 } 499 500 KitIterResult kit_dwarf_enum_iter_next(KitDwarfEnumIter* it, 501 KitDwarfEnumVal* out) { 502 const KitDwarfType* t; 503 if (!it || !out) return KIT_ITER_ERROR; 504 if (!it->t) return KIT_ITER_END; 505 t = it->t; 506 if (t->kind != DTK_ENUM) return KIT_ITER_END; 507 if (it->idx >= t->nevals) return KIT_ITER_END; 508 out->name = t->evals[it->idx].name ? kit_slice_cstr(t->evals[it->idx].name) 509 : KIT_SLICE_NULL; 510 out->value = t->evals[it->idx].value; 511 it->idx++; 512 return KIT_ITER_ITEM; 513 } 514 515 void kit_dwarf_enum_iter_free(KitDwarfEnumIter* it) { 516 if (!it) return; 517 it->d->h->free(it->d->h, it, sizeof(*it)); 518 }