// Derived from Inferno utils/6l/l.h and related files. // https://bitbucket.org/inferno-os/inferno-os/src/default/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. package ld import ( "bufio" "cmd/internal/obj" "cmd/internal/sys" "debug/elf" "fmt" ) // Symbol is an entry in the symbol table. type Symbol struct { Name string Extname string Type obj.SymKind Version int16 Attr Attribute Localentry uint8 Dynid int32 Plt int32 Got int32 Align int32 Elfsym int32 LocalElfsym int32 Value int64 Size int64 // ElfType is set for symbols read from shared libraries by ldshlibsyms. It // is not set for symbols defined by the packages being linked or by symbols // read by ldelf (and so is left as elf.STT_NOTYPE). ElfType elf.SymType Sub *Symbol Outer *Symbol Gotype *Symbol Reachparent *Symbol File string Dynimplib string Dynimpvers string Sect *Section FuncInfo *FuncInfo // P contains the raw symbol data. P []byte R []Reloc } func (s *Symbol) String() string { if s.Version == 0 { return s.Name } return fmt.Sprintf("%s<%d>", s.Name, s.Version) } func (s *Symbol) ElfsymForReloc() int32 { // If putelfsym created a local version of this symbol, use that in all // relocations. if s.LocalElfsym != 0 { return s.LocalElfsym } else { return s.Elfsym } } // Attribute is a set of common symbol attributes. type Attribute int16 const ( AttrDuplicateOK Attribute = 1 << iota AttrExternal AttrNoSplit AttrReachable AttrCgoExportDynamic AttrCgoExportStatic AttrSpecial AttrStackCheck AttrHidden AttrOnList AttrLocal AttrReflectMethod AttrMakeTypelink ) func (a Attribute) DuplicateOK() bool { return a&AttrDuplicateOK != 0 } func (a Attribute) External() bool { return a&AttrExternal != 0 } func (a Attribute) NoSplit() bool { return a&AttrNoSplit != 0 } func (a Attribute) Reachable() bool { return a&AttrReachable != 0 } func (a Attribute) CgoExportDynamic() bool { return a&AttrCgoExportDynamic != 0 } func (a Attribute) CgoExportStatic() bool { return a&AttrCgoExportStatic != 0 } func (a Attribute) Special() bool { return a&AttrSpecial != 0 } func (a Attribute) StackCheck() bool { return a&AttrStackCheck != 0 } func (a Attribute) Hidden() bool { return a&AttrHidden != 0 } func (a Attribute) OnList() bool { return a&AttrOnList != 0 } func (a Attribute) Local() bool { return a&AttrLocal != 0 } func (a Attribute) ReflectMethod() bool { return a&AttrReflectMethod != 0 } func (a Attribute) MakeTypelink() bool { return a&AttrMakeTypelink != 0 } func (a Attribute) CgoExport() bool { return a.CgoExportDynamic() || a.CgoExportStatic() } func (a *Attribute) Set(flag Attribute, value bool) { if value { *a |= flag } else { *a &^= flag } } // Reloc is a relocation. // // The typical Reloc rewrites part of a symbol at offset Off to address Sym. // A Reloc is stored in a slice on the Symbol it rewrites. // // Relocations are generated by the compiler as the type // cmd/internal/obj.Reloc, which is encoded into the object file wire // format and decoded by the linker into this type. A separate type is // used to hold linker-specific state about the relocation. // // Some relocations are created by cmd/link. type Reloc struct { Off int32 // offset to rewrite Siz uint8 // number of bytes to rewrite, 1, 2, or 4 Done uint8 // set to 1 when relocation is complete Variant RelocVariant // variation on Type Type obj.RelocType // the relocation type Add int64 // addend Xadd int64 // addend passed to external linker Sym *Symbol // symbol the relocation addresses Xsym *Symbol // symbol passed to external linker } type Auto struct { Asym *Symbol Gotype *Symbol Aoffset int32 Name int16 } type Shlib struct { Path string Hash []byte Deps []string File *elf.File gcdataAddresses map[*Symbol]uint64 } // Link holds the context for writing object code from a compiler // or for reading that input into the linker. type Link struct { Syms *Symbols Arch *sys.Arch Debugvlog int Bso *bufio.Writer Loaded bool // set after all inputs have been loaded as symbols Tlsg *Symbol Libdir []string Library []*Library Shlibs []Shlib Tlsoffset int Textp []*Symbol Filesyms []*Symbol Moduledata *Symbol tramps []*Symbol // trampolines } // The smallest possible offset from the hardware stack pointer to a local // variable on the stack. Architectures that use a link register save its value // on the stack in the function prologue and so always have a pointer between // the hardware stack pointer and the local variable area. func (ctxt *Link) FixedFrameSize() int64 { switch ctxt.Arch.Family { case sys.AMD64, sys.I386: return 0 case sys.PPC64: // PIC code on ppc64le requires 32 bytes of stack, and it's easier to // just use that much stack always on ppc64x. return int64(4 * ctxt.Arch.PtrSize) default: return int64(ctxt.Arch.PtrSize) } } func (l *Link) Logf(format string, args ...interface{}) { fmt.Fprintf(l.Bso, format, args...) l.Bso.Flush() } type Library struct { Objref string Srcref string File string Pkg string Shlib string hash string imports []*Library textp []*Symbol // text symbols defined in this library dupTextSyms []*Symbol // dupok text symbols defined in this library } func (l Library) String() string { return l.Pkg } type FuncInfo struct { Args int32 Locals int32 Autom []Auto Pcsp Pcdata Pcfile Pcdata Pcline Pcdata Pcdata []Pcdata Funcdata []*Symbol Funcdataoff []int64 File []*Symbol } type Pcdata struct { P []byte } type Pciter struct { d Pcdata p []byte pc uint32 nextpc uint32 pcscale uint32 value int32 start int done int } // RelocVariant is a linker-internal variation on a relocation. type RelocVariant uint8 const ( RV_NONE RelocVariant = iota RV_POWER_LO RV_POWER_HI RV_POWER_HA RV_POWER_DS // RV_390_DBL is a s390x-specific relocation variant that indicates that // the value to be placed into the relocatable field should first be // divided by 2. RV_390_DBL RV_CHECK_OVERFLOW RelocVariant = 1 << 7 RV_TYPE_MASK RelocVariant = RV_CHECK_OVERFLOW - 1 )