| // 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 Addr Addr; | |
| typedef struct Prog Prog; | |
| typedef struct LSym LSym; | |
| typedef struct Reloc Reloc; | |
| typedef struct Auto Auto; | |
| typedef struct Hist Hist; | |
| typedef struct Link Link; | |
| typedef struct Plist Plist; | |
| typedef struct LinkArch LinkArch; | |
| typedef struct Library Library; | |
| typedef struct Pcln Pcln; | |
| typedef struct Pcdata Pcdata; | |
| typedef struct Pciter Pciter; | |
| // prevent incompatible type signatures between liblink and 8l on Plan 9 | |
| #pragma incomplete struct Node | |
| struct Addr | |
| { | |
| vlong offset; | |
| union | |
| { | |
| char sval[8]; | |
| float64 dval; | |
| Prog* branch; // for 5g, 6g, 8g | |
| } u; | |
| LSym* sym; | |
| LSym* gotype; | |
| short type; | |
| uint8 index; | |
| int8 scale; | |
| int8 reg; // for 5l | |
| int8 name; // for 5l | |
| int8 class; // for 5l | |
| uint8 etype; // for 5g, 6g, 8g | |
| int32 offset2; // for 5l, 8l | |
| struct Node* node; // for 5g, 6g, 8g | |
| int64 width; // for 5g, 6g, 8g | |
| }; | |
| struct Reloc | |
| { | |
| int32 off; | |
| uchar siz; | |
| uchar done; | |
| int32 type; | |
| int64 add; | |
| int64 xadd; | |
| LSym* sym; | |
| LSym* xsym; | |
| }; | |
| struct Prog | |
| { | |
| vlong pc; | |
| int32 lineno; | |
| Prog* link; | |
| short as; | |
| uchar reg; // arm only | |
| uchar scond; // arm only | |
| Addr from; | |
| Addr to; | |
| // for 5g, 6g, 8g internal use | |
| void* opt; | |
| // for 5l, 6l, 8l internal use | |
| Prog* forwd; | |
| Prog* pcond; | |
| Prog* comefrom; // 6l, 8l | |
| Prog* pcrel; // 5l | |
| int32 spadj; | |
| uchar mark; | |
| uchar back; // 6l, 8l | |
| char ft; /* 6l, 8l oclass cache */ | |
| char tt; // 6l, 8l | |
| uchar optab; // 5l | |
| uchar isize; // 6l, 8l | |
| char width; /* fake for DATA */ | |
| char mode; /* 16, 32, or 64 in 6l, 8l; internal use in 5g, 6g, 8g */ | |
| }; | |
| // 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 external; | |
| uchar nosplit; | |
| uchar reachable; | |
| uchar cgoexport; | |
| uchar special; | |
| uchar stkcheck; | |
| uchar hide; | |
| uchar leaf; // arm only | |
| uchar fnptr; // arm only | |
| uchar seenglobl; | |
| uchar onlist; // on the textp or datap lists | |
| int16 symid; // for writing .5/.6/.8 files | |
| 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; | |
| Prog* text; | |
| Prog* etext; | |
| Pcln* pcln; | |
| // SDATA, SBSS | |
| uchar* p; | |
| int32 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, | |
| SNOPTRDATA, | |
| SINITARR, | |
| SDATA, | |
| SWINDOWS, | |
| 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_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_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, | |
| }; | |
| // Auto.type | |
| enum | |
| { | |
| A_AUTO = 1, | |
| A_PARAM, | |
| }; | |
| struct Auto | |
| { | |
| LSym* asym; | |
| Auto* link; | |
| int32 aoffset; | |
| int16 type; | |
| LSym* gotype; | |
| }; | |
| enum | |
| { | |
| LINKHASH = 100003, | |
| }; | |
| struct Hist | |
| { | |
| Hist* link; | |
| char* name; | |
| int32 line; | |
| int32 offset; | |
| }; | |
| struct Plist | |
| { | |
| LSym* name; | |
| Prog* firstpc; | |
| int recur; | |
| Plist* link; | |
| }; | |
| 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 (*ignore)(char*); // do not emit names satisfying this function | |
| int32 debugasm; // -S flag in compiler | |
| int32 debugline; // -L flag in compiler | |
| int32 debughist; // -O flag in linker | |
| int32 debugread; // -W flag in linker | |
| int32 debugvlog; // -v flag in linker | |
| int32 debugstack; // -K flag in linker | |
| int32 debugzerostack; // -Z flag in linker | |
| int32 debugdivmod; // -M flag in 5l | |
| int32 debugfloat; // -F flag in 5l | |
| int32 debugpcln; // -O flag in linker | |
| int32 flag_shared; // -shared flag in linker | |
| int32 iself; | |
| Biobuf* bso; // for -v flag | |
| char* pathname; | |
| int32 windows; | |
| char* trimpath; | |
| char* goroot; | |
| char* goroot_final; | |
| // hash table of all symbols | |
| LSym* hash[LINKHASH]; | |
| LSym* allsym; | |
| int32 nsymbol; | |
| // file-line history | |
| Hist* hist; | |
| Hist* ehist; | |
| // all programs | |
| Plist* plist; | |
| Plist* plast; | |
| // code generation | |
| LSym* sym_div; | |
| LSym* sym_divu; | |
| LSym* sym_mod; | |
| LSym* sym_modu; | |
| LSym* symmorestack[20]; | |
| LSym* gmsym; | |
| LSym* plan9tos; | |
| Prog* curp; | |
| Prog* printp; | |
| Prog* blitrl; | |
| Prog* elitrl; | |
| int rexflag; | |
| int rep; // for nacl | |
| int repn; // for nacl | |
| int lock; // for nacl | |
| int asmode; | |
| uchar* andptr; | |
| uchar and[100]; | |
| int32 instoffset; | |
| int32 autosize; | |
| int32 armsize; | |
| // for reading input files (during linker) | |
| vlong pc; | |
| char** libdir; | |
| int32 nlibdir; | |
| int32 maxlibdir; | |
| Library* library; | |
| int libraryp; | |
| int nlibrary; | |
| int tlsoffset; | |
| void (*diag)(char*, ...); | |
| int mode; | |
| Auto* curauto; | |
| Auto* curhist; | |
| LSym* cursym; | |
| int version; | |
| LSym* textp; | |
| LSym* etextp; | |
| int32 histdepth; | |
| int32 nhistfile; | |
| LSym* filesyms; | |
| }; | |
| // LinkArch is the definition of a single architecture. | |
| struct LinkArch | |
| { | |
| char* name; // "arm", "amd64", and so on | |
| int thechar; // '5', '6', and so on | |
| void (*addstacksplit)(Link*, LSym*); | |
| void (*assemble)(Link*, LSym*); | |
| int (*datasize)(Prog*); | |
| void (*follow)(Link*, LSym*); | |
| int (*iscall)(Prog*); | |
| int (*isdata)(Prog*); | |
| Prog* (*prg)(void); | |
| void (*progedit)(Link*, Prog*); | |
| void (*settextflag)(Prog*, int); | |
| int (*symtype)(Addr*); | |
| int (*textflag)(Prog*); | |
| int minlc; | |
| int ptrsize; | |
| int regsize; | |
| // TODO: Give these the same values on all systems. | |
| int D_ADDR; | |
| int D_AUTO; | |
| int D_BRANCH; | |
| int D_CONST; | |
| int D_EXTERN; | |
| int D_FCONST; | |
| int D_NONE; | |
| int D_PARAM; | |
| int D_SCONST; | |
| int D_STATIC; | |
| int ACALL; | |
| int ADATA; | |
| int AEND; | |
| int AFUNCDATA; | |
| int AGLOBL; | |
| int AJMP; | |
| int ANOP; | |
| int APCDATA; | |
| int ARET; | |
| int ATEXT; | |
| int ATYPE; | |
| int AUSEFIELD; | |
| }; | |
| /* 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]; | |
| // asm5.c | |
| void span5(Link *ctxt, LSym *s); | |
| int chipfloat5(Link *ctxt, float64 e); | |
| int chipzero5(Link *ctxt, float64 e); | |
| // asm6.c | |
| void span6(Link *ctxt, LSym *s); | |
| // asm8.c | |
| void span8(Link *ctxt, LSym *s); | |
| // data.c | |
| 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); | |
| 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); | |
| void mangle(char *file); | |
| void savedata(Link *ctxt, LSym *s, Prog *p, char *pn); | |
| vlong setaddr(Link *ctxt, LSym *s, vlong off, LSym *t); | |
| vlong setaddrplus(Link *ctxt, LSym *s, vlong off, LSym *t, vlong add); | |
| vlong setuint16(Link *ctxt, LSym *s, vlong r, uint16 v); | |
| vlong setuint32(Link *ctxt, LSym *s, vlong r, uint32 v); | |
| vlong setuint64(Link *ctxt, LSym *s, vlong r, uint64 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 siz); | |
| // go.c | |
| void double2ieee(uint64 *ieee, double native); | |
| void* emallocz(long n); | |
| void* erealloc(void *p, long n); | |
| char* estrdup(char *p); | |
| char* expandpkg(char *t0, char *pkg); | |
| // ld.c | |
| void addhist(Link *ctxt, int32 line, int type); | |
| void addlib(Link *ctxt, char *src, char *obj, char *path); | |
| void addlibpath(Link *ctxt, char *srcref, char *objref, char *file, char *pkg); | |
| void collapsefrog(Link *ctxt, LSym *s); | |
| void copyhistfrog(Link *ctxt, char *buf, int nbuf); | |
| int find1(int32 l, int c); | |
| void linkgetline(Link *ctxt, int32 line, LSym **f, int32 *l); | |
| void histtoauto(Link *ctxt); | |
| void mkfwd(LSym*); | |
| void nuxiinit(void); | |
| void savehist(Link *ctxt, int32 line, int32 off); | |
| Prog* copyp(Link*, Prog*); | |
| Prog* appendp(Link*, Prog*); | |
| vlong atolwhex(char*); | |
| // list[568].c | |
| void listinit5(void); | |
| void listinit6(void); | |
| void listinit8(void); | |
| // obj.c | |
| int linklinefmt(Link *ctxt, Fmt *fp); | |
| void linklinehist(Link *ctxt, int lineno, char *f, int offset); | |
| Plist* linknewplist(Link *ctxt); | |
| void linkprfile(Link *ctxt, int32 l); | |
| // objfile.c | |
| void ldobjfile(Link *ctxt, Biobuf *b, char *pkg, int64 len, char *path); | |
| void writeobj(Link *ctxt, Biobuf *b); | |
| // pass.c | |
| Prog* brchain(Link *ctxt, Prog *p); | |
| Prog* brloop(Link *ctxt, Prog *p); | |
| void linkpatch(Link *ctxt, LSym *sym); | |
| // pcln.c | |
| void linkpcln(Link*, LSym*); | |
| // sym.c | |
| LSym* linklookup(Link *ctxt, char *name, int v); | |
| Link* linknew(LinkArch*); | |
| LSym* linknewsym(Link *ctxt, char *symb, int v); | |
| LSym* linkrlookup(Link *ctxt, char *name, int v); | |
| int linksymfmt(Fmt *f); | |
| int headtype(char*); | |
| char* headstr(int); | |
| extern char* anames5[]; | |
| extern char* anames6[]; | |
| extern char* anames8[]; | |
| extern LinkArch link386; | |
| extern LinkArch linkamd64; | |
| extern LinkArch linkamd64p32; | |
| extern LinkArch linkarm; | |
| #pragma varargck type "A" int | |
| #pragma varargck type "D" Addr* | |
| #pragma varargck type "lD" Addr* | |
| #pragma varargck type "P" Prog* | |
| #pragma varargck type "R" int | |
| // TODO(ality): remove this workaround. | |
| // It's here because Pconv in liblink/list?.c references %L. | |
| #pragma varargck type "L" int32 |