link.c (77219B)
1 /* link_emit_elf: write a static ET_EXEC ELF64 image to the 2 * caller-provided Writer. 3 * 4 * 64-bit little-endian only. The per-arch ELF reloc-type tables in 5 * obj/elf_reloc_<arch>.c handle RelocKind <-> ELF translation; this 6 * file gets e_machine from the link arch descriptor. 7 * 8 * File layout (in write order): 9 * 10 * [headers PT_LOAD, PF_R, mapped at IMAGE_BASE] 11 * Ehdr64 12 * Phdr64[nphdr] -- one per loaded segment + headers + 13 * PT_NOTE .note.gnu.build-id -- 12 + 16 = 28 bytes 14 * (deterministic 16-byte id) pad to PAGE 15 * 16 * [PT_LOAD per kept image segment, in img->segments order] 17 * segment bytes (padded to its file_offset) 18 * 19 * [non-allocatable sections, file-only] 20 * .symtab -- ELF64_SYM_SIZE * nsyms 21 * .strtab -- NUL-led blob 22 * .shstrtab -- NUL-led blob 23 * 24 * [section header table at e_shoff] 25 * Shdr64[nshdr] 26 * 27 * Section header schema (for nm / objdump -t / gdb consumption): 28 * 29 * 0 SHN_UNDEF (zero entry) 30 * N one shdr per loaded sub-region: .text/.rodata/.data/.bss as 31 * the corresponding RX/R/RW segments materialize (.bss split 32 * out as the trailing memsz>filesz tail of the RW segment). 33 * 1 .note.gnu.build-id (allocatable, in headers PT_LOAD) 34 * 1 .symtab (sh_link -> .strtab; sh_info = first non-local idx) 35 * 1 .strtab 36 * 1 .shstrtab (Ehdr64.e_shstrndx) 37 * 38 * Build-id is computed deterministically over the post-relocation 39 * segment bytes (FNV-1a 64 over each segment, mixed into a 128-bit 40 * accumulator). The 16-byte digest is written into the note before the 41 * note is emitted to the Writer. 42 * 43 * The image image-relative addresses on entry are bumped by 44 * align_up(headers_size, PAGE) before relocs are applied, exactly as 45 * before — segment bytes / symbol vaddrs land at their final IMAGE_BASE 46 * absolute addresses by the time relocs run. */ 47 48 #include "link/link.h" 49 50 #include <string.h> 51 52 #include "core/heap.h" 53 #include "core/pool.h" 54 #include "core/slice.h" 55 #include "core/util.h" 56 #include "core/vec.h" 57 #include "link/link_arch.h" 58 #include "link/link_internal.h" 59 #include "obj/bytebuf.h" 60 #include "obj/elf/elf.h" 61 #include "obj/elf/link_dyn.h" 62 #include "obj/format.h" 63 64 /* ---- ELF64 wire structs (subset) ---- */ 65 66 #define EI_NIDENT 16 67 68 typedef struct __attribute__((packed)) Ehdr64 { 69 u8 e_ident[EI_NIDENT]; 70 u16 e_type; 71 u16 e_machine; 72 u32 e_version; 73 u64 e_entry; 74 u64 e_phoff; 75 u64 e_shoff; 76 u32 e_flags; 77 u16 e_ehsize; 78 u16 e_phentsize; 79 u16 e_phnum; 80 u16 e_shentsize; 81 u16 e_shnum; 82 u16 e_shstrndx; 83 } Ehdr64; 84 85 typedef struct __attribute__((packed)) Phdr64 { 86 u32 p_type; 87 u32 p_flags; 88 u64 p_offset; 89 u64 p_vaddr; 90 u64 p_paddr; 91 u64 p_filesz; 92 u64 p_memsz; 93 u64 p_align; 94 } Phdr64; 95 96 typedef struct __attribute__((packed)) Shdr64 { 97 u32 sh_name; 98 u32 sh_type; 99 u64 sh_flags; 100 u64 sh_addr; 101 u64 sh_offset; 102 u64 sh_size; 103 u32 sh_link; 104 u32 sh_info; 105 u64 sh_addralign; 106 u64 sh_entsize; 107 } Shdr64; 108 109 /* ---- ELF32 wire structs (RV32 static ET_EXEC) ---- 110 * 111 * Ehdr32/Shdr32 keep the ELF64 field ORDER, only narrowing the 112 * native-width members to u32. Phdr32 REORDERS p_flags to AFTER the 113 * sizes (vs Phdr64 where p_flags is field #2) — the packed struct below 114 * encodes that order, so the by-name field assignments in the phdr build 115 * loop stay correct under either class. */ 116 typedef struct __attribute__((packed)) Ehdr32 { 117 u8 e_ident[EI_NIDENT]; 118 u16 e_type; 119 u16 e_machine; 120 u32 e_version; 121 u32 e_entry; 122 u32 e_phoff; 123 u32 e_shoff; 124 u32 e_flags; 125 u16 e_ehsize; 126 u16 e_phentsize; 127 u16 e_phnum; 128 u16 e_shentsize; 129 u16 e_shnum; 130 u16 e_shstrndx; 131 } Ehdr32; 132 133 typedef struct __attribute__((packed)) Phdr32 { 134 u32 p_type; 135 u32 p_offset; 136 u32 p_vaddr; 137 u32 p_paddr; 138 u32 p_filesz; 139 u32 p_memsz; 140 u32 p_flags; 141 u32 p_align; 142 } Phdr32; 143 144 typedef struct __attribute__((packed)) Shdr32 { 145 u32 sh_name; 146 u32 sh_type; 147 u32 sh_flags; 148 u32 sh_addr; 149 u32 sh_offset; 150 u32 sh_size; 151 u32 sh_link; 152 u32 sh_info; 153 u32 sh_addralign; 154 u32 sh_entsize; 155 } Shdr32; 156 157 #define PT_NOTE 4 158 #define PT_TLS 7 159 160 /* Static ET_EXEC base. ET_DYN (PIE) uses 0 — the loader picks the 161 * runtime base. The active value lives in `img_base` below; the macro 162 * stays for the static path's hard-coded vaddrs. */ 163 #define IMAGE_BASE_STATIC 0x400000ULL 164 165 #define BUILD_ID_DESC_LEN 16u 166 #define NOTE_NAME_GNU "GNU" 167 #define NOTE_NAME_GNU_LEN 4u /* "GNU\0" */ 168 #define NOTE_BUILD_ID_TYPE 3u 169 #define BUILD_ID_NOTE_BYTES (12u + NOTE_NAME_GNU_LEN + BUILD_ID_DESC_LEN) 170 171 /* ---- byte writer helpers ---- */ 172 173 static void write_bytes(Writer* w, const void* data, size_t n) { 174 w->write(w, data, n); 175 } 176 177 static void write_zeroes(Writer* w, size_t n) { 178 static const u8 zeroes[256] = {0}; 179 while (n) { 180 size_t step = n > sizeof(zeroes) ? sizeof(zeroes) : n; 181 w->write(w, zeroes, step); 182 n -= step; 183 } 184 } 185 186 static u32 perms_to_pflags(u32 secflags) { 187 u32 f = PF_R; 188 if (secflags & SF_EXEC) f |= PF_X; 189 if (secflags & SF_WRITE) f |= PF_W; 190 return f; 191 } 192 193 static u32 dynstr_find_sym(Compiler* c, const LinkDynState* dyn, Sym name, 194 const char* tag) { 195 Slice nm_s = pool_slice(c->global, name); 196 const char* nm = nm_s.s; 197 size_t namelen = nm_s.len; 198 if (nm && namelen) { 199 u32 si; 200 for (si = 0; si + namelen < dyn->dynstr_len; ++si) { 201 if (dyn->dynstr[si + namelen] == 0 && 202 memcmp(dyn->dynstr + si, nm, namelen) == 0) 203 return si; 204 } 205 } 206 compiler_panic(c, SRCLOC_NONE, "link_emit_elf: %s missing from .dynstr", 207 tag ? tag : "dynamic string"); 208 return 0; 209 } 210 211 /* ---- class-aware header serializers ---- 212 * 213 * The writer builds every header in the wide Ehdr64/Phdr64/Shdr64 214 * in-memory form, then serializes to the on-disk class. On ELFCLASS64 215 * the bytes are the wide struct verbatim (preserving the existing 216 * byte-exact RV64/x86_64/aa64 output). On ELFCLASS32 the native-width 217 * fields narrow to u32 and Phdr fields reorder (p_flags after sizes). 218 * The serialized record sizes are the wire constants in elf.h. */ 219 static size_t elf_ehdr_sz(int class32) { 220 return class32 ? ELF32_EHDR_SIZE : sizeof(Ehdr64); 221 } 222 static size_t elf_phdr_sz(int class32) { 223 return class32 ? ELF32_PHDR_SIZE : sizeof(Phdr64); 224 } 225 static size_t elf_shdr_sz(int class32) { 226 return class32 ? ELF32_SHDR_SIZE : sizeof(Shdr64); 227 } 228 229 static void write_ehdr(Writer* w, const Ehdr64* e, int class32) { 230 if (!class32) { 231 write_bytes(w, e, sizeof(*e)); 232 return; 233 } 234 Ehdr32 e32; 235 memset(&e32, 0, sizeof e32); 236 memcpy(e32.e_ident, e->e_ident, EI_NIDENT); 237 e32.e_type = e->e_type; 238 e32.e_machine = e->e_machine; 239 e32.e_version = e->e_version; 240 e32.e_entry = (u32)e->e_entry; 241 e32.e_phoff = (u32)e->e_phoff; 242 e32.e_shoff = (u32)e->e_shoff; 243 e32.e_flags = e->e_flags; 244 e32.e_ehsize = e->e_ehsize; 245 e32.e_phentsize = e->e_phentsize; 246 e32.e_phnum = e->e_phnum; 247 e32.e_shentsize = e->e_shentsize; 248 e32.e_shnum = e->e_shnum; 249 e32.e_shstrndx = e->e_shstrndx; 250 write_bytes(w, &e32, sizeof e32); 251 } 252 253 static void write_phdrs(Writer* w, const Phdr64* phdrs, u32 n, int class32) { 254 if (!class32) { 255 write_bytes(w, phdrs, sizeof(Phdr64) * n); 256 return; 257 } 258 for (u32 i = 0; i < n; ++i) { 259 const Phdr64* p = &phdrs[i]; 260 Phdr32 p32; 261 p32.p_type = p->p_type; 262 p32.p_offset = (u32)p->p_offset; 263 p32.p_vaddr = (u32)p->p_vaddr; 264 p32.p_paddr = (u32)p->p_paddr; 265 p32.p_filesz = (u32)p->p_filesz; 266 p32.p_memsz = (u32)p->p_memsz; 267 p32.p_flags = p->p_flags; 268 p32.p_align = (u32)p->p_align; 269 write_bytes(w, &p32, sizeof p32); 270 } 271 } 272 273 static void write_shdr(Writer* w, const Shdr64* s, int class32) { 274 if (!class32) { 275 write_bytes(w, s, sizeof(*s)); 276 return; 277 } 278 Shdr32 s32; 279 s32.sh_name = s->sh_name; 280 s32.sh_type = s->sh_type; 281 s32.sh_flags = (u32)s->sh_flags; 282 s32.sh_addr = (u32)s->sh_addr; 283 s32.sh_offset = (u32)s->sh_offset; 284 s32.sh_size = (u32)s->sh_size; 285 s32.sh_link = s->sh_link; 286 s32.sh_info = s->sh_info; 287 s32.sh_addralign = (u32)s->sh_addralign; 288 s32.sh_entsize = (u32)s->sh_entsize; 289 write_bytes(w, &s32, sizeof s32); 290 } 291 292 /* Scripted-layout post-pass: vaddrs are already final (the script 293 * pinned them via `. = …`), so only file offsets need to bump to 294 * leave room for ehdr+phdrs. Mirror of shift_image_addresses but 295 * touches only the file dimension. */ 296 static void shift_image_file_offsets(LinkImage* img, u64 delta) { 297 u32 i; 298 for (i = 0; i < img->nsegments; ++i) img->segments[i].file_offset += delta; 299 for (i = 0; i < img->nsections; ++i) img->sections[i].file_offset += delta; 300 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) 301 LinkRelocs_at(&img->relocs, i)->write_file_offset += delta; 302 } 303 304 static void shift_image_addresses(LinkImage* img, u64 delta) { 305 u32 i; 306 for (i = 0; i < img->nsegments; ++i) { 307 img->segments[i].file_offset += delta; 308 img->segments[i].vaddr += delta; 309 img->segments[i].paddr += delta; 310 } 311 for (i = 0; i < img->nsections; ++i) { 312 /* File-only debug sections carry DWARF-section-relative bases, not 313 * load addresses — they live outside any PT_LOAD and must not shift 314 * with the loaded image. Their file_offset is assigned fresh by the 315 * trailing-offset pass below. */ 316 if (img->sections[i].file_only) continue; 317 img->sections[i].file_offset += delta; 318 img->sections[i].vaddr += delta; 319 } 320 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { 321 LinkRelocs_at(&img->relocs, i)->write_file_offset += delta; 322 LinkRelocs_at(&img->relocs, i)->write_vaddr += delta; 323 } 324 for (i = 0; i < LinkSyms_count(&img->syms); ++i) { 325 LinkSymbol* s = LinkSyms_at(&img->syms, i); 326 if (s->kind == SK_ABS) continue; 327 if (!s->defined) continue; 328 /* A symbol resolved into a file-only debug section (e.g. the local 329 * SK_SECTION symbol a DWARF R_ABS32 targets) holds a sec-relative 330 * offset, not a load address — leave it unshifted so the apply pass 331 * writes the right DWARF offset. */ 332 if (s->section_id != LINK_SEC_NONE && s->section_id <= img->nsections && 333 img->sections[s->section_id - 1].file_only) 334 continue; 335 s->vaddr += delta; 336 } 337 /* tls_vaddr lives in the same image-relative coordinate system as 338 * the segments it tracks, so it bumps with them. */ 339 if (img->tls_memsz) img->tls_vaddr += delta; 340 /* Dyn-link state mirrors a few segment / section vaddrs and pre- 341 * populated DynRela.r_offset values from layout_dyn. Bump them so 342 * the post-shift .rela.plt / .dynamic emit and apply_all_relocs see 343 * the right addresses (sym_plt_vaddr is read to redirect CALL26 344 * against imports). */ 345 if (img->dyn) { 346 LinkDynState* dyn = img->dyn; 347 if (dyn->plt_vaddr) dyn->plt_vaddr += delta; 348 if (dyn->got_plt_vaddr) dyn->got_plt_vaddr += delta; 349 if (dyn->dynamic_vaddr) dyn->dynamic_vaddr += delta; 350 if (dyn->sym_plt_vaddr) { 351 u32 j; 352 for (j = 0; j < dyn->sym_dynidx_size; ++j) 353 if (dyn->sym_plt_vaddr[j]) dyn->sym_plt_vaddr[j] += delta; 354 } 355 if (dyn->rela_plt) { 356 u32 j; 357 for (j = 0; j < dyn->nrela_plt; ++j) dyn->rela_plt[j].r_offset += delta; 358 } 359 /* rela_dyn is populated by apply_all_relocs (which runs after this 360 * shift), so its records are already in post-shift coordinates. */ 361 } 362 } 363 364 /* --section-start / -Tdata / -Tbss: force the FINAL runtime address of a named 365 * output section to exactly the requested value (GNU-ld semantics). Applied 366 * here, AFTER shift_image_addresses, so the requested address is compared 367 * against the section's final p_vaddr (img_base + post-shift vaddr); the delta 368 * absorbs both the headers load-page (headers_load) and the runtime image base 369 * (img_base) with no special-casing, including below-base requests. The 370 * matched section's whole segment is shifted uniformly so intra-segment offsets 371 * and symbol addresses stay consistent, mirroring shift_image_addresses. Must 372 * run before apply_all_relocs so reloc sites see the pinned addresses. Scripted 373 * images pin addresses via the script and carry no pins here. */ 374 static void apply_section_starts(LinkImage* img, u64 img_base) { 375 Linker* l = img->linker; 376 u32 i, j; 377 if (!l || img->scripted) return; 378 for (i = 0; i < l->nsection_starts; ++i) { 379 const KitLinkSectionStart* ss = &l->section_starts[i]; 380 LinkSegmentId target_seg = LINK_SEG_NONE; 381 i64 delta = 0; 382 if (!ss->name.s || ss->name.len == 0) continue; 383 /* Find the matched output section and compute the shift that lands its 384 * final address on ss->addr. (A name-less warning was already issued at 385 * layout time by link_apply_section_starts.) */ 386 for (j = 0; j < img->nsections; ++j) { 387 LinkSection* sec = &img->sections[j]; 388 Slice nm = sec->name ? pool_slice(img->c->global, sec->name) : SLICE_NULL; 389 if (!nm.s || nm.len != ss->name.len || 390 memcmp(nm.s, ss->name.s, nm.len) != 0) 391 continue; 392 if (sec->file_only) continue; 393 if (sec->segment_id != LINK_SEG_NONE && 394 sec->segment_id <= img->nsegments) { 395 target_seg = sec->segment_id; 396 delta = (i64)ss->addr - (i64)(img_base + sec->vaddr); 397 } else { 398 /* No containing segment (rare): pin the section's vaddr directly so 399 * img_base + vaddr == ss->addr. */ 400 sec->vaddr = ss->addr - img_base; 401 } 402 break; 403 } 404 if (target_seg == LINK_SEG_NONE || delta == 0) continue; 405 /* Shift the whole segment (segment + its sections + the symbols and reloc 406 * sites resolved into them) so the pinned section lands exactly, keeping 407 * every relative placement within the segment. */ 408 img->segments[target_seg - 1].vaddr += (u64)delta; 409 img->segments[target_seg - 1].paddr += (u64)delta; 410 for (j = 0; j < img->nsections; ++j) 411 if (img->sections[j].segment_id == target_seg) 412 img->sections[j].vaddr += (u64)delta; 413 for (j = 0; j < LinkSyms_count(&img->syms); ++j) { 414 LinkSymbol* s = LinkSyms_at(&img->syms, j); 415 if (s->kind == SK_ABS || !s->defined) continue; 416 if (s->section_id == LINK_SEC_NONE || s->section_id > img->nsections) 417 continue; 418 if (img->sections[s->section_id - 1].segment_id == target_seg) 419 s->vaddr += (u64)delta; 420 } 421 for (j = 0; j < LinkRelocs_count(&img->relocs); ++j) { 422 LinkRelocApply* r = LinkRelocs_at(&img->relocs, j); 423 if (r->link_section_id == LINK_SEC_NONE || 424 r->link_section_id > img->nsections) 425 continue; 426 if (img->sections[r->link_section_id - 1].segment_id == target_seg) 427 r->write_vaddr += (u64)delta; 428 } 429 } 430 } 431 432 /* AArch64 ELF ABI: the per-thread TLS block starts at TP + 16 bytes 433 * (the TCB sits ahead of the TLS image). RISC-V psABI normally points 434 * tp at the start of the TLS image; the kit harness's start.c 435 * places a 16-byte TCB ahead of .tdata and biases tp accordingly, so 436 * the TPREL offset for both arches is (target - tls_vaddr) + 16. */ 437 #define TLS_TCB_SIZE 16ull 438 439 static int reloc_is_tlsle(RelocKind k, int tls_variant_ii) { 440 if (k == R_TPOFF64 && !tls_variant_ii) return 1; 441 return k == R_AARCH64_TLSLE_ADD_TPREL_HI12 || 442 k == R_AARCH64_TLSLE_ADD_TPREL_LO12_NC || 443 k == R_AARCH64_TLSDESC_ADR_PAGE21 || 444 k == R_AARCH64_TLSDESC_LD64_LO12 || k == R_AARCH64_TLSDESC_ADD_LO12 || 445 k == R_AARCH64_TLSDESC_CALL || k == R_RV_TPREL_HI20 || 446 k == R_RV_TPREL_LO12_I || k == R_RV_TPREL_LO12_S || 447 k == R_RV_TLS_GD_HI20; 448 } 449 450 /* Variant-I TP bias: distance from the TLS image start to where `tp` points. 451 * - AArch64 (AAPCS64): tp points at a 16-byte TCB ahead of the image -> +16 452 * for both hosted and freestanding. 453 * - RISC-V: the psABI points tp at the *start* of the image, so hosted libcs 454 * (FreeBSD/Linux _init_tls) want +0; kit's own freestanding start.c places 455 * a 16-byte TCB ahead of .tdata and biases tp to match AArch64, so 456 * freestanding rv64/rv32 keep +16. */ 457 static u64 tls_tcb_bias(Compiler* c) { 458 /* The per-arch freestanding bias lives in the ELF arch descriptor 459 * (ObjElfArchOps.tls_tp_bias): 16 for AArch64/RISC-V variant-I, 0 for 460 * x86_64 variant-II. RISC-V is the only arch whose *hosted* bias 461 * differs from its freestanding bias (the psABI points tp at the image 462 * start, so hosted libcs want +0); that split stays here. */ 463 const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF); 464 const ObjElfArchOps* arch = 465 (fmt && fmt->elf_arch) ? fmt->elf_arch(c->target.arch) : NULL; 466 u64 bias = arch ? (u64)arch->tls_tp_bias : TLS_TCB_SIZE; 467 if ((c->target.arch == KIT_ARCH_RV64 || c->target.arch == KIT_ARCH_RV32) && 468 c->target.os != KIT_OS_FREESTANDING) 469 return 0ull; 470 return bias; 471 } 472 473 /* x86_64 SysV ABI: TLS variant II — the per-thread TLS image sits at 474 * *negative* offsets from %fs (which points at the TCB). start.c 475 * lays out [tdata | tbss | TCB] and arch_prctl(ARCH_SET_FS, &TCB), so 476 * a symbol at offset X within the TLS image is at fs-relative offset 477 * (X - tls_memsz). The two ELF reloc kinds R_X86_64_TPOFF32/_TPOFF64 478 * encode that signed offset directly at the reloc site (no TCB bias — 479 * variant II's TCB sits *after* the image, so TPOFF is negative). */ 480 static int reloc_is_x64_tlsle(RelocKind k, int tls_variant_ii) { 481 if (!tls_variant_ii) return 0; 482 return k == R_TPOFF64 || k == R_X64_TPOFF32 || k == R_X64_DTPOFF32; 483 } 484 485 static int is_x64_tlsld_relaxed_get_addr_call(const LinkImage* img, 486 const LinkRelocApply* r, 487 const LinkSymbol* tgt, 488 const u8* P_bytes) { 489 Slice nm; 490 if (r->kind != R_X64_PLT32 && r->kind != R_PLT32) return 0; 491 if (!tgt->name) return 0; 492 if (r->offset < 8u) return 0; 493 nm = pool_slice(img->c->global, tgt->name); 494 if (!slice_eq_cstr(nm, "__tls_get_addr")) return 0; 495 return P_bytes[-8] == 0x64u && P_bytes[-7] == 0x48u && 496 P_bytes[-6] == 0x8bu && P_bytes[-5] == 0x04u && 497 P_bytes[-4] == 0x25u && P_bytes[-3] == 0x00u && 498 P_bytes[-2] == 0x00u && P_bytes[-1] == 0x00u && 499 P_bytes[0] == 0x00u && P_bytes[1] == 0x90u && 500 P_bytes[2] == 0x90u && P_bytes[3] == 0x90u; 501 } 502 503 static int rv_tlsgd_hi_at(const LinkImage* img, u64 write_vaddr) { 504 u32 i; 505 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { 506 const LinkRelocApply* hi = LinkRelocs_at(&img->relocs, i); 507 if (hi->kind == R_RV_TLS_GD_HI20 && hi->write_vaddr == write_vaddr) 508 return 1; 509 } 510 return 0; 511 } 512 513 static int rv_lo12_pairs_tlsgd(const LinkImage* img, const LinkRelocApply* r, 514 const LinkSymbol* tgt) { 515 if (r->kind != R_RV_PCREL_LO12_I) return 0; 516 return rv_tlsgd_hi_at(img, tgt->vaddr); 517 } 518 519 static int is_rv_tlsgd_get_addr_call(const LinkImage* img, 520 const LinkRelocApply* r, 521 const LinkSymbol* tgt, const u8* P_bytes) { 522 Slice nm; 523 u32 i; 524 (void)P_bytes; 525 if (r->kind != R_PLT32 && r->kind != R_RV_CALL) return 0; 526 if (!tgt->name) return 0; 527 if (r->offset < 8u) return 0; 528 nm = pool_slice(img->c->global, tgt->name); 529 if (!slice_eq_cstr(nm, "__tls_get_addr")) return 0; 530 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { 531 const LinkRelocApply* hi = LinkRelocs_at(&img->relocs, i); 532 u64 span; 533 if (hi->kind != R_RV_TLS_GD_HI20) continue; 534 if (hi->input_id != r->input_id || hi->section_id != r->section_id) 535 continue; 536 if (hi->link_section_id != r->link_section_id) continue; 537 if (hi->write_vaddr >= r->write_vaddr) continue; 538 span = r->write_vaddr - hi->write_vaddr; 539 if (span >= 8u && span <= 24u) return 1; 540 } 541 return 0; 542 } 543 544 static int reloc_is_abs(RelocKind k) { return k == R_ABS32 || k == R_ABS64; } 545 546 /* Function-call relocs that may route through the PLT when the target 547 * is imported. aarch64 CALL26/JUMP26, x86_64 PLT32, and risc-v CALL_PLT 548 * (which kit maps to R_PLT32) all carry the "call this address; if 549 * it's not resolvable here use the PLT trampoline" contract; the apply 550 * pass overwrites S with the PLT entry vaddr in that case. */ 551 static int reloc_is_branch26(RelocKind k) { 552 return k == R_AARCH64_CALL26 || k == R_AARCH64_JUMP26 || k == R_X64_PLT32 || 553 k == R_PLT32 || k == R_RV_CALL; 554 } 555 556 static void emit_dyn_record(LinkImage* img, u64 site_vaddr, u32 reloc_type, 557 u32 dynidx, i64 addend) { 558 LinkDynState* dyn = img->dyn; 559 if (!dyn || !dyn->rela_dyn) return; 560 if (dyn->nrela_dyn >= dyn->cap_rela_dyn) { 561 compiler_panic(img->c, SRCLOC_NONE, 562 "link: too many .rela.dyn records (%u >= %u); raise " 563 "cap_rela_dyn in layout_dyn", 564 dyn->nrela_dyn, dyn->cap_rela_dyn); 565 } 566 DynRela* r = &dyn->rela_dyn[dyn->nrela_dyn++]; 567 r->r_offset = site_vaddr; 568 r->r_info = ELF64_R_INFO((u64)dynidx, reloc_type); 569 r->r_addend = addend; 570 } 571 572 static const ObjElfArchOps* elf_arch_or_panic(Compiler* c, const char* where) { 573 const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF); 574 const ObjElfArchOps* arch = 575 fmt && fmt->elf_arch ? fmt->elf_arch(c->target.arch) : NULL; 576 if (!arch) 577 compiler_panic(c, SRCLOC_NONE, "%.*s: no ELF arch descriptor", 578 SLICE_ARG(slice_from_cstr(where))); 579 return arch; 580 } 581 582 static void emit_relative_record(LinkImage* img, u64 site_vaddr, u64 addend) { 583 const ObjElfArchOps* arch = elf_arch_or_panic(img->c, "link"); 584 emit_dyn_record(img, site_vaddr, arch->r_relative, 0, (i64)addend); 585 } 586 587 static void emit_globdat_record(LinkImage* img, u64 site_vaddr, u32 dynidx, 588 i64 addend) { 589 const ObjElfArchOps* arch = elf_arch_or_panic(img->c, "link"); 590 emit_dyn_record(img, site_vaddr, arch->r_glob_dat, dynidx, addend); 591 } 592 593 /* RISC-V PCREL_LO12_* references the address of an AUIPC carrying the 594 * paired PCREL_HI20. Given the AUIPC's site vaddr (post-shift), find 595 * its PCREL_HI20 reloc and compute the displacement that AUIPC 596 * encoded — the LO12 then takes the low 12 bits of the same disp. 597 * 598 * Linear scan over img->relocs is fine in practice: kernel images and 599 * cg cases produce at most a few hundred relocs total. */ 600 static i64 rv_pcrel_lo12_disp(LinkImage* img, u64 auipc_vaddr, u64 img_base) { 601 u32 i; 602 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { 603 const LinkRelocApply* hi = LinkRelocs_at(&img->relocs, i); 604 const LinkSymbol* hi_tgt; 605 u64 hi_S, hi_P; 606 if (hi->kind != R_RV_PCREL_HI20 && hi->kind != R_RV_GOT_HI20 && 607 hi->kind != R_RV_TLS_GOT_HI20) 608 continue; 609 if (hi->write_vaddr + img_base != auipc_vaddr) continue; 610 hi_tgt = LinkSyms_at(&img->syms, hi->target - 1); 611 hi_S = (hi_tgt->kind == SK_ABS) ? hi_tgt->vaddr : hi_tgt->vaddr + img_base; 612 hi_P = hi->write_vaddr + img_base; 613 return (i64)hi_S + hi->addend - (i64)hi_P; 614 } 615 compiler_panic(img->c, SRCLOC_NONE, 616 "link: PCREL_LO12 at 0x%llx has no paired PCREL_HI20", 617 (unsigned long long)auipc_vaddr); 618 return 0; 619 } 620 621 static void apply_all_relocs(LinkImage* img, u64 img_base) { 622 u32 i; 623 int dyn_output = img->pie || img->shared; 624 int tls_vi = (int)link_arch_desc_for(img->c)->tls_variant_ii; 625 for (i = 0; i < LinkRelocs_count(&img->relocs); ++i) { 626 LinkRelocApply* r = LinkRelocs_at(&img->relocs, i); 627 const LinkSymbol* tgt = LinkSyms_at(&img->syms, r->target - 1); 628 const LinkSection* sec = &img->sections[r->link_section_id - 1]; 629 const LinkSegment* seg; 630 u64 S, P; 631 u8* P_bytes; 632 633 /* File-only debug section: not loaded, so no dynamic reloc and no 634 * img_base. Write the final value straight into the registry buffer 635 * at the reloc offset. A SK_SECTION target resolves to its DWARF 636 * sec-relative base (tgt->vaddr, kept unshifted); a code/data symbol 637 * resolves to its link-time vaddr (img_base + vaddr) for low_pc / 638 * set_address. Mirrors the JIT debug view (link_jit.c). */ 639 if (sec->segment_id == LINK_SEG_NONE) { 640 u8* dbg = link_fileonly_bytes(img, r->link_section_id); 641 if (!dbg) continue; 642 if (tgt->kind == SK_SECTION || tgt->kind == SK_ABS) 643 S = tgt->vaddr; 644 else 645 S = img_base + tgt->vaddr; 646 link_reloc_apply(img->c, r->kind, dbg + r->offset, S, r->addend, 0); 647 continue; 648 } 649 seg = &img->segments[sec->segment_id - 1]; 650 /* NOLOAD / NOBITS output section: the segment carries no on-disk bytes 651 * (segment_bytes left NULL), so there is no patch site to write. A kept 652 * PROGBITS input routed into a NOLOAD output (link_section_kept ignores 653 * NOLOAD) still collects its relocs with a real segment_id, but the value 654 * can never be observed at runtime — skip the apply rather than dereference 655 * a NULL segment buffer (mirrors the file-only branch above). */ 656 if (img->segment_bytes[seg->id - 1] == NULL) continue; 657 if (reloc_is_tlsle(r->kind, tls_vi) || reloc_is_x64_tlsle(r->kind, tls_vi)) 658 /* Both the direct local-exec relocs and the internal R_TPOFF64 used to 659 * fill a TLS-IE GOT slot resolve to a tp-relative offset within THIS 660 * image's TLS block — only meaningful for a thread-local defined here. 661 * Reject an imported or non-thread-local target rather than emit a 662 * bogus offset (kit has no initial-exec/global-dynamic fallback). */ 663 link_require_local_tls(img->c, tgt); 664 if (reloc_is_tlsle(r->kind, tls_vi)) { 665 /* S is the target's TP-relative offset: distance from the TLS image 666 * start plus the arch/OS TCB bias (see tls_tcb_bias). Both vaddrs are 667 * in the same (post-shift, image-relative) coordinate system, so 668 * img_base cancels out. */ 669 S = (tgt->vaddr - img->tls_vaddr) + tls_tcb_bias(img->c); 670 } else if (reloc_is_x64_tlsle(r->kind, tls_vi)) { 671 /* x86_64 variant II: TP points just past the TLS image, so a symbol at 672 * offset X within the image is at TP-relative offset (X - tls_size). 673 * The runtime (FreeBSD/glibc _init_tls) allocates the block rounded up 674 * to the TLS alignment, so tls_size must be round_up(memsz, align) -- 675 * using the raw memsz is off by the rounding remainder whenever memsz 676 * is not a multiple of align, handing back a garbage TLS address (e.g. 677 * jemalloc's tsd, faulting non-canonical). Cast through i64/u64 so the 678 * apply writes the full 32- or 64-bit signed value. */ 679 u64 a = img->tls_align ? img->tls_align : 1u; 680 u64 tls_size = (img->tls_memsz + a - 1u) & ~(a - 1u); 681 i64 off = (i64)(tgt->vaddr - img->tls_vaddr) - (i64)tls_size; 682 S = (u64)off; 683 } else if (r->kind == R_RV_PCREL_LO12_I || r->kind == R_RV_PCREL_LO12_S) { 684 /* PCREL_LO12: rewrite S so that link_reloc_apply's existing 685 * LO12_I/LO12_S encoder produces the right low 12 bits of the 686 * paired AUIPC's PC-relative displacement. The reloc's own 687 * addend is unused; signed lo12 = disp & 0xfff. */ 688 P = r->write_vaddr + img_base; 689 P_bytes = img->segment_bytes[seg->id - 1] + 690 (size_t)(r->write_file_offset - seg->file_offset); 691 if (rv_lo12_pairs_tlsgd(img, r, tgt)) continue; 692 { 693 i64 disp = rv_pcrel_lo12_disp(img, tgt->vaddr + img_base, img_base); 694 RelocKind alias = 695 (r->kind == R_RV_PCREL_LO12_I) ? R_RV_LO12_I : R_RV_LO12_S; 696 link_reloc_apply(img->c, alias, P_bytes, (u64)disp, 0, P); 697 } 698 continue; 699 } else { 700 S = tgt->vaddr + img_base; 701 if (tgt->kind == SK_ABS) S = tgt->vaddr; 702 } 703 P = r->write_vaddr + img_base; 704 P_bytes = img->segment_bytes[seg->id - 1] + 705 (size_t)(r->write_file_offset - seg->file_offset); 706 707 if (is_rv_tlsgd_get_addr_call(img, r, tgt, P_bytes)) continue; 708 709 /* Imported target: redirect / rewrite per reloc kind (Phase 5). 710 * 711 * - CALL26 / JUMP26: target the import's PLT entry. The PLT stub 712 * reads .got.plt[3+i], which the loader pre-fills via JUMP_SLOT 713 * (.rela.plt). S becomes the PLT-entry vaddr; the existing 714 * apply path computes the disp from there. 715 * - R_ABS{32,64}: leave the patch site at zero and emit a 716 * GLOB_DAT record so the loader writes the resolved address 717 * into the site at load time. This covers both 718 * layout_got-emitted .got slot fills (target = import) and any 719 * direct absolute reference in user data (e.g. a function 720 * pointer initializer). 721 * - GOT-page / LO12-NC against an import: emit_reloc_records has 722 * already redirected the target from the import to the 723 * synthetic .got slot symbol, so the apply path here sees the 724 * slot, not the import — nothing special needed; the slot's 725 * own R_ABS64 fill against the (vaddr=0) import will trip the 726 * abs-import branch above and emit GLOB_DAT. 727 * 728 * Anything else against an imported symbol (e.g. PREL19 / ADR 729 * etc.) is rare in real binaries and would need its own 730 * dynamic-reloc kind; panic loudly so a future test that needs 731 * it announces itself. */ 732 if (tgt->imported) { 733 /* `tgt` may be a per-input shadow LinkSymbol — resolve_undefs 734 * stamps `imported = 1` on every undef matched by name, but 735 * collect_imports only stashes plt_vaddr / dynidx on the 736 * canonical entry registered in img->globals. Resolve to the 737 * canonical id before indexing the dyn-state arrays. */ 738 LinkSymId canon_id = tgt->id; 739 if (tgt->name != 0) { 740 LinkSymId hit = symhash_get(&img->globals, tgt->name); 741 if (hit != LINK_SYM_NONE) canon_id = hit; 742 } 743 u32 dynidx = (img->dyn && canon_id < img->dyn->sym_dynidx_size) 744 ? img->dyn->sym_dynidx[canon_id] 745 : 0u; 746 if (is_x64_tlsld_relaxed_get_addr_call(img, r, tgt, P_bytes)) continue; 747 if (reloc_is_branch26(r->kind)) { 748 u64 plt_v = (img->dyn && canon_id < img->dyn->sym_dynidx_size) 749 ? img->dyn->sym_plt_vaddr[canon_id] 750 : 0u; 751 if (plt_v == 0) 752 compiler_panic(img->c, SRCLOC_NONE, 753 "link: imported sym has no PLT entry (CALL26)"); 754 S = plt_v + img_base; 755 link_reloc_apply(img->c, r->kind, P_bytes, S, r->addend, P); 756 continue; 757 } 758 if (reloc_is_abs(r->kind)) { 759 if (dynidx == 0) 760 compiler_panic(img->c, SRCLOC_NONE, 761 "link: imported sym has no .dynsym entry"); 762 emit_globdat_record(img, r->write_vaddr, dynidx, r->addend); 763 /* Site bytes are irrelevant: the loader's GLOB_DAT writes 764 * (sym_value + r_addend) into r_offset before user code runs, 765 * overwriting whatever's there. Leaving the existing zero 766 * fill saves a write. */ 767 continue; 768 } 769 { 770 Slice nm_s = 771 tgt->name ? pool_slice(img->c->global, tgt->name) : SLICE_NULL; 772 const char* nm = nm_s.s ? nm_s.s : ""; 773 size_t nl = nm_s.len; 774 compiler_panic( 775 img->c, SRCLOC_NONE, 776 "link: unhandled reloc kind %u against imported symbol '%.*s'", 777 (unsigned)r->kind, (int)nl, nm); 778 } 779 } 780 781 /* PIE: an absolute reloc against a defined non-imported symbol 782 * stays image-relative in the file (the loader adds load-base via 783 * a synthesized R_AARCH64_RELATIVE). img_base is 0 for PIE so 784 * S above is already image-relative — the apply writes that into 785 * the site, and the RELATIVE record tells the loader to add 786 * load_base on top. */ 787 if (dyn_output && reloc_is_abs(r->kind) && tgt->defined && 788 tgt->kind != SK_ABS) { 789 /* RELA RELATIVE ignores the in-place site value: the loader writes 790 * (load_base + r_addend) into the slot. So the addend must be the 791 * full image-relative target — symbol vaddr plus the reloc's own 792 * addend — not just the symbol vaddr. Dropping r->addend collapses 793 * every entry of an addend-bearing table (jump tables, labeladdr 794 * arrays, &sym+off initializers) onto the symbol base. */ 795 emit_relative_record(img, r->write_vaddr, tgt->vaddr + (u64)r->addend); 796 } 797 link_reloc_apply(img->c, r->kind, P_bytes, S, r->addend, P); 798 } 799 } 800 801 /* The build-id payload is a format-agnostic image identity hash — 802 * see link_image_id_compute in link_image_id.c. Mach-O wraps the 803 * same bytes in LC_UUID; ELF wraps them in a .note.gnu.build-id. */ 804 805 /* String tables (.shstrtab / .strtab) use the shared ObjByteBuf dedup builder 806 * (objbb_*, obj/bytebuf.h). Both must lead with a NUL so name offset 0 reads as 807 * the empty string, so each is seeded with objbb_u8(&b, 0) right after init. */ 808 809 /* ---- symtab builder ---- */ 810 811 typedef struct SymRec { 812 u32 st_name; 813 u8 st_info; 814 u8 st_other; 815 u16 st_shndx; 816 u64 st_value; 817 u64 st_size; 818 } SymRec; 819 820 static u8 sym_kind_to_st_type(u8 kind) { 821 /* Shared elf.h table maps SK_COMMON -> STT_OBJECT (the on-disk shape 822 * for tentative definitions). The linker, however, writes COMMON as 823 * STT_NOTYPE; override that one entry locally. */ 824 if (kind == SK_COMMON) return STT_NOTYPE; 825 return elf_st_type(kind); 826 } 827 828 static u8 sym_bind_to_st_bind(u8 bind) { return elf_st_bind(bind); } 829 830 /* Produces one symbol record on the wire from a SymRec. Elf32_Sym (16B) 831 * REORDERS fields vs Elf64_Sym (24B): st_value/st_size come BEFORE 832 * st_info/st_other/st_shndx, so select the byte layout by class32. */ 833 static void write_sym_rec(Writer* w, const SymRec* r, int class32) { 834 if (class32) { 835 u8 buf[ELF32_SYM_SIZE]; 836 u32 i; 837 buf[0] = (u8)(r->st_name); 838 buf[1] = (u8)(r->st_name >> 8); 839 buf[2] = (u8)(r->st_name >> 16); 840 buf[3] = (u8)(r->st_name >> 24); 841 for (i = 0; i < 4; ++i) buf[4 + i] = (u8)(r->st_value >> (i * 8)); 842 for (i = 0; i < 4; ++i) buf[8 + i] = (u8)(r->st_size >> (i * 8)); 843 buf[12] = r->st_info; 844 buf[13] = r->st_other; 845 buf[14] = (u8)(r->st_shndx); 846 buf[15] = (u8)(r->st_shndx >> 8); 847 write_bytes(w, buf, sizeof buf); 848 return; 849 } 850 u8 buf[ELF64_SYM_SIZE]; 851 buf[0] = (u8)(r->st_name); 852 buf[1] = (u8)(r->st_name >> 8); 853 buf[2] = (u8)(r->st_name >> 16); 854 buf[3] = (u8)(r->st_name >> 24); 855 buf[4] = r->st_info; 856 buf[5] = r->st_other; 857 buf[6] = (u8)(r->st_shndx); 858 buf[7] = (u8)(r->st_shndx >> 8); 859 { 860 u32 i; 861 for (i = 0; i < 8; ++i) buf[8 + i] = (u8)(r->st_value >> (i * 8)); 862 for (i = 0; i < 8; ++i) buf[16 + i] = (u8)(r->st_size >> (i * 8)); 863 } 864 write_bytes(w, buf, sizeof buf); 865 } 866 867 static void refresh_dynsym_exports(LinkImage* img, u64 img_base) { 868 LinkDynState* dyn; 869 const LinkSection* sec_dynsym; 870 const LinkSegment* seg; 871 u8* bytes; 872 u32 i; 873 if (!img || !img->dyn) return; 874 dyn = img->dyn; 875 if (!dyn->sym_dynidx || dyn->sec_dynsym == LINK_SEC_NONE) return; 876 sec_dynsym = &img->sections[dyn->sec_dynsym - 1]; 877 seg = &img->segments[sec_dynsym->segment_id - 1]; 878 bytes = img->segment_bytes[seg->id - 1] + 879 (size_t)(sec_dynsym->file_offset - seg->file_offset); 880 881 for (i = 0; i < LinkSyms_count(&img->syms); ++i) { 882 const LinkSymbol* s = LinkSyms_at(&img->syms, i); 883 u32 dynidx; 884 DynSymRec* r; 885 if (!s->defined || s->imported) continue; 886 if (s->id >= dyn->sym_dynidx_size) continue; 887 dynidx = dyn->sym_dynidx[s->id]; 888 if (dynidx == 0 || dynidx >= dyn->ndynsym) continue; 889 890 r = &dyn->dynsym[dynidx]; 891 r->st_value = (s->kind == SK_ABS) ? s->vaddr : img_base + s->vaddr; 892 r->st_size = s->size; 893 r->st_shndx = (s->kind == SK_ABS) ? SHN_ABS : 1u; 894 } 895 896 for (i = 0; i < dyn->ndynsym; ++i) { 897 u8* p = bytes + (u64)i * ELF64_SYM_SIZE; 898 const DynSymRec* r = &dyn->dynsym[i]; 899 wr_u32_le(p + 0, r->st_name); 900 p[4] = r->st_info; 901 p[5] = r->st_other; 902 wr_u16_le(p + 6, r->st_shndx); 903 wr_u64_le(p + 8, r->st_value); 904 wr_u64_le(p + 16, r->st_size); 905 } 906 } 907 908 /* ---- section header layout ---- * 909 * 910 * Per-segment cuts: each kept image segment contributes 1 .text/.rodata 911 * shdr for its file portion, plus a separate .bss shdr for the trailing 912 * NOBITS portion of an RW segment (memsz > filesz). The headers PT_LOAD 913 * contributes a single .note.gnu.build-id shdr. Trailing non-alloc 914 * shdrs: .symtab .strtab .shstrtab (always 3). */ 915 916 typedef struct OutShdr { 917 u32 shdr_idx; /* 1-based; assigned during planning */ 918 LinkSegmentId segment_id; 919 Sym name; 920 u16 sem; /* SecSem from source LinkSection */ 921 u32 flags; /* SF_* from source LinkSection */ 922 u32 align; 923 u64 vaddr; 924 u64 file_offset; 925 u64 size; 926 int is_nobits; 927 int is_fileonly; /* non-allocatable .debug_* section (no PT_LOAD) */ 928 } OutShdr; 929 930 static u16 sym_shndx_for(const LinkSymbol* s, const OutShdr* outshdrs, 931 u32 noutshdr) { 932 if (!s->defined) return SHN_UNDEF; 933 if (s->kind == SK_ABS) return SHN_ABS; 934 if (s->kind == SK_FILE) return SHN_ABS; 935 if (s->kind == SK_COMMON) return SHN_COMMON; 936 /* Find an output shdr whose [vaddr, vaddr+size) covers s->vaddr. 937 * Boundary symbols match at the upper edge. */ 938 { 939 u32 i; 940 for (i = 0; i < noutshdr; ++i) { 941 u64 lo, hi; 942 /* File-only debug shdrs sit at sec-relative vaddrs (0-based) and 943 * never contain a loaded symbol — skip them so a low-vaddr code 944 * symbol (e.g. PIE, img_base 0) isn't mis-attributed to a 945 * .debug_* section whose [0,size) range happens to overlap. */ 946 if (outshdrs[i].is_fileonly) continue; 947 lo = outshdrs[i].vaddr; 948 hi = lo + outshdrs[i].size; 949 if (s->vaddr >= lo && s->vaddr <= hi) return (u16)outshdrs[i].shdr_idx; 950 } 951 } 952 return SHN_ABS; 953 } 954 955 static u32 sec_sem_to_sht(u16 sem) { 956 switch (sem) { 957 case SSEM_PROGBITS: 958 return SHT_PROGBITS; 959 case SSEM_NOBITS: 960 return SHT_NOBITS; 961 case SSEM_NOTE: 962 return SHT_NOTE; 963 case SSEM_INIT_ARRAY: 964 return SHT_INIT_ARRAY; 965 case SSEM_FINI_ARRAY: 966 return SHT_FINI_ARRAY; 967 case SSEM_PREINIT_ARRAY: 968 return SHT_PREINIT_ARRAY; 969 default: 970 return SHT_PROGBITS; 971 } 972 } 973 974 static u64 sec_flags_to_shf(u32 flags) { 975 u64 r = 0; 976 if (flags & SF_ALLOC) r |= SHF_ALLOC; 977 if (flags & SF_EXEC) r |= SHF_EXECINSTR; 978 if (flags & SF_WRITE) r |= SHF_WRITE; 979 if (flags & SF_TLS) r |= SHF_TLS; 980 if (flags & SF_MERGE) r |= SHF_MERGE; 981 if (flags & SF_STRINGS) r |= SHF_STRINGS; 982 if (flags & SF_LINK_ORDER) r |= SHF_LINK_ORDER; 983 if (flags & SF_RETAIN) r |= SHF_GNU_RETAIN; 984 return r; 985 } 986 987 /* Output-shdr sort order: loaded sections first, by (segment_id, vaddr); 988 * then file-only debug sections after all segments, grouped by name (so 989 * same-name multi-input contributions are adjacent and merge into one 990 * output section) and ordered by their sec-relative base. Returns 1 if 991 * `a` should sort before `b`. */ 992 static int shdr_sort_less(const LinkSection* a, const LinkSection* b) { 993 if (a->file_only != b->file_only) return b->file_only; /* loaded first */ 994 if (a->file_only) { 995 if (a->name != b->name) return a->name < b->name; 996 return a->vaddr < b->vaddr; 997 } 998 if (a->segment_id != b->segment_id) return a->segment_id < b->segment_id; 999 return a->vaddr < b->vaddr; 1000 } 1001 1002 void link_emit_elf(LinkImage* img, Writer* w) { 1003 Heap* heap = img->heap; 1004 Compiler* c = img->c; 1005 const ObjElfArchOps* arch = elf_arch_or_panic(c, "link_emit_elf"); 1006 u32 e_machine = arch->e_machine; 1007 /* class32: ELFCLASS32 (RV32) output, derived from target ptr width. 1008 * ptr_size must be 4 or 8 (every supported arch sets one of these). */ 1009 int class32 = (c->target.ptr_size == 4); 1010 /* RV32 is static-only in v1: dynamic linking (link_dyn.c) and the 1011 * PIE re-serialize block below remain ELFCLASS64. Gate here so the 1012 * dynamic path is never reached for a 32-bit image. */ 1013 if (class32 && (img->pie || img->dyn)) 1014 compiler_panic(c, SRCLOC_NONE, 1015 "rv32: dynamic/PIE linking unsupported; static only"); 1016 if (!img->shared && img->entry_sym == LINK_SYM_NONE) 1017 compiler_panic(c, SRCLOC_NONE, "link_emit_elf: no resolved entry symbol"); 1018 /* IFUNC trampolines: layout_iplt builds the .iplt stubs + .igot.plt 1019 * slots and (when emit_static_exe was set) synthesizes a 1020 * .init_array entry that calls __kit_ifunc_init at startup. The 1021 * rt member walks .iplt.pairs and fills each slot before user code 1022 * runs. The ELF writer doesn't have to do anything special here. */ 1023 1024 /* PIE / ET_DYN: img_base is 0 (the loader picks the runtime base; 1025 * absolute relocs against internal symbols are emitted as 1026 * R_AARCH64_RELATIVE in .rela.dyn). Otherwise classic ET_EXEC at 1027 * IMAGE_BASE_STATIC. 1028 * 1029 * Scripted: the linker script pinned absolute vaddrs (e.g. 1030 * `. = 0x40080000`); img_base stays 0 and the headers PT_LOAD / 1031 * build-id note are dropped — the script's image is consumed by a 1032 * raw loader (qemu -kernel, a bootloader) that doesn't need a 1033 * self-describing memory image. */ 1034 int pie = img->pie; 1035 int shared = img->shared; 1036 int scripted = img->scripted; 1037 /* Static ET_EXEC base: a `kit ld -Ttext ADDR` override (e.g. 0x80000000 for a 1038 * qemu `virt` image) wins over IMAGE_BASE_STATIC; PIE/scripted keep base 0. 1039 */ 1040 u64 img_base = (pie || shared || scripted) ? 0ULL 1041 : img->text_base_set ? img->text_base 1042 : IMAGE_BASE_STATIC; 1043 1044 /* ---- plan number of program headers ---- 1045 * 1046 * 1 headers PT_LOAD + nsegments PT_LOAD + 1 PT_NOTE (build-id) 1047 * + 1 PT_TLS when this image carries any TLS sections. 1048 * + dynamic phdrs when PIE/shared also has real dynamic-link state. PIE 1049 * executables get PT_PHDR / PT_INTERP / PT_DYNAMIC / PT_GNU_STACK; DSOs 1050 * get PT_PHDR / PT_DYNAMIC / PT_GNU_STACK. 1051 * 1052 * Scripted images skip the headers PT_LOAD and PT_NOTE: phdrs are 1053 * just the per-segment PT_LOADs. */ 1054 u32 has_tls = img->tls_memsz ? 1u : 0u; 1055 u32 nphdr_section_notes = 0; 1056 { 1057 u32 i; 1058 for (i = 0; i < img->nsections; ++i) { 1059 const LinkSection* s = &img->sections[i]; 1060 if (!s->file_only && s->sem == SSEM_NOTE && s->size) { 1061 nphdr_section_notes++; 1062 } 1063 } 1064 } 1065 u32 nphdr_extra_dyn = ((pie || shared) && img->dyn) ? (shared ? 3u : 4u) : 0u; 1066 u32 nphdr_headers = scripted ? 0u : 1u; 1067 u32 nphdr_buildid = scripted ? 0u : 1u; 1068 u32 nphdr_total = nphdr_headers + img->nsegments + nphdr_buildid + 1069 nphdr_section_notes + has_tls + nphdr_extra_dyn; 1070 u64 build_id_note_bytes = scripted ? 0ULL : BUILD_ID_NOTE_BYTES; 1071 /* Class-selected on-disk header sizes (ELF32: 52/32/40, ELF64: 64/56/64). */ 1072 u64 ehdr_sz = elf_ehdr_sz(class32); 1073 u64 phent_sz = elf_phdr_sz(class32); 1074 u64 headers_size = 1075 ehdr_sz + (u64)nphdr_total * phent_sz + build_id_note_bytes; 1076 u64 headers_load = ALIGN_UP(headers_size, (u64)PAGE_SIZE); 1077 1078 /* The build-id note lives inside the headers PT_LOAD at this offset. */ 1079 u64 build_id_off = ehdr_sz + (u64)nphdr_total * phent_sz; 1080 u64 build_id_addr = img_base + build_id_off; 1081 1082 /* Record final emit facts for the link-map / symbols side-files (consumed 1083 * after emit, off the format-neutral image). The headers PT_LOAD below maps 1084 * at img_base with p_filesz == p_memsz == headers_size; scripted images 1085 * emit no headers segment (see the nphdr_headers gate above). */ 1086 img->load_base = img_base; 1087 if (!scripted) { 1088 img->headers_present = 1; 1089 img->headers_filesz = headers_size; 1090 img->headers_memsz = headers_size; 1091 img->headers_align = PAGE_SIZE; 1092 } 1093 1094 /* ---- shift image addresses, apply relocations ---- 1095 * 1096 * Must happen before segshdrs/symtab construction so they observe 1097 * post-shift vaddrs (the values that will land in the file). */ 1098 if (scripted) 1099 shift_image_file_offsets(img, headers_load); 1100 else 1101 shift_image_addresses(img, headers_load); 1102 /* --section-start / -Tdata / -Tbss: pin chosen sections to their exact final 1103 * runtime addresses now that vaddrs are post-shift (and before relocs see 1104 * them). No-op for scripted images. */ 1105 apply_section_starts(img, img_base); 1106 apply_all_relocs(img, img_base); 1107 1108 /* ---- write .dynamic body + re-serialize .rela.dyn (PIE only) ---- 1109 * 1110 * Both depend on post-shift vaddrs. .dynamic embeds image-relative 1111 * pointers to .dynsym/.dynstr/.gnu.hash/.rela.dyn/.rela.plt/.got.plt 1112 * (the loader adds load_base at runtime). .rela.dyn picked up 1113 * RELATIVE records during apply_all_relocs; rewrite the section 1114 * bytes to include them. */ 1115 if ((pie || shared) && img->dyn) { 1116 LinkDynState* dyn = img->dyn; 1117 const LinkSection* sec_dynamic = &img->sections[dyn->sec_dynamic - 1]; 1118 const LinkSection* sec_dynsym = &img->sections[dyn->sec_dynsym - 1]; 1119 const LinkSection* sec_dynstr = &img->sections[dyn->sec_dynstr - 1]; 1120 const LinkSection* sec_gnuhash = &img->sections[dyn->sec_gnu_hash - 1]; 1121 const LinkSection* sec_reladyn = &img->sections[dyn->sec_rela_dyn - 1]; 1122 const LinkSection* sec_relaplt = (dyn->sec_rela_plt != LINK_SEC_NONE) 1123 ? &img->sections[dyn->sec_rela_plt - 1] 1124 : NULL; 1125 const LinkSection* sec_gotplt = (dyn->sec_got_plt != LINK_SEC_NONE) 1126 ? &img->sections[dyn->sec_got_plt - 1] 1127 : NULL; 1128 const LinkSection* sec_versym = 1129 (dyn->sec_gnu_version != LINK_SEC_NONE) 1130 ? &img->sections[dyn->sec_gnu_version - 1] 1131 : NULL; 1132 const LinkSection* sec_verneed = 1133 (dyn->sec_gnu_version_r != LINK_SEC_NONE) 1134 ? &img->sections[dyn->sec_gnu_version_r - 1] 1135 : NULL; 1136 const LinkSegment* dseg = &img->segments[sec_dynamic->segment_id - 1]; 1137 u8* dyn_bytes_at = img->segment_bytes[dseg->id - 1] + 1138 (size_t)(sec_dynamic->file_offset - dseg->file_offset); 1139 1140 refresh_dynsym_exports(img, img_base); 1141 1142 /* Build DT_* entries in order. Layout matches count_dynamic_entries. */ 1143 u32 written = 0; 1144 u8* p = dyn_bytes_at; 1145 #define DT_PUT(TAG, VAL) \ 1146 do { \ 1147 wr_u64_le(p, (u64)(TAG)); \ 1148 wr_u64_le(p + 8, (u64)(VAL)); \ 1149 p += 16; \ 1150 written++; \ 1151 } while (0) 1152 1153 /* DT_NEEDED entries — d_un.d_val is the offset of the soname 1154 * within .dynstr. The dynstr was built in layout_dyn with 1155 * dedup; look each soname up by name to compute its offset. */ 1156 { 1157 u32 ni; 1158 for (ni = 0; ni < dyn->nneeded; ++ni) { 1159 Sym soname = dyn->needed[ni]; 1160 u32 off = dynstr_find_sym(c, dyn, soname, "DT_NEEDED soname"); 1161 DT_PUT(DT_NEEDED, off); 1162 } 1163 } 1164 if (dyn->soname) 1165 DT_PUT(DT_SONAME, dynstr_find_sym(c, dyn, dyn->soname, "DT_SONAME")); 1166 for (u32 ri = 0; ri < dyn->nrpaths; ++ri) 1167 DT_PUT(DT_RPATH, dynstr_find_sym(c, dyn, dyn->rpaths[ri], "DT_RPATH")); 1168 for (u32 ri = 0; ri < dyn->nrunpaths; ++ri) 1169 DT_PUT(DT_RUNPATH, 1170 dynstr_find_sym(c, dyn, dyn->runpaths[ri], "DT_RUNPATH")); 1171 1172 DT_PUT(DT_STRTAB, img_base + sec_dynstr->vaddr); 1173 DT_PUT(DT_STRSZ, sec_dynstr->size); 1174 DT_PUT(DT_SYMTAB, img_base + sec_dynsym->vaddr); 1175 DT_PUT(DT_SYMENT, 24); 1176 DT_PUT(DT_GNU_HASH, img_base + sec_gnuhash->vaddr); 1177 /* Symbol-version tables (only when an import bound a versioned export). */ 1178 if (dyn->nverneed && sec_versym && sec_verneed) { 1179 DT_PUT(DT_VERSYM, img_base + sec_versym->vaddr); 1180 DT_PUT(DT_VERNEED, img_base + sec_verneed->vaddr); 1181 DT_PUT(DT_VERNEEDNUM, dyn->nverneed); 1182 } 1183 /* DT_PLT* / DT_JMPREL only make sense when there's a PLT. Emitting 1184 * them with size=0 / vaddr=0 (or pointing past the end of any 1185 * PT_LOAD) trips llvm-readelf's "address not in any segment" check 1186 * and confuses some loaders' DT walk. */ 1187 if (dyn->nrela_plt) { 1188 DT_PUT(DT_PLTGOT, sec_gotplt ? (img_base + sec_gotplt->vaddr) : 0); 1189 DT_PUT(DT_PLTRELSZ, sec_relaplt ? sec_relaplt->size : 0); 1190 DT_PUT(DT_PLTREL, DT_RELA); 1191 DT_PUT(DT_JMPREL, sec_relaplt ? (img_base + sec_relaplt->vaddr) : 0); 1192 } 1193 if (dyn->cap_rela_dyn) { 1194 DT_PUT(DT_RELA, img_base + sec_reladyn->vaddr); 1195 DT_PUT(DT_RELASZ, sec_reladyn->size); 1196 DT_PUT(DT_RELAENT, 24); 1197 } 1198 DT_PUT(DT_FLAGS_1, DF_1_NOW); 1199 DT_PUT(DT_NULL, 0); 1200 #undef DT_PUT 1201 1202 /* Pad any pre-allocated tail with DT_NULL. */ 1203 while (written < dyn->ndyn_entries) { 1204 wr_u64_le(p, 0); 1205 wr_u64_le(p + 8, 0); 1206 p += 16; 1207 written++; 1208 } 1209 1210 /* Re-serialize .rela.dyn body. GLOB_DAT records (imports against 1211 * .got slots) and RELATIVE records (PIE internal abs64 fixups) 1212 * are both populated during apply_all_relocs; layout_dyn pre-counts 1213 * the exact number of runtime relocation records. */ 1214 { 1215 const LinkSegment* rdseg = &img->segments[sec_reladyn->segment_id - 1]; 1216 u8* rd_bytes = img->segment_bytes[rdseg->id - 1] + 1217 (size_t)(sec_reladyn->file_offset - rdseg->file_offset); 1218 u32 i; 1219 for (i = 0; i < dyn->nrela_dyn; ++i) { 1220 const DynRela* rr = &dyn->rela_dyn[i]; 1221 u8* rp = rd_bytes + (u64)i * ELF64_RELA_SIZE; 1222 wr_u64_le(rp + 0, rr->r_offset); 1223 wr_u64_le(rp + 8, rr->r_info); 1224 wr_u64_le(rp + 16, (u64)rr->r_addend); 1225 } 1226 } 1227 1228 /* Re-serialize .rela.plt body. JUMP_SLOT records were written by 1229 * layout_dyn at pre-shift vaddrs; shift_image_addresses bumped 1230 * dyn->rela_plt[i].r_offset along with the rest, so the post-shift 1231 * values match the .got.plt slot vaddrs the loader will patch. */ 1232 if (sec_relaplt && dyn->nrela_plt) { 1233 const LinkSegment* rpseg = &img->segments[sec_relaplt->segment_id - 1]; 1234 u8* rp_bytes = img->segment_bytes[rpseg->id - 1] + 1235 (size_t)(sec_relaplt->file_offset - rpseg->file_offset); 1236 u32 i; 1237 for (i = 0; i < dyn->nrela_plt; ++i) { 1238 const DynRela* rr = &dyn->rela_plt[i]; 1239 u8* rp = rp_bytes + (u64)i * ELF64_RELA_SIZE; 1240 wr_u64_le(rp + 0, rr->r_offset); 1241 wr_u64_le(rp + 8, rr->r_info); 1242 wr_u64_le(rp + 16, (u64)rr->r_addend); 1243 } 1244 } 1245 1246 /* Re-write .got.plt[0] = &.dynamic with the post-shift vaddr. 1247 * layout_dyn wrote the pre-shift value into the segment bytes; 1248 * shift_image_addresses bumped dyn->dynamic_vaddr so we can refill 1249 * the slot here. Slots 1 and 2 (link_map cookie, 1250 * _dl_runtime_resolve) are loader-owned for lazy binding; under 1251 * DF_1_NOW they're never read so leaving them zero is fine. */ 1252 if (sec_gotplt && dyn->dynamic_vaddr) { 1253 const LinkSegment* gpseg = &img->segments[sec_gotplt->segment_id - 1]; 1254 u8* gp_bytes = img->segment_bytes[gpseg->id - 1] + 1255 (size_t)(sec_gotplt->file_offset - gpseg->file_offset); 1256 wr_u64_le(gp_bytes, dyn->dynamic_vaddr); 1257 } 1258 } 1259 1260 /* ---- compute build-id (post-reloc, deterministic) ---- 1261 * 1262 * Format-agnostic — Mach-O LC_UUID will hash the same bytes. */ 1263 u8 build_id[BUILD_ID_DESC_LEN]; 1264 link_image_id_compute(img, build_id); 1265 1266 /* ---- plan section headers covering loaded segments ---- 1267 * 1268 * Worst case: 1 file shdr per segment + 1 .bss shdr if RW has a tail. 1269 * shdr indices: 0=NULL, 1..nsegshdr=these, then build-id/symtab/... 1270 */ 1271 /* Walk img->sections sorted by (segment_id, vaddr) and merge into 1272 * one OutShdr per (segment_id, name) run. layout already places 1273 * same-name sections adjacent within a segment, so a stable 1274 * by-vaddr sort followed by run-length grouping captures it. */ 1275 OutShdr* outshdrs; 1276 u32 noutshdr = 0; 1277 u32 outshdr_cap = img->nsections + 1u; 1278 outshdrs = (OutShdr*)heap->alloc(heap, sizeof(*outshdrs) * outshdr_cap, 1279 _Alignof(OutShdr)); 1280 if (!outshdrs) 1281 compiler_panic(c, SRCLOC_NONE, "link_emit_elf: oom on outshdrs"); 1282 memset(outshdrs, 0, sizeof(*outshdrs) * outshdr_cap); 1283 { 1284 /* Build a sort index over LinkSection ids by (segment_id, vaddr). */ 1285 u32* order = (u32*)heap->alloc(heap, sizeof(u32) * (img->nsections + 1u), 1286 _Alignof(u32)); 1287 if (!order && img->nsections) 1288 compiler_panic(c, SRCLOC_NONE, "link_emit_elf: oom on shdr sort"); 1289 u32 i, j; 1290 for (i = 0; i < img->nsections; ++i) order[i] = i; 1291 /* Insertion sort — section count is small. */ 1292 for (i = 1; i < img->nsections; ++i) { 1293 u32 cur = order[i]; 1294 const LinkSection* a = &img->sections[cur]; 1295 j = i; 1296 while (j > 0) { 1297 const LinkSection* b = &img->sections[order[j - 1]]; 1298 if (!shdr_sort_less(a, b)) break; /* a not before b → stop (stable) */ 1299 order[j] = order[j - 1]; 1300 --j; 1301 } 1302 order[j] = cur; 1303 } 1304 for (i = 0; i < img->nsections; ++i) { 1305 const LinkSection* ls = &img->sections[order[i]]; 1306 OutShdr* tail = noutshdr ? &outshdrs[noutshdr - 1] : NULL; 1307 int merge = tail && tail->segment_id == ls->segment_id && 1308 tail->name == ls->name && 1309 tail->is_nobits == (ls->sem == SSEM_NOBITS); 1310 if (merge) { 1311 u64 end = ls->vaddr + ls->size; 1312 u64 prev_end = tail->vaddr + tail->size; 1313 if (end > prev_end) tail->size = end - tail->vaddr; 1314 if (ls->align > tail->align) tail->align = ls->align; 1315 } else { 1316 OutShdr* o = &outshdrs[noutshdr]; 1317 o->shdr_idx = 1u + noutshdr; 1318 o->segment_id = ls->segment_id; 1319 o->name = ls->name; 1320 o->sem = ls->sem; 1321 o->flags = ls->flags; 1322 o->align = ls->align; 1323 o->vaddr = ls->vaddr; 1324 o->file_offset = ls->file_offset; 1325 o->size = ls->size; 1326 o->is_nobits = (ls->sem == SSEM_NOBITS); 1327 o->is_fileonly = ls->file_only; 1328 noutshdr++; 1329 } 1330 } 1331 heap->free(heap, order, sizeof(u32) * (img->nsections + 1u)); 1332 } 1333 1334 /* ---- build .shstrtab ---- */ 1335 ObjByteBuf shstrtab; 1336 objbb_init(&shstrtab, heap); 1337 objbb_reserve(&shstrtab, 128); 1338 objbb_u8(&shstrtab, 0); /* leading NUL: name offset 0 = empty string */ 1339 u32 sh_name_symtab = objbb_append_cstr(&shstrtab, ".symtab"); 1340 u32 sh_name_strtab = objbb_append_cstr(&shstrtab, ".strtab"); 1341 u32 sh_name_shstrtab = objbb_append_cstr(&shstrtab, ".shstrtab"); 1342 u32 sh_name_buildid = 1343 scripted ? 0u : objbb_append_cstr(&shstrtab, ".note.gnu.build-id"); 1344 /* Per-output-shdr names — interned strings from input section names. */ 1345 u32* outshdr_name_off = 1346 (u32*)heap->alloc(heap, sizeof(u32) * (noutshdr + 1u), _Alignof(u32)); 1347 if (!outshdr_name_off && noutshdr) 1348 compiler_panic(c, SRCLOC_NONE, "link_emit_elf: oom on shdr name table"); 1349 { 1350 u32 i; 1351 for (i = 0; i < noutshdr; ++i) { 1352 const OutShdr* o = &outshdrs[i]; 1353 if (o->name) { 1354 Slice nm_s = pool_slice(c->global, o->name); 1355 const char* nm = nm_s.s; 1356 size_t nlen = nm_s.len; 1357 outshdr_name_off[i] = 1358 nm && nlen ? objbb_append_str(&shstrtab, nm, (u32)nlen) : 0; 1359 } else { 1360 outshdr_name_off[i] = 0; 1361 } 1362 } 1363 } 1364 1365 u32 nbuildid_shdr = scripted ? 0u : 1u; 1366 u32 nshdr = 1u + noutshdr + nbuildid_shdr + 3u; 1367 u32 shndx_symtab = 1u + noutshdr + nbuildid_shdr; 1368 u32 shndx_strtab = shndx_symtab + 1u; 1369 u32 shndx_shstrtab = shndx_strtab + 1u; 1370 1371 /* ---- build .symtab + .strtab ---- 1372 * 1373 * Two passes (locals first, then globals/weaks). Slot 0 is 1374 * STN_UNDEF. Globals are deduped via img->globals — only the 1375 * canonical entry per name is emitted, since per-input undef 1376 * records keep their own LinkSymId after resolve_undefs's 1377 * "copy fields from canonical def" step. sh_info = first non-local 1378 * idx. */ 1379 ObjByteBuf strtab; 1380 objbb_init(&strtab, heap); 1381 objbb_reserve(&strtab, 256); 1382 objbb_u8(&strtab, 0); /* leading NUL: name offset 0 = empty string */ 1383 1384 SymRec* recs = (SymRec*)heap->alloc( 1385 heap, sizeof(*recs) * (LinkSyms_count(&img->syms) + 1u), 1386 _Alignof(SymRec)); 1387 if (!recs) compiler_panic(c, SRCLOC_NONE, "link_emit_elf: oom on symrecs"); 1388 u32 nsyms_emit = 0; 1389 u32 first_global_idx; 1390 memset(&recs[nsyms_emit++], 0, sizeof(*recs)); /* slot 0 */ 1391 first_global_idx = nsyms_emit; 1392 1393 { 1394 u32 pass, i; 1395 for (pass = 0; pass < 2; ++pass) { 1396 int want_local = (pass == 0); 1397 if (!want_local) first_global_idx = nsyms_emit; 1398 for (i = 0; i < LinkSyms_count(&img->syms); ++i) { 1399 const LinkSymbol* s = LinkSyms_at(&img->syms, i); 1400 int is_local = (s->bind == SB_LOCAL); 1401 size_t namelen = 0; 1402 const char* nm; 1403 u8 st_type, st_bind; 1404 u16 shndx; 1405 u64 st_value; 1406 SymRec* r; 1407 if (want_local != is_local) continue; 1408 if (s->name == 0 && s->kind != SK_FILE) continue; 1409 /* Dedupe globals: per-input undef-of-X and the canonical 1410 * def-of-X are separate img->syms entries (resolve_undefs 1411 * mirrors fields onto the undef). Only the canonical 1412 * (first registered) entry is in img->globals. Skip the 1413 * shadow copies. */ 1414 if (!is_local && s->name && 1415 !link_symbol_is_canonical_global(img, s)) 1416 continue; 1417 { 1418 Slice nm_s = s->name ? pool_slice(c->global, s->name) : SLICE_NULL; 1419 nm = nm_s.s ? nm_s.s : ""; 1420 namelen = nm_s.len; 1421 } 1422 shndx = sym_shndx_for(s, outshdrs, noutshdr); 1423 /* st_value: in ET_EXEC, defined non-ABS symbols carry 1424 * absolute virtual addresses (IMAGE_BASE + image 1425 * vaddr); ABS symbols carry their own value verbatim. */ 1426 if (s->kind == SK_FILE) 1427 st_value = 0; 1428 else if (s->kind == SK_ABS) 1429 st_value = s->vaddr; 1430 else if (s->defined) 1431 st_value = img_base + s->vaddr; 1432 else 1433 st_value = 0; 1434 st_type = sym_kind_to_st_type(s->kind); 1435 st_bind = sym_bind_to_st_bind(s->bind); 1436 r = &recs[nsyms_emit++]; 1437 memset(r, 0, sizeof(*r)); 1438 r->st_name = 1439 (nm && namelen) ? objbb_append_str(&strtab, nm, (u32)namelen) : 0; 1440 r->st_info = ELF64_ST_INFO(st_bind, st_type); 1441 r->st_other = STV_DEFAULT; 1442 r->st_shndx = shndx; 1443 r->st_value = st_value; 1444 r->st_size = s->size; 1445 } 1446 } 1447 } 1448 1449 /* ---- compute file offsets for trailing non-alloc sections ---- */ 1450 /* End of segment data: the highest (file_offset + file_size) across 1451 * loaded segments. */ 1452 u64 end_of_segs = headers_load; 1453 { 1454 u32 i; 1455 for (i = 0; i < img->nsegments; ++i) { 1456 const LinkSegment* seg = &img->segments[i]; 1457 u64 e = seg->file_offset + seg->file_size; 1458 if (e > end_of_segs) end_of_segs = e; 1459 } 1460 } 1461 /* File-only debug sections go in the trailing non-alloc region, after 1462 * the loaded segments and before .symtab. Assign each merged debug 1463 * OutShdr a file offset (and propagate it back to its constituent 1464 * LinkSections for the byte-write pass). */ 1465 u64 dbg_cursor = end_of_segs; 1466 if (img->dbg_count) { 1467 u32 oi; 1468 for (oi = 0; oi < noutshdr; ++oi) { 1469 OutShdr* o = &outshdrs[oi]; 1470 u32 si; 1471 if (!o->is_fileonly) continue; 1472 o->file_offset = ALIGN_UP(dbg_cursor, o->align ? o->align : 1u); 1473 for (si = 0; si < img->dbg_count; ++si) { 1474 LinkSection* ls = &img->sections[img->dbg_first_lsid - 1 + si]; 1475 if (ls->name == o->name) 1476 ls->file_offset = o->file_offset + ls->vaddr; /* base within run */ 1477 } 1478 dbg_cursor = o->file_offset + o->size; 1479 } 1480 } 1481 u64 symtab_off = ALIGN_UP(dbg_cursor, (u64)8u); 1482 u32 sym_size = class32 ? ELF32_SYM_SIZE : ELF64_SYM_SIZE; 1483 u64 symtab_size = (u64)sym_size * nsyms_emit; 1484 u64 strtab_off = symtab_off + symtab_size; 1485 u64 strtab_size = strtab.len; 1486 u64 shstrtab_off = strtab_off + strtab_size; 1487 u64 shstrtab_size = shstrtab.len; 1488 u64 shdr_off = ALIGN_UP(shstrtab_off + shstrtab_size, (u64)8u); 1489 1490 /* ---- build phdrs ---- */ 1491 Phdr64* phdrs = (Phdr64*)heap->alloc(heap, sizeof(Phdr64) * nphdr_total, 1492 _Alignof(Phdr64)); 1493 if (!phdrs) compiler_panic(c, SRCLOC_NONE, "link_emit_elf: oom on phdrs"); 1494 memset(phdrs, 0, sizeof(Phdr64) * nphdr_total); 1495 { 1496 u32 pi = 0; 1497 /* PT_PHDR points at the phdr table itself within the headers 1498 * PT_LOAD. Required by the runtime loader for ET_DYN to know 1499 * where its own program headers live. Must appear before the 1500 * first PT_LOAD on dynamic exes (musl checks). */ 1501 if ((pie || shared) && img->dyn) { 1502 phdrs[pi].p_type = PT_PHDR; 1503 phdrs[pi].p_flags = PF_R; 1504 phdrs[pi].p_offset = sizeof(Ehdr64); 1505 phdrs[pi].p_vaddr = img_base + sizeof(Ehdr64); 1506 phdrs[pi].p_paddr = phdrs[pi].p_vaddr; 1507 phdrs[pi].p_filesz = (u64)nphdr_total * sizeof(Phdr64); 1508 phdrs[pi].p_memsz = phdrs[pi].p_filesz; 1509 phdrs[pi].p_align = 8; 1510 pi++; 1511 } 1512 /* Headers PT_LOAD (covers ehdr + phdrs + build-id note). 1513 * Scripted images don't emit one — see plan note above. */ 1514 if (!scripted) { 1515 phdrs[pi].p_type = PT_LOAD; 1516 phdrs[pi].p_flags = PF_R; 1517 phdrs[pi].p_offset = 0; 1518 phdrs[pi].p_vaddr = img_base; 1519 phdrs[pi].p_paddr = img_base; 1520 phdrs[pi].p_filesz = headers_size; 1521 phdrs[pi].p_memsz = headers_size; 1522 phdrs[pi].p_align = PAGE_SIZE; 1523 pi++; 1524 } 1525 /* Per-segment PT_LOAD. */ 1526 u32 i; 1527 for (i = 0; i < img->nsegments; ++i) { 1528 const LinkSegment* seg = &img->segments[i]; 1529 Phdr64* p = &phdrs[pi++]; 1530 p->p_type = seg->phdr_type ? seg->phdr_type : PT_LOAD; 1531 p->p_flags = 1532 seg->phdr_flags_set ? seg->phdr_flags : perms_to_pflags(seg->flags); 1533 p->p_offset = seg->file_offset; 1534 p->p_vaddr = img_base + seg->vaddr; /* post-shift */ 1535 p->p_paddr = img_base + seg->paddr; 1536 p->p_filesz = seg->file_size; 1537 /* TLS .tbss is per-thread template space, not a loadable bss 1538 * region — PT_TLS already records the full memsz (incl. .tbss) 1539 * for the loader's per-thread allocation, so the matching 1540 * PT_LOAD must not extend memsz past filesz. qemu-riscv64 1541 * rejects PT_LOADs with memsz>filesz on non-writable mappings 1542 * ("PT_LOAD with non-writable bss"), and the SEG_TLS perms are 1543 * SF_ALLOC|SF_TLS only. */ 1544 p->p_memsz = (seg->flags & SF_TLS) ? seg->file_size : seg->mem_size; 1545 p->p_align = seg->align ? seg->align : PAGE_SIZE; 1546 } 1547 /* Allocatable SHT_NOTE sections can also be addressed by PT_NOTE. QEMU's 1548 * x86 PVH loader uses this for XEN_ELFNOTE_PHYS32_ENTRY while the bytes 1549 * still live in the normal read-only PT_LOAD. */ 1550 for (i = 0; i < img->nsections; ++i) { 1551 const LinkSection* s = &img->sections[i]; 1552 Phdr64* p; 1553 if (s->file_only || s->sem != SSEM_NOTE || s->size == 0) continue; 1554 p = &phdrs[pi++]; 1555 p->p_type = PT_NOTE; 1556 p->p_flags = PF_R; 1557 p->p_offset = s->file_offset; 1558 p->p_vaddr = img_base + s->vaddr; 1559 p->p_paddr = p->p_vaddr; 1560 p->p_filesz = s->size; 1561 p->p_memsz = s->size; 1562 p->p_align = s->align ? s->align : 4; 1563 } 1564 /* PT_NOTE for build-id. Scripted images skip the build-id entirely. */ 1565 if (!scripted) { 1566 phdrs[pi].p_type = PT_NOTE; 1567 phdrs[pi].p_flags = PF_R; 1568 phdrs[pi].p_offset = build_id_off; 1569 phdrs[pi].p_vaddr = build_id_addr; 1570 phdrs[pi].p_paddr = build_id_addr; 1571 phdrs[pi].p_filesz = BUILD_ID_NOTE_BYTES; 1572 phdrs[pi].p_memsz = BUILD_ID_NOTE_BYTES; 1573 phdrs[pi].p_align = 4; 1574 pi++; 1575 } 1576 /* PT_TLS describing the .tdata template + .tbss zero-fill. 1577 * vaddr/file_offset point at the same bytes the matching 1578 * PT_LOAD already covers — the loader uses PT_TLS to size 1579 * each thread's TLS block and to seed it from .tdata. */ 1580 if (has_tls) { 1581 phdrs[pi].p_type = PT_TLS; 1582 phdrs[pi].p_flags = PF_R; 1583 phdrs[pi].p_offset = img->tls_vaddr; 1584 phdrs[pi].p_vaddr = img_base + img->tls_vaddr; 1585 phdrs[pi].p_paddr = phdrs[pi].p_vaddr; 1586 phdrs[pi].p_filesz = img->tls_filesz; 1587 phdrs[pi].p_memsz = img->tls_memsz; 1588 phdrs[pi].p_align = img->tls_align ? img->tls_align : 1u; 1589 pi++; 1590 } 1591 /* Dynamic phdrs. PT_INTERP and PT_DYNAMIC point at the matching 1592 * sections (which layout_dyn placed in the ro/rw_dyn segments). 1593 * PT_GNU_STACK marks the stack as non-executable (filesz=0). */ 1594 if ((pie || shared) && img->dyn) { 1595 LinkDynState* dyn = img->dyn; 1596 const LinkSection* sec_dynamic = &img->sections[dyn->sec_dynamic - 1]; 1597 if (!shared) { 1598 const LinkSection* sec_interp = &img->sections[dyn->sec_interp - 1]; 1599 phdrs[pi].p_type = PT_INTERP; 1600 phdrs[pi].p_flags = PF_R; 1601 phdrs[pi].p_offset = sec_interp->file_offset; 1602 phdrs[pi].p_vaddr = img_base + sec_interp->vaddr; 1603 phdrs[pi].p_paddr = phdrs[pi].p_vaddr; 1604 phdrs[pi].p_filesz = sec_interp->size; 1605 phdrs[pi].p_memsz = sec_interp->size; 1606 phdrs[pi].p_align = 1; 1607 pi++; 1608 } 1609 phdrs[pi].p_type = PT_DYNAMIC; 1610 phdrs[pi].p_flags = PF_R | PF_W; 1611 phdrs[pi].p_offset = sec_dynamic->file_offset; 1612 phdrs[pi].p_vaddr = img_base + sec_dynamic->vaddr; 1613 phdrs[pi].p_paddr = phdrs[pi].p_vaddr; 1614 phdrs[pi].p_filesz = sec_dynamic->size; 1615 phdrs[pi].p_memsz = sec_dynamic->size; 1616 phdrs[pi].p_align = 8; 1617 pi++; 1618 phdrs[pi].p_type = PT_GNU_STACK; 1619 phdrs[pi].p_flags = PF_R | PF_W; 1620 phdrs[pi].p_offset = 0; 1621 phdrs[pi].p_vaddr = 0; 1622 phdrs[pi].p_paddr = 0; 1623 phdrs[pi].p_filesz = 0; 1624 phdrs[pi].p_memsz = 0; 1625 phdrs[pi].p_align = 16; 1626 pi++; 1627 /* PT_GNU_RELRO would mark the read-only-after-relocation span 1628 * here. Phase 6 leaves it out — it's an optimization the loader 1629 * can live without, and our ro_seg already lives in a PF_R 1630 * PT_LOAD that's never made writable. */ 1631 } else if (pie || shared) { 1632 /* dyn was nominally requested but layout_dyn early-out — no 1633 * imports and no DSO inputs. INTERP/DYNAMIC loader headers are skipped. 1634 */ 1635 (void)0; 1636 } 1637 (void)pi; 1638 } 1639 1640 /* ---- build ehdr ---- */ 1641 Ehdr64 ehdr; 1642 memset(&ehdr, 0, sizeof(ehdr)); 1643 ehdr.e_ident[0] = ELFMAG0; 1644 ehdr.e_ident[1] = ELFMAG1; 1645 ehdr.e_ident[2] = ELFMAG2; 1646 ehdr.e_ident[3] = ELFMAG3; 1647 ehdr.e_ident[4] = class32 ? ELFCLASS32 : ELFCLASS64; 1648 ehdr.e_ident[5] = ELFDATA2LSB; 1649 ehdr.e_ident[6] = EV_CURRENT; 1650 ehdr.e_ident[7] = ELFOSABI_NONE; 1651 /* Brand FreeBSD executables with EI_OSABI=ELFOSABI_FREEBSD; the kernel 1652 * matches that brand directly. Without it a static binary is rejected with 1653 * ENOEXEC -- the FreeBSD ABI note crt1.o carries is not sufficient on its 1654 * own for kit's images (the kernel's note scan does not recognize the 1655 * layout), so we set the OSABI on every arch (FreeBSD/clang only sets it on 1656 * amd64/aarch64, but the riscv64 kernel accepts it too). */ 1657 if (img->c->target.os == KIT_OS_FREEBSD) ehdr.e_ident[7] = ELFOSABI_FREEBSD; 1658 ehdr.e_type = (pie || shared) ? ET_DYN : ET_EXEC; 1659 ehdr.e_machine = (u16)e_machine; 1660 ehdr.e_version = EV_CURRENT; 1661 ehdr.e_entry = img->entry_sym == LINK_SYM_NONE 1662 ? 0 1663 : img_base + 1664 LinkSyms_at(&img->syms, img->entry_sym - 1)->vaddr; 1665 ehdr.e_phoff = ehdr_sz; 1666 ehdr.e_shoff = shdr_off; 1667 /* Preserve the linker's psABI merge. RVC/TSO are presence bits and were 1668 * ORed across selected inputs; float-ABI/RVE/reserved bits were required to 1669 * agree. A synthetic/no-input image falls back to the arch descriptor. */ 1670 ehdr.e_flags = arch->e_flags; 1671 if (e_machine == EM_RISCV && img->have_elf_e_flags) { 1672 ehdr.e_flags = img->elf_e_flags; 1673 } else if (e_machine == EM_RISCV) { 1674 u32 fa = elf_riscv_float_abi_to_e_flags(c->target.float_abi); 1675 ehdr.e_flags = (ehdr.e_flags & ~(u32)EF_RISCV_FLOAT_ABI_MASK) | fa; 1676 } 1677 ehdr.e_ehsize = (u16)ehdr_sz; 1678 ehdr.e_phentsize = (u16)phent_sz; 1679 ehdr.e_phnum = (u16)nphdr_total; 1680 ehdr.e_shentsize = (u16)elf_shdr_sz(class32); 1681 ehdr.e_shnum = (u16)nshdr; 1682 ehdr.e_shstrndx = (u16)shndx_shstrtab; 1683 1684 /* ---- write ehdr, phdrs, build-id note, pad ---- */ 1685 u64 cur_off; 1686 write_ehdr(w, &ehdr, class32); 1687 write_phdrs(w, phdrs, nphdr_total, class32); 1688 cur_off = ehdr_sz + phent_sz * nphdr_total; 1689 1690 /* .note.gnu.build-id wire format: 1691 * u32 namesz = 4 ("GNU\0") 1692 * u32 descsz = 16 1693 * u32 type = NT_GNU_BUILD_ID (3) 1694 * "GNU\0" 1695 * <16 bytes of build-id> 1696 * 1697 * Scripted images don't carry build-id; they have no PT_NOTE phdr to 1698 * point at it and the file payload would just be dead bytes. */ 1699 if (!scripted) { 1700 u8 nh[12]; 1701 u32 v; 1702 v = NOTE_NAME_GNU_LEN; 1703 nh[0] = (u8)v; 1704 nh[1] = (u8)(v >> 8); 1705 nh[2] = (u8)(v >> 16); 1706 nh[3] = (u8)(v >> 24); 1707 v = BUILD_ID_DESC_LEN; 1708 nh[4] = (u8)v; 1709 nh[5] = (u8)(v >> 8); 1710 nh[6] = (u8)(v >> 16); 1711 nh[7] = (u8)(v >> 24); 1712 v = NOTE_BUILD_ID_TYPE; 1713 nh[8] = (u8)v; 1714 nh[9] = (u8)(v >> 8); 1715 nh[10] = (u8)(v >> 16); 1716 nh[11] = (u8)(v >> 24); 1717 write_bytes(w, nh, sizeof nh); 1718 write_bytes(w, NOTE_NAME_GNU "\0", NOTE_NAME_GNU_LEN); 1719 write_bytes(w, build_id, BUILD_ID_DESC_LEN); 1720 cur_off += BUILD_ID_NOTE_BYTES; 1721 } 1722 1723 /* Pad to first segment file_offset (== headers_load). */ 1724 { 1725 u32 i; 1726 for (i = 0; i < img->nsegments; ++i) { 1727 const LinkSegment* seg = &img->segments[i]; 1728 /* Alias program headers (a section listed under several :phdrs) have no 1729 * byte buffer of their own — their file range already lives on disk via 1730 * the primary segment, so skip them here (their phdr still describes the 1731 * shared file range). */ 1732 if (seg->file_size == 0 || img->segment_bytes[seg->id - 1] == NULL) 1733 continue; 1734 if (cur_off < seg->file_offset) { 1735 write_zeroes(w, (size_t)(seg->file_offset - cur_off)); 1736 cur_off = seg->file_offset; 1737 } 1738 write_bytes(w, img->segment_bytes[seg->id - 1], (size_t)seg->file_size); 1739 cur_off += seg->file_size; 1740 } 1741 } 1742 1743 /* ---- write file-only debug sections ---- * 1744 * 1745 * Emit each merged debug OutShdr at its assigned file offset by 1746 * writing its constituent contributions in base order (the registry 1747 * is per-name base-ascending). OutShdrs were placed at ascending file 1748 * offsets, so cur_off advances monotonically. */ 1749 if (img->dbg_count) { 1750 u32 oi; 1751 for (oi = 0; oi < noutshdr; ++oi) { 1752 const OutShdr* o = &outshdrs[oi]; 1753 u32 si; 1754 if (!o->is_fileonly) continue; 1755 if (cur_off < o->file_offset) { 1756 write_zeroes(w, (size_t)(o->file_offset - cur_off)); 1757 cur_off = o->file_offset; 1758 } 1759 for (si = 0; si < img->dbg_count; ++si) { 1760 const LinkSection* ls = &img->sections[img->dbg_first_lsid - 1 + si]; 1761 if (ls->name != o->name || img->dbg_size[si] == 0) continue; 1762 write_bytes(w, img->dbg_bytes[si], (size_t)img->dbg_size[si]); 1763 cur_off += img->dbg_size[si]; 1764 } 1765 } 1766 } 1767 1768 /* ---- write trailing non-alloc sections ---- */ 1769 if (cur_off < symtab_off) { 1770 write_zeroes(w, (size_t)(symtab_off - cur_off)); 1771 cur_off = symtab_off; 1772 } 1773 { 1774 u32 i; 1775 for (i = 0; i < nsyms_emit; ++i) write_sym_rec(w, &recs[i], class32); 1776 cur_off += symtab_size; 1777 } 1778 if (strtab.len) { 1779 write_bytes(w, strtab.data, strtab.len); 1780 cur_off += strtab.len; 1781 } 1782 if (shstrtab.len) { 1783 write_bytes(w, shstrtab.data, shstrtab.len); 1784 cur_off += shstrtab.len; 1785 } 1786 1787 /* ---- write section header table ---- */ 1788 if (cur_off < shdr_off) { 1789 write_zeroes(w, (size_t)(shdr_off - cur_off)); 1790 cur_off = shdr_off; 1791 } 1792 { 1793 Shdr64 sh; 1794 u32 i; 1795 /* shdr 0: NULL */ 1796 memset(&sh, 0, sizeof(sh)); 1797 write_shdr(w, &sh, class32); 1798 /* Locate dyn-section names (interned earlier in layout_dyn) so 1799 * we can override sh_type / sh_link / sh_info / sh_entsize for 1800 * .dynsym / .dynstr / .gnu.hash / .rela.dyn / .rela.plt / 1801 * .dynamic. The sh_link cross-references (e.g., .dynsym -> 1802 * .dynstr) need the matching shdr indices, which we look up by 1803 * comparing OutShdr.name to the same Sym values. */ 1804 Sym n_dynsym = 0, n_dynstr = 0, n_gnuhash = 0; 1805 Sym n_reladyn = 0, n_relaplt = 0, n_dynamic = 0; 1806 Sym n_gotplt = 0, n_gnuver = 0, n_gnuver_r = 0; 1807 if ((pie || shared) && img->dyn) { 1808 n_dynsym = pool_intern_slice(c->global, SLICE_LIT(".dynsym")); 1809 n_dynstr = pool_intern_slice(c->global, SLICE_LIT(".dynstr")); 1810 n_gnuhash = pool_intern_slice(c->global, SLICE_LIT(".gnu.hash")); 1811 n_reladyn = pool_intern_slice(c->global, SLICE_LIT(".rela.dyn")); 1812 n_relaplt = pool_intern_slice(c->global, SLICE_LIT(".rela.plt")); 1813 n_dynamic = pool_intern_slice(c->global, SLICE_LIT(".dynamic")); 1814 n_gotplt = pool_intern_slice(c->global, SLICE_LIT(".got.plt")); 1815 n_gnuver = pool_intern_slice(c->global, SLICE_LIT(".gnu.version")); 1816 n_gnuver_r = pool_intern_slice(c->global, SLICE_LIT(".gnu.version_r")); 1817 } 1818 /* Two-pass: first find dynsym/dynstr/gotplt indices for sh_link 1819 * fixups, then emit. */ 1820 u32 idx_dynsym = 0, idx_dynstr = 0, idx_gotplt = 0; 1821 if ((pie || shared) && img->dyn) { 1822 for (i = 0; i < noutshdr; ++i) { 1823 Sym nm = outshdrs[i].name; 1824 u32 ix = outshdrs[i].shdr_idx; 1825 if (nm == n_dynsym) 1826 idx_dynsym = ix; 1827 else if (nm == n_dynstr) 1828 idx_dynstr = ix; 1829 else if (nm == n_gotplt) 1830 idx_gotplt = ix; 1831 } 1832 } 1833 /* per-name output shdrs */ 1834 for (i = 0; i < noutshdr; ++i) { 1835 const OutShdr* o = &outshdrs[i]; 1836 memset(&sh, 0, sizeof(sh)); 1837 sh.sh_name = outshdr_name_off[i]; 1838 sh.sh_type = sec_sem_to_sht(o->sem); 1839 sh.sh_flags = sec_flags_to_shf(o->flags); 1840 sh.sh_addr = img_base + o->vaddr; 1841 /* File-only debug sections aren't loaded: SHT_PROGBITS, no 1842 * SHF_ALLOC, sh_addr 0. addr2line / gdb read them by file offset. */ 1843 if (o->is_fileonly) { 1844 sh.sh_type = SHT_PROGBITS; 1845 sh.sh_flags = 0; 1846 sh.sh_addr = 0; 1847 } 1848 sh.sh_offset = o->file_offset; 1849 sh.sh_size = o->size; 1850 sh.sh_link = 0; 1851 sh.sh_info = 0; 1852 sh.sh_addralign = o->align ? o->align : 1; 1853 sh.sh_entsize = (o->sem == SSEM_INIT_ARRAY || o->sem == SSEM_FINI_ARRAY || 1854 o->sem == SSEM_PREINIT_ARRAY) 1855 ? 8 1856 : 0; 1857 /* Dyn-section overrides: sh_type / sh_link / sh_info / entsize. */ 1858 if ((pie || shared) && img->dyn) { 1859 if (o->name == n_dynsym) { 1860 sh.sh_type = SHT_DYNSYM; 1861 sh.sh_link = idx_dynstr; 1862 sh.sh_info = img->dyn->first_global; 1863 sh.sh_entsize = 24; 1864 } else if (o->name == n_dynstr) { 1865 sh.sh_type = SHT_STRTAB; 1866 } else if (o->name == n_gnuhash) { 1867 sh.sh_type = SHT_GNU_HASH; 1868 sh.sh_link = idx_dynsym; 1869 } else if (o->name == n_reladyn) { 1870 sh.sh_type = SHT_RELA; 1871 sh.sh_link = idx_dynsym; 1872 sh.sh_entsize = 24; 1873 } else if (o->name == n_relaplt) { 1874 sh.sh_type = SHT_RELA; 1875 sh.sh_link = idx_dynsym; 1876 sh.sh_info = idx_gotplt; 1877 sh.sh_entsize = 24; 1878 sh.sh_flags |= SHF_INFO_LINK; 1879 } else if (o->name == n_dynamic) { 1880 sh.sh_type = SHT_DYNAMIC; 1881 sh.sh_link = idx_dynstr; 1882 sh.sh_entsize = 16; 1883 } else if (o->name == n_gnuver) { 1884 sh.sh_type = SHT_GNU_VERSYM; 1885 sh.sh_link = idx_dynsym; 1886 sh.sh_entsize = 2; 1887 } else if (o->name == n_gnuver_r) { 1888 sh.sh_type = SHT_GNU_VERNEED; 1889 sh.sh_link = idx_dynstr; 1890 sh.sh_info = img->dyn->nverneed; 1891 } else if (o->name == n_gotplt) { 1892 sh.sh_entsize = 8; 1893 } 1894 } 1895 write_shdr(w, &sh, class32); 1896 } 1897 /* shdr: .note.gnu.build-id (allocatable; in headers PT_LOAD) */ 1898 if (!scripted) { 1899 memset(&sh, 0, sizeof(sh)); 1900 sh.sh_name = sh_name_buildid; 1901 sh.sh_type = SHT_NOTE; 1902 sh.sh_flags = SHF_ALLOC; 1903 sh.sh_addr = build_id_addr; 1904 sh.sh_offset = build_id_off; 1905 sh.sh_size = BUILD_ID_NOTE_BYTES; 1906 sh.sh_addralign = 4; 1907 write_shdr(w, &sh, class32); 1908 } 1909 /* shdr: .symtab */ 1910 memset(&sh, 0, sizeof(sh)); 1911 sh.sh_name = sh_name_symtab; 1912 sh.sh_type = SHT_SYMTAB; 1913 sh.sh_flags = 0; 1914 sh.sh_addr = 0; 1915 sh.sh_offset = symtab_off; 1916 sh.sh_size = symtab_size; 1917 sh.sh_link = shndx_strtab; 1918 sh.sh_info = first_global_idx; 1919 sh.sh_addralign = 8; 1920 sh.sh_entsize = sym_size; 1921 write_shdr(w, &sh, class32); 1922 /* shdr: .strtab */ 1923 memset(&sh, 0, sizeof(sh)); 1924 sh.sh_name = sh_name_strtab; 1925 sh.sh_type = SHT_STRTAB; 1926 sh.sh_offset = strtab_off; 1927 sh.sh_size = strtab_size; 1928 sh.sh_addralign = 1; 1929 write_shdr(w, &sh, class32); 1930 /* shdr: .shstrtab */ 1931 memset(&sh, 0, sizeof(sh)); 1932 sh.sh_name = sh_name_shstrtab; 1933 sh.sh_type = SHT_STRTAB; 1934 sh.sh_offset = shstrtab_off; 1935 sh.sh_size = shstrtab_size; 1936 sh.sh_addralign = 1; 1937 write_shdr(w, &sh, class32); 1938 } 1939 1940 heap->free(heap, phdrs, sizeof(Phdr64) * nphdr_total); 1941 heap->free(heap, recs, sizeof(*recs) * (LinkSyms_count(&img->syms) + 1u)); 1942 heap->free(heap, outshdrs, sizeof(*outshdrs) * outshdr_cap); 1943 if (outshdr_name_off) 1944 heap->free(heap, outshdr_name_off, sizeof(u32) * (noutshdr + 1u)); 1945 objbb_fini(&strtab); 1946 objbb_fini(&shstrtab); 1947 }