From: Jeremy Faller Date: Mon, 27 Jan 2020 20:31:41 +0000 (-0500) Subject: [dev.link] cmd/link: use new sym format in pe loader X-Git-Tag: go1.15beta1~679^2~138 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=83ba044be67c03a3054e359907111473342fd22b;p=gostls13.git [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 TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- diff --git a/src/cmd/link/internal/ld/ar.go b/src/cmd/link/internal/ld/ar.go index 9e770e2615..268f40e92d 100644 --- a/src/cmd/link/internal/ld/ar.go +++ b/src/cmd/link/internal/ld/ar.go @@ -104,30 +104,13 @@ func hostArchive(ctxt *Link, name string) { any := true for any { var load []uint64 - if ctxt.IsELF { - returnAllUndefs := -1 - undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) - for _, symIdx := range undefs { - name := ctxt.loader.SymName(symIdx) - if off := armap[name]; off != 0 && !loaded[off] { - load = append(load, off) - 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 - } - } - } + returnAllUndefs := -1 + undefs := ctxt.loader.UndefinedRelocTargets(returnAllUndefs) + for _, symIdx := range undefs { + name := ctxt.loader.SymName(symIdx) + if off := armap[name]; off != 0 && !loaded[off] { + load = append(load, off) + loaded[off] = true } } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 1652724a44..912d283221 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -1883,10 +1883,10 @@ func ldobj(ctxt *Link, f *bio.Reader, lib *sym.Library, length int64, pn string, Errorf(nil, "%v", err) return } - if rsrc != nil { + if rsrc != 0 { 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) } @@ -2812,9 +2812,6 @@ func (ctxt *Link) loadlibfull() { ctxt.cgodata = nil addToTextp(ctxt) - - // Drop the loader. - ctxt.loader = nil } func (ctxt *Link) dumpsyms() { diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 9b362ca8b8..e0168fbc56 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -98,7 +98,7 @@ var ( ) 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. diff --git a/src/cmd/link/internal/ld/pe.go b/src/cmd/link/internal/ld/pe.go index 4ab346e733..e20d7da9aa 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" @@ -282,7 +283,7 @@ type Dll struct { } var ( - rsrcsym *sym.Symbol + rsrcsym loader.Sym PESECTHEADR int32 PEFILEHEADR int32 pe64 int @@ -1469,27 +1470,30 @@ 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:] + relocs := ctxt.loader.Relocs(rsrcsym) + for i := 0; i < relocs.Count; i++ { + r := relocs.At(i) + p := data[r.Off:] val := uint32(int64(h.virtualAddress) + r.Add) // 32-bit little-endian @@ -1500,8 +1504,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[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go index 78e75c0a35..02a15dc155 100644 --- a/src/cmd/link/internal/loader/loader.go +++ b/src/cmd/link/internal/loader/loader.go @@ -228,6 +228,8 @@ type Loader struct { extname map[Sym]string // stores Extname symbol attribute elfType map[Sym]elf.SymType // stores elf type symbol property 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 // 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), elfType: make(map[Sym]elf.SymType), symFile: make(map[Sym]string), + plt: make(map[Sym]int32), + got: make(map[Sym]int32), attrTopFrame: make(map[Sym]struct{}), attrSpecial: 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 } -// 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) { // reject bad symbols 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 // the Go compiler for variable symbols). This version relies on // 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 { 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 diff --git a/src/cmd/link/internal/loader/symbolbuilder.go b/src/cmd/link/internal/loader/symbolbuilder.go index e34bc98955..b629961070 100644 --- a/src/cmd/link/internal/loader/symbolbuilder.go +++ b/src/cmd/link/internal/loader/symbolbuilder.go @@ -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) SetDynimplib(value string) { sb.l.SetSymDynimplib(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) { sb.setReachable() diff --git a/src/cmd/link/internal/loadpe/ldpe.go b/src/cmd/link/internal/loadpe/ldpe.go index 7924d16b7c..807e4e9038 100644 --- a/src/cmd/link/internal/loadpe/ldpe.go +++ b/src/cmd/link/internal/loadpe/ldpe.go @@ -145,14 +145,24 @@ func (f *peBiobuf) ReadAt(p []byte, off int64) (int, error) { 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. // 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. -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) { - lookup := func(name string, version int) *sym.Symbol { - return l.LookupOrCreate(name, version) +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) (*loader.SymbolBuilder, loader.Sym) { + 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) // 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) f, err := pe.NewFile(sr) if err != nil { - return nil, nil, err + return nil, 0, err } 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) - 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) { 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 - s.Type = sym.SNOPTRBSS + bld.SetType(sym.SNOPTRBSS) 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 - s.Type = sym.STEXT + bld.SetType(sym.STEXT) 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() if err != nil { - return nil, nil, err + return nil, 0, err } sectdata[sect] = data - s.P = data + bld.SetData(data) } - s.Size = int64(sect.Size) + bld.SetSize(int64(sect.Size)) sectsyms[sect] = s if sect.Name == ".rsrc" { rsrc = s @@ -234,35 +244,35 @@ func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, input *bio.Read continue } - rs := make([]sym.Reloc, rsect.NumberOfRelocations) + rs := make([]loader.Reloc, rsect.NumberOfRelocations) for j, r := range rsect.Relocs { rp := &rs[j] 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] - gosym, err := readpesym(arch, lookup, f, pesym, sectsyms, localSymVersion) + _, gosym, err := readpesym(l, arch, l.LookupOrCreateSym, f, pesym, sectsyms, localSymVersion) if err != nil { - return nil, nil, err + return nil, 0, err } - if gosym == nil { + if gosym == 0 { name, err := pesym.FullName(f.StringTable) if err != nil { 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.Siz = 4 + rp.Size = 4 rp.Off = int32(r.VirtualAddress) switch arch.Family { 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: switch r.Type { 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, 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:]))) case IMAGE_REL_AMD64_ADDR64: // R_X86_64_64 - rp.Siz = 8 + rp.Size = 8 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: switch r.Type { 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: 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] - s.R = rs - s.R = s.R[:rsect.NumberOfRelocations] + bld, _ := l.MakeSymbolUpdater(sectsyms[rsect]) + bld.SetRelocs(rs[:rsect.NumberOfRelocations]) } // 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) if err != nil { - return nil, nil, err + return nil, 0, err } if name == "" { 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 { - return nil, nil, err + return nil, 0, err } if pesym.SectionNumber == 0 { // extern - if s.Type == sym.SDYNIMPORT { - s.SetPlt(-2) // flag for dynimport in PE object files. + if l.SymType(s) == sym.SDYNIMPORT { + 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 - s.Type = sym.SNOPTRDATA - s.Size = int64(pesym.Value) + if l.SymType(s) == sym.SXREF && pesym.Value > 0 { // global data + bld = makeUpdater(l, bld, s) + bld.SetType(sym.SNOPTRDATA) + bld.SetSize(int64(pesym.Value)) } continue } else if pesym.SectionNumber > 0 && int(pesym.SectionNumber) <= len(f.Sections) { sect = f.Sections[pesym.SectionNumber-1] 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 { - 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 { - return nil, rsrc, nil + return nil, 0, nil } - if s.Outer != nil { - if s.Attr.DuplicateOK() { + if l.OuterSym(s) != 0 { + if l.AttrDuplicateOK(s) { 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] - s.Sub = sectsym.Sub - sectsym.Sub = s - s.Type = sectsym.Type - s.Attr |= sym.AttrSubSymbol - s.Value = int64(pesym.Value) - s.Size = 4 - s.Outer = sectsym - if sectsym.Type == sym.STEXT { - if s.Attr.External() && !s.Attr.DuplicateOK() { - return nil, nil, fmt.Errorf("%s: duplicate symbol definition", s.Name) + bld.SetType(l.SymType(sectsym)) + l.PrependSub(sectsym, s) + bld.SetValue(int64(pesym.Value)) + bld.SetSize(4) + if l.SymType(sectsym) == sym.STEXT { + if bld.External() && !bld.DuplicateOK() { + return nil, 0, fmt.Errorf("%s: duplicate symbol definition", l.SymName(s)) } - 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. for _, sect := range f.Sections { s := sectsyms[sect] - if s == nil { + if s == 0 { continue } - if s.Sub != nil { - s.Sub = sym.SortSub(s.Sub) - } - if s.Type == sym.STEXT { - if s.Attr.OnList() { - 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) + l.SortSub(s) + if l.SymType(s) == sym.STEXT { + for ; s != 0; s = l.SubSym(s) { + if l.AttrOnList(s) { + return nil, 0, fmt.Errorf("symbol %s listed multiple times", l.SymName(s)) } - s.Attr |= sym.AttrOnList + l.SetAttrOnList(s, true) 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] == '.' } -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) if err != nil { - return nil, err + return nil, 0, err } var name string if issect(pesym) { - name = sectsyms[f.Sections[pesym.SectionNumber-1]].Name + name = l.SymName(sectsyms[f.Sections[pesym.SectionNumber-1]]) } else { name = symname switch arch.Family { @@ -475,10 +479,11 @@ func readpesym(arch *sys.Arch, lookup func(string, int) *sym.Symbol, f *pe.File, name = name[:i] } - var s *sym.Symbol + var s loader.Sym + var bld *loader.SymbolBuilder switch pesym.Type { 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: 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: s = lookup(name, localSymVersion) - s.Attr |= sym.AttrDuplicateOK + bld = makeUpdater(l, bld, s) + bld.SetDuplicateOK(true) 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) { - s.Type = sym.SXREF + if s != 0 && l.SymType(s) == 0 && (pesym.StorageClass != IMAGE_SYM_CLASS_STATIC || pesym.Value != 0) { + bld = makeUpdater(l, bld, s) + bld.SetType(sym.SXREF) } 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 }