diff options
Diffstat (limited to 'src/cmd/link/internal/loadmacho/ldmacho.go')
-rw-r--r-- | src/cmd/link/internal/loadmacho/ldmacho.go | 170 |
1 files changed, 80 insertions, 90 deletions
diff --git a/src/cmd/link/internal/loadmacho/ldmacho.go b/src/cmd/link/internal/loadmacho/ldmacho.go index 85a1ebc631..d1ff82f9eb 100644 --- a/src/cmd/link/internal/loadmacho/ldmacho.go +++ b/src/cmd/link/internal/loadmacho/ldmacho.go @@ -14,7 +14,6 @@ import ( "cmd/link/internal/sym" "encoding/binary" "fmt" - "io" "sort" ) @@ -101,7 +100,7 @@ type ldMachoSect struct { flags uint32 res1 uint32 res2 uint32 - sym *sym.Symbol + sym loader.Sym rel []ldMachoRel } @@ -132,7 +131,7 @@ type ldMachoSym struct { desc uint16 kind int8 value uint64 - sym *sym.Symbol + sym loader.Sym } type ldMachoDysymtab struct { @@ -320,10 +319,9 @@ func macholoadrel(m *ldMachoObj, sect *ldMachoSect) int { return 0 } rel := make([]ldMachoRel, sect.nreloc) - n := int(sect.nreloc * 8) - buf := make([]byte, n) m.f.MustSeek(m.base+int64(sect.reloff), 0) - if _, err := io.ReadFull(m.f, buf); err != nil { + buf, _, err := m.f.Slice(uint64(sect.nreloc * 8)) + if err != nil { return -1 } for i := uint32(0); i < sect.nreloc; i++ { @@ -364,10 +362,9 @@ func macholoadrel(m *ldMachoObj, sect *ldMachoSect) int { func macholoaddsym(m *ldMachoObj, d *ldMachoDysymtab) int { n := int(d.nindirectsyms) - - p := make([]byte, n*4) m.f.MustSeek(m.base+int64(d.indirectsymoff), 0) - if _, err := io.ReadFull(m.f, p); err != nil { + p, _, err := m.f.Slice(uint64(n * 4)) + if err != nil { return -1 } @@ -383,9 +380,9 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int { return 0 } - strbuf := make([]byte, symtab.strsize) m.f.MustSeek(m.base+int64(symtab.stroff), 0) - if _, err := io.ReadFull(m.f, strbuf); err != nil { + strbuf, _, err := m.f.Slice(uint64(symtab.strsize)) + if err != nil { return -1 } @@ -394,9 +391,9 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int { symsize = 16 } n := int(symtab.nsym * uint32(symsize)) - symbuf := make([]byte, n) m.f.MustSeek(m.base+int64(symtab.symoff), 0) - if _, err := io.ReadFull(m.f, symbuf); err != nil { + symbuf, _, err := m.f.Slice(uint64(n)) + if err != nil { return -1 } sym := make([]ldMachoSym, symtab.nsym) @@ -424,28 +421,17 @@ func macholoadsym(m *ldMachoObj, symtab *ldMachoSymtab) int { return 0 } -func Load(l *loader.Loader, arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) ([]*sym.Symbol, error) { - newSym := func(name string, version int) *sym.Symbol { - return l.LookupOrCreate(name, version, syms) - } - return load(arch, syms.IncVersion(), newSym, f, pkg, length, pn) -} - -func LoadOld(arch *sys.Arch, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) { - return load(arch, syms.IncVersion(), syms.Lookup, f, pkg, length, pn) -} - -// load the Mach-O file pn from f. +// Load the Mach-O file pn from f. // Symbols are written into syms, and a slice of the text symbols is returned. -func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Symbol, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) { - errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) { +func Load(l *loader.Loader, arch *sys.Arch, localSymVersion int, f *bio.Reader, pkg string, length int64, pn string) (textp []loader.Sym, err error) { + errorf := func(str string, args ...interface{}) ([]loader.Sym, error) { return nil, fmt.Errorf("loadmacho: %v: %v", pn, fmt.Sprintf(str, args...)) } base := f.Offset() - var hdr [7 * 4]uint8 - if _, err := io.ReadFull(f, hdr[:]); err != nil { + hdr, _, err := f.Slice(7 * 4) + if err != nil { return errorf("reading hdr: %v", err) } @@ -499,8 +485,8 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym } m.cmd = make([]ldMachoCmd, ncmd) - cmdp := make([]byte, cmdsz) - if _, err := io.ReadFull(f, cmdp); err != nil { + cmdp, _, err := f.Slice(uint64(cmdsz)) + if err != nil { return errorf("reading cmds: %v", err) } @@ -559,8 +545,8 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym } f.MustSeek(m.base+int64(c.seg.fileoff), 0) - dat := make([]byte, c.seg.filesz) - if _, err := io.ReadFull(f, dat); err != nil { + dat, readOnly, err := f.Slice(uint64(c.seg.filesz)) + if err != nil { return errorf("cannot load object data: %v", err) } @@ -573,30 +559,32 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym continue } name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name) - s := lookup(name, localSymVersion) - if s.Type != 0 { + s := l.LookupOrCreateSym(name, localSymVersion) + bld := l.MakeSymbolUpdater(s) + if bld.Type() != 0 { return errorf("duplicate %s/%s", sect.segname, sect.name) } if sect.flags&0xff == 1 { // S_ZEROFILL - s.P = make([]byte, sect.size) + bld.SetData(make([]byte, sect.size)) } else { - s.P = dat[sect.addr-c.seg.vmaddr:][:sect.size] + bld.SetReadOnly(readOnly) + bld.SetData(dat[sect.addr-c.seg.vmaddr:][:sect.size]) } - s.Size = int64(len(s.P)) + bld.SetSize(int64(len(bld.Data()))) if sect.segname == "__TEXT" { if sect.name == "__text" { - s.Type = sym.STEXT + bld.SetType(sym.STEXT) } else { - s.Type = sym.SRODATA + bld.SetType(sym.SRODATA) } } else { if sect.name == "__bss" { - s.Type = sym.SNOPTRBSS - s.P = s.P[:0] + bld.SetType(sym.SNOPTRBSS) + bld.SetData(nil) } else { - s.Type = sym.SNOPTRDATA + bld.SetType(sym.SNOPTRDATA) } } @@ -621,12 +609,12 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym if machsym.type_&N_EXT == 0 { v = localSymVersion } - s := lookup(name, v) + s := l.LookupOrCreateSym(name, v) if machsym.type_&N_EXT == 0 { - s.Attr |= sym.AttrDuplicateOK + l.SetAttrDuplicateOK(s, true) } if machsym.desc&(N_WEAK_REF|N_WEAK_DEF) != 0 { - s.Attr |= sym.AttrDuplicateOK + l.SetAttrDuplicateOK(s, true) } machsym.sym = s if machsym.sectnum == 0 { // undefined @@ -637,35 +625,32 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym } sect := &c.seg.sect[machsym.sectnum-1] + bld := l.MakeSymbolUpdater(s) outer := sect.sym - if outer == nil { + if outer == 0 { continue // ignore reference to invalid section } - if s.Outer != nil { - if s.Attr.DuplicateOK() { + if osym := l.OuterSym(s); osym != 0 { + if l.AttrDuplicateOK(s) { continue } - return errorf("duplicate symbol reference: %s in both %s and %s", s.Name, s.Outer.Name, sect.sym.Name) + return errorf("duplicate symbol reference: %s in both %s and %s", l.SymName(s), l.SymName(osym), l.SymName(sect.sym)) } - s.Type = outer.Type - s.Attr |= sym.AttrSubSymbol - s.Sub = outer.Sub - outer.Sub = s - s.Outer = outer - s.Value = int64(machsym.value - sect.addr) - if !s.Attr.CgoExportDynamic() { - s.SetDynimplib("") // satisfy dynimport + bld.SetType(l.SymType(outer)) + l.PrependSub(outer, s) + + bld.SetValue(int64(machsym.value - sect.addr)) + if !l.AttrCgoExportDynamic(s) { + bld.SetDynimplib("") // satisfy dynimport } - if outer.Type == sym.STEXT { - if s.Attr.External() && !s.Attr.DuplicateOK() { + if l.SymType(outer) == sym.STEXT { + if bld.External() && !bld.DuplicateOK() { return errorf("%v: duplicate symbol definition", s) } - s.Attr |= sym.AttrExternal + bld.SetExternal(true) } - - machsym.sym = s } // Sort outer lists by address, adding to textp. @@ -673,33 +658,37 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym for i := 0; uint32(i) < c.seg.nsect; i++ { sect := &c.seg.sect[i] s := sect.sym - if s == nil { + if s == 0 { continue } - if s.Sub != nil { - s.Sub = sym.SortSub(s.Sub) + bld := l.MakeSymbolUpdater(s) + if bld.SubSym() != 0 { + + bld.SortSub() // assign sizes, now that we know symbols in sorted order. - for s1 := s.Sub; s1 != nil; s1 = s1.Sub { - if s1.Sub != nil { - s1.Size = s1.Sub.Value - s1.Value + for s1 := bld.Sub(); s1 != 0; s1 = l.SubSym(s1) { + s1Bld := l.MakeSymbolUpdater(s1) + if sub := l.SubSym(s1); sub != 0 { + s1Bld.SetSize(l.SymValue(sub) - l.SymValue(s1)) } else { - s1.Size = s.Value + s.Size - s1.Value + dlen := int64(len(l.Data(s))) + s1Bld.SetSize(l.SymValue(s) + dlen - l.SymValue(s1)) } } } - if s.Type == sym.STEXT { - if s.Attr.OnList() { - return errorf("symbol %s listed multiple times", s.Name) + if bld.Type() == sym.STEXT { + if bld.OnList() { + return errorf("symbol %s listed multiple times", bld.Name()) } - s.Attr |= sym.AttrOnList + bld.SetOnList(true) textp = append(textp, s) - for s1 := s.Sub; s1 != nil; s1 = s1.Sub { - if s1.Attr.OnList() { - return errorf("symbol %s listed multiple times", s1.Name) + for s1 := bld.Sub(); s1 != 0; s1 = l.SubSym(s1) { + if l.AttrOnList(s1) { + return errorf("symbol %s listed multiple times", l.RawSymName(s1)) } - s1.Attr |= sym.AttrOnList + l.SetAttrOnList(s1, true) textp = append(textp, s1) } } @@ -709,14 +698,14 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym for i := 0; uint32(i) < c.seg.nsect; i++ { sect := &c.seg.sect[i] s := sect.sym - if s == nil { + if s == 0 { continue } macholoadrel(m, sect) if sect.rel == nil { continue } - r := make([]sym.Reloc, sect.nreloc) + r := make([]loader.Reloc, sect.nreloc) rpi := 0 Reloc: for j := uint32(0); j < sect.nreloc; j++ { @@ -741,7 +730,7 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym return errorf("unsupported scattered relocation %d/%d", int(rel.type_), int(sect.rel[j+1].type_)) } - rp.Siz = rel.length + rp.Size = rel.length rp.Off = int32(rel.addr) // NOTE(rsc): I haven't worked out why (really when) @@ -765,7 +754,7 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym for k := 0; uint32(k) < c.seg.nsect; k++ { ks := &c.seg.sect[k] if ks.addr <= uint64(rel.value) && uint64(rel.value) < ks.addr+ks.size { - if ks.sym != nil { + if ks.sym != 0 { rp.Sym = ks.sym rp.Add += int64(uint64(rel.value) - ks.addr) } else if ks.segname == "__IMPORT" && ks.name == "__pointers" { @@ -805,11 +794,12 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym return errorf("unsupported scattered relocation: invalid address %#x", rel.addr) } - rp.Siz = rel.length + rp.Size = rel.length rp.Type = objabi.MachoRelocOffset + (objabi.RelocType(rel.type_) << 1) + objabi.RelocType(rel.pcrel) rp.Off = int32(rel.addr) // Handle X86_64_RELOC_SIGNED referencing a section (rel->extrn == 0). + p := l.Data(s) if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_SIGNED { // Calculate the addend as the offset into the section. // @@ -828,9 +818,9 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym // [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h] secaddr := c.seg.sect[rel.symnum-1].addr - rp.Add = int64(uint64(int64(int32(e.Uint32(s.P[rp.Off:])))+int64(rp.Off)+4) - secaddr) + rp.Add = int64(uint64(int64(int32(e.Uint32(p[rp.Off:])))+int64(rp.Off)+4) - secaddr) } else { - rp.Add = int64(int32(e.Uint32(s.P[rp.Off:]))) + rp.Add = int64(int32(e.Uint32(p[rp.Off:]))) } // An unsigned internal relocation has a value offset @@ -844,7 +834,7 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym // it *is* the PC being subtracted. Use that to make // it match our version of PC-relative. if rel.pcrel != 0 && arch.Family == sys.I386 { - rp.Add += int64(rp.Off) + int64(rp.Siz) + rp.Add += int64(rp.Off) + int64(rp.Size) } if rel.extrn == 0 { if rel.symnum < 1 || rel.symnum > c.seg.nsect { @@ -852,7 +842,7 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym } rp.Sym = c.seg.sect[rel.symnum-1].sym - if rp.Sym == nil { + if rp.Sym == 0 { return errorf("invalid relocation: %s", c.seg.sect[rel.symnum-1].name) } @@ -874,9 +864,9 @@ func load(arch *sys.Arch, localSymVersion int, lookup func(string, int) *sym.Sym rpi++ } - sort.Sort(sym.RelocByOff(r[:rpi])) - s.R = r - s.R = s.R[:rpi] + sort.Sort(loader.RelocByOff(r[:rpi])) + sb := l.MakeSymbolUpdater(sect.sym) + sb.SetRelocs(r[:rpi]) } return textp, nil |