2015-02-27 22:57:28 -05:00
|
|
|
package ld
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"bytes"
|
2016-04-06 21:45:29 -07:00
|
|
|
"cmd/internal/bio"
|
2017-04-18 12:53:25 -07:00
|
|
|
"cmd/internal/objabi"
|
2016-04-06 12:01:40 -07:00
|
|
|
"cmd/internal/sys"
|
2015-02-27 22:57:28 -05:00
|
|
|
"encoding/binary"
|
|
|
|
|
"fmt"
|
2015-09-23 15:46:00 +12:00
|
|
|
"io"
|
2015-02-27 22:57:28 -05:00
|
|
|
"log"
|
|
|
|
|
"sort"
|
|
|
|
|
"strings"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Derived from Plan 9 from User Space's src/libmach/elf.h, elf.c
|
|
|
|
|
http://code.swtch.com/plan9port/src/tip/src/libmach/
|
|
|
|
|
|
|
|
|
|
Copyright © 2004 Russ Cox.
|
|
|
|
|
Portions Copyright © 2008-2010 Google Inc.
|
|
|
|
|
Portions Copyright © 2010 The Go Authors.
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
const (
|
2015-03-04 10:28:18 +13:00
|
|
|
ElfClassNone = 0
|
|
|
|
|
ElfClass32 = 1
|
|
|
|
|
ElfClass64 = 2
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfDataNone = 0
|
|
|
|
|
ElfDataLsb = 1
|
|
|
|
|
ElfDataMsb = 2
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfTypeNone = 0
|
|
|
|
|
ElfTypeRelocatable = 1
|
|
|
|
|
ElfTypeExecutable = 2
|
|
|
|
|
ElfTypeSharedObject = 3
|
|
|
|
|
ElfTypeCore = 4
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfMachNone = 0
|
|
|
|
|
ElfMach32100 = 1
|
|
|
|
|
ElfMachSparc = 2
|
|
|
|
|
ElfMach386 = 3
|
|
|
|
|
ElfMach68000 = 4
|
|
|
|
|
ElfMach88000 = 5
|
|
|
|
|
ElfMach486 = 6
|
|
|
|
|
ElfMach860 = 7
|
|
|
|
|
ElfMachMips = 8
|
|
|
|
|
ElfMachS370 = 9
|
|
|
|
|
ElfMachMipsLe = 10
|
|
|
|
|
ElfMachParisc = 15
|
|
|
|
|
ElfMachVpp500 = 17
|
|
|
|
|
ElfMachSparc32Plus = 18
|
|
|
|
|
ElfMach960 = 19
|
|
|
|
|
ElfMachPower = 20
|
|
|
|
|
ElfMachPower64 = 21
|
|
|
|
|
ElfMachS390 = 22
|
|
|
|
|
ElfMachV800 = 36
|
|
|
|
|
ElfMachFr20 = 37
|
|
|
|
|
ElfMachRh32 = 38
|
|
|
|
|
ElfMachRce = 39
|
|
|
|
|
ElfMachArm = 40
|
|
|
|
|
ElfMachAlpha = 41
|
|
|
|
|
ElfMachSH = 42
|
|
|
|
|
ElfMachSparc9 = 43
|
|
|
|
|
ElfMachAmd64 = 62
|
2015-03-08 14:14:53 +01:00
|
|
|
ElfMachArm64 = 183
|
2015-03-04 10:28:18 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfAbiNone = 0
|
|
|
|
|
ElfAbiSystemV = 0
|
|
|
|
|
ElfAbiHPUX = 1
|
|
|
|
|
ElfAbiNetBSD = 2
|
|
|
|
|
ElfAbiLinux = 3
|
|
|
|
|
ElfAbiSolaris = 6
|
|
|
|
|
ElfAbiAix = 7
|
|
|
|
|
ElfAbiIrix = 8
|
|
|
|
|
ElfAbiFreeBSD = 9
|
|
|
|
|
ElfAbiTru64 = 10
|
|
|
|
|
ElfAbiModesto = 11
|
|
|
|
|
ElfAbiOpenBSD = 12
|
2015-02-27 22:57:28 -05:00
|
|
|
ElfAbiARM = 97
|
|
|
|
|
ElfAbiEmbedded = 255
|
2015-03-04 10:28:18 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfSectNone = 0
|
|
|
|
|
ElfSectProgbits = 1
|
|
|
|
|
ElfSectSymtab = 2
|
|
|
|
|
ElfSectStrtab = 3
|
|
|
|
|
ElfSectRela = 4
|
|
|
|
|
ElfSectHash = 5
|
|
|
|
|
ElfSectDynamic = 6
|
|
|
|
|
ElfSectNote = 7
|
|
|
|
|
ElfSectNobits = 8
|
|
|
|
|
ElfSectRel = 9
|
|
|
|
|
ElfSectShlib = 10
|
|
|
|
|
ElfSectDynsym = 11
|
2015-02-27 22:57:28 -05:00
|
|
|
ElfSectFlagWrite = 0x1
|
|
|
|
|
ElfSectFlagAlloc = 0x2
|
|
|
|
|
ElfSectFlagExec = 0x4
|
2015-03-04 10:28:18 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfSymBindLocal = 0
|
|
|
|
|
ElfSymBindGlobal = 1
|
|
|
|
|
ElfSymBindWeak = 2
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfSymTypeNone = 0
|
|
|
|
|
ElfSymTypeObject = 1
|
|
|
|
|
ElfSymTypeFunc = 2
|
|
|
|
|
ElfSymTypeSection = 3
|
|
|
|
|
ElfSymTypeFile = 4
|
2016-11-28 16:19:03 -08:00
|
|
|
ElfSymTypeCommon = 5
|
|
|
|
|
ElfSymTypeTLS = 6
|
2015-03-04 10:28:18 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
2015-02-27 22:57:28 -05:00
|
|
|
ElfSymShnNone = 0
|
|
|
|
|
ElfSymShnAbs = 0xFFF1
|
|
|
|
|
ElfSymShnCommon = 0xFFF2
|
2015-03-04 10:28:18 +13:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
|
|
|
|
ElfProgNone = 0
|
|
|
|
|
ElfProgLoad = 1
|
|
|
|
|
ElfProgDynamic = 2
|
|
|
|
|
ElfProgInterp = 3
|
|
|
|
|
ElfProgNote = 4
|
|
|
|
|
ElfProgShlib = 5
|
|
|
|
|
ElfProgPhdr = 6
|
|
|
|
|
ElfProgFlagExec = 0x1
|
|
|
|
|
ElfProgFlagWrite = 0x2
|
|
|
|
|
ElfProgFlagRead = 0x4
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
const (
|
2015-02-27 22:57:28 -05:00
|
|
|
ElfNotePrStatus = 1
|
|
|
|
|
ElfNotePrFpreg = 2
|
|
|
|
|
ElfNotePrPsinfo = 3
|
|
|
|
|
ElfNotePrTaskstruct = 4
|
|
|
|
|
ElfNotePrAuxv = 6
|
|
|
|
|
ElfNotePrXfpreg = 0x46e62b7f
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type ElfHdrBytes struct {
|
|
|
|
|
Ident [16]uint8
|
|
|
|
|
Type [2]uint8
|
|
|
|
|
Machine [2]uint8
|
|
|
|
|
Version [4]uint8
|
|
|
|
|
Entry [4]uint8
|
|
|
|
|
Phoff [4]uint8
|
|
|
|
|
Shoff [4]uint8
|
|
|
|
|
Flags [4]uint8
|
|
|
|
|
Ehsize [2]uint8
|
|
|
|
|
Phentsize [2]uint8
|
|
|
|
|
Phnum [2]uint8
|
|
|
|
|
Shentsize [2]uint8
|
|
|
|
|
Shnum [2]uint8
|
|
|
|
|
Shstrndx [2]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSectBytes struct {
|
|
|
|
|
Name [4]uint8
|
|
|
|
|
Type [4]uint8
|
|
|
|
|
Flags [4]uint8
|
|
|
|
|
Addr [4]uint8
|
|
|
|
|
Off [4]uint8
|
|
|
|
|
Size [4]uint8
|
|
|
|
|
Link [4]uint8
|
|
|
|
|
Info [4]uint8
|
|
|
|
|
Align [4]uint8
|
|
|
|
|
Entsize [4]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfProgBytes struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSymBytes struct {
|
|
|
|
|
Name [4]uint8
|
|
|
|
|
Value [4]uint8
|
|
|
|
|
Size [4]uint8
|
|
|
|
|
Info uint8
|
|
|
|
|
Other uint8
|
|
|
|
|
Shndx [2]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfHdrBytes64 struct {
|
|
|
|
|
Ident [16]uint8
|
|
|
|
|
Type [2]uint8
|
|
|
|
|
Machine [2]uint8
|
|
|
|
|
Version [4]uint8
|
|
|
|
|
Entry [8]uint8
|
|
|
|
|
Phoff [8]uint8
|
|
|
|
|
Shoff [8]uint8
|
|
|
|
|
Flags [4]uint8
|
|
|
|
|
Ehsize [2]uint8
|
|
|
|
|
Phentsize [2]uint8
|
|
|
|
|
Phnum [2]uint8
|
|
|
|
|
Shentsize [2]uint8
|
|
|
|
|
Shnum [2]uint8
|
|
|
|
|
Shstrndx [2]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSectBytes64 struct {
|
|
|
|
|
Name [4]uint8
|
|
|
|
|
Type [4]uint8
|
|
|
|
|
Flags [8]uint8
|
|
|
|
|
Addr [8]uint8
|
|
|
|
|
Off [8]uint8
|
|
|
|
|
Size [8]uint8
|
|
|
|
|
Link [4]uint8
|
|
|
|
|
Info [4]uint8
|
|
|
|
|
Align [8]uint8
|
|
|
|
|
Entsize [8]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfProgBytes64 struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSymBytes64 struct {
|
|
|
|
|
Name [4]uint8
|
|
|
|
|
Info uint8
|
|
|
|
|
Other uint8
|
|
|
|
|
Shndx [2]uint8
|
|
|
|
|
Value [8]uint8
|
|
|
|
|
Size [8]uint8
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSect struct {
|
|
|
|
|
name string
|
|
|
|
|
nameoff uint32
|
|
|
|
|
type_ uint32
|
|
|
|
|
flags uint64
|
|
|
|
|
addr uint64
|
|
|
|
|
off uint64
|
|
|
|
|
size uint64
|
|
|
|
|
link uint32
|
|
|
|
|
info uint32
|
|
|
|
|
align uint64
|
|
|
|
|
entsize uint64
|
|
|
|
|
base []byte
|
2016-08-19 11:35:54 -04:00
|
|
|
sym *Symbol
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfObj struct {
|
2016-04-08 19:14:03 +10:00
|
|
|
f *bio.Reader
|
2015-03-05 13:57:36 -05:00
|
|
|
base int64 // offset in f where ELF begins
|
|
|
|
|
length int64 // length of ELF
|
2015-02-27 22:57:28 -05:00
|
|
|
is64 int
|
|
|
|
|
name string
|
|
|
|
|
e binary.ByteOrder
|
|
|
|
|
sect []ElfSect
|
|
|
|
|
nsect uint
|
|
|
|
|
shstrtab string
|
|
|
|
|
nsymtab int
|
|
|
|
|
symtab *ElfSect
|
|
|
|
|
symstr *ElfSect
|
|
|
|
|
type_ uint32
|
|
|
|
|
machine uint32
|
|
|
|
|
version uint32
|
|
|
|
|
entry uint64
|
|
|
|
|
phoff uint64
|
|
|
|
|
shoff uint64
|
|
|
|
|
flags uint32
|
|
|
|
|
ehsize uint32
|
|
|
|
|
phentsize uint32
|
|
|
|
|
phnum uint32
|
|
|
|
|
shentsize uint32
|
|
|
|
|
shnum uint32
|
|
|
|
|
shstrndx uint32
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type ElfSym struct {
|
|
|
|
|
name string
|
|
|
|
|
value uint64
|
|
|
|
|
size uint64
|
|
|
|
|
bind uint8
|
|
|
|
|
type_ uint8
|
|
|
|
|
other uint8
|
|
|
|
|
shndx uint16
|
2016-08-19 11:35:54 -04:00
|
|
|
sym *Symbol
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var ElfMagic = [4]uint8{0x7F, 'E', 'L', 'F'}
|
|
|
|
|
|
2015-09-23 15:46:00 +12:00
|
|
|
const (
|
2016-08-22 10:33:13 -04:00
|
|
|
TagFile = 1
|
|
|
|
|
TagCPUName = 4
|
|
|
|
|
TagCPURawName = 5
|
|
|
|
|
TagCompatibility = 32
|
|
|
|
|
TagNoDefaults = 64
|
|
|
|
|
TagAlsoCompatibleWith = 65
|
|
|
|
|
TagABIVFPArgs = 28
|
2015-09-23 15:46:00 +12:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type elfAttribute struct {
|
|
|
|
|
tag uint64
|
|
|
|
|
sval string
|
|
|
|
|
ival uint64
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type elfAttributeList struct {
|
|
|
|
|
data []byte
|
|
|
|
|
err error
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *elfAttributeList) string() string {
|
|
|
|
|
if a.err != nil {
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
nul := bytes.IndexByte(a.data, 0)
|
|
|
|
|
if nul < 0 {
|
|
|
|
|
a.err = io.EOF
|
|
|
|
|
return ""
|
|
|
|
|
}
|
|
|
|
|
s := string(a.data[:nul])
|
|
|
|
|
a.data = a.data[nul+1:]
|
|
|
|
|
return s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *elfAttributeList) uleb128() uint64 {
|
|
|
|
|
if a.err != nil {
|
|
|
|
|
return 0
|
|
|
|
|
}
|
|
|
|
|
v, size := binary.Uvarint(a.data)
|
|
|
|
|
a.data = a.data[size:]
|
|
|
|
|
return v
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Read an elfAttribute from the list following the rules used on ARM systems.
|
|
|
|
|
func (a *elfAttributeList) armAttr() elfAttribute {
|
|
|
|
|
attr := elfAttribute{tag: a.uleb128()}
|
|
|
|
|
switch {
|
2016-08-22 10:33:13 -04:00
|
|
|
case attr.tag == TagCompatibility:
|
2015-09-23 15:46:00 +12:00
|
|
|
attr.ival = a.uleb128()
|
|
|
|
|
attr.sval = a.string()
|
|
|
|
|
|
|
|
|
|
case attr.tag == 64: // Tag_nodefaults has no argument
|
|
|
|
|
|
|
|
|
|
case attr.tag == 65: // Tag_also_compatible_with
|
|
|
|
|
// Not really, but we don't actually care about this tag.
|
|
|
|
|
attr.sval = a.string()
|
|
|
|
|
|
|
|
|
|
// Tag with string argument
|
2016-08-22 10:33:13 -04:00
|
|
|
case attr.tag == TagCPUName || attr.tag == TagCPURawName || (attr.tag >= 32 && attr.tag&1 != 0):
|
2015-09-23 15:46:00 +12:00
|
|
|
attr.sval = a.string()
|
|
|
|
|
|
|
|
|
|
default: // Tag with integer argument
|
|
|
|
|
attr.ival = a.uleb128()
|
|
|
|
|
}
|
|
|
|
|
return attr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (a *elfAttributeList) done() bool {
|
|
|
|
|
if a.err != nil || len(a.data) == 0 {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Look for the attribute that indicates the object uses the hard-float ABI (a
|
|
|
|
|
// file-level attribute with tag Tag_VFP_arch and value 1). Unfortunately the
|
|
|
|
|
// format used means that we have to parse all of the file-level attributes to
|
|
|
|
|
// find the one we are looking for. This format is slightly documented in "ELF
|
|
|
|
|
// for the ARM Architecture" but mostly this is derived from reading the source
|
|
|
|
|
// to gold and readelf.
|
2016-08-21 13:52:23 -04:00
|
|
|
func parseArmAttributes(ctxt *Link, e binary.ByteOrder, data []byte) {
|
2015-09-23 15:46:00 +12:00
|
|
|
// We assume the soft-float ABI unless we see a tag indicating otherwise.
|
|
|
|
|
if ehdr.flags == 0x5000002 {
|
|
|
|
|
ehdr.flags = 0x5000202
|
|
|
|
|
}
|
|
|
|
|
if data[0] != 'A' {
|
2016-08-25 12:32:42 +10:00
|
|
|
// TODO(dfc) should this be ctxt.Diag ?
|
|
|
|
|
ctxt.Logf(".ARM.attributes has unexpected format %c\n", data[0])
|
2015-09-23 15:46:00 +12:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
data = data[1:]
|
|
|
|
|
for len(data) != 0 {
|
|
|
|
|
sectionlength := e.Uint32(data)
|
|
|
|
|
sectiondata := data[4:sectionlength]
|
|
|
|
|
data = data[sectionlength:]
|
|
|
|
|
|
|
|
|
|
nulIndex := bytes.IndexByte(sectiondata, 0)
|
|
|
|
|
if nulIndex < 0 {
|
2016-08-25 12:32:42 +10:00
|
|
|
// TODO(dfc) should this be ctxt.Diag ?
|
|
|
|
|
ctxt.Logf("corrupt .ARM.attributes (section name not NUL-terminated)\n")
|
2015-09-23 15:46:00 +12:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
name := string(sectiondata[:nulIndex])
|
|
|
|
|
sectiondata = sectiondata[nulIndex+1:]
|
|
|
|
|
|
|
|
|
|
if name != "aeabi" {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
for len(sectiondata) != 0 {
|
|
|
|
|
subsectiontag, sz := binary.Uvarint(sectiondata)
|
|
|
|
|
subsectionsize := e.Uint32(sectiondata[sz:])
|
|
|
|
|
subsectiondata := sectiondata[sz+4 : subsectionsize]
|
|
|
|
|
sectiondata = sectiondata[subsectionsize:]
|
|
|
|
|
|
2016-08-22 10:33:13 -04:00
|
|
|
if subsectiontag == TagFile {
|
2015-09-23 15:46:00 +12:00
|
|
|
attrList := elfAttributeList{data: subsectiondata}
|
|
|
|
|
for !attrList.done() {
|
|
|
|
|
attr := attrList.armAttr()
|
2016-08-22 10:33:13 -04:00
|
|
|
if attr.tag == TagABIVFPArgs && attr.ival == 1 {
|
2015-09-23 15:46:00 +12:00
|
|
|
ehdr.flags = 0x5000402 // has entry point, Version5 EABI, hard-float ABI
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if attrList.err != nil {
|
2016-08-25 12:32:42 +10:00
|
|
|
// TODO(dfc) should this be ctxt.Diag ?
|
|
|
|
|
ctxt.Logf("could not parse .ARM.attributes\n")
|
2015-09-23 15:46:00 +12:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func ldelf(ctxt *Link, f *bio.Reader, pkg string, length int64, pn string) {
|
2016-08-21 18:25:28 -04:00
|
|
|
if ctxt.Debugvlog != 0 {
|
2017-04-18 12:53:25 -07:00
|
|
|
ctxt.Logf("%5.2f ldelf %s\n", Cputime(), pn)
|
2015-03-02 12:35:15 -05:00
|
|
|
}
|
|
|
|
|
|
2016-09-20 15:46:37 +12:00
|
|
|
localSymVersion := ctxt.Syms.IncVersion()
|
2016-04-08 19:14:03 +10:00
|
|
|
base := f.Offset()
|
2015-03-02 12:35:15 -05:00
|
|
|
|
2015-02-27 22:57:28 -05:00
|
|
|
var add uint64
|
2015-03-02 12:35:15 -05:00
|
|
|
var e binary.ByteOrder
|
|
|
|
|
var elfobj *ElfObj
|
|
|
|
|
var flag int
|
|
|
|
|
var hdr *ElfHdrBytes
|
|
|
|
|
var hdrbuf [64]uint8
|
2015-02-27 22:57:28 -05:00
|
|
|
var info uint64
|
|
|
|
|
var is64 int
|
2015-03-02 12:35:15 -05:00
|
|
|
var j int
|
2015-02-27 22:57:28 -05:00
|
|
|
var n int
|
2015-03-02 12:35:15 -05:00
|
|
|
var name string
|
2015-02-27 22:57:28 -05:00
|
|
|
var p []byte
|
|
|
|
|
var r []Reloc
|
2015-03-02 12:35:15 -05:00
|
|
|
var rela int
|
2015-02-27 22:57:28 -05:00
|
|
|
var rp *Reloc
|
2015-03-02 12:35:15 -05:00
|
|
|
var rsect *ElfSect
|
2016-08-19 11:35:54 -04:00
|
|
|
var s *Symbol
|
2015-03-02 12:35:15 -05:00
|
|
|
var sect *ElfSect
|
|
|
|
|
var sym ElfSym
|
2016-08-19 11:35:54 -04:00
|
|
|
var symbols []*Symbol
|
2016-04-08 18:19:10 +02:00
|
|
|
if _, err := io.ReadFull(f, hdrbuf[:]); err != nil {
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
hdr = new(ElfHdrBytes)
|
|
|
|
|
binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
|
|
|
|
|
if string(hdr.Ident[:4]) != "\x7FELF" {
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file", pn)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
switch hdr.Ident[5] {
|
|
|
|
|
case ElfDataLsb:
|
|
|
|
|
e = binary.LittleEndian
|
|
|
|
|
|
|
|
|
|
case ElfDataMsb:
|
|
|
|
|
e = binary.BigEndian
|
|
|
|
|
|
|
|
|
|
default:
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file", pn)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read header
|
|
|
|
|
elfobj = new(ElfObj)
|
|
|
|
|
|
|
|
|
|
elfobj.e = e
|
|
|
|
|
elfobj.f = f
|
2016-04-14 19:04:45 -07:00
|
|
|
elfobj.base = base
|
2015-02-27 22:57:28 -05:00
|
|
|
elfobj.length = length
|
|
|
|
|
elfobj.name = pn
|
|
|
|
|
|
|
|
|
|
is64 = 0
|
|
|
|
|
if hdr.Ident[4] == ElfClass64 {
|
|
|
|
|
is64 = 1
|
2015-03-02 12:35:15 -05:00
|
|
|
hdr := new(ElfHdrBytes64)
|
2015-02-27 22:57:28 -05:00
|
|
|
binary.Read(bytes.NewReader(hdrbuf[:]), binary.BigEndian, hdr) // only byte arrays; byte order doesn't matter
|
|
|
|
|
elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
|
|
|
|
|
elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
|
|
|
|
|
elfobj.version = e.Uint32(hdr.Version[:])
|
|
|
|
|
elfobj.phoff = e.Uint64(hdr.Phoff[:])
|
|
|
|
|
elfobj.shoff = e.Uint64(hdr.Shoff[:])
|
|
|
|
|
elfobj.flags = e.Uint32(hdr.Flags[:])
|
|
|
|
|
elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
|
|
|
|
|
elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
|
|
|
|
|
elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
|
|
|
|
|
elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
|
|
|
|
|
elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
|
|
|
|
|
elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
|
|
|
|
|
} else {
|
|
|
|
|
elfobj.type_ = uint32(e.Uint16(hdr.Type[:]))
|
|
|
|
|
elfobj.machine = uint32(e.Uint16(hdr.Machine[:]))
|
|
|
|
|
elfobj.version = e.Uint32(hdr.Version[:])
|
|
|
|
|
elfobj.entry = uint64(e.Uint32(hdr.Entry[:]))
|
|
|
|
|
elfobj.phoff = uint64(e.Uint32(hdr.Phoff[:]))
|
|
|
|
|
elfobj.shoff = uint64(e.Uint32(hdr.Shoff[:]))
|
|
|
|
|
elfobj.flags = e.Uint32(hdr.Flags[:])
|
|
|
|
|
elfobj.ehsize = uint32(e.Uint16(hdr.Ehsize[:]))
|
|
|
|
|
elfobj.phentsize = uint32(e.Uint16(hdr.Phentsize[:]))
|
|
|
|
|
elfobj.phnum = uint32(e.Uint16(hdr.Phnum[:]))
|
|
|
|
|
elfobj.shentsize = uint32(e.Uint16(hdr.Shentsize[:]))
|
|
|
|
|
elfobj.shnum = uint32(e.Uint16(hdr.Shnum[:]))
|
|
|
|
|
elfobj.shstrndx = uint32(e.Uint16(hdr.Shstrndx[:]))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elfobj.is64 = is64
|
|
|
|
|
|
2017-04-20 10:45:01 +10:00
|
|
|
if v := uint32(hdr.Ident[6]); v != elfobj.version {
|
|
|
|
|
Errorf(nil, "%s: malformed elf version: got %d, want %d", pn, v, elfobj.version)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if e.Uint16(hdr.Type[:]) != ElfTypeRelocatable {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf but not elf relocatable object", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
switch SysArch.Family {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf %s unimplemented", pn, SysArch.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
|
2016-10-18 23:50:45 +02:00
|
|
|
case sys.MIPS:
|
|
|
|
|
if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass32 {
|
|
|
|
|
Errorf(nil, "%s: elf object but not mips", pn)
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.MIPS64:
|
2015-09-10 11:32:49 -04:00
|
|
|
if elfobj.machine != ElfMachMips || hdr.Ident[4] != ElfClass64 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not mips64", pn)
|
2015-09-10 11:32:49 -04:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.ARM:
|
2015-02-27 22:57:28 -05:00
|
|
|
if e != binary.LittleEndian || elfobj.machine != ElfMachArm || hdr.Ident[4] != ElfClass32 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not arm", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.AMD64:
|
2015-02-27 22:57:28 -05:00
|
|
|
if e != binary.LittleEndian || elfobj.machine != ElfMachAmd64 || hdr.Ident[4] != ElfClass64 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not amd64", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.ARM64:
|
2015-03-08 14:14:53 +01:00
|
|
|
if e != binary.LittleEndian || elfobj.machine != ElfMachArm64 || hdr.Ident[4] != ElfClass64 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not arm64", pn)
|
2015-03-08 14:14:53 +01:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.I386:
|
2015-02-27 22:57:28 -05:00
|
|
|
if e != binary.LittleEndian || elfobj.machine != ElfMach386 || hdr.Ident[4] != ElfClass32 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not 386", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
2016-04-06 12:01:40 -07:00
|
|
|
case sys.PPC64:
|
2015-02-27 22:57:28 -05:00
|
|
|
if elfobj.machine != ElfMachPower64 || hdr.Ident[4] != ElfClass64 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not ppc64", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
2016-04-06 12:01:40 -07:00
|
|
|
|
|
|
|
|
case sys.S390X:
|
2016-03-18 16:57:54 -04:00
|
|
|
if elfobj.machine != ElfMachS390 || hdr.Ident[4] != ElfClass64 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object but not s390x", pn)
|
2016-03-18 16:57:54 -04:00
|
|
|
return
|
|
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load section list into memory.
|
|
|
|
|
elfobj.sect = make([]ElfSect, elfobj.shnum)
|
|
|
|
|
|
|
|
|
|
elfobj.nsect = uint(elfobj.shnum)
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2016-04-08 19:14:03 +10:00
|
|
|
if f.Seek(int64(uint64(base)+elfobj.shoff+uint64(int64(i)*int64(elfobj.shentsize))), 0) < 0 {
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file", pn)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
sect = &elfobj.sect[i]
|
|
|
|
|
if is64 != 0 {
|
|
|
|
|
var b ElfSectBytes64
|
|
|
|
|
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := binary.Read(f, e, &b); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-14 19:04:45 -07:00
|
|
|
sect.nameoff = e.Uint32(b.Name[:])
|
2015-02-27 22:57:28 -05:00
|
|
|
sect.type_ = e.Uint32(b.Type[:])
|
|
|
|
|
sect.flags = e.Uint64(b.Flags[:])
|
|
|
|
|
sect.addr = e.Uint64(b.Addr[:])
|
|
|
|
|
sect.off = e.Uint64(b.Off[:])
|
|
|
|
|
sect.size = e.Uint64(b.Size[:])
|
|
|
|
|
sect.link = e.Uint32(b.Link[:])
|
|
|
|
|
sect.info = e.Uint32(b.Info[:])
|
|
|
|
|
sect.align = e.Uint64(b.Align[:])
|
|
|
|
|
sect.entsize = e.Uint64(b.Entsize[:])
|
|
|
|
|
} else {
|
|
|
|
|
var b ElfSectBytes
|
|
|
|
|
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := binary.Read(f, e, &b); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
2016-04-14 19:04:45 -07:00
|
|
|
sect.nameoff = e.Uint32(b.Name[:])
|
2015-02-27 22:57:28 -05:00
|
|
|
sect.type_ = e.Uint32(b.Type[:])
|
|
|
|
|
sect.flags = uint64(e.Uint32(b.Flags[:]))
|
|
|
|
|
sect.addr = uint64(e.Uint32(b.Addr[:]))
|
|
|
|
|
sect.off = uint64(e.Uint32(b.Off[:]))
|
|
|
|
|
sect.size = uint64(e.Uint32(b.Size[:]))
|
|
|
|
|
sect.link = e.Uint32(b.Link[:])
|
|
|
|
|
sect.info = e.Uint32(b.Info[:])
|
|
|
|
|
sect.align = uint64(e.Uint32(b.Align[:]))
|
|
|
|
|
sect.entsize = uint64(e.Uint32(b.Entsize[:]))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// read section string table and translate names
|
|
|
|
|
if elfobj.shstrndx >= uint32(elfobj.nsect) {
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file: shstrndx out of range %d >= %d", pn, elfobj.shstrndx, elfobj.nsect)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sect = &elfobj.sect[elfobj.shstrndx]
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, sect); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
if elfobj.sect[i].nameoff != 0 {
|
|
|
|
|
elfobj.sect[i].name = cstring(sect.base[elfobj.sect[i].nameoff:])
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load string table for symbols into memory.
|
|
|
|
|
elfobj.symtab = section(elfobj, ".symtab")
|
|
|
|
|
|
|
|
|
|
if elfobj.symtab == nil {
|
|
|
|
|
// our work is done here - no symbols means nothing can refer to this file
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if elfobj.symtab.link <= 0 || elfobj.symtab.link >= uint32(elfobj.nsect) {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: elf object has symbol table with invalid string table link", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
elfobj.symstr = &elfobj.sect[elfobj.symtab.link]
|
|
|
|
|
if is64 != 0 {
|
|
|
|
|
elfobj.nsymtab = int(elfobj.symtab.size / ELF64SYMSIZE)
|
|
|
|
|
} else {
|
|
|
|
|
elfobj.nsymtab = int(elfobj.symtab.size / ELF32SYMSIZE)
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, elfobj.symtab); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, elfobj.symstr); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load text and data segments into memory.
|
|
|
|
|
// they are not as small as the section lists, but we'll need
|
|
|
|
|
// the memory anyway for the symbol images, so we might
|
|
|
|
|
// as well use one large chunk.
|
|
|
|
|
|
|
|
|
|
// create symbols for elfmapped sections
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
sect = &elfobj.sect[i]
|
2015-09-23 15:46:00 +12:00
|
|
|
if sect.type_ == SHT_ARM_ATTRIBUTES && sect.name == ".ARM.attributes" {
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, sect); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-09-23 15:46:00 +12:00
|
|
|
}
|
2016-08-21 13:52:23 -04:00
|
|
|
parseArmAttributes(ctxt, e, sect.base[:sect.size])
|
2015-09-23 15:46:00 +12:00
|
|
|
}
|
2015-02-27 22:57:28 -05:00
|
|
|
if (sect.type_ != ElfSectProgbits && sect.type_ != ElfSectNobits) || sect.flags&ElfSectFlagAlloc == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if sect.type_ != ElfSectNobits {
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, sect); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
name = fmt.Sprintf("%s(%s)", pkg, sect.name)
|
2016-09-20 15:46:37 +12:00
|
|
|
s = ctxt.Syms.Lookup(name, localSymVersion)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
switch int(sect.flags) & (ElfSectFlagAlloc | ElfSectFlagWrite | ElfSectFlagExec) {
|
|
|
|
|
default:
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: unexpected flags for ELF section %s", pn, sect.name)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
case ElfSectFlagAlloc:
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SRODATA
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
case ElfSectFlagAlloc + ElfSectFlagWrite:
|
|
|
|
|
if sect.type_ == ElfSectNobits {
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SNOPTRBSS
|
2015-02-27 22:57:28 -05:00
|
|
|
} else {
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SNOPTRDATA
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ElfSectFlagAlloc + ElfSectFlagExec:
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = STEXT
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sect.name == ".got" || sect.name == ".toc" {
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SELFGOT
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
if sect.type_ == ElfSectProgbits {
|
|
|
|
|
s.P = sect.base
|
|
|
|
|
s.P = s.P[:sect.size]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.Size = int64(sect.size)
|
|
|
|
|
s.Align = int32(sect.align)
|
|
|
|
|
sect.sym = s
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// enter sub-symbols into symbol table.
|
|
|
|
|
// symbol 0 is the null symbol.
|
2016-08-19 11:35:54 -04:00
|
|
|
symbols = make([]*Symbol, elfobj.nsymtab)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 1; i < elfobj.nsymtab; i++ {
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := readelfsym(ctxt, elfobj, i, &sym, 1, localSymVersion); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
symbols[i] = sym.sym
|
2016-11-28 16:19:03 -08:00
|
|
|
if sym.type_ != ElfSymTypeFunc && sym.type_ != ElfSymTypeObject && sym.type_ != ElfSymTypeNone && sym.type_ != ElfSymTypeCommon {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2016-11-28 16:19:03 -08:00
|
|
|
if sym.shndx == ElfSymShnCommon || sym.type_ == ElfSymTypeCommon {
|
2015-02-27 22:57:28 -05:00
|
|
|
s = sym.sym
|
|
|
|
|
if uint64(s.Size) < sym.size {
|
|
|
|
|
s.Size = int64(sym.size)
|
|
|
|
|
}
|
2017-04-19 15:15:35 +12:00
|
|
|
if s.Type == 0 || s.Type == SXREF {
|
|
|
|
|
s.Type = SNOPTRBSS
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if uint(sym.shndx) >= elfobj.nsect || sym.shndx == 0 {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// even when we pass needSym == 1 to readelfsym, it might still return nil to skip some unwanted symbols
|
|
|
|
|
if sym.sym == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-04-12 12:16:20 -07:00
|
|
|
sect = &elfobj.sect[sym.shndx]
|
2015-02-27 22:57:28 -05:00
|
|
|
if sect.sym == nil {
|
2015-03-05 13:57:36 -05:00
|
|
|
if strings.HasPrefix(sym.name, ".Linfo_string") { // clang does this
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2015-11-04 18:20:57 -08:00
|
|
|
|
|
|
|
|
if sym.name == "" && sym.type_ == 0 && sect.name == ".debug_str" {
|
|
|
|
|
// This reportedly happens with clang 3.7 on ARM.
|
|
|
|
|
// See issue 13139.
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2016-03-18 16:57:54 -04:00
|
|
|
if strings.HasPrefix(sym.name, ".LASF") { // gcc on s390x does this
|
|
|
|
|
continue
|
|
|
|
|
}
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(sym.sym, "%s: sym#%d: ignoring symbol in section %d (type %d)", pn, i, sym.shndx, sym.type_)
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s = sym.sym
|
|
|
|
|
if s.Outer != nil {
|
2016-03-02 07:59:49 -05:00
|
|
|
if s.Attr.DuplicateOK() {
|
2015-02-27 22:57:28 -05:00
|
|
|
continue
|
|
|
|
|
}
|
2015-04-09 07:37:17 -04:00
|
|
|
Exitf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sect.sym.Name)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
s.Sub = sect.sym.Sub
|
|
|
|
|
sect.sym.Sub = s
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = sect.sym.Type | s.Type&^SMASK | SSUB
|
2016-03-02 07:59:49 -05:00
|
|
|
if !s.Attr.CgoExportDynamic() {
|
2015-02-27 22:57:28 -05:00
|
|
|
s.Dynimplib = "" // satisfy dynimport
|
|
|
|
|
}
|
|
|
|
|
s.Value = int64(sym.value)
|
|
|
|
|
s.Size = int64(sym.size)
|
|
|
|
|
s.Outer = sect.sym
|
2017-04-19 15:15:35 +12:00
|
|
|
if sect.sym.Type == STEXT {
|
2016-03-02 07:59:49 -05:00
|
|
|
if s.Attr.External() && !s.Attr.DuplicateOK() {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(s, "%s: duplicate symbol definition", pn)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2016-03-02 07:59:49 -05:00
|
|
|
s.Attr |= AttrExternal
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if elfobj.machine == ElfMachPower64 {
|
|
|
|
|
flag = int(sym.other) >> 5
|
|
|
|
|
if 2 <= flag && flag <= 6 {
|
|
|
|
|
s.Localentry = 1 << uint(flag-2)
|
|
|
|
|
} else if flag == 7 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(s, "%s: invalid sym.other 0x%x", pn, sym.other)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Sort outer lists by address, adding to textp.
|
|
|
|
|
// This keeps textp in increasing address order.
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
s = elfobj.sect[i].sym
|
|
|
|
|
if s == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if s.Sub != nil {
|
2016-08-22 10:53:05 +12:00
|
|
|
s.Sub = listsort(s.Sub)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
2017-04-19 15:15:35 +12:00
|
|
|
if s.Type == STEXT {
|
2016-03-02 07:59:49 -05:00
|
|
|
if s.Attr.OnList() {
|
2015-02-27 22:57:28 -05:00
|
|
|
log.Fatalf("symbol %s listed multiple times", s.Name)
|
|
|
|
|
}
|
2016-03-02 07:59:49 -05:00
|
|
|
s.Attr |= AttrOnList
|
2016-08-19 22:40:38 -04:00
|
|
|
ctxt.Textp = append(ctxt.Textp, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
for s = s.Sub; s != nil; s = s.Sub {
|
2016-03-02 07:59:49 -05:00
|
|
|
if s.Attr.OnList() {
|
2015-02-27 22:57:28 -05:00
|
|
|
log.Fatalf("symbol %s listed multiple times", s.Name)
|
|
|
|
|
}
|
2016-03-02 07:59:49 -05:00
|
|
|
s.Attr |= AttrOnList
|
2016-08-19 22:40:38 -04:00
|
|
|
ctxt.Textp = append(ctxt.Textp, s)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// load relocations
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
rsect = &elfobj.sect[i]
|
|
|
|
|
if rsect.type_ != ElfSectRela && rsect.type_ != ElfSectRel {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
if rsect.info >= uint32(elfobj.nsect) || elfobj.sect[rsect.info].base == nil {
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
sect = &elfobj.sect[rsect.info]
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := elfmap(elfobj, rsect); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
rela = 0
|
|
|
|
|
if rsect.type_ == ElfSectRela {
|
|
|
|
|
rela = 1
|
|
|
|
|
}
|
|
|
|
|
n = int(rsect.size / uint64(4+4*is64) / uint64(2+rela))
|
|
|
|
|
r = make([]Reloc, n)
|
|
|
|
|
p = rsect.base
|
|
|
|
|
for j = 0; j < n; j++ {
|
|
|
|
|
add = 0
|
|
|
|
|
rp = &r[j]
|
|
|
|
|
if is64 != 0 {
|
|
|
|
|
// 64-bit rel/rela
|
|
|
|
|
rp.Off = int32(e.Uint64(p))
|
|
|
|
|
|
|
|
|
|
p = p[8:]
|
|
|
|
|
info = e.Uint64(p)
|
|
|
|
|
p = p[8:]
|
|
|
|
|
if rela != 0 {
|
|
|
|
|
add = e.Uint64(p)
|
|
|
|
|
p = p[8:]
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
// 32-bit rel/rela
|
|
|
|
|
rp.Off = int32(e.Uint32(p))
|
|
|
|
|
|
|
|
|
|
p = p[4:]
|
|
|
|
|
info = uint64(e.Uint32(p))
|
|
|
|
|
info = info>>8<<32 | info&0xff // convert to 64-bit info
|
|
|
|
|
p = p[4:]
|
|
|
|
|
if rela != 0 {
|
|
|
|
|
add = uint64(e.Uint32(p))
|
|
|
|
|
p = p[4:]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if info&0xffffffff == 0 { // skip R_*_NONE relocation
|
|
|
|
|
j--
|
|
|
|
|
n--
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if info>>32 == 0 { // absolute relocation, don't bother reading the null symbol
|
|
|
|
|
rp.Sym = nil
|
|
|
|
|
} else {
|
2017-04-20 10:45:01 +10:00
|
|
|
if err := readelfsym(ctxt, elfobj, int(info>>32), &sym, 0, 0); err != nil {
|
|
|
|
|
Errorf(nil, "%s: malformed elf file: %v", pn, err)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
sym.sym = symbols[info>>32]
|
|
|
|
|
if sym.sym == nil {
|
2017-04-20 10:45:01 +10:00
|
|
|
Errorf(nil, "%s: malformed elf file: %s#%d: reloc of invalid sym #%d %s shndx=%d type=%d", pn, sect.sym.Name, j, int(info>>32), sym.name, sym.shndx, sym.type_)
|
|
|
|
|
return
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rp.Sym = sym.sym
|
|
|
|
|
}
|
|
|
|
|
|
2017-04-18 12:53:25 -07:00
|
|
|
rp.Type = 256 + objabi.RelocType(info)
|
2016-08-19 22:40:38 -04:00
|
|
|
rp.Siz = relSize(ctxt, pn, uint32(info))
|
2015-02-27 22:57:28 -05:00
|
|
|
if rela != 0 {
|
|
|
|
|
rp.Add = int64(add)
|
|
|
|
|
} else {
|
|
|
|
|
// load addend from image
|
|
|
|
|
if rp.Siz == 4 {
|
|
|
|
|
rp.Add = int64(e.Uint32(sect.base[rp.Off:]))
|
|
|
|
|
} else if rp.Siz == 8 {
|
|
|
|
|
rp.Add = int64(e.Uint64(sect.base[rp.Off:]))
|
|
|
|
|
} else {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "invalid rela size %d", rp.Siz)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if rp.Siz == 2 {
|
|
|
|
|
rp.Add = int64(int16(rp.Add))
|
|
|
|
|
}
|
|
|
|
|
if rp.Siz == 4 {
|
|
|
|
|
rp.Add = int64(int32(rp.Add))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//print("rel %s %d %d %s %#llx\n", sect->sym->name, rp->type, rp->siz, rp->sym->name, rp->add);
|
|
|
|
|
sort.Sort(rbyoff(r[:n]))
|
|
|
|
|
// just in case
|
|
|
|
|
|
|
|
|
|
s = sect.sym
|
|
|
|
|
s.R = r
|
|
|
|
|
s.R = s.R[:n]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func section(elfobj *ElfObj, name string) *ElfSect {
|
2015-03-02 12:35:15 -05:00
|
|
|
for i := 0; uint(i) < elfobj.nsect; i++ {
|
2015-02-27 22:57:28 -05:00
|
|
|
if elfobj.sect[i].name != "" && name != "" && elfobj.sect[i].name == name {
|
|
|
|
|
return &elfobj.sect[i]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func elfmap(elfobj *ElfObj, sect *ElfSect) (err error) {
|
|
|
|
|
if sect.base != nil {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sect.off+sect.size > uint64(elfobj.length) {
|
|
|
|
|
err = fmt.Errorf("elf section past end of file")
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sect.base = make([]byte, sect.size)
|
2016-04-08 18:19:10 +02:00
|
|
|
if elfobj.f.Seek(int64(uint64(elfobj.base)+sect.off), 0) < 0 {
|
|
|
|
|
return fmt.Errorf("short read: seek not successful")
|
|
|
|
|
}
|
|
|
|
|
if _, err := io.ReadFull(elfobj.f, sect.base); err != nil {
|
|
|
|
|
return fmt.Errorf("short read: %v", err)
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
2016-09-20 15:46:37 +12:00
|
|
|
func readelfsym(ctxt *Link, elfobj *ElfObj, i int, sym *ElfSym, needSym int, localSymVersion int) (err error) {
|
2015-02-27 22:57:28 -05:00
|
|
|
if i >= elfobj.nsymtab || i < 0 {
|
|
|
|
|
err = fmt.Errorf("invalid elf symbol index")
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if i == 0 {
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "readym: read null symbol!")
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if elfobj.is64 != 0 {
|
|
|
|
|
b := new(ElfSymBytes64)
|
|
|
|
|
binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF64SYMSIZE:(i+1)*ELF64SYMSIZE]), elfobj.e, b)
|
|
|
|
|
sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
|
|
|
|
|
sym.value = elfobj.e.Uint64(b.Value[:])
|
|
|
|
|
sym.size = elfobj.e.Uint64(b.Size[:])
|
|
|
|
|
sym.shndx = elfobj.e.Uint16(b.Shndx[:])
|
|
|
|
|
sym.bind = b.Info >> 4
|
|
|
|
|
sym.type_ = b.Info & 0xf
|
|
|
|
|
sym.other = b.Other
|
|
|
|
|
} else {
|
|
|
|
|
b := new(ElfSymBytes)
|
|
|
|
|
binary.Read(bytes.NewReader(elfobj.symtab.base[i*ELF32SYMSIZE:(i+1)*ELF32SYMSIZE]), elfobj.e, b)
|
|
|
|
|
sym.name = cstring(elfobj.symstr.base[elfobj.e.Uint32(b.Name[:]):])
|
|
|
|
|
sym.value = uint64(elfobj.e.Uint32(b.Value[:]))
|
|
|
|
|
sym.size = uint64(elfobj.e.Uint32(b.Size[:]))
|
|
|
|
|
sym.shndx = elfobj.e.Uint16(b.Shndx[:])
|
|
|
|
|
sym.bind = b.Info >> 4
|
|
|
|
|
sym.type_ = b.Info & 0xf
|
|
|
|
|
sym.other = b.Other
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 11:35:54 -04:00
|
|
|
var s *Symbol
|
2015-02-27 22:57:28 -05:00
|
|
|
if sym.name == "_GLOBAL_OFFSET_TABLE_" {
|
|
|
|
|
sym.name = ".got"
|
|
|
|
|
}
|
|
|
|
|
if sym.name == ".TOC." {
|
|
|
|
|
// Magic symbol on ppc64. Will be set to this object
|
|
|
|
|
// file's .got+0x8000.
|
|
|
|
|
sym.bind = ElfSymBindLocal
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch sym.type_ {
|
|
|
|
|
case ElfSymTypeSection:
|
|
|
|
|
s = elfobj.sect[sym.shndx].sym
|
|
|
|
|
|
2016-11-28 16:19:03 -08:00
|
|
|
case ElfSymTypeObject, ElfSymTypeFunc, ElfSymTypeNone, ElfSymTypeCommon:
|
2015-02-27 22:57:28 -05:00
|
|
|
switch sym.bind {
|
|
|
|
|
case ElfSymBindGlobal:
|
|
|
|
|
if needSym != 0 {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s = ctxt.Syms.Lookup(sym.name, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
|
|
|
|
// for global scoped hidden symbols we should insert it into
|
|
|
|
|
// symbol hash table, but mark them as hidden.
|
|
|
|
|
// __i686.get_pc_thunk.bx is allowed to be duplicated, to
|
|
|
|
|
// workaround that we set dupok.
|
|
|
|
|
// TODO(minux): correctly handle __i686.get_pc_thunk.bx without
|
|
|
|
|
// set dupok generally. See http://codereview.appspot.com/5823055/
|
|
|
|
|
// comment #5 for details.
|
|
|
|
|
if s != nil && sym.other == 2 {
|
2017-05-01 00:56:09 +00:00
|
|
|
s.Type |= SHIDDEN
|
|
|
|
|
s.Attr |= AttrDuplicateOK
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ElfSymBindLocal:
|
2016-04-06 12:01:40 -07:00
|
|
|
if SysArch.Family == sys.ARM && (strings.HasPrefix(sym.name, "$a") || strings.HasPrefix(sym.name, "$d")) {
|
2015-03-05 13:57:36 -05:00
|
|
|
// binutils for arm generate these mapping
|
2015-02-27 22:57:28 -05:00
|
|
|
// symbols, ignore these
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if sym.name == ".TOC." {
|
|
|
|
|
// We need to be able to look this up,
|
|
|
|
|
// so put it in the hash table.
|
|
|
|
|
if needSym != 0 {
|
2016-09-20 15:46:37 +12:00
|
|
|
s = ctxt.Syms.Lookup(sym.name, localSymVersion)
|
2017-05-01 00:56:09 +00:00
|
|
|
s.Type |= SHIDDEN
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if needSym != 0 {
|
2016-02-24 11:55:20 +01:00
|
|
|
// local names and hidden global names are unique
|
|
|
|
|
// and should only be referenced by their index, not name, so we
|
|
|
|
|
// don't bother to add them into the hash table
|
2016-09-20 15:46:37 +12:00
|
|
|
s = ctxt.Syms.newsym(sym.name, localSymVersion)
|
2015-02-27 22:57:28 -05:00
|
|
|
|
2017-05-01 00:56:09 +00:00
|
|
|
s.Type |= SHIDDEN
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case ElfSymBindWeak:
|
|
|
|
|
if needSym != 0 {
|
cmd/link: use ctxt.{Lookup,ROLookup} in favour of function versions of same
Done with two eg templates:
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linklookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.Lookup(name, v)
}
package p
import (
"cmd/link/internal/ld"
)
func before(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ld.Linkrlookup(ctxt, name, v)
}
func after(ctxt *ld.Link, name string, v int) *ld.Symbol {
return ctxt.Syms.ROLookup(name, v)
}
Change-Id: I00647dbf62294557bd24c29ad1f108fc786335f1
Reviewed-on: https://go-review.googlesource.com/29343
Run-TryBot: Michael Hudson-Doyle <michael.hudson@canonical.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2016-09-20 15:06:08 +12:00
|
|
|
s = ctxt.Syms.Lookup(sym.name, 0)
|
2015-02-27 22:57:28 -05:00
|
|
|
if sym.other == 2 {
|
2017-05-01 00:56:09 +00:00
|
|
|
s.Type |= SHIDDEN
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
err = fmt.Errorf("%s: invalid symbol binding %d", sym.name, sym.bind)
|
|
|
|
|
return err
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if s != nil && s.Type == 0 && sym.type_ != ElfSymTypeSection {
|
2017-04-19 15:15:35 +12:00
|
|
|
s.Type = SXREF
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
sym.sym = s
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type rbyoff []Reloc
|
|
|
|
|
|
|
|
|
|
func (x rbyoff) Len() int {
|
|
|
|
|
return len(x)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x rbyoff) Swap(i, j int) {
|
|
|
|
|
x[i], x[j] = x[j], x[i]
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (x rbyoff) Less(i, j int) bool {
|
2015-03-02 12:35:15 -05:00
|
|
|
a := &x[i]
|
|
|
|
|
b := &x[j]
|
2015-02-27 22:57:28 -05:00
|
|
|
if a.Off < b.Off {
|
|
|
|
|
return true
|
|
|
|
|
}
|
|
|
|
|
if a.Off > b.Off {
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
return false
|
|
|
|
|
}
|
|
|
|
|
|
2016-08-19 22:40:38 -04:00
|
|
|
func relSize(ctxt *Link, pn string, elftype uint32) uint8 {
|
2016-04-06 20:06:12 -07:00
|
|
|
// TODO(mdempsky): Replace this with a struct-valued switch statement
|
|
|
|
|
// once golang.org/issue/15164 is fixed or found to not impair cmd/link
|
|
|
|
|
// performance.
|
2016-04-06 12:01:40 -07:00
|
|
|
|
2016-04-06 20:06:12 -07:00
|
|
|
const (
|
|
|
|
|
AMD64 = uint32(sys.AMD64)
|
|
|
|
|
ARM = uint32(sys.ARM)
|
|
|
|
|
I386 = uint32(sys.I386)
|
|
|
|
|
PPC64 = uint32(sys.PPC64)
|
|
|
|
|
S390X = uint32(sys.S390X)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
switch uint32(SysArch.Family) | elftype<<24 {
|
2015-02-27 22:57:28 -05:00
|
|
|
default:
|
2016-09-17 09:39:33 -04:00
|
|
|
Errorf(nil, "%s: unknown relocation type %d; compiled without -fpic?", pn, elftype)
|
2015-02-27 22:57:28 -05:00
|
|
|
fallthrough
|
|
|
|
|
|
2016-04-06 20:06:12 -07:00
|
|
|
case S390X | R_390_8<<24:
|
|
|
|
|
return 1
|
|
|
|
|
|
|
|
|
|
case PPC64 | R_PPC64_TOC16<<24,
|
|
|
|
|
PPC64 | R_PPC64_TOC16_LO<<24,
|
|
|
|
|
PPC64 | R_PPC64_TOC16_HI<<24,
|
|
|
|
|
PPC64 | R_PPC64_TOC16_HA<<24,
|
|
|
|
|
PPC64 | R_PPC64_TOC16_DS<<24,
|
|
|
|
|
PPC64 | R_PPC64_TOC16_LO_DS<<24,
|
|
|
|
|
PPC64 | R_PPC64_REL16_LO<<24,
|
|
|
|
|
PPC64 | R_PPC64_REL16_HI<<24,
|
|
|
|
|
PPC64 | R_PPC64_REL16_HA<<24,
|
|
|
|
|
S390X | R_390_16<<24,
|
|
|
|
|
S390X | R_390_GOT16<<24,
|
|
|
|
|
S390X | R_390_PC16<<24,
|
|
|
|
|
S390X | R_390_PC16DBL<<24,
|
|
|
|
|
S390X | R_390_PLT16DBL<<24:
|
|
|
|
|
return 2
|
|
|
|
|
|
|
|
|
|
case ARM | R_ARM_ABS32<<24,
|
|
|
|
|
ARM | R_ARM_GOT32<<24,
|
|
|
|
|
ARM | R_ARM_PLT32<<24,
|
|
|
|
|
ARM | R_ARM_GOTOFF<<24,
|
|
|
|
|
ARM | R_ARM_GOTPC<<24,
|
|
|
|
|
ARM | R_ARM_THM_PC22<<24,
|
|
|
|
|
ARM | R_ARM_REL32<<24,
|
|
|
|
|
ARM | R_ARM_CALL<<24,
|
|
|
|
|
ARM | R_ARM_V4BX<<24,
|
|
|
|
|
ARM | R_ARM_GOT_PREL<<24,
|
|
|
|
|
ARM | R_ARM_PC24<<24,
|
|
|
|
|
ARM | R_ARM_JUMP24<<24,
|
|
|
|
|
AMD64 | R_X86_64_PC32<<24,
|
|
|
|
|
AMD64 | R_X86_64_PLT32<<24,
|
|
|
|
|
AMD64 | R_X86_64_GOTPCREL<<24,
|
|
|
|
|
AMD64 | R_X86_64_GOTPCRELX<<24,
|
|
|
|
|
AMD64 | R_X86_64_REX_GOTPCRELX<<24,
|
|
|
|
|
I386 | R_386_32<<24,
|
|
|
|
|
I386 | R_386_PC32<<24,
|
|
|
|
|
I386 | R_386_GOT32<<24,
|
|
|
|
|
I386 | R_386_PLT32<<24,
|
|
|
|
|
I386 | R_386_GOTOFF<<24,
|
|
|
|
|
I386 | R_386_GOTPC<<24,
|
|
|
|
|
I386 | R_386_GOT32X<<24,
|
|
|
|
|
PPC64 | R_PPC64_REL24<<24,
|
|
|
|
|
PPC64 | R_PPC_REL32<<24,
|
|
|
|
|
S390X | R_390_32<<24,
|
|
|
|
|
S390X | R_390_PC32<<24,
|
|
|
|
|
S390X | R_390_GOT32<<24,
|
|
|
|
|
S390X | R_390_PLT32<<24,
|
|
|
|
|
S390X | R_390_PC32DBL<<24,
|
|
|
|
|
S390X | R_390_PLT32DBL<<24,
|
|
|
|
|
S390X | R_390_GOTPCDBL<<24,
|
|
|
|
|
S390X | R_390_GOTENT<<24:
|
|
|
|
|
return 4
|
|
|
|
|
|
|
|
|
|
case AMD64 | R_X86_64_64<<24,
|
2017-08-11 16:22:10 -04:00
|
|
|
AMD64 | R_X86_64_PC64<<24,
|
2016-04-06 20:06:12 -07:00
|
|
|
PPC64 | R_PPC64_ADDR64<<24,
|
|
|
|
|
S390X | R_390_GLOB_DAT<<24,
|
|
|
|
|
S390X | R_390_RELATIVE<<24,
|
|
|
|
|
S390X | R_390_GOTOFF<<24,
|
|
|
|
|
S390X | R_390_GOTPC<<24,
|
|
|
|
|
S390X | R_390_64<<24,
|
|
|
|
|
S390X | R_390_PC64<<24,
|
|
|
|
|
S390X | R_390_GOT64<<24,
|
|
|
|
|
S390X | R_390_PLT64<<24:
|
|
|
|
|
return 8
|
2015-02-27 22:57:28 -05:00
|
|
|
}
|
|
|
|
|
}
|