aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/link/internal/ld/pe.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/link/internal/ld/pe.go')
-rw-r--r--src/cmd/link/internal/ld/pe.go152
1 files changed, 79 insertions, 73 deletions
diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go
index f775132393..364e757985 100644
--- a/src/cmd/link/internal/ld/pe.go
+++ b/src/cmd/link/internal/ld/pe.go
@@ -10,6 +10,7 @@ package ld
import (
"cmd/internal/objabi"
"cmd/internal/sys"
+ "cmd/link/internal/loader"
"cmd/link/internal/sym"
"debug/pe"
"encoding/binary"
@@ -237,7 +238,7 @@ var dosstub = []uint8{
}
type Imp struct {
- s *sym.Symbol
+ s loader.Sym
off uint64
next *Imp
argsize int
@@ -252,13 +253,13 @@ type Dll struct {
}
var (
- rsrcsym *sym.Symbol
+ rsrcsym loader.Sym
PESECTHEADR int32
PEFILEHEADR int32
pe64 int
dr *Dll
- dexport [1024]*sym.Symbol
- nexport int
+
+ dexport = make([]loader.Sym, 0, 1024)
)
// peStringTable is a COFF string table.
@@ -542,8 +543,8 @@ func (f *peFile) emitRelocations(ctxt *Link) {
syms []*sym.Symbol
}{
{f.textSect, &Segtext, ctxt.Textp},
- {f.rdataSect, &Segrodata, datap},
- {f.dataSect, &Segdata, datap},
+ {f.rdataSect, &Segrodata, ctxt.datap},
+ {f.dataSect, &Segdata, ctxt.datap},
}
for _, s := range sects {
s.peSect.emitRelocations(ctxt.Out, func() int {
@@ -957,8 +958,15 @@ func Peinit(ctxt *Link) {
if ctxt.LinkMode == LinkInternal {
// some mingw libs depend on this symbol, for example, FindPESectionByName
- ctxt.xdefine("__image_base__", sym.SDATA, PEBASE)
- ctxt.xdefine("_image_base__", sym.SDATA, PEBASE)
+ for _, name := range [2]string{"__image_base__", "_image_base__"} {
+ s := ctxt.loader.LookupOrCreateSym(name, 0)
+ sb := ctxt.loader.MakeSymbolUpdater(s)
+ sb.SetType(sym.SDATA)
+ sb.SetValue(PEBASE)
+ ctxt.loader.SetAttrReachable(s, true)
+ ctxt.loader.SetAttrSpecial(s, true)
+ ctxt.loader.SetAttrLocal(s, true)
+ }
}
HEADR = PEFILEHEADR
@@ -996,16 +1004,18 @@ func strput(out *OutBuf, s string) {
}
func initdynimport(ctxt *Link) *Dll {
+ ldr := ctxt.loader
var d *Dll
dr = nil
var m *Imp
- for _, s := range ctxt.Syms.Allsym {
- if !s.Attr.Reachable() || s.Type != sym.SDYNIMPORT {
+ for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
+ if !ldr.AttrReachable(s) || ldr.SymType(s) != sym.SDYNIMPORT {
continue
}
+ dynlib := ldr.SymDynimplib(s)
for d = dr; d != nil; d = d.next {
- if d.name == s.Dynimplib() {
+ if d.name == dynlib {
m = new(Imp)
break
}
@@ -1013,7 +1023,7 @@ func initdynimport(ctxt *Link) *Dll {
if d == nil {
d = new(Dll)
- d.name = s.Dynimplib()
+ d.name = dynlib
d.next = dr
dr = d
m = new(Imp)
@@ -1024,15 +1034,15 @@ func initdynimport(ctxt *Link) *Dll {
// of uinptrs this function consumes. Store the argsize and discard
// the %n suffix if any.
m.argsize = -1
- extName := s.Extname()
+ extName := ldr.SymExtname(s)
if i := strings.IndexByte(extName, '%'); i >= 0 {
var err error
m.argsize, err = strconv.Atoi(extName[i+1:])
if err != nil {
- Errorf(s, "failed to parse stdcall decoration: %v", err)
+ ctxt.Errorf(s, "failed to parse stdcall decoration: %v", err)
}
m.argsize *= ctxt.Arch.PtrSize
- s.SetExtname(extName[:i])
+ ldr.SetSymExtname(s, extName[:i])
}
m.s = s
@@ -1040,42 +1050,38 @@ func initdynimport(ctxt *Link) *Dll {
d.ms = m
}
- if ctxt.LinkMode == LinkExternal {
+ if ctxt.IsExternal() {
// Add real symbol name
for d := dr; d != nil; d = d.next {
for m = d.ms; m != nil; m = m.next {
- m.s.Type = sym.SDATA
- m.s.Grow(int64(ctxt.Arch.PtrSize))
- dynName := m.s.Extname()
+ sb := ldr.MakeSymbolUpdater(m.s)
+ sb.SetType(sym.SDATA)
+ sb.Grow(int64(ctxt.Arch.PtrSize))
+ dynName := sb.Extname()
// only windows/386 requires stdcall decoration
- if ctxt.Arch.Family == sys.I386 && m.argsize >= 0 {
+ if ctxt.Is386() && m.argsize >= 0 {
dynName += fmt.Sprintf("@%d", m.argsize)
}
- dynSym := ctxt.Syms.Lookup(dynName, 0)
- dynSym.Attr |= sym.AttrReachable
- dynSym.Type = sym.SHOSTOBJ
- r := m.s.AddRel()
- r.Sym = dynSym
- r.Off = 0
- r.Siz = uint8(ctxt.Arch.PtrSize)
- r.Type = objabi.R_ADDR
+ dynSym := ldr.CreateSymForUpdate(dynName, 0)
+ dynSym.SetReachable(true)
+ dynSym.SetType(sym.SHOSTOBJ)
+ sb.AddReloc(loader.Reloc{Sym: dynSym.Sym(), Type: objabi.R_ADDR, Off: 0, Size: uint8(ctxt.Arch.PtrSize)})
}
}
} else {
- dynamic := ctxt.Syms.Lookup(".windynamic", 0)
- dynamic.Attr |= sym.AttrReachable
- dynamic.Type = sym.SWINDOWS
+ dynamic := ldr.CreateSymForUpdate(".windynamic", 0)
+ dynamic.SetReachable(true)
+ dynamic.SetType(sym.SWINDOWS)
for d := dr; d != nil; d = d.next {
for m = d.ms; m != nil; m = m.next {
- m.s.Type = sym.SWINDOWS
- m.s.Attr |= sym.AttrSubSymbol
- m.s.Sub = dynamic.Sub
- dynamic.Sub = m.s
- m.s.Value = dynamic.Size
- dynamic.Size += int64(ctxt.Arch.PtrSize)
+ sb := ldr.MakeSymbolUpdater(m.s)
+ sb.SetType(sym.SWINDOWS)
+ dynamic.PrependSub(m.s)
+ sb.SetValue(dynamic.Size())
+ dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
}
- dynamic.Size += int64(ctxt.Arch.PtrSize)
+ dynamic.SetSize(dynamic.Size() + int64(ctxt.Arch.PtrSize))
}
}
@@ -1095,6 +1101,7 @@ func peimporteddlls() []string {
}
func addimports(ctxt *Link, datsect *peSection) {
+ ldr := ctxt.loader
startoff := ctxt.Out.Offset()
dynamic := ctxt.Syms.Lookup(".windynamic", 0)
@@ -1117,7 +1124,7 @@ func addimports(ctxt *Link, datsect *peSection) {
for m := d.ms; m != nil; m = m.next {
m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff)
ctxt.Out.Write16(0) // hint
- strput(ctxt.Out, m.s.Extname())
+ strput(ctxt.Out, ldr.SymExtname(m.s))
}
}
@@ -1198,36 +1205,31 @@ func addimports(ctxt *Link, datsect *peSection) {
out.SeekSet(endoff)
}
-type byExtname []*sym.Symbol
-
-func (s byExtname) Len() int { return len(s) }
-func (s byExtname) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s byExtname) Less(i, j int) bool { return s[i].Extname() < s[j].Extname() }
-
func initdynexport(ctxt *Link) {
- nexport = 0
- for _, s := range ctxt.Syms.Allsym {
- if !s.Attr.Reachable() || !s.Attr.CgoExportDynamic() {
+ ldr := ctxt.loader
+ for s := loader.Sym(1); s < loader.Sym(ldr.NSym()); s++ {
+ if !ldr.AttrReachable(s) || !ldr.AttrCgoExportDynamic(s) {
continue
}
- if nexport+1 > len(dexport) {
- Errorf(s, "pe dynexport table is full")
+ if len(dexport)+1 > cap(dexport) {
+ ctxt.Errorf(s, "pe dynexport table is full")
errorexit()
}
- dexport[nexport] = s
- nexport++
+ dexport = append(dexport, s)
}
- sort.Sort(byExtname(dexport[:nexport]))
+ sort.Slice(dexport, func(i, j int) bool { return ldr.SymExtname(dexport[i]) < ldr.SymExtname(dexport[j]) })
}
func addexports(ctxt *Link) {
+ ldr := ctxt.loader
var e IMAGE_EXPORT_DIRECTORY
+ nexport := len(dexport)
size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1
- for i := 0; i < nexport; i++ {
- size += len(dexport[i].Extname()) + 1
+ for _, s := range dexport {
+ size += len(ldr.Syms[s].Extname()) + 1
}
if nexport == 0 {
@@ -1262,16 +1264,16 @@ func addexports(ctxt *Link) {
binary.Write(out, binary.LittleEndian, &e)
// put EXPORT Address Table
- for i := 0; i < nexport; i++ {
- out.Write32(uint32(dexport[i].Value - PEBASE))
+ for _, s := range dexport {
+ out.Write32(uint32(ldr.Syms[s].Value - PEBASE))
}
// put EXPORT Name Pointer Table
v := int(e.Name + uint32(len(*flagOutfile)) + 1)
- for i := 0; i < nexport; i++ {
+ for _, s := range dexport {
out.Write32(uint32(v))
- v += len(dexport[i].Extname()) + 1
+ v += len(ldr.Syms[s].Extname()) + 1
}
// put EXPORT Ordinal Table
@@ -1282,8 +1284,9 @@ func addexports(ctxt *Link) {
// put Names
out.WriteStringN(*flagOutfile, len(*flagOutfile)+1)
- for i := 0; i < nexport; i++ {
- out.WriteStringN(dexport[i].Extname(), len(dexport[i].Extname())+1)
+ for _, s := range dexport {
+ ss := ldr.Syms[s]
+ out.WriteStringN(ss.Extname(), len(ss.Extname())+1)
}
sect.pad(out, uint32(size))
}
@@ -1431,7 +1434,7 @@ func addPEBaseReloc(ctxt *Link) {
for _, s := range ctxt.Textp {
addPEBaseRelocSym(ctxt, s, &rt)
}
- for _, s := range datap {
+ for _, s := range ctxt.datap {
addPEBaseRelocSym(ctxt, s, &rt)
}
@@ -1455,28 +1458,31 @@ func (ctxt *Link) dope() {
initdynexport(ctxt)
}
-func setpersrc(ctxt *Link, sym *sym.Symbol) {
- if rsrcsym != nil {
- Errorf(sym, "too many .rsrc sections")
+func setpersrc(ctxt *Link, sym loader.Sym) {
+ if rsrcsym != 0 {
+ Errorf(nil, "too many .rsrc sections")
}
rsrcsym = sym
}
func addpersrc(ctxt *Link) {
- if rsrcsym == nil {
+ if rsrcsym == 0 {
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.checkOffset(ctxt.Out.Offset())
// relocation
- for ri := range rsrcsym.R {
- r := &rsrcsym.R[ri]
- p := rsrcsym.P[r.Off:]
- val := uint32(int64(h.virtualAddress) + r.Add)
+ relocs := ctxt.loader.Relocs(rsrcsym)
+ for i := 0; i < relocs.Count(); i++ {
+ r := relocs.At2(i)
+ p := data[r.Off():]
+ val := uint32(int64(h.virtualAddress) + r.Add())
// 32-bit little-endian
p[0] = byte(val)
@@ -1486,8 +1492,8 @@ func addpersrc(ctxt *Link) {
p[3] = byte(val >> 24)
}
- ctxt.Out.Write(rsrcsym.P)
- h.pad(ctxt.Out, uint32(rsrcsym.Size))
+ ctxt.Out.Write(data)
+ h.pad(ctxt.Out, uint32(size))
// update data directory
pefile.dataDirectory[pe.IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress