// Load loads 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, syms *sym.Symbols, f *bio.Reader, pkg string, length int64, pn string) (textp []*sym.Symbol, err error) {
- var j int
- var is64 bool
- var secaddr uint64
- var hdr [7 * 4]uint8
- var cmdp []byte
- var dat []byte
- var ncmd uint32
- var cmdsz uint32
- var ty uint32
- var sz uint32
- var off uint32
- var m *ldMachoObj
- var e binary.ByteOrder
- var sect *ldMachoSect
- var rel *ldMachoRel
- var rpi int
- var s *sym.Symbol
- var s1 *sym.Symbol
- var outer *sym.Symbol
- var c *ldMachoCmd
- var symtab *ldMachoSymtab
- var dsymtab *ldMachoDysymtab
- var r []sym.Reloc
- var rp *sym.Reloc
- var name string
-
errorf := func(str string, args ...interface{}) ([]*sym.Symbol, error) {
return nil, fmt.Errorf("loadmacho: %v: %v", pn, fmt.Sprintf(str, args...))
}
localSymVersion := syms.IncVersion()
base := f.Offset()
+
+ var hdr [7 * 4]uint8
if _, err := io.ReadFull(f, hdr[:]); err != nil {
- return errorf("%v", err)
+ return errorf("reading hdr: %v", err)
}
+ var e binary.ByteOrder
if binary.BigEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
e = binary.BigEndian
} else if binary.LittleEndian.Uint32(hdr[:])&^1 == 0xFEEDFACE {
return errorf("bad magic - not mach-o file")
}
- is64 = e.Uint32(hdr[:]) == 0xFEEDFACF
- ncmd = e.Uint32(hdr[4*4:])
- cmdsz = e.Uint32(hdr[5*4:])
+ is64 := e.Uint32(hdr[:]) == 0xFEEDFACF
+ ncmd := e.Uint32(hdr[4*4:])
+ cmdsz := e.Uint32(hdr[5*4:])
if ncmd > 0x10000 || cmdsz >= 0x01000000 {
return errorf("implausible mach-o header ncmd=%d cmdsz=%d", ncmd, cmdsz)
}
f.Seek(4, 1) // skip reserved word in header
}
- m = new(ldMachoObj)
-
- m.f = f
- m.e = e
- m.cputype = uint(e.Uint32(hdr[1*4:]))
- m.subcputype = uint(e.Uint32(hdr[2*4:]))
- m.filetype = e.Uint32(hdr[3*4:])
- m.ncmd = uint(ncmd)
- m.flags = e.Uint32(hdr[6*4:])
- m.is64 = is64
- m.base = base
- m.length = length
- m.name = pn
+ m := &ldMachoObj{
+ f: f,
+ e: e,
+ cputype: uint(e.Uint32(hdr[1*4:])),
+ subcputype: uint(e.Uint32(hdr[2*4:])),
+ filetype: e.Uint32(hdr[3*4:]),
+ ncmd: uint(ncmd),
+ flags: e.Uint32(hdr[6*4:]),
+ is64: is64,
+ base: base,
+ length: length,
+ name: pn,
+ }
switch arch.Family {
default:
}
m.cmd = make([]ldMachoCmd, ncmd)
- off = uint32(len(hdr))
- cmdp = make([]byte, cmdsz)
- if _, err2 := io.ReadFull(f, cmdp); err2 != nil {
+ cmdp := make([]byte, cmdsz)
+ if _, err := io.ReadFull(f, cmdp); err != nil {
return errorf("reading cmds: %v", err)
}
// read and parse load commands
- c = nil
+ var c *ldMachoCmd
- symtab = nil
- dsymtab = nil
+ var symtab *ldMachoSymtab
+ var dsymtab *ldMachoDysymtab
- for i := 0; uint32(i) < ncmd; i++ {
- ty = e.Uint32(cmdp)
- sz = e.Uint32(cmdp[4:])
+ off := uint32(len(hdr))
+ for i := uint32(0); i < ncmd; i++ {
+ ty := e.Uint32(cmdp)
+ sz := e.Uint32(cmdp[4:])
m.cmd[i].off = off
unpackcmd(cmdp, m, &m.cmd[i], uint(ty), uint(sz))
cmdp = cmdp[sz:]
return errorf("load segment out of range")
}
- dat = make([]byte, c.seg.filesz)
if f.Seek(m.base+int64(c.seg.fileoff), 0) < 0 {
- return errorf("cannot load object data: %v", err)
+ return errorf("cannot load object data: seek failed")
}
- if _, err2 := io.ReadFull(f, dat); err2 != nil {
+ dat := make([]byte, c.seg.filesz)
+ if _, err := io.ReadFull(f, dat); err != nil {
return errorf("cannot load object data: %v", err)
}
- for i := 0; uint32(i) < c.seg.nsect; i++ {
- sect = &c.seg.sect[i]
+ for i := uint32(0); i < c.seg.nsect; i++ {
+ sect := &c.seg.sect[i]
if sect.segname != "__TEXT" && sect.segname != "__DATA" {
continue
}
if sect.name == "__eh_frame" {
continue
}
- name = fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name)
- s = syms.Lookup(name, localSymVersion)
+ name := fmt.Sprintf("%s(%s/%s)", pkg, sect.segname, sect.name)
+ s := syms.Lookup(name, localSymVersion)
if s.Type != 0 {
return errorf("duplicate %s/%s", sect.segname, sect.name)
}
// enter sub-symbols into symbol table.
// have to guess sizes from next symbol.
- for i := 0; uint32(i) < symtab.nsym; i++ {
+ for i := uint32(0); i < symtab.nsym; i++ {
machsym := &symtab.sym[i]
if machsym.type_&N_STAB != 0 {
continue
}
// TODO: check sym->type against outer->type.
- name = machsym.name
+ name := machsym.name
if name[0] == '_' && name[1] != '\x00' {
name = name[1:]
if machsym.type_&N_EXT == 0 {
v = localSymVersion
}
- s = syms.Lookup(name, v)
+ s := syms.Lookup(name, v)
if machsym.type_&N_EXT == 0 {
s.Attr |= sym.AttrDuplicateOK
}
return errorf("reference to invalid section %d", machsym.sectnum)
}
- sect = &c.seg.sect[machsym.sectnum-1]
- outer = sect.sym
+ sect := &c.seg.sect[machsym.sectnum-1]
+ outer := sect.sym
if outer == nil {
return errorf("reference to invalid section %s/%s", sect.segname, sect.name)
}
// Sort outer lists by address, adding to textp.
// This keeps textp in increasing address order.
for i := 0; uint32(i) < c.seg.nsect; i++ {
- sect = &c.seg.sect[i]
- s = sect.sym
+ sect := &c.seg.sect[i]
+ s := sect.sym
if s == nil {
continue
}
s.Sub = sym.SortSub(s.Sub)
// assign sizes, now that we know symbols in sorted order.
- for s1 = s.Sub; s1 != nil; s1 = s1.Sub {
+ for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
if s1.Sub != nil {
s1.Size = s1.Sub.Value - s1.Value
} else {
}
s.Attr |= sym.AttrOnList
textp = append(textp, s)
- for s1 = s.Sub; s1 != nil; s1 = s1.Sub {
+ for s1 := s.Sub; s1 != nil; s1 = s1.Sub {
if s1.Attr.OnList() {
return errorf("symbol %s listed multiple times", s1.Name)
}
// load relocations
for i := 0; uint32(i) < c.seg.nsect; i++ {
- sect = &c.seg.sect[i]
- s = sect.sym
+ sect := &c.seg.sect[i]
+ s := sect.sym
if s == nil {
continue
}
if sect.rel == nil {
continue
}
- r = make([]sym.Reloc, sect.nreloc)
- rpi = 0
+ r := make([]sym.Reloc, sect.nreloc)
+ rpi := 0
Reloc:
- for j = 0; uint32(j) < sect.nreloc; j++ {
- rp = &r[rpi]
- rel = §.rel[j]
+ for j := uint32(0); j < sect.nreloc; j++ {
+ rp := &r[rpi]
+ rel := §.rel[j]
if rel.scattered != 0 {
if arch.Family != sys.I386 {
// mach-o only uses scattered relocation on 32-bit platforms
// reference that it is.
// assume that the second in the pair is in this section
// and use that as the pc-relative base.
- if uint32(j+1) >= sect.nreloc {
+ if j+1 >= sect.nreloc {
return errorf("unsupported scattered relocation %d", int(rel.type_))
}
// now consider the desired symbol.
// find the section where it lives.
- var ks *ldMachoSect
for k := 0; uint32(k) < c.seg.nsect; k++ {
- ks = &c.seg.sect[k]
+ ks := &c.seg.sect[k]
if ks.addr <= uint64(rel.value) && uint64(rel.value) < ks.addr+ks.size {
if ks.sym != nil {
rp.Sym = ks.sym
}
return errorf("unsupported scattered relocation: invalid address %#x", rel.addr)
-
}
rp.Siz = rel.length
// section found in the original object file.
//
// [For future reference, see Darwin's /usr/include/mach-o/x86_64/reloc.h]
- secaddr = c.seg.sect[rel.symnum-1].addr
+ 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)
} else {
// An unsigned internal relocation has a value offset
// by the section address.
if arch.Family == sys.AMD64 && rel.extrn == 0 && rel.type_ == MACHO_X86_64_RELOC_UNSIGNED {
- secaddr = c.seg.sect[rel.symnum-1].addr
+ secaddr := c.seg.sect[rel.symnum-1].addr
rp.Add -= int64(secaddr)
}