mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.link] cmd/link: use new sym format in pe loader
Change-Id: Ib784b8432ff4355b7ff4068801a0bcfcaf108950 Reviewed-on: https://go-review.googlesource.com/c/go/+/216718 Run-TryBot: Jeremy Faller <jeremy@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
8e2b5d3e71
commit
83ba044be6
7 changed files with 152 additions and 122 deletions
|
|
@ -104,30 +104,13 @@ func hostArchive(ctxt *Link, name string) {
|
||||||
any := true
|
any := true
|
||||||
for any {
|
for any {
|
||||||
var load []uint64
|
var load []uint64
|
||||||
if ctxt.IsELF {
|
returnAllUndefs := -1
|
||||||
returnAllUndefs := -1
|
undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
|
||||||
undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs)
|
for _, symIdx := range undefs {
|
||||||
for _, symIdx := range undefs {
|
name := ctxt.loader.SymName(symIdx)
|
||||||
name := ctxt.loader.SymName(symIdx)
|
if off := armap[name]; off != 0 && !loaded[off] {
|
||||||
if off := armap[name]; off != 0 && !loaded[off] {
|
load = append(load, off)
|
||||||
load = append(load, off)
|
loaded[off] = true
|
||||||
loaded[off] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for _, s := range ctxt.loader.Syms {
|
|
||||||
if s == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for i := range s.R {
|
|
||||||
r := &s.R[i] // Copying sym.Reloc has measurable impact on performance
|
|
||||||
if r.Sym != nil && r.Sym.Type == sym.SXREF {
|
|
||||||
if off := armap[r.Sym.Name]; off != 0 && !loaded[off] {
|
|
||||||
load = append(load, off)
|
|
||||||
loaded[off] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1883,10 +1883,10 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string,
|
||||||
Errorf(nil, "%v", err)
|
Errorf(nil, "%v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if rsrc != nil {
|
if rsrc != 0 {
|
||||||
setpersrc(ctxt, rsrc)
|
setpersrc(ctxt, rsrc)
|
||||||
}
|
}
|
||||||
ctxt.Textp = append(ctxt.Textp, textp...)
|
ctxt.Textp2 = append(ctxt.Textp2, textp...)
|
||||||
}
|
}
|
||||||
return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
|
return ldhostobj(ldpe, ctxt.HeadType, f, pkg, length, pn, file)
|
||||||
}
|
}
|
||||||
|
|
@ -2812,9 +2812,6 @@ func (ctxt *Link) loadlibfull() {
|
||||||
ctxt.cgodata = nil
|
ctxt.cgodata = nil
|
||||||
|
|
||||||
addToTextp(ctxt)
|
addToTextp(ctxt)
|
||||||
|
|
||||||
// Drop the loader.
|
|
||||||
ctxt.loader = nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ctxt *Link) dumpsyms() {
|
func (ctxt *Link) dumpsyms() {
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func (ctxt *Link) loaderSupport() bool {
|
func (ctxt *Link) loaderSupport() bool {
|
||||||
return ctxt.IsELF || ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix
|
return true //ctxt.IsELF || ctxt.HeadType == objabi.Hdarwin || ctxt.HeadType == objabi.Haix
|
||||||
}
|
}
|
||||||
|
|
||||||
// Main is the main entry point for the linker code.
|
// Main is the main entry point for the linker code.
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ package ld
|
||||||
import (
|
import (
|
||||||
"cmd/internal/objabi"
|
"cmd/internal/objabi"
|
||||||
"cmd/internal/sys"
|
"cmd/internal/sys"
|
||||||
|
"cmd/link/internal/loader"
|
||||||
"cmd/link/internal/sym"
|
"cmd/link/internal/sym"
|
||||||
"debug/pe"
|
"debug/pe"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
|
@ -282,7 +283,7 @@ type Dll struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
rsrcsym *sym.Symbol
|
rsrcsym loader.Sym
|
||||||
PESECTHEADR int32
|
PESECTHEADR int32
|
||||||
PEFILEHEADR int32
|
PEFILEHEADR int32
|
||||||
pe64 int
|
pe64 int
|
||||||
|
|
@ -1469,27 +1470,30 @@ func (ctxt *Link) dope() {
|
||||||
initdynexport(ctxt)
|
initdynexport(ctxt)
|
||||||
}
|
}
|
||||||
|
|
||||||
func setpersrc(ctxt *Link, sym *sym.Symbol) {
|
func setpersrc(ctxt *Link, sym loader.Sym) {
|
||||||
if rsrcsym != nil {
|
if rsrcsym != 0 {
|
||||||
Errorf(sym, "too many .rsrc sections")
|
Errorf(nil, "too many .rsrc sections")
|
||||||
}
|
}
|
||||||
|
|
||||||
rsrcsym = sym
|
rsrcsym = sym
|
||||||
}
|
}
|
||||||
|
|
||||||
func addpersrc(ctxt *Link) {
|
func addpersrc(ctxt *Link) {
|
||||||
if rsrcsym == nil {
|
if rsrcsym == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
h := pefile.addSection(".rsrc", int(rsrcsym.Size), int(rsrcsym.Size))
|
data := ctxt.loader.Data(rsrcsym)
|
||||||
|
size := len(data)
|
||||||
|
h := pefile.addSection(".rsrc", size, size)
|
||||||
h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
|
h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||||
h.checkOffset(ctxt.Out.Offset())
|
h.checkOffset(ctxt.Out.Offset())
|
||||||
|
|
||||||
// relocation
|
// relocation
|
||||||
for ri := range rsrcsym.R {
|
relocs := ctxt.loader.Relocs(rsrcsym)
|
||||||
r := &rsrcsym.R[ri]
|
for i := 0; i < relocs.Count; i++ {
|
||||||
p := rsrcsym.P[r.Off:]
|
r := relocs.At(i)
|
||||||
|
p := data[r.Off:]
|
||||||
val := uint32(int64(h.virtualAddress) + r.Add)
|
val := uint32(int64(h.virtualAddress) + r.Add)
|
||||||
|
|
||||||
// 32-bit little-endian
|
// 32-bit little-endian
|
||||||
|
|
@ -1500,8 +1504,8 @@ func addpersrc(ctxt *Link) {
|
||||||
p[3] = byte(val >> 24)
|
p[3] = byte(val >> 24)
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxt.Out.Write(rsrcsym.P)
|
ctxt.Out.Write(data)
|
||||||
h.pad(ctxt.Out, uint32(rsrcsym.Size))
|
h.pad(ctxt.Out, uint32(size))
|
||||||
|
|
||||||
// update data directory
|
// update data directory
|
||||||
pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
|
pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress
|
||||||
|
|
|
||||||
|
|
@ -228,6 +228,8 @@ type Loader struct {
|
||||||
extname map[Sym]string // stores Extname symbol attribute
|
extname map[Sym]string // stores Extname symbol attribute
|
||||||
elfType map[Sym]elf.SymType // stores elf type symbol property
|
elfType map[Sym]elf.SymType // stores elf type symbol property
|
||||||
symFile map[Sym]string // stores file for shlib-derived syms
|
symFile map[Sym]string // stores file for shlib-derived syms
|
||||||
|
plt map[Sym]int32 // stores dynimport for pe objects
|
||||||
|
got map[Sym]int32 // stores got for pe objects
|
||||||
|
|
||||||
// Used to implement field tracking; created during deadcode if
|
// Used to implement field tracking; created during deadcode if
|
||||||
// field tracking is enabled. Reachparent[K] contains the index of
|
// field tracking is enabled. Reachparent[K] contains the index of
|
||||||
|
|
@ -282,6 +284,8 @@ func NewLoader(flags uint32, elfsetstring elfsetstringFunc) *Loader {
|
||||||
attrReadOnly: make(map[Sym]bool),
|
attrReadOnly: make(map[Sym]bool),
|
||||||
elfType: make(map[Sym]elf.SymType),
|
elfType: make(map[Sym]elf.SymType),
|
||||||
symFile: make(map[Sym]string),
|
symFile: make(map[Sym]string),
|
||||||
|
plt: make(map[Sym]int32),
|
||||||
|
got: make(map[Sym]int32),
|
||||||
attrTopFrame: make(map[Sym]struct{}),
|
attrTopFrame: make(map[Sym]struct{}),
|
||||||
attrSpecial: make(map[Sym]struct{}),
|
attrSpecial: make(map[Sym]struct{}),
|
||||||
attrCgoExportDynamic: make(map[Sym]struct{}),
|
attrCgoExportDynamic: make(map[Sym]struct{}),
|
||||||
|
|
@ -1154,7 +1158,7 @@ func (l *Loader) SymElfType(i Sym) elf.SymType {
|
||||||
return elf.STT_NOTYPE
|
return elf.STT_NOTYPE
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetSymElfType sets the elf type attribute for a symbol.
|
// SetSymElfType sets the elf type attribute for a symbol.
|
||||||
func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
|
func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
|
||||||
// reject bad symbols
|
// reject bad symbols
|
||||||
if i > l.max || i == 0 {
|
if i > l.max || i == 0 {
|
||||||
|
|
@ -1167,6 +1171,30 @@ func (l *Loader) SetSymElfType(i Sym, et elf.SymType) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetPlt sets the plt value for pe symbols.
|
||||||
|
func (l *Loader) SetPlt(i Sym, v int32) {
|
||||||
|
if i > l.max || i == 0 {
|
||||||
|
panic("bad symbol for SetPlt")
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
delete(l.plt, i)
|
||||||
|
} else {
|
||||||
|
l.plt[i] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetGot sets the got value for pe symbols.
|
||||||
|
func (l *Loader) SetGot(i Sym, v int32) {
|
||||||
|
if i > l.max || i == 0 {
|
||||||
|
panic("bad symbol for SetPlt")
|
||||||
|
}
|
||||||
|
if v == 0 {
|
||||||
|
delete(l.got, i)
|
||||||
|
} else {
|
||||||
|
l.got[i] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// SymGoType returns the 'Gotype' property for a given symbol (set by
|
// SymGoType returns the 'Gotype' property for a given symbol (set by
|
||||||
// the Go compiler for variable symbols). This version relies on
|
// the Go compiler for variable symbols). This version relies on
|
||||||
// reading aux symbols for the target sym -- it could be that a faster
|
// reading aux symbols for the target sym -- it could be that a faster
|
||||||
|
|
@ -2078,6 +2106,14 @@ func (l *Loader) migrateAttributes(src Sym, dst *sym.Symbol) {
|
||||||
if et, ok := l.elfType[src]; ok {
|
if et, ok := l.elfType[src]; ok {
|
||||||
dst.SetElfType(et)
|
dst.SetElfType(et)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Copy pe objects values if set.
|
||||||
|
if plt, ok := l.plt[src]; ok {
|
||||||
|
dst.SetPlt(plt)
|
||||||
|
}
|
||||||
|
if got, ok := l.got[src]; ok {
|
||||||
|
dst.SetGot(got)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateExtSym creates a new external symbol with the specified name
|
// CreateExtSym creates a new external symbol with the specified name
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ func (sb *SymbolBuilder) SetLocalentry(value uint8) { sb.l.SetSymLocalentry(sb.
|
||||||
func (sb *SymbolBuilder) SetExtname(value string) { sb.l.SetSymExtname(sb.symIdx, value) }
|
func (sb *SymbolBuilder) SetExtname(value string) { sb.l.SetSymExtname(sb.symIdx, value) }
|
||||||
func (sb *SymbolBuilder) SetDynimplib(value string) { sb.l.SetSymDynimplib(sb.symIdx, value) }
|
func (sb *SymbolBuilder) SetDynimplib(value string) { sb.l.SetSymDynimplib(sb.symIdx, value) }
|
||||||
func (sb *SymbolBuilder) SetDynimpvers(value string) { sb.l.SetSymDynimpvers(sb.symIdx, value) }
|
func (sb *SymbolBuilder) SetDynimpvers(value string) { sb.l.SetSymDynimpvers(sb.symIdx, value) }
|
||||||
|
func (sb *SymbolBuilder) SetPlt(value int32) { sb.l.SetPlt(sb.symIdx, value) }
|
||||||
|
func (sb *SymbolBuilder) SetGot(value int32) { sb.l.SetGot(sb.symIdx, value) }
|
||||||
|
|
||||||
func (sb *SymbolBuilder) AddBytes(data []byte) {
|
func (sb *SymbolBuilder) AddBytes(data []byte) {
|
||||||
sb.setReachable()
|
sb.setReachable()
|
||||||
|
|
|
||||||
|
|
@ -145,14 +145,24 @@ func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) {
|
||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// makeUpdater creates a loader.SymbolBuilder if one hasn't been created previously.
|
||||||
|
// We use this to lazily make SymbolBuilders as we don't always need a builder, and creating them for all symbols might be an error.
|
||||||
|
func makeUpdater(l *loader.Loader, bld *loader.SymbolBuilder, s loader.Sym) *loader.SymbolBuilder {
|
||||||
|
if bld != nil {
|
||||||
|
return bld
|
||||||
|
}
|
||||||
|
bld, _ = l.MakeSymbolUpdater(s)
|
||||||
|
return bld
|
||||||
|
}
|
||||||
|
|
||||||
// Load loads the PE file pn from input.
|
// Load loads the PE file pn from input.
|
||||||
// Symbols are written into syms, and a slice of the text symbols is returned.
|
// Symbols are written into syms, and a slice of the text symbols is returned.
|
||||||
// If an .rsrc section is found, its symbol is returned as rsrc.
|
// If an .rsrc section is found, its symbol is returned as rsrc.
|
||||||
func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, rsrc *sym.Symbol, err error) {
|
func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, rsrc loader.Sym, err error) {
|
||||||
lookup := func(name string, version int) *sym.Symbol {
|
lookup := func(name string, version int) (*loader.SymbolBuilder, loader.Sym) {
|
||||||
return l.LookupOrCreate(name, version)
|
return l.MakeSymbolUpdater(l.LookupOrCreateSym(name, version))
|
||||||
}
|
}
|
||||||
sectsyms := make(map[*pe.Section]*sym.Symbol)
|
sectsyms := make(map[*pe.Section]loader.Sym)
|
||||||
sectdata := make(map[*pe.Section][]byte)
|
sectdata := make(map[*pe.Section][]byte)
|
||||||
|
|
||||||
// Some input files are archives containing multiple of
|
// Some input files are archives containing multiple of
|
||||||
|
|
@ -164,7 +174,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
// TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details)
|
// TODO: replace pe.NewFile with pe.Load (grep for "add Load function" in debug/pe for details)
|
||||||
f, err := pe.NewFile(sr)
|
f, err := pe.NewFile(sr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
|
@ -183,34 +193,34 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
}
|
}
|
||||||
|
|
||||||
name := fmt.Sprintf("%s(%s)", pkg, sect.Name)
|
name := fmt.Sprintf("%s(%s)", pkg, sect.Name)
|
||||||
s := lookup(name, localSymVersion)
|
bld, s := lookup(name, localSymVersion)
|
||||||
|
|
||||||
switch sect.Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE) {
|
switch sect.Characteristics & (IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE) {
|
||||||
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: //.rdata
|
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ: //.rdata
|
||||||
s.Type = sym.SRODATA
|
bld.SetType(sym.SRODATA)
|
||||||
|
|
||||||
case IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.bss
|
case IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.bss
|
||||||
s.Type = sym.SNOPTRBSS
|
bld.SetType(sym.SNOPTRBSS)
|
||||||
|
|
||||||
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.data
|
case IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE: //.data
|
||||||
s.Type = sym.SNOPTRDATA
|
bld.SetType(sym.SNOPTRDATA)
|
||||||
|
|
||||||
case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: //.text
|
case IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ: //.text
|
||||||
s.Type = sym.STEXT
|
bld.SetType(sym.STEXT)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
|
return nil, 0, fmt.Errorf("unexpected flags %#06x for PE section %s", sect.Characteristics, sect.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Type != sym.SNOPTRBSS {
|
if bld.Type() != sym.SNOPTRBSS {
|
||||||
data, err := sect.Data()
|
data, err := sect.Data()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
sectdata[sect] = data
|
sectdata[sect] = data
|
||||||
s.P = data
|
bld.SetData(data)
|
||||||
}
|
}
|
||||||
s.Size = int64(sect.Size)
|
bld.SetSize(int64(sect.Size))
|
||||||
sectsyms[sect] = s
|
sectsyms[sect] = s
|
||||||
if sect.Name == ".rsrc" {
|
if sect.Name == ".rsrc" {
|
||||||
rsrc = s
|
rsrc = s
|
||||||
|
|
@ -234,35 +244,35 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
rs := make([]sym.Reloc, rsect.NumberOfRelocations)
|
rs := make([]loader.Reloc, rsect.NumberOfRelocations)
|
||||||
for j, r := range rsect.Relocs {
|
for j, r := range rsect.Relocs {
|
||||||
rp := &rs[j]
|
rp := &rs[j]
|
||||||
if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
|
if int(r.SymbolTableIndex) >= len(f.COFFSymbols) {
|
||||||
return nil, nil, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols))
|
return nil, 0, fmt.Errorf("relocation number %d symbol index idx=%d cannot be large then number of symbols %d", j, r.SymbolTableIndex, len(f.COFFSymbols))
|
||||||
}
|
}
|
||||||
pesym := &f.COFFSymbols[r.SymbolTableIndex]
|
pesym := &f.COFFSymbols[r.SymbolTableIndex]
|
||||||
gosym, err := readpesym(arch, lookup, f, pesym, sectsyms, localSymVersion)
|
_, gosym, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
if gosym == nil {
|
if gosym == 0 {
|
||||||
name, err := pesym.FullName(f.StringTable)
|
name, err := pesym.FullName(f.StringTable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
name = string(pesym.Name[:])
|
name = string(pesym.Name[:])
|
||||||
}
|
}
|
||||||
return nil, nil, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type)
|
return nil, 0, fmt.Errorf("reloc of invalid sym %s idx=%d type=%d", name, r.SymbolTableIndex, pesym.Type)
|
||||||
}
|
}
|
||||||
|
|
||||||
rp.Sym = gosym
|
rp.Sym = gosym
|
||||||
rp.Siz = 4
|
rp.Size = 4
|
||||||
rp.Off = int32(r.VirtualAddress)
|
rp.Off = int32(r.VirtualAddress)
|
||||||
switch arch.Family {
|
switch arch.Family {
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
|
return nil, 0, fmt.Errorf("%s: unsupported arch %v", pn, arch.Family)
|
||||||
case sys.I386, sys.AMD64:
|
case sys.I386, sys.AMD64:
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type)
|
return nil, 0, fmt.Errorf("%s: %v: unknown relocation type %v", pn, sectsyms[rsect], r.Type)
|
||||||
|
|
||||||
case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32,
|
case IMAGE_REL_I386_REL32, IMAGE_REL_AMD64_REL32,
|
||||||
IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32
|
IMAGE_REL_AMD64_ADDR32, // R_X86_64_PC32
|
||||||
|
|
@ -278,7 +288,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
rp.Add = int64(int32(binary.LittleEndian.Uint32(sectdata[rsect][rp.Off:])))
|
||||||
|
|
||||||
case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
|
case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64
|
||||||
rp.Siz = 8
|
rp.Size = 8
|
||||||
|
|
||||||
rp.Type = objabi.R_ADDR
|
rp.Type = objabi.R_ADDR
|
||||||
|
|
||||||
|
|
@ -289,7 +299,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
case sys.ARM:
|
case sys.ARM:
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type)
|
return nil, 0, fmt.Errorf("%s: %v: unknown ARM relocation type %v", pn, sectsyms[rsect], r.Type)
|
||||||
|
|
||||||
case IMAGE_REL_ARM_SECREL:
|
case IMAGE_REL_ARM_SECREL:
|
||||||
rp.Type = objabi.R_PCREL
|
rp.Type = objabi.R_PCREL
|
||||||
|
|
@ -316,11 +326,10 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sort.Sort(sym.RelocByOff(rs[:rsect.NumberOfRelocations]))
|
sort.Sort(loader.RelocByOff(rs[:rsect.NumberOfRelocations]))
|
||||||
|
|
||||||
s := sectsyms[rsect]
|
bld, _ := l.MakeSymbolUpdater(sectsyms[rsect])
|
||||||
s.R = rs
|
bld.SetRelocs(rs[:rsect.NumberOfRelocations])
|
||||||
s.R = s.R[:rsect.NumberOfRelocations]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// enter sub-symbols into symbol table.
|
// enter sub-symbols into symbol table.
|
||||||
|
|
@ -331,7 +340,7 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
|
|
||||||
name, err := pesym.FullName(f.StringTable)
|
name, err := pesym.FullName(f.StringTable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
if name == "" {
|
if name == "" {
|
||||||
continue
|
continue
|
||||||
|
|
@ -353,54 +362,56 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := readpesym(arch, lookup, f, pesym, sectsyms, localSymVersion)
|
bld, s, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if pesym.SectionNumber == 0 { // extern
|
if pesym.SectionNumber == 0 { // extern
|
||||||
if s.Type == sym.SDYNIMPORT {
|
if l.SymType(s) == sym.SDYNIMPORT {
|
||||||
s.SetPlt(-2) // flag for dynimport in PE object files.
|
bld = makeUpdater(l, bld, s)
|
||||||
|
bld.SetPlt(-2) // flag for dynimport in PE object files.
|
||||||
}
|
}
|
||||||
if s.Type == sym.SXREF && pesym.Value > 0 { // global data
|
if l.SymType(s) == sym.SXREF && pesym.Value > 0 { // global data
|
||||||
s.Type = sym.SNOPTRDATA
|
bld = makeUpdater(l, bld, s)
|
||||||
s.Size = int64(pesym.Value)
|
bld.SetType(sym.SNOPTRDATA)
|
||||||
|
bld.SetSize(int64(pesym.Value))
|
||||||
}
|
}
|
||||||
|
|
||||||
continue
|
continue
|
||||||
} else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
|
} else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) {
|
||||||
sect = f.Sections[pesym.SectionNumber-1]
|
sect = f.Sections[pesym.SectionNumber-1]
|
||||||
if _, found := sectsyms[sect]; !found {
|
if _, found := sectsyms[sect]; !found {
|
||||||
return nil, nil, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
|
return nil, 0, fmt.Errorf("%s: %v: missing sect.sym", pn, s)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return nil, nil, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
|
return nil, 0, fmt.Errorf("%s: %v: sectnum < 0!", pn, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
if sect == nil {
|
if sect == nil {
|
||||||
return nil, rsrc, nil
|
return nil, 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.Outer != nil {
|
if l.OuterSym(s) != 0 {
|
||||||
if s.Attr.DuplicateOK() {
|
if l.AttrDuplicateOK(s) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
return nil, nil, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, s.Name, s.Outer.Name, sectsyms[sect].Name)
|
outerName := l.SymName(l.OuterSym(s))
|
||||||
|
sectName := l.SymName(sectsyms[sect])
|
||||||
|
return nil, 0, fmt.Errorf("%s: duplicate symbol reference: %s in both %s and %s", pn, l.SymName(s), outerName, sectName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bld = makeUpdater(l, bld, s)
|
||||||
sectsym := sectsyms[sect]
|
sectsym := sectsyms[sect]
|
||||||
s.Sub = sectsym.Sub
|
bld.SetType(l.SymType(sectsym))
|
||||||
sectsym.Sub = s
|
l.PrependSub(sectsym, s)
|
||||||
s.Type = sectsym.Type
|
bld.SetValue(int64(pesym.Value))
|
||||||
s.Attr |= sym.AttrSubSymbol
|
bld.SetSize(4)
|
||||||
s.Value = int64(pesym.Value)
|
if l.SymType(sectsym) == sym.STEXT {
|
||||||
s.Size = 4
|
if bld.External() && !bld.DuplicateOK() {
|
||||||
s.Outer = sectsym
|
return nil, 0, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s))
|
||||||
if sectsym.Type == sym.STEXT {
|
|
||||||
if s.Attr.External() && !s.Attr.DuplicateOK() {
|
|
||||||
return nil, nil, fmt.Errorf("%s: duplicate symbol definition", s.Name)
|
|
||||||
}
|
}
|
||||||
s.Attr |= sym.AttrExternal
|
bld.SetExternal(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -408,23 +419,16 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read
|
||||||
// This keeps textp in increasing address order.
|
// This keeps textp in increasing address order.
|
||||||
for _, sect := range f.Sections {
|
for _, sect := range f.Sections {
|
||||||
s := sectsyms[sect]
|
s := sectsyms[sect]
|
||||||
if s == nil {
|
if s == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if s.Sub != nil {
|
l.SortSub(s)
|
||||||
s.Sub = sym.SortSub(s.Sub)
|
if l.SymType(s) == sym.STEXT {
|
||||||
}
|
for ; s != 0; s = l.SubSym(s) {
|
||||||
if s.Type == sym.STEXT {
|
if l.AttrOnList(s) {
|
||||||
if s.Attr.OnList() {
|
return nil, 0, fmt.Errorf("symbol %s listed multiple times", l.SymName(s))
|
||||||
return nil, nil, fmt.Errorf("symbol %s listed multiple times", s.Name)
|
|
||||||
}
|
|
||||||
s.Attr |= sym.AttrOnList
|
|
||||||
textp = append(textp, s)
|
|
||||||
for s = s.Sub; s != nil; s = s.Sub {
|
|
||||||
if s.Attr.OnList() {
|
|
||||||
return nil, nil, fmt.Errorf("symbol %s listed multiple times", s.Name)
|
|
||||||
}
|
}
|
||||||
s.Attr |= sym.AttrOnList
|
l.SetAttrOnList(s, true)
|
||||||
textp = append(textp, s)
|
textp = append(textp, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -437,14 +441,14 @@ func issect(s *pe.COFFSymbol) bool {
|
||||||
return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
|
return s.StorageClass == IMAGE_SYM_CLASS_STATIC && s.Type == 0 && s.Name[0] == '.'
|
||||||
}
|
}
|
||||||
|
|
||||||
func readpesym(arch *sys.Arch, lookup func(string, int) *sym.Symbol, f *pe.File, pesym *pe.COFFSymbol, sectsyms map[*pe.Section]*sym.Symbol, localSymVersion int) (*sym.Symbol, error) {
|
func readpesym(l *loader.Loader, arch *sys.Arch, lookup func(string, int) loader.Sym, f *pe.File, pesym *pe.COFFSymbol, sectsyms map[*pe.Section]loader.Sym, localSymVersion int) (*loader.SymbolBuilder, loader.Sym, error) {
|
||||||
symname, err := pesym.FullName(f.StringTable)
|
symname, err := pesym.FullName(f.StringTable)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, 0, err
|
||||||
}
|
}
|
||||||
var name string
|
var name string
|
||||||
if issect(pesym) {
|
if issect(pesym) {
|
||||||
name = sectsyms[f.Sections[pesym.SectionNumber-1]].Name
|
name = l.SymName(sectsyms[f.Sections[pesym.SectionNumber-1]])
|
||||||
} else {
|
} else {
|
||||||
name = symname
|
name = symname
|
||||||
switch arch.Family {
|
switch arch.Family {
|
||||||
|
|
@ -475,10 +479,11 @@ func readpesym(arch *sys.Arch, lookup func(string, int) *sym.Symbol, f *pe.File,
|
||||||
name = name[:i]
|
name = name[:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
var s *sym.Symbol
|
var s loader.Sym
|
||||||
|
var bld *loader.SymbolBuilder
|
||||||
switch pesym.Type {
|
switch pesym.Type {
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
|
return nil, 0, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)
|
||||||
|
|
||||||
case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
|
case IMAGE_SYM_DTYPE_FUNCTION, IMAGE_SYM_DTYPE_NULL:
|
||||||
switch pesym.StorageClass {
|
switch pesym.StorageClass {
|
||||||
|
|
@ -487,19 +492,22 @@ func readpesym(arch *sys.Arch, lookup func(string, int) *sym.Symbol, f *pe.File,
|
||||||
|
|
||||||
case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
|
case IMAGE_SYM_CLASS_NULL, IMAGE_SYM_CLASS_STATIC, IMAGE_SYM_CLASS_LABEL:
|
||||||
s = lookup(name, localSymVersion)
|
s = lookup(name, localSymVersion)
|
||||||
s.Attr |= sym.AttrDuplicateOK
|
bld = makeUpdater(l, bld, s)
|
||||||
|
bld.SetDuplicateOK(true)
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
|
return nil, 0, fmt.Errorf("%s: invalid symbol binding %d", symname, pesym.StorageClass)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if s != nil && s.Type == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
|
if s != 0 && l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) {
|
||||||
s.Type = sym.SXREF
|
bld = makeUpdater(l, bld, s)
|
||||||
|
bld.SetType(sym.SXREF)
|
||||||
}
|
}
|
||||||
if strings.HasPrefix(symname, "__imp_") {
|
if strings.HasPrefix(symname, "__imp_") {
|
||||||
s.SetGot(-2) // flag for __imp_
|
bld = makeUpdater(l, bld, s)
|
||||||
|
bld.SetGot(-2) // flag for __imp_
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return bld, s, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue