root/include/link.h

/* [<][>][^][v][top][bottom][index][help] */

INCLUDED FROM


// 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

/* [<][>][^][v][top][bottom][index][help] */