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:
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