// selfhost/cmd/6l/sym.ww — port of cmd/6l/sym.c. // // Linker symbol table. Singly-linked list, usually a few hundred // entries; hashing isn't worth it yet. use mem; type lsym = struct { name: str, val: u64, // offset within combined .text once linked defined: i32, // 1 if some lobj defines this symbol owner: *lobj, idx_in_owner: i32, // Dynamic-linking fields. Set by l_resolve when an undefined sym // is provided by some loaded lso. plt_idx and dynsym_idx default // to -1 (set explicitly by l_resolve, not by amalloc-zeroing). is_dyn: i32, dyn_lib: *lso, dyn_version: str, // matched export's version; len 0 if none plt_idx: i32, dynsym_idx: i32, snext: *lsym, }; type lrel = struct { off: u64, // offset within combined .text kind: i32, // R_X86_64_* sym: *lsym, addend: i64, rnext: *lrel, }; type lobj = struct { path: str, buf: *u8, // object bytes len: u64, text_off: u64, // offset of .text in combined output text_size: u64, onext: *lobj, }; // lexport — one entry per GLOBAL/WEAK symbol exported by a loaded .so. // Stored as a chain in the order the .so's dynsym presents them, so // l_so_provides_v's first-match semantics agree with the C version. type lexport = struct { name: str, version: str, // len 0 for unversioned globals enext: *lexport, }; type lso = struct { path: str, // full filesystem path used to load soname: str, // DT_SONAME, or basename if missing exports: *lexport, // dynsym-order chain of exported names sonext: *lso, }; type lnk = struct { a: *arena, objs: *lobj, sos: *lso, syms: *lsym, rels: *lrel, text: *u8, // combined .text textcap: u64, textlen: u64, errs: i32, dyn_n: i32, // number of syms routed through PLT }; fn streq(a: str, b: str) bool = { if (a.len != b.len) { return false; }; let i: i32 = 0; for (i < a.len) { if (a[i] != b[i]) { return false; }; i += 1; }; return true; }; export fn l_intern(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; }; s = s.snext; }; let n: *lsym = amalloc(l.a, 96u64): *lsym; n.name = name; n.snext = l.syms; l.syms = n; return n; }; export fn l_lookup(l: *lnk, name: str) *lsym = { let s: *lsym = l.syms; for (s != nil) { if (streq(s.name, name)) { return s; }; s = s.snext; }; return nil; };