// Derived from Inferno utils/6l/l.h and related files. // http://code.google.com/p/inferno-os/source/browse/utils/6l/l.h // // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) // Portions Copyright © 1997-1999 Vita Nuova Limited // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) // Portions Copyright © 2004,2006 Bruce Ellis // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others // Portions Copyright © 2009 The Go Authors. All rights reserved. // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. typedef struct LSym LSym; typedef struct Reloc Reloc; typedef struct Auto Auto; typedef struct Link Link; typedef struct LinkArch LinkArch; typedef struct Library Library; typedef struct Pcln Pcln; typedef struct Pcdata Pcdata; typedef struct Pciter Pciter; struct Reloc { int32 off; uchar siz; uchar done; int32 type; int32 variant; // RV_*: variant on computed value int64 add; int64 xadd; LSym* sym; LSym* xsym; }; // prevent incompatible type signatures between liblink and 8l on Plan 9 #pragma incomplete struct Section struct LSym { char* name; char* extname; // name used in external object files short type; short version; uchar dupok; uchar cfunc; uchar external; uchar nosplit; uchar reachable; uchar cgoexport; uchar special; uchar stkcheck; uchar hide; uchar leaf; // arm only uchar localentry; // ppc64: instrs between global & local entry uchar onlist; // on the textp or datap lists int32 dynid; int32 sig; int32 plt; int32 got; int32 align; // if non-zero, required alignment in bytes int32 elfsym; int32 args; // size of stack frame incoming arguments area int32 locals; // size of stack frame locals area (arm only?) vlong value; vlong size; LSym* hash; // in hash table LSym* allsym; // in all symbol list LSym* next; // in text or data list LSym* sub; // in SSUB list LSym* outer; // container of sub LSym* gotype; LSym* reachparent; LSym* queue; char* file; char* dynimplib; char* dynimpvers; struct Section* sect; // STEXT Auto* autom; Pcln* pcln; // SDATA, SBSS uchar* p; int np; int32 maxp; Reloc* r; int32 nr; int32 maxr; }; // LSym.type enum { Sxxx, /* order here is order in output file */ /* readonly, executable */ STEXT, SELFRXSECT, /* readonly, non-executable */ STYPE, SSTRING, SGOSTRING, SGOFUNC, SRODATA, SFUNCTAB, STYPELINK, SSYMTAB, // TODO: move to unmapped section SPCLNTAB, SELFROSECT, /* writable, non-executable */ SMACHOPLT, SELFSECT, SMACHO, /* Mach-O __nl_symbol_ptr */ SMACHOGOT, SWINDOWS, SELFGOT, /* also .toc in ppc64 ABI */ SNOPTRDATA, SINITARR, SDATA, SBSS, SNOPTRBSS, STLSBSS, /* not mapped */ SXREF, SMACHOSYMSTR, SMACHOSYMTAB, SMACHOINDIRECTPLT, SMACHOINDIRECTGOT, SFILE, SFILEPATH, SCONST, SDYNIMPORT, SHOSTOBJ, SSUB = 1<<8, /* sub-symbol, linked from parent via ->sub list */ SMASK = SSUB - 1, SHIDDEN = 1<<9, // hidden or local symbol }; // Reloc.type enum { R_ADDR = 1, R_ADDRPOWER, // relocation for loading 31-bit address using addis and addi/ld/st for Power R_SIZE, R_CALL, // relocation for direct PC-relative call R_CALLARM, // relocation for ARM direct call R_CALLIND, // marker for indirect call (no actual relocating necessary) R_CALLPOWER, // relocation for Power direct call R_CONST, R_PCREL, R_TLS, R_TLS_LE, // TLS local exec offset from TLS segment register R_TLS_IE, // TLS initial exec offset from TLS base pointer R_GOTOFF, R_PLT0, R_PLT1, R_PLT2, R_USEFIELD, R_POWER_TOC, // ELF R_PPC64_TOC16* }; // Reloc.variant enum { RV_NONE, // identity variant RV_POWER_LO, // x & 0xFFFF RV_POWER_HI, // x >> 16 RV_POWER_HA, // (x + 0x8000) >> 16 RV_POWER_DS, // x & 0xFFFC, check x&0x3 == 0 RV_CHECK_OVERFLOW = 1<<8, // check overflow flag RV_TYPE_MASK = (RV_CHECK_OVERFLOW - 1), }; // Auto.name enum { A_AUTO = 1, A_PARAM, }; struct Auto { LSym* asym; Auto* link; int32 aoffset; int16 name; LSym* gotype; }; enum { LINKHASH = 100003, }; struct Library { char *objref; // object where we found the reference char *srcref; // src file where we found the reference char *file; // object file char *pkg; // import path }; struct Pcdata { uchar *p; int n; int m; }; struct Pcln { Pcdata pcsp; Pcdata pcfile; Pcdata pcline; Pcdata *pcdata; int npcdata; LSym **funcdata; int64 *funcdataoff; int nfuncdata; LSym **file; int nfile; int mfile; LSym *lastfile; int lastindex; }; // Pcdata iterator. // for(pciterinit(ctxt, &it, &pcd); !it.done; pciternext(&it)) { it.value holds in [it.pc, it.nextpc) } struct Pciter { Pcdata d; uchar *p; uint32 pc; uint32 nextpc; uint32 pcscale; int32 value; int start; int done; }; void pciterinit(Link*, Pciter*, Pcdata*); void pciternext(Pciter*); // symbol version, incremented each time a file is loaded. // version==1 is reserved for savehist. enum { HistVersion = 1, }; // Link holds the context for writing object code from a compiler // to be linker input or for reading that input into the linker. struct Link { int32 thechar; // '5' (arm), '6' (amd64), etc. char* thestring; // full name of architecture ("arm", "amd64", ..) int32 goarm; // for arm only, GOARM setting int headtype; LinkArch* arch; int32 debugasm; // -S flag in compiler int32 debugvlog; // -v flag in linker Biobuf* bso; // for -v flag int32 windows; char* goroot; // hash table of all symbols LSym* hash[LINKHASH]; LSym* allsym; int32 nsymbol; // code generation LSym* tlsg; // for reading input files (during linker) char** libdir; int32 nlibdir; int32 maxlibdir; Library* library; int libraryp; int nlibrary; int tlsoffset; void (*diag)(char*, ...); LSym* cursym; int version; LSym* textp; LSym* etextp; int32 nhistfile; LSym* filesyms; }; enum { LittleEndian = 0x04030201, BigEndian = 0x01020304, }; // LinkArch is the definition of a single architecture. struct LinkArch { char* name; // "arm", "amd64", and so on int thechar; // '5', '6', and so on int32 endian; // LittleEndian or BigEndian int minlc; int ptrsize; int regsize; }; /* executable header types */ enum { Hunknown = 0, Hdarwin, Hdragonfly, Helf, Hfreebsd, Hlinux, Hnacl, Hnetbsd, Hopenbsd, Hplan9, Hsolaris, Hwindows, }; enum { LinkAuto = 0, LinkInternal, LinkExternal, }; extern uchar fnuxi8[8]; extern uchar fnuxi4[4]; extern uchar inuxi1[1]; extern uchar inuxi2[2]; extern uchar inuxi4[4]; extern uchar inuxi8[8]; vlong addaddr(Link *ctxt, LSym *s, LSym *t); vlong addaddrplus(Link *ctxt, LSym *s, LSym *t, vlong add); vlong addaddrplus4(Link *ctxt, LSym *s, LSym *t, vlong add); void addlib(Link *ctxt, char *src, char *obj, char *pathname); void addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg); vlong addpcrelplus(Link *ctxt, LSym *s, LSym *t, vlong add); Reloc* addrel(LSym *s); vlong addsize(Link *ctxt, LSym *s, LSym *t); vlong adduint16(Link *ctxt, LSym *s, uint16 v); vlong adduint32(Link *ctxt, LSym *s, uint32 v); vlong adduint64(Link *ctxt, LSym *s, uint64 v); vlong adduint8(Link *ctxt, LSym *s, uint8 v); vlong adduintxx(Link *ctxt, LSym *s, uint64 v, int wid); vlong atolwhex(char *s); void* emallocz(long n); void* erealloc(void *p, long n); char* estrdup(char *p); char* expandpkg(char *t0, char *pkg); int find1(int32 l, int c); char* headstr(int v); int headtype(char *name); void ldobjfile(Link *ctxt, Biobuf *f, char *pkg, int64 len, char *pn); LSym* linklookup(Link *ctxt, char *name, int v); Link* linknew(LinkArch *arch); LSym* linknewsym(Link *ctxt, char *symb, int v); LSym* linkrlookup(Link *ctxt, char *name, int v); void nuxiinit(LinkArch *arch); void pciterinit(Link *ctxt, Pciter *it, Pcdata *d); void pciternext(Pciter *it); vlong setaddr(Link *ctxt, LSym *s, vlong off, LSym *t); vlong setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add); vlong setuint32(Link *ctxt, LSym *s, vlong r, uint32 v); vlong setuint8(Link *ctxt, LSym *s, vlong r, uint8 v); vlong setuintxx(Link *ctxt, LSym *s, vlong off, uint64 v, vlong wid); void symgrow(Link *ctxt, LSym *s, vlong lsiz); extern LinkArch link386; extern LinkArch linkamd64; extern LinkArch linkamd64p32; extern LinkArch linkarm; extern LinkArch linkppc64; extern LinkArch linkppc64le;