/* * l.h — w6l-private header. Loads relocatable ELF64 .o files (the * format produced by w6a) and links them into a static executable. * * No archives yet (phase 8). No dynamic linking ever. */ #ifndef SIX_L_H #define SIX_L_H #include #include #include typedef int8_t i8; typedef int16_t i16; typedef int32_t i32; typedef int64_t i64; typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; typedef uint64_t u64; typedef struct Lsym Lsym; typedef struct Lrel Lrel; typedef struct Lobj Lobj; typedef struct Lso Lso; typedef struct Lnk Lnk; struct Lsym { const char *name; u64 val; /* offset within combined .text once linked */ int defined; /* 1 if a Lobj defines this symbol */ Lobj *owner; int idx_in_owner; /* Dynamic-linking fields. Set by l_resolve when an undefined sym * is provided by some loaded Lso. Patched-in PLT slot index lets * the relocator route PC32/PLT32 references through the stub. */ int is_dyn; Lso *dyn_lib; const char *dyn_version; /* matched export's version, NULL if none */ int plt_idx; /* 0..dyn_n-1, -1 if no PLT slot */ int dynsym_idx; /* index in emitted .dynsym, -1 otherwise */ Lsym *next; }; struct Lrel { u64 off; /* offset within combined .text */ int kind; /* R_X86_64_* */ Lsym *sym; i64 addend; Lrel *next; }; struct Lobj { const char *path; u8 *buf; /* mmapped or read-in object bytes */ u64 len; u64 text_off; /* offset of .text in combined output */ u64 text_size; Lobj *next; }; struct Lso { const char *path; /* full filesystem path used to load */ const char *soname; /* DT_SONAME, or basename if missing */ char **exports; /* NULL-terminated list of GLOBAL/WEAK syms */ char **versions; /* parallel to exports[]; NULL for unversioned, * else strdup'd version name e.g. "GLIBC_2.2.5" */ Lso *next; }; struct Lnk { Lobj *objs; Lso *sos; Lsym *syms; Lrel *rels; u8 *text; /* combined .text */ u64 textcap, textlen; int errs; int dyn_n; /* number of symbols routed through PLT */ }; /* obj.c */ int l_load(Lnk*, const char *path); int l_read_all(const char *path, u8 **out, u64 *len); /* shared helper */ /* dyn.c */ int l_load_so(Lnk*, const char *path); int l_so_provides(Lso*, const char *name); /* l_so_provides_v: same, but also returns the export's version name * (NULL for unversioned globals) via *out_version on a hit. */ int l_so_provides_v(Lso*, const char *name, const char **out_version); /* sym.c */ Lsym *l_intern(Lnk*, const char *name); Lsym *l_lookup(Lnk*, const char *name); /* pass.c */ int l_resolve(Lnk*); int l_relocate(Lnk*, u64 base); /* out.c */ int l_emit_elf(Lnk*, FILE *out, u64 base, u64 entry); /* dynout.c — emit a dynamic-linked ELF executable. Called by * l_emit_elf when l->sos is non-empty. */ int l_emit_dyn_elf(Lnk*, FILE *out, u64 base, u64 entry); #endif