kit

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

commit 21fd4234fd63e43ca4828e8ff798dc05f845a941
parent 69fac96d4e100e83ff5c3f79b043c4aad3d327fd
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Wed,  3 Jun 2026 10:31:55 -0700

obj: single-source ELF sym tables + writer LE helpers

Refactor (1): SymKind/SymBind/SymVis -> ELF wire value was restated as
forward switches in both link.c (sym_kind_to_st_type/sym_bind_to_st_bind)
and emit.c (sym_kind_to_elf/sym_bind_to_elf/sym_vis_to_elf). Collapse to
three single-source tables in elf.h (kElfStType/kElfStBind/kElfStOther),
each behind a static-inline accessor (elf_st_type/bind/other) so unused
TUs don't trip -Wunused-const-variable. The base SK_COMMON->STT_OBJECT
shape lives in the table; link.c keeps its one-line COMMON->STT_NOTYPE
override at its call site. read.c's inverse switches are untouched
(single-source already).

Refactor (2): the byte-identical Writer-bridging LE emit helpers
(elf_wr_u8/16/32/64, coff_wr_u8/16/32/64, macho wr_u32/wr_u64) are
folded into writer_u8/16/32/64_le in core/bytes.h, with the per-format
spellings now thin #define aliases. read.c's elf_rd_* call sites route
to rd_*_le directly.

No functional change; build + test-elf/coff/macho/link/ar green.

(cherry picked from commit 911caf7f4ee09e3f98b7e1961a6034586c751650)

Diffstat:
Msrc/core/bytes.h | 27+++++++++++++++++++++++++++
Msrc/obj/coff/coff.h | 32+++++++-------------------------
Msrc/obj/elf/elf.h | 76+++++++++++++++++++++++++++++++++++++++++++++++-----------------------------
Msrc/obj/elf/emit.c | 65++++++++---------------------------------------------------------
Msrc/obj/elf/link.c | 36++++++------------------------------
Msrc/obj/elf/read.c | 124++++++++++++++++++++++++++++++++++++++++----------------------------------------
Msrc/obj/macho/emit.c | 16++++------------
7 files changed, 161 insertions(+), 215 deletions(-)

diff --git a/src/core/bytes.h b/src/core/bytes.h @@ -50,4 +50,31 @@ static inline void wr_u32_be(u8* p, u32 v) { p[3] = (u8)(v); } +/* Writer-bridging little-endian emit helpers — stage to a stack buffer + * via the wr_*_le primitives above, then push the bytes through a + * Writer. ELF / COFF / Mach-O object emitters all share these. */ + +static inline void writer_u8_le(Writer* w, u32 v) { + u8 b = (u8)v; + kit_writer_write(w, &b, 1); +} + +static inline void writer_u16_le(Writer* w, u32 v) { + u8 b[2]; + wr_u16_le(b, (u16)v); + kit_writer_write(w, b, 2); +} + +static inline void writer_u32_le(Writer* w, u32 v) { + u8 b[4]; + wr_u32_le(b, v); + kit_writer_write(w, b, 4); +} + +static inline void writer_u64_le(Writer* w, u64 v) { + u8 b[8]; + wr_u64_le(b, v); + kit_writer_write(w, b, 8); +} + #endif diff --git a/src/obj/coff/coff.h b/src/obj/coff/coff.h @@ -566,31 +566,13 @@ u32 coff_aarch64_reloc_to(u32 kind /* RelocKind */); u32 coff_aarch64_reloc_from(u32 wire_type); /* ---- little-endian byte writers/readers (Writer-based) ---- - * Reads use rd_u*_le from core/bytes.h directly; only writes need the - * Writer-bridging wrappers. */ - -static inline void coff_wr_u8(Writer* w, u32 v) { - u8 b = (u8)v; - kit_writer_write(w, &b, 1); -} - -static inline void coff_wr_u16(Writer* w, u32 v) { - u8 b[2]; - wr_u16_le(b, (u16)v); - kit_writer_write(w, b, 2); -} - -static inline void coff_wr_u32(Writer* w, u32 v) { - u8 b[4]; - wr_u32_le(b, v); - kit_writer_write(w, b, 4); -} - -static inline void coff_wr_u64(Writer* w, u64 v) { - u8 b[8]; - wr_u64_le(b, v); - kit_writer_write(w, b, 8); -} + * Writes go through the shared writer_u*_le helpers (core/bytes.h); the + * coff_wr_* / coff_rd_* aliases keep the COFF spelling at call sites. */ + +#define coff_wr_u8 writer_u8_le +#define coff_wr_u16 writer_u16_le +#define coff_wr_u32 writer_u32_le +#define coff_wr_u64 writer_u64_le static inline u16 coff_rd_u16(const u8* p) { return rd_u16_le(p); } static inline u32 coff_rd_u32(const u8* p) { return rd_u32_le(p); } diff --git a/src/obj/elf/elf.h b/src/obj/elf/elf.h @@ -120,6 +120,45 @@ #define ELF64_R_TYPE(i) ((u32)((i) & 0xffffffffu)) #define ELF64_R_INFO(s, t) ((((u64)(s)) << 32) | ((u64)(t) & 0xffffffffull)) +/* ---- kit SymKind/SymBind/SymVis -> ELF wire value, single source ---- + * One table per axis, indexed by the kit obj.h enum, wrapped in a + * static-inline accessor so unused TUs that include elf.h don't trip + * -Wunused-const-variable. SK_COMMON maps to STT_OBJECT here (the shape + * clang/gcc/GNU-as emit: STT_OBJECT + shndx=SHN_COMMON); the linker's + * symbol writer overrides COMMON to STT_NOTYPE at its call site. */ +static inline u8 elf_st_type(u8 kind /* SymKind */) { + static const u8 kElfStType[] = { + [SK_UNDEF] = STT_NOTYPE, [SK_FUNC] = STT_FUNC, + [SK_OBJ] = STT_OBJECT, [SK_SECTION] = STT_SECTION, + [SK_FILE] = STT_FILE, [SK_COMMON] = STT_OBJECT, + [SK_TLS] = STT_TLS, [SK_ABS] = STT_NOTYPE, + [SK_NOTYPE] = STT_NOTYPE, [SK_IFUNC] = STT_GNU_IFUNC, + }; + if (kind >= (u8)(sizeof kElfStType / sizeof kElfStType[0])) return STT_NOTYPE; + return kElfStType[kind]; +} + +static inline u8 elf_st_bind(u8 bind /* SymBind */) { + static const u8 kElfStBind[] = { + [SB_LOCAL] = STB_LOCAL, + [SB_GLOBAL] = STB_GLOBAL, + [SB_WEAK] = STB_WEAK, + }; + if (bind >= (u8)(sizeof kElfStBind / sizeof kElfStBind[0])) return STB_LOCAL; + return kElfStBind[bind]; +} + +static inline u8 elf_st_other(u8 vis /* SymVis */) { + static const u8 kElfStOther[] = { + [SV_DEFAULT] = STV_DEFAULT, + [SV_HIDDEN] = STV_HIDDEN, + [SV_PROTECTED] = STV_PROTECTED, + [SV_INTERNAL] = STV_INTERNAL, + }; + if (vis >= (u8)(sizeof kElfStOther / sizeof kElfStOther[0])) return STV_DEFAULT; + return kElfStOther[vis]; +} + /* ---- program header ---- */ #define PT_NULL 0 #define PT_LOAD 1 @@ -343,37 +382,16 @@ u32 elf_x86_64_reloc_from(u32 elf_type); u32 elf_riscv64_reloc_to(u32 kind /* RelocKind */); u32 elf_riscv64_reloc_from(u32 elf_type); -/* ---- little-endian byte writers/readers (Writer-based) ---- - * Reads use rd_u*_le from core/bytes.h directly; only writes need the - * Writer-bridging wrappers below. */ +/* ---- little-endian byte writers (Writer-based) ---- + * Writes go through the shared writer_u*_le helpers (core/bytes.h); the + * elf_wr_* aliases keep the ELF spelling at existing call sites. Reads + * use rd_u*_le from core/bytes.h directly. */ #include "core/bytes.h" -static inline void elf_wr_u8(Writer* w, u32 v) { - u8 b = (u8)v; - kit_writer_write(w, &b, 1); -} - -static inline void elf_wr_u16(Writer* w, u32 v) { - u8 b[2]; - wr_u16_le(b, (u16)v); - kit_writer_write(w, b, 2); -} - -static inline void elf_wr_u32(Writer* w, u32 v) { - u8 b[4]; - wr_u32_le(b, v); - kit_writer_write(w, b, 4); -} - -static inline void elf_wr_u64(Writer* w, u64 v) { - u8 b[8]; - wr_u64_le(b, v); - kit_writer_write(w, b, 8); -} - -static inline u16 elf_rd_u16(const u8* p) { return rd_u16_le(p); } -static inline u32 elf_rd_u32(const u8* p) { return rd_u32_le(p); } -static inline u64 elf_rd_u64(const u8* p) { return rd_u64_le(p); } +#define elf_wr_u8 writer_u8_le +#define elf_wr_u16 writer_u16_le +#define elf_wr_u32 writer_u32_le +#define elf_wr_u64 writer_u64_le #endif /* KIT_OBJ_ELF_H */ diff --git a/src/obj/elf/emit.c b/src/obj/elf/emit.c @@ -116,65 +116,16 @@ static u32 sec_sem_to_elf(u16 sem) { } } -static u8 sym_bind_to_elf(u16 bind) { - switch (bind) { - case SB_LOCAL: - return STB_LOCAL; - case SB_GLOBAL: - return STB_GLOBAL; - case SB_WEAK: - return STB_WEAK; - default: - return STB_LOCAL; - } -} +static u8 sym_bind_to_elf(u16 bind) { return elf_st_bind((u8)bind); } -static u8 sym_kind_to_elf(u16 kind) { - switch (kind) { - case SK_UNDEF: - return STT_NOTYPE; - case SK_FUNC: - return STT_FUNC; - case SK_OBJ: - return STT_OBJECT; - case SK_SECTION: - return STT_SECTION; - case SK_FILE: - return STT_FILE; - /* Tentative definitions: real ELF emitters (clang, gcc, GNU as) - * write these as STT_OBJECT with shndx=SHN_COMMON. STT_COMMON is - * a near-extinct convention that llvm-readelf renders as the - * literal type name "COMMON" — emitting it breaks roundtrip - * against any toolchain-produced .o. */ - case SK_COMMON: - return STT_OBJECT; - case SK_TLS: - return STT_TLS; - case SK_ABS: - return STT_NOTYPE; /* SHN_ABS, NOTYPE */ - case SK_NOTYPE: - return STT_NOTYPE; - case SK_IFUNC: - return STT_GNU_IFUNC; - default: - return STT_NOTYPE; - } -} +/* SK_COMMON -> STT_OBJECT: real ELF emitters (clang, gcc, GNU as) write + * tentative definitions as STT_OBJECT with shndx=SHN_COMMON. STT_COMMON + * is a near-extinct convention that llvm-readelf renders as the literal + * type name "COMMON" — emitting it breaks roundtrip against any + * toolchain-produced .o. The shared elf.h table encodes this directly. */ +static u8 sym_kind_to_elf(u16 kind) { return elf_st_type((u8)kind); } -static u8 sym_vis_to_elf(u8 vis) { - switch (vis) { - case SV_DEFAULT: - return STV_DEFAULT; - case SV_HIDDEN: - return STV_HIDDEN; - case SV_PROTECTED: - return STV_PROTECTED; - case SV_INTERNAL: - return STV_INTERNAL; - default: - return STV_DEFAULT; - } -} +static u8 sym_vis_to_elf(u8 vis) { return elf_st_other(vis); } static u16 sym_shndx(const ObjSym* s, const u32* obj_to_elf, u32 nsec) { if (s->kind == SK_COMMON) return (u16)SHN_COMMON; diff --git a/src/obj/elf/link.c b/src/obj/elf/link.c @@ -540,38 +540,14 @@ typedef struct SymRec { } SymRec; static u8 sym_kind_to_st_type(u8 kind) { - switch (kind) { - case SK_FUNC: - return STT_FUNC; - case SK_OBJ: - return STT_OBJECT; - case SK_SECTION: - return STT_SECTION; - case SK_FILE: - return STT_FILE; - case SK_TLS: - return STT_TLS; - case SK_IFUNC: - return STT_GNU_IFUNC; - case SK_NOTYPE: - case SK_ABS: - case SK_UNDEF: - default: - return STT_NOTYPE; - } + /* Shared elf.h table maps SK_COMMON -> STT_OBJECT (the on-disk shape + * for tentative definitions). The linker, however, writes COMMON as + * STT_NOTYPE; override that one entry locally. */ + if (kind == SK_COMMON) return STT_NOTYPE; + return elf_st_type(kind); } -static u8 sym_bind_to_st_bind(u8 bind) { - switch (bind) { - case SB_GLOBAL: - return STB_GLOBAL; - case SB_WEAK: - return STB_WEAK; - case SB_LOCAL: - default: - return STB_LOCAL; - } -} +static u8 sym_bind_to_st_bind(u8 bind) { return elf_st_bind(bind); } /* Produces one Elf64_Sym record on the wire from a SymRec. */ static void write_sym_rec(Writer* w, const SymRec* r) { diff --git a/src/obj/elf/read.c b/src/obj/elf/read.c @@ -44,16 +44,16 @@ typedef struct ShdrRec { } ShdrRec; static void parse_shdr(const u8* p, ShdrRec* out) { - out->sh_name = elf_rd_u32(p + 0); - out->sh_type = elf_rd_u32(p + 4); - out->sh_flags = elf_rd_u64(p + 8); - out->sh_addr = elf_rd_u64(p + 16); - out->sh_offset = elf_rd_u64(p + 24); - out->sh_size = elf_rd_u64(p + 32); - out->sh_link = elf_rd_u32(p + 40); - out->sh_info = elf_rd_u32(p + 44); - out->sh_addralign = elf_rd_u64(p + 48); - out->sh_entsize = elf_rd_u64(p + 56); + out->sh_name = rd_u32_le(p + 0); + out->sh_type = rd_u32_le(p + 4); + out->sh_flags = rd_u64_le(p + 8); + out->sh_addr = rd_u64_le(p + 16); + out->sh_offset = rd_u64_le(p + 24); + out->sh_size = rd_u64_le(p + 32); + out->sh_link = rd_u32_le(p + 40); + out->sh_info = rd_u32_le(p + 44); + out->sh_addralign = rd_u64_le(p + 48); + out->sh_entsize = rd_u64_le(p + 56); } /* ---- mappers ---- */ @@ -251,13 +251,13 @@ static void read_elf_image(Compiler* c, ObjBuilder* ob, const u8* data, obj_image_ensure(ob, e_type == ET_DYN ? OBJ_KIND_DYN : OBJ_KIND_EXEC); if (!im) compiler_panic(c, no_loc(), "read_elf: obj_image_ensure failed"); - obj_image_set_entry(im, elf_rd_u64(data + 24)); + obj_image_set_entry(im, rd_u64_le(data + 24)); /* Program headers -> segments (+ PT_INTERP string, image base). */ { - u64 e_phoff = elf_rd_u64(data + 32); - u16 e_phentsize = elf_rd_u16(data + 54); - u16 e_phnum = elf_rd_u16(data + 56); + u64 e_phoff = rd_u64_le(data + 32); + u16 e_phentsize = rd_u16_le(data + 54); + u16 e_phnum = rd_u16_le(data + 56); int have_base = 0; u64 image_base = 0; if (e_phnum) { @@ -269,13 +269,13 @@ static void read_elf_image(Compiler* c, ObjBuilder* ob, const u8* data, "read_elf: program header table out of range"); for (u16 i = 0; i < e_phnum; ++i) { const u8* p = data + e_phoff + (u64)i * ELF64_PHDR_SIZE; - u32 p_type = elf_rd_u32(p + 0); - u32 p_flags = elf_rd_u32(p + 4); - u64 p_offset = elf_rd_u64(p + 8); - u64 p_vaddr = elf_rd_u64(p + 16); - u64 p_filesz = elf_rd_u64(p + 32); - u64 p_memsz = elf_rd_u64(p + 40); - u64 p_align = elf_rd_u64(p + 48); + u32 p_type = rd_u32_le(p + 0); + u32 p_flags = rd_u32_le(p + 4); + u64 p_offset = rd_u64_le(p + 8); + u64 p_vaddr = rd_u64_le(p + 16); + u64 p_filesz = rd_u64_le(p + 32); + u64 p_memsz = rd_u64_le(p + 40); + u64 p_align = rd_u64_le(p + 48); ObjSegment seg; seg.name = intern_cstr(c, pt_type_name(p_type)); seg.vaddr = p_vaddr; @@ -324,8 +324,8 @@ static void read_elf_image(Compiler* c, ObjBuilder* ob, const u8* data, const u8* dynp = data + dsh->sh_offset; u64 dynsz = dsh->sh_size; for (u64 off = 0; off + 16 <= dynsz; off += 16) { - u64 tag = elf_rd_u64(dynp + off); - u64 val = elf_rd_u64(dynp + off + 8); + u64 tag = rd_u64_le(dynp + off); + u64 val = rd_u64_le(dynp + off + 8); if (tag == DT_NULL) break; if (tag != DT_NEEDED && tag != DT_SONAME && tag != DT_RPATH && tag != DT_RUNPATH) @@ -371,11 +371,11 @@ static void read_elf_image(Compiler* c, ObjBuilder* ob, const u8* data, dynsym_names = arena_zarray(c->scratch, Sym, ndynsym ? ndynsym : 1); for (u32 i = 1; i < ndynsym; ++i) { const u8* p = base + (u64)i * ELF64_SYM_SIZE; - u32 st_name = elf_rd_u32(p + 0); + u32 st_name = rd_u32_le(p + 0); u8 st_info = p[4]; - u16 st_shndx = elf_rd_u16(p + 6); - u64 st_value = elf_rd_u64(p + 8); - u64 st_size = elf_rd_u64(p + 16); + u16 st_shndx = rd_u16_le(p + 6); + u64 st_value = rd_u64_le(p + 8); + u64 st_size = rd_u64_le(p + 16); u32 nlen; const char* nm = strtab_lookup(strtab, strtab_sz, st_name, &nlen); Sym sn = @@ -415,9 +415,9 @@ static void read_elf_image(Compiler* c, ObjBuilder* ob, const u8* data, base = data + sh->sh_offset; for (j = 0; j < nrec; ++j) { const u8* p = base + (u64)j * entsize; - u64 r_offset = elf_rd_u64(p + 0); - u64 r_info = elf_rd_u64(p + 8); - i64 r_addend = is_rela ? (i64)elf_rd_u64(p + 16) : 0; + u64 r_offset = rd_u64_le(p + 0); + u64 r_info = rd_u64_le(p + 8); + i64 r_addend = is_rela ? (i64)rd_u64_le(p + 16) : 0; u32 esym = ELF64_R_SYM(r_info); u32 kind = reloc_from(ELF64_R_TYPE(r_info)); ObjImageReloc dr; @@ -450,7 +450,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, compiler_panic(c, no_loc(), "read_elf: not ELFDATA2LSB (got %u)", data[EI_DATA]); - u16 e_type = elf_rd_u16(data + 16); + u16 e_type = rd_u16_le(data + 16); /* ET_REL parses to the section/symbol/reloc view only. ET_EXEC/ET_DYN * additionally get the linked-image view (read_elf_image, below); their * section tables still parse through the same passes. ET_CORE and other @@ -461,7 +461,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, "ET_EXEC, or ET_DYN)", (u32)e_type); - u16 e_machine = elf_rd_u16(data + 18); + u16 e_machine = rd_u16_le(data + 18); const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF); const ObjElfArchOps* arch = fmt && fmt->elf_machine ? fmt->elf_machine(e_machine) : NULL; @@ -472,11 +472,11 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, } reloc_from = arch->reloc_from; - u64 e_shoff = elf_rd_u64(data + 40); - u32 e_flags = elf_rd_u32(data + 48); - u16 e_shentsize = elf_rd_u16(data + 58); - u16 e_shnum = elf_rd_u16(data + 60); - u16 e_shstrndx = elf_rd_u16(data + 62); + u64 e_shoff = rd_u64_le(data + 40); + u32 e_flags = rd_u32_le(data + 48); + u16 e_shentsize = rd_u16_le(data + 58); + u16 e_shnum = rd_u16_le(data + 60); + u16 e_shstrndx = rd_u16_le(data + 62); /* A fully section-stripped image (objcopy --strip-sections, packers, * some release binaries) sets e_shoff/e_shnum to zero: the section @@ -632,12 +632,12 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, const u8* base = data + sh->sh_offset; for (u32 i = 1; i < nsyms; ++i) { /* skip index 0 */ const u8* p = base + (u64)i * ELF64_SYM_SIZE; - u32 st_name = elf_rd_u32(p + 0); + u32 st_name = rd_u32_le(p + 0); u8 st_info = p[4]; u8 st_other = p[5]; - u16 st_shndx = elf_rd_u16(p + 6); - u64 st_value = elf_rd_u64(p + 8); - u64 st_size = elf_rd_u64(p + 16); + u16 st_shndx = rd_u16_le(p + 6); + u64 st_value = rd_u64_le(p + 8); + u64 st_size = rd_u64_le(p + 16); u32 nlen; const char* nm = strtab_lookup(strtab, strtab_sz, st_name, &nlen); @@ -707,9 +707,9 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, const u8* base = data + sh->sh_offset; for (u32 j = 0; j < nrec; ++j) { const u8* p = base + (u64)j * entsize; - u64 r_offset = elf_rd_u64(p + 0); - u64 r_info = elf_rd_u64(p + 8); - i64 r_addend = is_rela ? (i64)elf_rd_u64(p + 16) : 0; + u64 r_offset = rd_u64_le(p + 0); + u64 r_info = rd_u64_le(p + 8); + i64 r_addend = is_rela ? (i64)rd_u64_le(p + 16) : 0; u32 esym = ELF64_R_SYM(r_info); u32 etype = ELF64_R_TYPE(r_info); @@ -738,7 +738,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, if (sh->sh_size < 4 || (sh->sh_size % 4)) continue; const u8* p = data + sh->sh_offset; - u32 flags = elf_rd_u32(p); + u32 flags = rd_u32_le(p); u32 nm_len; const char* gnm = strtab_lookup(shstrtab, shstrtab_sz, sh->sh_name, &nm_len); @@ -751,7 +751,7 @@ ObjBuilder* read_elf(Compiler* c, const char* name, const u8* data, ObjGroupId gid = obj_group(ob, gname, signature, flags); u32 n = (u32)(sh->sh_size / 4) - 1; for (u32 j = 0; j < n; ++j) { - u32 shndx = elf_rd_u32(p + 4 + j * 4); + u32 shndx = rd_u32_le(p + 4 + j * 4); if (shndx < e_shnum && elf_to_obj[shndx] != OBJ_SEC_NONE) obj_group_add_section(ob, gid, elf_to_obj[shndx]); } @@ -792,10 +792,10 @@ static int parse_phdr(const u8* data, size_t len, u64 e_phoff, u16 e_phentsize, if (e_phoff + (u64)e_phnum * ELF64_PHDR_SIZE > len) return 0; for (i = 0; i < e_phnum; ++i) { const u8* p = data + e_phoff + (u64)i * ELF64_PHDR_SIZE; - u32 p_type = elf_rd_u32(p + 0); + u32 p_type = rd_u32_le(p + 0); if (p_type != want_type) continue; - *out_offset = elf_rd_u64(p + 8); - *out_filesz = elf_rd_u64(p + 32); + *out_offset = rd_u64_le(p + 8); + *out_filesz = rd_u64_le(p + 32); return 1; } return 0; @@ -816,12 +816,12 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data, if (data[EI_DATA] != ELFDATA2LSB) compiler_panic(c, no_loc(), "read_elf_dso: not ELFDATA2LSB"); - u16 e_type = elf_rd_u16(data + 16); + u16 e_type = rd_u16_le(data + 16); if (e_type != ET_DYN) compiler_panic(c, no_loc(), "read_elf_dso: expected ET_DYN, got e_type=%u", (u32)e_type); - u16 e_machine = elf_rd_u16(data + 18); + u16 e_machine = rd_u16_le(data + 18); { const ObjFormatImpl* fmt = obj_format_lookup(KIT_OBJ_ELF); const ObjElfArchOps* arch = @@ -831,13 +831,13 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data, (u32)e_machine); } - u64 e_phoff = elf_rd_u64(data + 32); - u64 e_shoff = elf_rd_u64(data + 40); - u16 e_phentsize = elf_rd_u16(data + 54); - u16 e_phnum = elf_rd_u16(data + 56); - u16 e_shentsize = elf_rd_u16(data + 58); - u16 e_shnum = elf_rd_u16(data + 60); - u16 e_shstrndx = elf_rd_u16(data + 62); + u64 e_phoff = rd_u64_le(data + 32); + u64 e_shoff = rd_u64_le(data + 40); + u16 e_phentsize = rd_u16_le(data + 54); + u16 e_phnum = rd_u16_le(data + 56); + u16 e_shentsize = rd_u16_le(data + 58); + u16 e_shnum = rd_u16_le(data + 60); + u16 e_shstrndx = rd_u16_le(data + 62); if (e_shentsize != ELF64_SHDR_SIZE) compiler_panic(c, no_loc(), "read_elf_dso: unexpected e_shentsize %u", @@ -885,8 +885,8 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data, u64 dynsz = dsh->sh_size; /* DT entries are 16 bytes: (d_tag: u64, d_un: u64). */ for (u64 off = 0; off + 16 <= dynsz; off += 16) { - u64 tag = elf_rd_u64(dynp + off); - u64 val = elf_rd_u64(dynp + off + 8); + u64 tag = rd_u64_le(dynp + off); + u64 val = rd_u64_le(dynp + off + 8); if (tag == DT_NULL) break; if (tag == DT_SONAME) { u32 nlen; @@ -930,10 +930,10 @@ ObjBuilder* read_elf_dso(Compiler* c, const char* name, const u8* data, const u8* base = data + sh->sh_offset; for (u32 i = 1; i < nsyms; ++i) { /* skip index 0 */ const u8* p = base + (u64)i * ELF64_SYM_SIZE; - u32 st_name = elf_rd_u32(p + 0); + u32 st_name = rd_u32_le(p + 0); u8 st_info = p[4]; u8 st_other = p[5]; - u16 st_shndx = elf_rd_u16(p + 6); + u16 st_shndx = rd_u16_le(p + 6); /* Skip the DSO's own undefined imports — they don't satisfy any * undef in our consumer. Locals (STB_LOCAL) likewise aren't diff --git a/src/obj/macho/emit.c b/src/obj/macho/emit.c @@ -40,19 +40,11 @@ static SrcLoc no_loc(void) { return l; } -/* ---- LE writer helpers (Writer-based) ---- */ +/* ---- LE writer helpers (Writer-based) ---- + * Thin aliases onto the shared writer_u*_le helpers (core/bytes.h). */ -static void wr_u32(Writer* w, u32 v) { - u8 b[4]; - wr_u32_le(b, v); - kit_writer_write(w, b, 4); -} - -static void wr_u64(Writer* w, u64 v) { - u8 b[8]; - wr_u64_le(b, v); - kit_writer_write(w, b, 8); -} +#define wr_u32 writer_u32_le +#define wr_u64 writer_u64_le static void wr_name16(Writer* w, const char* s, u32 len) { /* Mach-O section/segment names are 16-byte zero-padded fields. Names