github.com/dannin/go@v0.0.0-20161031215817-d35dfd405eaa/src/cmd/link/internal/ld/link.go (about)

     1  // Derived from Inferno utils/6l/l.h and related files.
     2  // https://bitbucket.org/inferno-os/inferno-os/src/default/utils/6l/l.h
     3  //
     4  //	Copyright © 1994-1999 Lucent Technologies Inc.  All rights reserved.
     5  //	Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
     6  //	Portions Copyright © 1997-1999 Vita Nuova Limited
     7  //	Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
     8  //	Portions Copyright © 2004,2006 Bruce Ellis
     9  //	Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
    10  //	Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
    11  //	Portions Copyright © 2009 The Go Authors. All rights reserved.
    12  //
    13  // Permission is hereby granted, free of charge, to any person obtaining a copy
    14  // of this software and associated documentation files (the "Software"), to deal
    15  // in the Software without restriction, including without limitation the rights
    16  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    17  // copies of the Software, and to permit persons to whom the Software is
    18  // furnished to do so, subject to the following conditions:
    19  //
    20  // The above copyright notice and this permission notice shall be included in
    21  // all copies or substantial portions of the Software.
    22  //
    23  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    24  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    25  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
    26  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    27  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    28  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    29  // THE SOFTWARE.
    30  
    31  package ld
    32  
    33  import (
    34  	"bufio"
    35  	"cmd/internal/obj"
    36  	"cmd/internal/sys"
    37  	"debug/elf"
    38  	"fmt"
    39  )
    40  
    41  // Symbol is an entry in the symbol table.
    42  type Symbol struct {
    43  	Name        string
    44  	Extname     string
    45  	Type        obj.SymKind
    46  	Version     int16
    47  	Attr        Attribute
    48  	Localentry  uint8
    49  	Dynid       int32
    50  	Plt         int32
    51  	Got         int32
    52  	Align       int32
    53  	Elfsym      int32
    54  	LocalElfsym int32
    55  	Value       int64
    56  	Size        int64
    57  	// ElfType is set for symbols read from shared libraries by ldshlibsyms. It
    58  	// is not set for symbols defined by the packages being linked or by symbols
    59  	// read by ldelf (and so is left as elf.STT_NOTYPE).
    60  	ElfType     elf.SymType
    61  	Sub         *Symbol
    62  	Outer       *Symbol
    63  	Gotype      *Symbol
    64  	Reachparent *Symbol
    65  	File        string
    66  	Dynimplib   string
    67  	Dynimpvers  string
    68  	Sect        *Section
    69  	FuncInfo    *FuncInfo
    70  	// P contains the raw symbol data.
    71  	P []byte
    72  	R []Reloc
    73  }
    74  
    75  func (s *Symbol) String() string {
    76  	if s.Version == 0 {
    77  		return s.Name
    78  	}
    79  	return fmt.Sprintf("%s<%d>", s.Name, s.Version)
    80  }
    81  
    82  func (s *Symbol) ElfsymForReloc() int32 {
    83  	// If putelfsym created a local version of this symbol, use that in all
    84  	// relocations.
    85  	if s.LocalElfsym != 0 {
    86  		return s.LocalElfsym
    87  	} else {
    88  		return s.Elfsym
    89  	}
    90  }
    91  
    92  // Attribute is a set of common symbol attributes.
    93  type Attribute int16
    94  
    95  const (
    96  	AttrDuplicateOK Attribute = 1 << iota
    97  	AttrExternal
    98  	AttrNoSplit
    99  	AttrReachable
   100  	AttrCgoExportDynamic
   101  	AttrCgoExportStatic
   102  	AttrSpecial
   103  	AttrStackCheck
   104  	AttrHidden
   105  	AttrOnList
   106  	AttrLocal
   107  	AttrReflectMethod
   108  	AttrMakeTypelink
   109  )
   110  
   111  func (a Attribute) DuplicateOK() bool      { return a&AttrDuplicateOK != 0 }
   112  func (a Attribute) External() bool         { return a&AttrExternal != 0 }
   113  func (a Attribute) NoSplit() bool          { return a&AttrNoSplit != 0 }
   114  func (a Attribute) Reachable() bool        { return a&AttrReachable != 0 }
   115  func (a Attribute) CgoExportDynamic() bool { return a&AttrCgoExportDynamic != 0 }
   116  func (a Attribute) CgoExportStatic() bool  { return a&AttrCgoExportStatic != 0 }
   117  func (a Attribute) Special() bool          { return a&AttrSpecial != 0 }
   118  func (a Attribute) StackCheck() bool       { return a&AttrStackCheck != 0 }
   119  func (a Attribute) Hidden() bool           { return a&AttrHidden != 0 }
   120  func (a Attribute) OnList() bool           { return a&AttrOnList != 0 }
   121  func (a Attribute) Local() bool            { return a&AttrLocal != 0 }
   122  func (a Attribute) ReflectMethod() bool    { return a&AttrReflectMethod != 0 }
   123  func (a Attribute) MakeTypelink() bool     { return a&AttrMakeTypelink != 0 }
   124  
   125  func (a Attribute) CgoExport() bool {
   126  	return a.CgoExportDynamic() || a.CgoExportStatic()
   127  }
   128  
   129  func (a *Attribute) Set(flag Attribute, value bool) {
   130  	if value {
   131  		*a |= flag
   132  	} else {
   133  		*a &^= flag
   134  	}
   135  }
   136  
   137  // Reloc is a relocation.
   138  //
   139  // The typical Reloc rewrites part of a symbol at offset Off to address Sym.
   140  // A Reloc is stored in a slice on the Symbol it rewrites.
   141  //
   142  // Relocations are generated by the compiler as the type
   143  // cmd/internal/obj.Reloc, which is encoded into the object file wire
   144  // format and decoded by the linker into this type. A separate type is
   145  // used to hold linker-specific state about the relocation.
   146  //
   147  // Some relocations are created by cmd/link.
   148  type Reloc struct {
   149  	Off     int32         // offset to rewrite
   150  	Siz     uint8         // number of bytes to rewrite, 1, 2, or 4
   151  	Done    uint8         // set to 1 when relocation is complete
   152  	Variant RelocVariant  // variation on Type
   153  	Type    obj.RelocType // the relocation type
   154  	Add     int64         // addend
   155  	Xadd    int64         // addend passed to external linker
   156  	Sym     *Symbol       // symbol the relocation addresses
   157  	Xsym    *Symbol       // symbol passed to external linker
   158  }
   159  
   160  type Auto struct {
   161  	Asym    *Symbol
   162  	Gotype  *Symbol
   163  	Aoffset int32
   164  	Name    int16
   165  }
   166  
   167  type Shlib struct {
   168  	Path            string
   169  	Hash            []byte
   170  	Deps            []string
   171  	File            *elf.File
   172  	gcdataAddresses map[*Symbol]uint64
   173  }
   174  
   175  // Link holds the context for writing object code from a compiler
   176  // or for reading that input into the linker.
   177  type Link struct {
   178  	Syms *Symbols
   179  
   180  	Arch      *sys.Arch
   181  	Debugvlog int
   182  	Bso       *bufio.Writer
   183  
   184  	Loaded bool // set after all inputs have been loaded as symbols
   185  
   186  	Tlsg       *Symbol
   187  	Libdir     []string
   188  	Library    []*Library
   189  	Shlibs     []Shlib
   190  	Tlsoffset  int
   191  	Textp      []*Symbol
   192  	Filesyms   []*Symbol
   193  	Moduledata *Symbol
   194  
   195  	tramps []*Symbol // trampolines
   196  }
   197  
   198  // The smallest possible offset from the hardware stack pointer to a local
   199  // variable on the stack. Architectures that use a link register save its value
   200  // on the stack in the function prologue and so always have a pointer between
   201  // the hardware stack pointer and the local variable area.
   202  func (ctxt *Link) FixedFrameSize() int64 {
   203  	switch ctxt.Arch.Family {
   204  	case sys.AMD64, sys.I386:
   205  		return 0
   206  	case sys.PPC64:
   207  		// PIC code on ppc64le requires 32 bytes of stack, and it's easier to
   208  		// just use that much stack always on ppc64x.
   209  		return int64(4 * ctxt.Arch.PtrSize)
   210  	default:
   211  		return int64(ctxt.Arch.PtrSize)
   212  	}
   213  }
   214  
   215  func (l *Link) Logf(format string, args ...interface{}) {
   216  	fmt.Fprintf(l.Bso, format, args...)
   217  	l.Bso.Flush()
   218  }
   219  
   220  type Library struct {
   221  	Objref      string
   222  	Srcref      string
   223  	File        string
   224  	Pkg         string
   225  	Shlib       string
   226  	hash        []byte
   227  	imports     []*Library
   228  	textp       []*Symbol // text symbols defined in this library
   229  	dupTextSyms []*Symbol // dupok text symbols defined in this library
   230  }
   231  
   232  func (l Library) String() string {
   233  	return l.Pkg
   234  }
   235  
   236  type FuncInfo struct {
   237  	Args        int32
   238  	Locals      int32
   239  	Autom       []Auto
   240  	Pcsp        Pcdata
   241  	Pcfile      Pcdata
   242  	Pcline      Pcdata
   243  	Pcdata      []Pcdata
   244  	Funcdata    []*Symbol
   245  	Funcdataoff []int64
   246  	File        []*Symbol
   247  }
   248  
   249  type Pcdata struct {
   250  	P []byte
   251  }
   252  
   253  type Pciter struct {
   254  	d       Pcdata
   255  	p       []byte
   256  	pc      uint32
   257  	nextpc  uint32
   258  	pcscale uint32
   259  	value   int32
   260  	start   int
   261  	done    int
   262  }
   263  
   264  // RelocVariant is a linker-internal variation on a relocation.
   265  type RelocVariant uint8
   266  
   267  const (
   268  	RV_NONE RelocVariant = iota
   269  	RV_POWER_LO
   270  	RV_POWER_HI
   271  	RV_POWER_HA
   272  	RV_POWER_DS
   273  
   274  	// RV_390_DBL is a s390x-specific relocation variant that indicates that
   275  	// the value to be placed into the relocatable field should first be
   276  	// divided by 2.
   277  	RV_390_DBL
   278  
   279  	RV_CHECK_OVERFLOW RelocVariant = 1 << 7
   280  	RV_TYPE_MASK      RelocVariant = RV_CHECK_OVERFLOW - 1
   281  )