object_file.c (25266B)
1 /* Public KitObjFile reader. Wraps the internal read_/obj_ surface 2 * and exposes format-neutral object inspection. */ 3 4 #include <kit/object.h> 5 #include <setjmp.h> 6 #include <string.h> 7 8 #include "core/buf.h" 9 #include "core/core.h" 10 #include "core/heap.h" 11 #include "core/pool.h" 12 #include "core/slice.h" 13 #include "core/vec.h" 14 #include "obj/format.h" 15 #include "obj/obj.h" 16 17 struct KitObjFile { 18 Compiler compiler; 19 const KitContext* ctx; 20 KitTarget* resolved_target; 21 ObjBuilder* ob; 22 ObjFmt fmt; 23 KitTargetSpec target; 24 const u8** sec_data_cache; 25 u32* sec_data_size; 26 u32 sec_data_n; 27 }; 28 29 KitStatus kit_obj_open(const KitContext* ctx, KitSlice name, 30 const KitSlice* input, KitObjFile** out) { 31 Heap* h; 32 KitObjFile* f; 33 const ObjFormatImpl* impl; 34 KitTargetSpec target; 35 KitStatus st; 36 37 if (!out) return KIT_INVALID; 38 *out = NULL; 39 if (!ctx || !ctx->heap || !input) return KIT_INVALID; 40 if (!input->data && input->len > 0) return KIT_INVALID; 41 42 st = kit_detect_target(input->data, input->len, &target); 43 if (st != KIT_OK) return st; 44 impl = obj_format_lookup(target.obj); 45 if (!impl || !impl->read) return KIT_UNSUPPORTED; 46 47 h = ctx->heap; 48 f = (KitObjFile*)h->alloc(h, sizeof(*f), _Alignof(KitObjFile)); 49 if (!f) return KIT_NOMEM; 50 memset(f, 0, sizeof(*f)); 51 f->ctx = ctx; 52 f->fmt = target.obj; 53 f->target = target; 54 55 { 56 KitTargetOptions topts; 57 memset(&topts, 0, sizeof topts); 58 topts.spec = target; 59 st = kit_target_new(ctx, &topts, &f->resolved_target); 60 if (st != KIT_OK) { 61 h->free(h, f, sizeof(*f)); 62 return st; 63 } 64 } 65 st = compiler_init(&f->compiler, f->resolved_target, ctx); 66 if (st != KIT_OK) { 67 kit_target_free(f->resolved_target); 68 h->free(h, f, sizeof(*f)); 69 return st; 70 } 71 { 72 PanicFrame panic; 73 compiler_panic_push(&f->compiler, &panic); 74 if (setjmp(panic.env)) { 75 compiler_run_cleanups(&f->compiler); 76 compiler_panic_pop(&f->compiler, &panic); 77 compiler_fini(&f->compiler); 78 kit_target_free(f->resolved_target); 79 h->free(h, f, sizeof(*f)); 80 return KIT_MALFORMED; 81 } 82 f->ob = impl->read(&f->compiler, name.s, input->data, input->len); 83 compiler_panic_pop(&f->compiler, &panic); 84 } 85 if (!f->ob) { 86 compiler_fini(&f->compiler); 87 kit_target_free(f->resolved_target); 88 h->free(h, f, sizeof(*f)); 89 return KIT_MALFORMED; 90 } 91 *out = f; 92 return KIT_OK; 93 } 94 95 void kit_obj_free(KitObjFile* f) { 96 Heap* h; 97 if (!f) return; 98 h = f->ctx->heap; 99 if (f->sec_data_cache) { 100 u32 i; 101 for (i = 0; i < f->sec_data_n; ++i) { 102 if (f->sec_data_cache[i]) { 103 h->free(h, (void*)f->sec_data_cache[i], f->sec_data_size[i]); 104 } 105 } 106 h->free(h, f->sec_data_cache, sizeof(*f->sec_data_cache) * f->sec_data_n); 107 h->free(h, f->sec_data_size, sizeof(*f->sec_data_size) * f->sec_data_n); 108 } 109 if (f->ob) obj_free(f->ob); 110 compiler_fini(&f->compiler); 111 kit_target_free(f->resolved_target); 112 h->free(h, f, sizeof(*f)); 113 } 114 115 KitObjFmt kit_obj_fmt(const KitObjFile* f) { return f->fmt; } 116 117 /* Public object-format name <-> KitObjFmt mapping (objcopy/objdump bfdname 118 * spellings). Thin wrappers over the internal obj_format name registry. */ 119 KitStatus kit_obj_fmt_from_name(const char* name, KitObjFmt* out) { 120 return obj_format_fmt_from_name(name, out) ? KIT_OK : KIT_NOT_FOUND; 121 } 122 123 const char* kit_obj_fmt_name(KitObjFmt fmt) { return obj_format_fmt_name(fmt); } 124 125 KitTargetSpec kit_obj_target(const KitObjFile* f) { return f->target; } 126 127 uint32_t kit_obj_nsections(const KitObjFile* f) { 128 return obj_section_count(f->ob); 129 } 130 131 KitStatus kit_obj_section(const KitObjFile* f, KitObjSection idx, 132 KitObjSecInfo* out) { 133 const Section* sec; 134 if (!f || !out) return KIT_INVALID; 135 if (idx >= obj_section_count(f->ob)) return KIT_NOT_FOUND; 136 sec = obj_section_get(f->ob, (ObjSecId)(idx + 1)); 137 if (!sec) return KIT_NOT_FOUND; 138 out->name = 139 sec->name ? pool_slice(f->compiler.global, sec->name) : SLICE_LIT(""); 140 out->kind = (KitSecKind)sec->kind; 141 out->flags = (uint32_t)sec->flags; 142 out->size = sec->bss_size ? sec->bss_size : sec->bytes.total; 143 out->addr = sec->addr; 144 out->align = sec->align > 1u ? sec->align : 1u; 145 out->entsize = sec->entsize; 146 return KIT_OK; 147 } 148 149 KitStatus kit_obj_section_data(const KitObjFile* cf, KitObjSection idx, 150 const uint8_t** data_out, size_t* len_out) { 151 KitObjFile* f = (KitObjFile*)cf; 152 const Section* sec; 153 Heap* h; 154 u32 n; 155 u8* buf; 156 157 if (!f || !data_out || !len_out) return KIT_INVALID; 158 *data_out = NULL; 159 *len_out = 0; 160 161 n = obj_section_count(f->ob); 162 if (idx >= n) return KIT_NOT_FOUND; 163 164 sec = obj_section_get(f->ob, (ObjSecId)(idx + 1)); 165 if (!sec) return KIT_NOT_FOUND; 166 if (sec->bss_size || sec->bytes.total == 0) return KIT_OK; 167 168 h = f->ctx->heap; 169 170 if (!f->sec_data_cache) { 171 f->sec_data_cache = (const u8**)h->alloc(h, sizeof(*f->sec_data_cache) * n, 172 _Alignof(const u8*)); 173 if (!f->sec_data_cache) return KIT_NOMEM; 174 f->sec_data_size = 175 (u32*)h->alloc(h, sizeof(*f->sec_data_size) * n, _Alignof(u32)); 176 if (!f->sec_data_size) { 177 h->free(h, f->sec_data_cache, sizeof(*f->sec_data_cache) * n); 178 f->sec_data_cache = NULL; 179 return KIT_NOMEM; 180 } 181 { 182 u32 i; 183 for (i = 0; i < n; ++i) { 184 f->sec_data_cache[i] = NULL; 185 f->sec_data_size[i] = 0; 186 } 187 } 188 f->sec_data_n = n; 189 } 190 191 if (f->sec_data_cache[idx]) { 192 *data_out = f->sec_data_cache[idx]; 193 *len_out = f->sec_data_size[idx]; 194 return KIT_OK; 195 } 196 197 buf = (u8*)h->alloc(h, sec->bytes.total, 1); 198 if (!buf) return KIT_NOMEM; 199 buf_flatten(&sec->bytes, buf); 200 f->sec_data_cache[idx] = buf; 201 f->sec_data_size[idx] = sec->bytes.total; 202 *data_out = buf; 203 *len_out = sec->bytes.total; 204 return KIT_OK; 205 } 206 207 KitStatus kit_obj_section_format_flags(const KitObjFile* f, KitObjSection idx, 208 uint32_t* raw_type_out, 209 uint32_t* raw_flags_out) { 210 const Section* sec; 211 if (!f) return KIT_INVALID; 212 if (idx >= obj_section_count(f->ob)) return KIT_NOT_FOUND; 213 sec = obj_section_get(f->ob, (ObjSecId)(idx + 1)); 214 if (!sec) return KIT_NOT_FOUND; 215 if (raw_type_out) *raw_type_out = sec->ext_type; 216 if (raw_flags_out) *raw_flags_out = sec->ext_flags; 217 return KIT_OK; 218 } 219 220 KitStatus kit_obj_section_by_name(const KitObjFile* f, KitSlice name, 221 KitObjSection* out) { 222 u32 n, i; 223 if (!f || !out) return KIT_INVALID; 224 n = obj_section_count(f->ob); 225 for (i = 0; i < n; ++i) { 226 const Section* sec = obj_section_get(f->ob, (ObjSecId)(i + 1)); 227 if (!sec || !sec->name) continue; 228 if (slice_eq(pool_slice(f->compiler.global, sec->name), name)) { 229 *out = i; 230 return KIT_OK; 231 } 232 } 233 return KIT_NOT_FOUND; 234 } 235 236 static void fill_syminfo(const KitObjFile* f, ObjSymId id, const ObjSym* sym, 237 KitObjSymInfo* out) { 238 out->name = 239 sym->name ? pool_slice(f->compiler.global, sym->name) : SLICE_LIT(""); 240 out->id = (id != OBJ_SYM_NONE) ? (KitObjSymbol)id : KIT_OBJ_SYMBOL_NONE; 241 out->bind = (KitSymBind)sym->bind; 242 out->kind = (KitSymKind)sym->kind; 243 out->section = sym->section_id != OBJ_SEC_NONE 244 ? (KitObjSection)(sym->section_id - 1) 245 : KIT_SECTION_NONE; 246 out->value = sym->value; 247 out->size = sym->size; 248 } 249 250 KitStatus kit_obj_symbol_by_name(const KitObjFile* f, KitSlice name, 251 KitObjSymInfo* out) { 252 ObjSymIter* it; 253 ObjSymEntry e; 254 if (!f || !out) return KIT_INVALID; 255 it = obj_symiter_new(f->ob); 256 if (!it) return KIT_NOMEM; 257 while (obj_symiter_next(it, &e)) { 258 if (!e.sym || !e.sym->name) continue; 259 if (slice_eq(pool_slice(f->compiler.global, e.sym->name), name)) { 260 fill_syminfo(f, e.id, e.sym, out); 261 obj_symiter_free(it); 262 return KIT_OK; 263 } 264 } 265 obj_symiter_free(it); 266 return KIT_NOT_FOUND; 267 } 268 269 struct KitObjSymIter { 270 KitObjFile* file; 271 ObjSymIter* inner; /* .symtab walk; NULL when iterating the dynamic table */ 272 u32 dyn_idx; /* next index into obj_image dynsyms (dynamic mode) */ 273 int dynamic; 274 }; 275 276 /* Shared by kit_obj_symiter_new (.symtab) and kit_obj_dynsymiter_new 277 * (.dynsym). When dynamic, the inner ObjSymIter is unused and we walk the 278 * image's dynamic symbol table by index. */ 279 static KitStatus symiter_make(KitObjFile* f, int dynamic, KitObjSymIter** out) { 280 Heap* h; 281 KitObjSymIter* it; 282 if (!f || !out) return KIT_INVALID; 283 h = f->ctx->heap; 284 it = (KitObjSymIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjSymIter)); 285 if (!it) return KIT_NOMEM; 286 it->file = f; 287 it->inner = NULL; 288 it->dyn_idx = 0; 289 it->dynamic = dynamic; 290 if (!dynamic) { 291 it->inner = obj_symiter_new(f->ob); 292 if (!it->inner) { 293 h->free(h, it, sizeof(*it)); 294 return KIT_NOMEM; 295 } 296 } 297 *out = it; 298 return KIT_OK; 299 } 300 301 KitStatus kit_obj_symiter_new(KitObjFile* f, KitObjSymIter** out) { 302 return symiter_make(f, 0, out); 303 } 304 305 KitStatus kit_obj_dynsymiter_new(KitObjFile* f, KitObjSymIter** out) { 306 return symiter_make(f, 1, out); 307 } 308 309 KitIterResult kit_obj_symiter_next(KitObjSymIter* it, KitObjSymInfo* out) { 310 ObjSymEntry entry; 311 if (!it || !out) return KIT_ITER_ERROR; 312 if (it->dynamic) { 313 const ObjImage* im = obj_image(it->file->ob); 314 const ObjImageSym* s; 315 if (it->dyn_idx >= obj_image_ndynsyms(im)) return KIT_ITER_END; 316 s = obj_image_dynsym(im, it->dyn_idx++); 317 out->name = pool_slice(it->file->compiler.global, s->name); 318 out->id = KIT_OBJ_SYMBOL_NONE; 319 out->bind = (KitSymBind)s->bind; 320 out->kind = (KitSymKind)s->kind; 321 out->section = s->section != OBJ_SEC_NONE ? (KitObjSection)(s->section - 1) 322 : KIT_SECTION_NONE; 323 out->value = s->value; 324 out->size = s->size; 325 return KIT_ITER_ITEM; 326 } 327 if (!obj_symiter_next(it->inner, &entry)) return KIT_ITER_END; 328 fill_syminfo(it->file, entry.id, entry.sym, out); 329 return KIT_ITER_ITEM; 330 } 331 332 void kit_obj_symiter_free(KitObjSymIter* it) { 333 Heap* h; 334 if (!it) return; 335 if (it->inner) obj_symiter_free(it->inner); 336 h = it->file->ctx->heap; 337 h->free(h, it, sizeof(*it)); 338 } 339 340 struct KitObjRelocIter { 341 KitObjFile* file; 342 u32 idx; 343 u32 total; 344 int dynamic; /* iterate obj_image dynamic relocs instead of section relocs */ 345 }; 346 347 static KitStatus reliter_make(KitObjFile* f, int dynamic, 348 KitObjRelocIter** out) { 349 Heap* h; 350 KitObjRelocIter* it; 351 if (!f || !out) return KIT_INVALID; 352 h = f->ctx->heap; 353 it = (KitObjRelocIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjRelocIter)); 354 if (!it) return KIT_NOMEM; 355 it->file = f; 356 it->idx = 0; 357 it->dynamic = dynamic; 358 it->total = 359 dynamic ? obj_image_ndynrelocs(obj_image(f->ob)) : obj_reloc_total(f->ob); 360 *out = it; 361 return KIT_OK; 362 } 363 364 KitStatus kit_obj_reliter_new(KitObjFile* f, KitObjRelocIter** out) { 365 return reliter_make(f, 0, out); 366 } 367 368 KitStatus kit_obj_dynreliter_new(KitObjFile* f, KitObjRelocIter** out) { 369 return reliter_make(f, 1, out); 370 } 371 372 /* Format-specific canonical spelling of a reloc kind (e.g. "R_X86_64_PLT32", 373 * "R_AARCH64_CALL26", "R_RISCV_CALL"), or NULL when the format has no per-arch 374 * name table (callers fall back to the arch-neutral reloc_kind_name). 375 * 376 * Consulted for every ELF arch whose ObjElfArchOps carries a reloc_name table 377 * (x86_64 / aarch64 / riscv): the kit-canonical RelocKind is lowered to its 378 * ELF wire type via reloc_to, then named — matching binutils objdump's 379 * spelling. The Mach-O / COFF formats have no reloc_name table yet and keep 380 * the arch-neutral spelling. reloc_to maps unsupported kinds to wire type 0; 381 * only R_NONE legitimately names that slot, so anything else falling through 382 * to 0 is reported as "no per-arch name" (NULL) rather than the format's NONE 383 * spelling. */ 384 static const char* kit_obj_reloc_kind_name(KitArchKind arch, KitObjFmt fmt, 385 u32 kind) { 386 const ObjFormatImpl* impl; 387 const ObjElfArchOps* ops; 388 u32 wire; 389 if (fmt != KIT_OBJ_ELF) return NULL; 390 impl = obj_format_lookup(fmt); 391 if (!impl || !impl->elf_arch) return NULL; 392 ops = impl->elf_arch(arch); 393 if (!ops || !ops->reloc_to || !ops->reloc_name) return NULL; 394 wire = ops->reloc_to(kind); 395 if (wire == 0u && (RelocKind)kind != R_NONE) return NULL; 396 return ops->reloc_name(wire); 397 } 398 399 KitIterResult kit_obj_reliter_next(KitObjRelocIter* it, KitObjReloc* out) { 400 const Reloc* r; 401 const ObjSym* sym; 402 if (!it || !out) return KIT_ITER_ERROR; 403 if (it->idx >= it->total) return KIT_ITER_END; 404 405 if (it->dynamic) { 406 const ObjImageReloc* dr = 407 obj_image_dynreloc(obj_image(it->file->ob), it->idx++); 408 const char* kn; 409 out->section = 410 dr->section ? (KitObjSection)(dr->section - 1) : KIT_SECTION_NONE; 411 out->offset = dr->offset; 412 out->addend = dr->addend; 413 out->kind.arch = it->file->target.arch; 414 out->kind.obj_fmt = it->file->fmt; 415 out->kind.code = (uint32_t)dr->kind; 416 kn = 417 kit_obj_reloc_kind_name(it->file->target.arch, it->file->fmt, dr->kind); 418 if (!kn) kn = reloc_kind_name(dr->kind); 419 out->kind_name = kn ? slice_from_cstr(kn) : SLICE_NULL; 420 out->sym = KIT_OBJ_SYMBOL_NONE; 421 out->sym_name = pool_slice(it->file->compiler.global, dr->sym_name); 422 return KIT_ITER_ITEM; 423 } 424 425 r = obj_reloc_at(it->file->ob, it->idx++); 426 out->section = 427 r->section_id ? (KitObjSection)(r->section_id - 1) : KIT_SECTION_NONE; 428 out->offset = r->offset; 429 out->addend = r->addend; 430 out->kind.arch = it->file->target.arch; 431 out->kind.obj_fmt = it->file->fmt; 432 out->kind.code = (uint32_t)r->kind; 433 { 434 /* Prefer the format-specific canonical spelling (e.g. "R_X86_64_PLT32"); 435 * fall back to the arch-neutral diagnostic spelling ("RV_CALL"). */ 436 const char* kn = 437 kit_obj_reloc_kind_name(it->file->target.arch, it->file->fmt, r->kind); 438 if (!kn) kn = reloc_kind_name(r->kind); 439 out->kind_name = kn ? slice_from_cstr(kn) : SLICE_NULL; 440 } 441 442 if (r->sym == OBJ_SYM_NONE) { 443 out->sym = KIT_OBJ_SYMBOL_NONE; 444 out->sym_name = SLICE_LIT(""); 445 } else { 446 out->sym = (KitObjSymbol)r->sym; 447 sym = obj_symbol_get(it->file->ob, r->sym); 448 out->sym_name = (sym && sym->name) 449 ? pool_slice(it->file->compiler.global, sym->name) 450 : SLICE_LIT(""); 451 } 452 return KIT_ITER_ITEM; 453 } 454 455 void kit_obj_reliter_free(KitObjRelocIter* it) { 456 Heap* h; 457 if (!it) return; 458 h = it->file->ctx->heap; 459 h->free(h, it, sizeof(*it)); 460 } 461 462 struct KitObjGroupIter { 463 KitObjFile* file; 464 ObjGroupIter* inner; 465 /* Translation scratch for the borrowed `sections` slice handed back to 466 * the caller. Lazily grown to the largest group's nsections. */ 467 KitObjSection* secbuf; 468 u32 seccap; 469 }; 470 471 KitStatus kit_obj_groupiter_new(KitObjFile* f, KitObjGroupIter** out) { 472 Heap* h; 473 KitObjGroupIter* it; 474 if (!f || !out) return KIT_INVALID; 475 h = f->ctx->heap; 476 it = (KitObjGroupIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjGroupIter)); 477 if (!it) return KIT_NOMEM; 478 memset(it, 0, sizeof(*it)); 479 it->file = f; 480 it->inner = obj_groupiter_new(f->ob); 481 if (!it->inner) { 482 h->free(h, it, sizeof(*it)); 483 return KIT_NOMEM; 484 } 485 *out = it; 486 return KIT_OK; 487 } 488 489 KitIterResult kit_obj_groupiter_next(KitObjGroupIter* it, 490 KitObjGroupInfo* out) { 491 ObjGroupEntry entry; 492 Heap* h; 493 u32 i; 494 if (!it || !out) return KIT_ITER_ERROR; 495 if (!obj_groupiter_next(it->inner, &entry)) return KIT_ITER_END; 496 h = it->file->ctx->heap; 497 if (entry.group->nsections > it->seccap) { 498 KitObjSection* nb; 499 nb = (KitObjSection*)h->alloc(h, sizeof(*nb) * entry.group->nsections, 500 _Alignof(KitObjSection)); 501 if (!nb) return KIT_ITER_ERROR; 502 if (it->secbuf) h->free(h, it->secbuf, sizeof(*it->secbuf) * it->seccap); 503 it->secbuf = nb; 504 it->seccap = entry.group->nsections; 505 } 506 for (i = 0; i < entry.group->nsections; ++i) { 507 ObjSecId sid = entry.group->sections[i]; 508 it->secbuf[i] = 509 (sid != OBJ_SEC_NONE) ? (KitObjSection)(sid - 1) : KIT_SECTION_NONE; 510 } 511 out->name = entry.group->name 512 ? pool_slice(it->file->compiler.global, entry.group->name) 513 : KIT_SLICE_NULL; 514 out->signature = (entry.group->signature != OBJ_SYM_NONE) 515 ? (KitObjSymbol)entry.group->signature 516 : KIT_OBJ_SYMBOL_NONE; 517 out->flags = entry.group->flags; 518 out->nsections = entry.group->nsections; 519 out->sections = it->secbuf; 520 return KIT_ITER_ITEM; 521 } 522 523 void kit_obj_groupiter_free(KitObjGroupIter* it) { 524 Heap* h; 525 if (!it) return; 526 h = it->file->ctx->heap; 527 if (it->secbuf) h->free(h, it->secbuf, sizeof(*it->secbuf) * it->seccap); 528 obj_groupiter_free(it->inner); 529 h->free(h, it, sizeof(*it)); 530 } 531 532 /* Accessor for disasm/jit to access the underlying ObjBuilder when both 533 * are inside libkit. Internal name kept stable for existing callers 534 * (src/link/link_jit.c, src/api/disasm.c). */ 535 ObjBuilder* kit_objfile_builder(const KitObjFile* f) { 536 return f ? f->ob : NULL; 537 } 538 539 /* Public alias of kit_objfile_builder. Promoted to the public API so the 540 * driver (and other libkit consumers) can take an opened object and feed 541 * it into kit_obj_builder_emit for a byte-equivalent roundtrip without 542 * re-implementing the read-then-replay loop. */ 543 KitObjBuilder* kit_obj_file_builder(const KitObjFile* f) { 544 return kit_objfile_builder(f); 545 } 546 547 /* Allocate an empty KitObjFile wrapping a private Compiler and a fresh 548 * ObjBuilder. Used by the JIT debug-view builder (src/link/link_jit.c) 549 * to assemble a synthetic object file from merged input debug sections. 550 * The handle is freed via kit_objfile_internal_free below — the public 551 * kit_obj_free path is keyed off obj_read_bytes, so the view path uses 552 * its own teardown that does not depend on the cached section data 553 * tables. */ 554 KitObjFile* kit_objfile_internal_new(const KitContext* ctx, 555 KitTargetSpec target, KitObjFmt fmt) { 556 Heap* h; 557 KitObjFile* f; 558 if (!ctx || !ctx->heap) return NULL; 559 h = ctx->heap; 560 f = (KitObjFile*)h->alloc(h, sizeof(*f), _Alignof(KitObjFile)); 561 if (!f) return NULL; 562 memset(f, 0, sizeof(*f)); 563 f->ctx = ctx; 564 f->fmt = fmt; 565 f->target = target; 566 { 567 KitTargetOptions topts; 568 KitStatus st; 569 memset(&topts, 0, sizeof topts); 570 topts.spec = target; 571 st = kit_target_new(ctx, &topts, &f->resolved_target); 572 if (st != KIT_OK) { 573 h->free(h, f, sizeof(*f)); 574 return NULL; 575 } 576 st = compiler_init(&f->compiler, f->resolved_target, ctx); 577 if (st != KIT_OK) { 578 kit_target_free(f->resolved_target); 579 h->free(h, f, sizeof(*f)); 580 return NULL; 581 } 582 } 583 { 584 PanicFrame panic; 585 compiler_panic_push(&f->compiler, &panic); 586 if (setjmp(panic.env)) { 587 compiler_run_cleanups(&f->compiler); 588 compiler_panic_pop(&f->compiler, &panic); 589 compiler_fini(&f->compiler); 590 kit_target_free(f->resolved_target); 591 h->free(h, f, sizeof(*f)); 592 return NULL; 593 } 594 f->ob = obj_new(&f->compiler); 595 compiler_panic_pop(&f->compiler, &panic); 596 } 597 if (!f->ob) { 598 compiler_fini(&f->compiler); 599 kit_target_free(f->resolved_target); 600 h->free(h, f, sizeof(*f)); 601 return NULL; 602 } 603 return f; 604 } 605 606 void kit_objfile_internal_free(KitObjFile* f) { 607 /* Same teardown contract as kit_obj_free: caller may have cached 608 * section data, so we route through the same path. */ 609 kit_obj_free(f); 610 } 611 612 /* ============================================================ 613 * Linked-image view 614 * ============================================================ */ 615 616 KitObjKind kit_obj_kind(const KitObjFile* f) { 617 const ObjImage* im; 618 if (!f) return KIT_OBJ_KIND_REL; 619 im = obj_image(f->ob); 620 if (!im) return KIT_OBJ_KIND_REL; 621 switch (obj_image_kind(im)) { 622 case OBJ_KIND_EXEC: 623 return KIT_OBJ_KIND_EXEC; 624 case OBJ_KIND_DYN: 625 return KIT_OBJ_KIND_DYN; 626 case OBJ_KIND_CORE: 627 return KIT_OBJ_KIND_CORE; 628 case OBJ_KIND_REL: 629 default: 630 return KIT_OBJ_KIND_REL; 631 } 632 } 633 634 KitStatus kit_obj_image_info(const KitObjFile* f, KitObjImageInfo* out) { 635 const ObjImage* im; 636 if (!f || !out) return KIT_INVALID; 637 im = obj_image(f->ob); 638 if (!im) return KIT_NOT_FOUND; 639 out->entry = obj_image_entry(im); 640 out->image_base = obj_image_base(im); 641 out->interp = pool_slice(f->compiler.global, obj_image_interp(im)); 642 out->soname = pool_slice(f->compiler.global, obj_image_soname(im)); 643 return KIT_OK; 644 } 645 646 struct KitObjSegIter { 647 KitObjFile* file; 648 u32 idx; 649 }; 650 651 KitStatus kit_obj_segiter_new(KitObjFile* f, KitObjSegIter** out) { 652 Heap* h; 653 KitObjSegIter* it; 654 if (!f || !out) return KIT_INVALID; 655 h = f->ctx->heap; 656 it = (KitObjSegIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjSegIter)); 657 if (!it) return KIT_NOMEM; 658 it->file = f; 659 it->idx = 0; 660 *out = it; 661 return KIT_OK; 662 } 663 664 KitIterResult kit_obj_segiter_next(KitObjSegIter* it, KitObjSegInfo* out) { 665 const ObjImage* im; 666 const ObjSegment* s; 667 if (!it || !out) return KIT_ITER_ERROR; 668 im = obj_image(it->file->ob); 669 if (it->idx >= obj_image_nsegments(im)) return KIT_ITER_END; 670 s = obj_image_segment(im, it->idx++); 671 out->name = pool_slice(it->file->compiler.global, s->name); 672 out->vaddr = s->vaddr; 673 out->vsize = s->vsize; 674 out->file_off = s->file_off; 675 out->file_size = s->file_size; 676 out->perms = s->perms; /* OBJ_SEG_* and KIT_SEG_* share bit values */ 677 out->align = s->align; 678 return KIT_ITER_ITEM; 679 } 680 681 void kit_obj_segiter_free(KitObjSegIter* it) { 682 Heap* h; 683 if (!it) return; 684 h = it->file->ctx->heap; 685 h->free(h, it, sizeof(*it)); 686 } 687 688 struct KitObjDepIter { 689 KitObjFile* file; 690 u32 idx; 691 KitSlice* import_buf; /* scratch for the current dep's import names */ 692 u32 import_cap; 693 }; 694 695 KitStatus kit_obj_depiter_new(KitObjFile* f, KitObjDepIter** out) { 696 Heap* h; 697 KitObjDepIter* it; 698 if (!f || !out) return KIT_INVALID; 699 h = f->ctx->heap; 700 it = (KitObjDepIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjDepIter)); 701 if (!it) return KIT_NOMEM; 702 it->file = f; 703 it->idx = 0; 704 it->import_buf = NULL; 705 it->import_cap = 0; 706 *out = it; 707 return KIT_OK; 708 } 709 710 KitIterResult kit_obj_depiter_next(KitObjDepIter* it, KitObjDepInfo* out) { 711 const ObjImage* im; 712 const ObjImageDep* d; 713 Heap* h; 714 u32 i; 715 if (!it || !out) return KIT_ITER_ERROR; 716 im = obj_image(it->file->ob); 717 if (it->idx >= obj_image_ndeps(im)) return KIT_ITER_END; 718 d = obj_image_dep(im, it->idx++); 719 out->name = pool_slice(it->file->compiler.global, d->name); 720 out->imports = NULL; 721 out->nimports = d->nimports; 722 if (d->nimports) { 723 h = it->file->ctx->heap; 724 if (it->import_cap < d->nimports) { 725 if (VEC_GROW(h, it->import_buf, it->import_cap, d->nimports)) 726 return KIT_ITER_ERROR; 727 } 728 for (i = 0; i < d->nimports; ++i) 729 it->import_buf[i] = pool_slice(it->file->compiler.global, d->imports[i]); 730 out->imports = it->import_buf; 731 } 732 return KIT_ITER_ITEM; 733 } 734 735 void kit_obj_depiter_free(KitObjDepIter* it) { 736 Heap* h; 737 if (!it) return; 738 h = it->file->ctx->heap; 739 if (it->import_buf) 740 h->free(h, it->import_buf, sizeof(*it->import_buf) * it->import_cap); 741 h->free(h, it, sizeof(*it)); 742 } 743 744 struct KitObjRpathIter { 745 KitObjFile* file; 746 u32 idx; 747 }; 748 749 KitStatus kit_obj_rpathiter_new(KitObjFile* f, KitObjRpathIter** out) { 750 Heap* h; 751 KitObjRpathIter* it; 752 if (!f || !out) return KIT_INVALID; 753 h = f->ctx->heap; 754 it = (KitObjRpathIter*)h->alloc(h, sizeof(*it), _Alignof(KitObjRpathIter)); 755 if (!it) return KIT_NOMEM; 756 it->file = f; 757 it->idx = 0; 758 *out = it; 759 return KIT_OK; 760 } 761 762 KitIterResult kit_obj_rpathiter_next(KitObjRpathIter* it, KitSlice* out) { 763 const ObjImage* im; 764 if (!it || !out) return KIT_ITER_ERROR; 765 im = obj_image(it->file->ob); 766 if (it->idx >= obj_image_nrpaths(im)) return KIT_ITER_END; 767 *out = pool_slice(it->file->compiler.global, obj_image_rpath(im, it->idx++)); 768 return KIT_ITER_ITEM; 769 } 770 771 void kit_obj_rpathiter_free(KitObjRpathIter* it) { 772 Heap* h; 773 if (!it) return; 774 h = it->file->ctx->heap; 775 h->free(h, it, sizeof(*it)); 776 } 777 778 struct KitObjImageRawIter { 779 KitObjFile* file; 780 u32 idx; 781 }; 782 783 KitStatus kit_obj_image_rawiter_new(KitObjFile* f, KitObjImageRawIter** out) { 784 Heap* h; 785 KitObjImageRawIter* it; 786 if (!f || !out) return KIT_INVALID; 787 if (!obj_image(f->ob)) return KIT_NOT_FOUND; /* relocatable: no image */ 788 h = f->ctx->heap; 789 it = (KitObjImageRawIter*)h->alloc(h, sizeof(*it), 790 _Alignof(KitObjImageRawIter)); 791 if (!it) return KIT_NOMEM; 792 it->file = f; 793 it->idx = 0; 794 *out = it; 795 return KIT_OK; 796 } 797 798 KitIterResult kit_obj_image_rawiter_next(KitObjImageRawIter* it, 799 KitObjImageRaw* out) { 800 const ObjImage* im; 801 const ObjImageRaw* r; 802 if (!it || !out) return KIT_ITER_ERROR; 803 im = obj_image(it->file->ob); 804 if (it->idx >= obj_image_nraws(im)) return KIT_ITER_END; 805 r = obj_image_raw(im, it->idx++); 806 out->tag = r->tag; 807 out->value = r->value; 808 out->extra = r->extra; 809 return KIT_ITER_ITEM; 810 } 811 812 void kit_obj_image_rawiter_free(KitObjImageRawIter* it) { 813 Heap* h; 814 if (!it) return; 815 h = it->file->ctx->heap; 816 h->free(h, it, sizeof(*it)); 817 }