diff options
Diffstat (limited to 'include/link.h')
-rw-r--r-- | include/link.h | 616 |
1 files changed, 616 insertions, 0 deletions
diff --git a/include/link.h b/include/link.h new file mode 100644 index 000000000..248497888 --- /dev/null +++ b/include/link.h @@ -0,0 +1,616 @@ +// 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, + R_USEFIELD, +}; + +// 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 |