diff options
Diffstat (limited to 'src/cmd/link/internal/ld/pe.go')
-rw-r--r-- | src/cmd/link/internal/ld/pe.go | 152 |
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 |