kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

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 }