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