diff options
author | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
---|---|---|
committer | Tianon Gravi <admwiggin@gmail.com> | 2015-01-15 11:54:00 -0700 |
commit | f154da9e12608589e8d5f0508f908a0c3e88a1bb (patch) | |
tree | f8255d51e10c6f1e0ed69702200b966c9556a431 /src/pkg/debug/macho | |
parent | 8d8329ed5dfb9622c82a9fbec6fd99a580f9c9f6 (diff) | |
download | golang-upstream/1.4.tar.gz |
Imported Upstream version 1.4upstream/1.4
Diffstat (limited to 'src/pkg/debug/macho')
-rw-r--r-- | src/pkg/debug/macho/fat.go | 146 | ||||
-rw-r--r-- | src/pkg/debug/macho/file.go | 524 | ||||
-rw-r--r-- | src/pkg/debug/macho/file_test.go | 210 | ||||
-rw-r--r-- | src/pkg/debug/macho/macho.go | 316 | ||||
-rw-r--r-- | src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec | bin | 28992 -> 0 bytes | |||
-rwxr-xr-x | src/pkg/debug/macho/testdata/gcc-386-darwin-exec | bin | 12588 -> 0 bytes | |||
-rwxr-xr-x | src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec | bin | 8512 -> 0 bytes | |||
-rw-r--r-- | src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug | bin | 4540 -> 0 bytes | |||
-rw-r--r-- | src/pkg/debug/macho/testdata/hello.c | 8 |
9 files changed, 0 insertions, 1204 deletions
diff --git a/src/pkg/debug/macho/fat.go b/src/pkg/debug/macho/fat.go deleted file mode 100644 index 93b831526..000000000 --- a/src/pkg/debug/macho/fat.go +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2014 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package macho - -import ( - "encoding/binary" - "fmt" - "io" - "os" -) - -// A FatFile is a Mach-O universal binary that contains at least one architecture. -type FatFile struct { - Magic uint32 - Arches []FatArch - closer io.Closer -} - -// A FatArchHeader represents a fat header for a specific image architecture. -type FatArchHeader struct { - Cpu Cpu - SubCpu uint32 - Offset uint32 - Size uint32 - Align uint32 -} - -const fatArchHeaderSize = 5 * 4 - -// A FatArch is a Mach-O File inside a FatFile. -type FatArch struct { - FatArchHeader - *File -} - -// ErrNotFat is returned from NewFatFile or OpenFat when the file is not a -// universal binary but may be a thin binary, based on its magic number. -var ErrNotFat = &FormatError{0, "not a fat Mach-O file", nil} - -// NewFatFile creates a new FatFile for accessing all the Mach-O images in a -// universal binary. The Mach-O binary is expected to start at position 0 in -// the ReaderAt. -func NewFatFile(r io.ReaderAt) (*FatFile, error) { - var ff FatFile - sr := io.NewSectionReader(r, 0, 1<<63-1) - - // Read the fat_header struct, which is always in big endian. - // Start with the magic number. - err := binary.Read(sr, binary.BigEndian, &ff.Magic) - if err != nil { - return nil, &FormatError{0, "error reading magic number", nil} - } else if ff.Magic != MagicFat { - // See if this is a Mach-O file via its magic number. The magic - // must be converted to little endian first though. - var buf [4]byte - binary.BigEndian.PutUint32(buf[:], ff.Magic) - leMagic := binary.LittleEndian.Uint32(buf[:]) - if leMagic == Magic32 || leMagic == Magic64 { - return nil, ErrNotFat - } else { - return nil, &FormatError{0, "invalid magic number", nil} - } - } - offset := int64(4) - - // Read the number of FatArchHeaders that come after the fat_header. - var narch uint32 - err = binary.Read(sr, binary.BigEndian, &narch) - if err != nil { - return nil, &FormatError{offset, "invalid fat_header", nil} - } - offset += 4 - - if narch < 1 { - return nil, &FormatError{offset, "file contains no images", nil} - } - - // Combine the Cpu and SubCpu (both uint32) into a uint64 to make sure - // there are not duplicate architectures. - seenArches := make(map[uint64]bool, narch) - // Make sure that all images are for the same MH_ type. - var machoType Type - - // Following the fat_header comes narch fat_arch structs that index - // Mach-O images further in the file. - ff.Arches = make([]FatArch, narch) - for i := uint32(0); i < narch; i++ { - fa := &ff.Arches[i] - err = binary.Read(sr, binary.BigEndian, &fa.FatArchHeader) - if err != nil { - return nil, &FormatError{offset, "invalid fat_arch header", nil} - } - offset += fatArchHeaderSize - - fr := io.NewSectionReader(r, int64(fa.Offset), int64(fa.Size)) - fa.File, err = NewFile(fr) - if err != nil { - return nil, err - } - - // Make sure the architecture for this image is not duplicate. - seenArch := (uint64(fa.Cpu) << 32) | uint64(fa.SubCpu) - if o, k := seenArches[seenArch]; o || k { - return nil, &FormatError{offset, fmt.Sprintf("duplicate architecture cpu=%v, subcpu=%#x", fa.Cpu, fa.SubCpu), nil} - } - seenArches[seenArch] = true - - // Make sure the Mach-O type matches that of the first image. - if i == 0 { - machoType = fa.Type - } else { - if fa.Type != machoType { - return nil, &FormatError{offset, fmt.Sprintf("Mach-O type for architecture #%d (type=%#x) does not match first (type=%#x)", i, fa.Type, machoType), nil} - } - } - } - - return &ff, nil -} - -// OpenFat opens the named file using os.Open and prepares it for use as a Mach-O -// universal binary. -func OpenFat(name string) (ff *FatFile, err error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - ff, err = NewFatFile(f) - if err != nil { - f.Close() - return nil, err - } - ff.closer = f - return -} - -func (ff *FatFile) Close() error { - var err error - if ff.closer != nil { - err = ff.closer.Close() - ff.closer = nil - } - return err -} diff --git a/src/pkg/debug/macho/file.go b/src/pkg/debug/macho/file.go deleted file mode 100644 index eefb74444..000000000 --- a/src/pkg/debug/macho/file.go +++ /dev/null @@ -1,524 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package macho implements access to Mach-O object files. -package macho - -// High level access to low level data structures. - -import ( - "bytes" - "debug/dwarf" - "encoding/binary" - "fmt" - "io" - "os" -) - -// A File represents an open Mach-O file. -type File struct { - FileHeader - ByteOrder binary.ByteOrder - Loads []Load - Sections []*Section - - Symtab *Symtab - Dysymtab *Dysymtab - - closer io.Closer -} - -// A Load represents any Mach-O load command. -type Load interface { - Raw() []byte -} - -// A LoadBytes is the uninterpreted bytes of a Mach-O load command. -type LoadBytes []byte - -func (b LoadBytes) Raw() []byte { return b } - -// A SegmentHeader is the header for a Mach-O 32-bit or 64-bit load segment command. -type SegmentHeader struct { - Cmd LoadCmd - Len uint32 - Name string - Addr uint64 - Memsz uint64 - Offset uint64 - Filesz uint64 - Maxprot uint32 - Prot uint32 - Nsect uint32 - Flag uint32 -} - -// A Segment represents a Mach-O 32-bit or 64-bit load segment command. -type Segment struct { - LoadBytes - SegmentHeader - - // Embed ReaderAt for ReadAt method. - // Do not embed SectionReader directly - // to avoid having Read and Seek. - // If a client wants Read and Seek it must use - // Open() to avoid fighting over the seek offset - // with other clients. - io.ReaderAt - sr *io.SectionReader -} - -// Data reads and returns the contents of the segment. -func (s *Segment) Data() ([]byte, error) { - dat := make([]byte, s.sr.Size()) - n, err := s.sr.ReadAt(dat, 0) - if n == len(dat) { - err = nil - } - return dat[0:n], err -} - -// Open returns a new ReadSeeker reading the segment. -func (s *Segment) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } - -type SectionHeader struct { - Name string - Seg string - Addr uint64 - Size uint64 - Offset uint32 - Align uint32 - Reloff uint32 - Nreloc uint32 - Flags uint32 -} - -type Section struct { - SectionHeader - - // Embed ReaderAt for ReadAt method. - // Do not embed SectionReader directly - // to avoid having Read and Seek. - // If a client wants Read and Seek it must use - // Open() to avoid fighting over the seek offset - // with other clients. - io.ReaderAt - sr *io.SectionReader -} - -// Data reads and returns the contents of the Mach-O section. -func (s *Section) Data() ([]byte, error) { - dat := make([]byte, s.sr.Size()) - n, err := s.sr.ReadAt(dat, 0) - if n == len(dat) { - err = nil - } - return dat[0:n], err -} - -// Open returns a new ReadSeeker reading the Mach-O section. -func (s *Section) Open() io.ReadSeeker { return io.NewSectionReader(s.sr, 0, 1<<63-1) } - -// A Dylib represents a Mach-O load dynamic library command. -type Dylib struct { - LoadBytes - Name string - Time uint32 - CurrentVersion uint32 - CompatVersion uint32 -} - -// A Symtab represents a Mach-O symbol table command. -type Symtab struct { - LoadBytes - SymtabCmd - Syms []Symbol -} - -// A Dysymtab represents a Mach-O dynamic symbol table command. -type Dysymtab struct { - LoadBytes - DysymtabCmd - IndirectSyms []uint32 // indices into Symtab.Syms -} - -/* - * Mach-O reader - */ - -// FormatError is returned by some operations if the data does -// not have the correct format for an object file. -type FormatError struct { - off int64 - msg string - val interface{} -} - -func (e *FormatError) Error() string { - msg := e.msg - if e.val != nil { - msg += fmt.Sprintf(" '%v'", e.val) - } - msg += fmt.Sprintf(" in record at byte %#x", e.off) - return msg -} - -// Open opens the named file using os.Open and prepares it for use as a Mach-O binary. -func Open(name string) (*File, error) { - f, err := os.Open(name) - if err != nil { - return nil, err - } - ff, err := NewFile(f) - if err != nil { - f.Close() - return nil, err - } - ff.closer = f - return ff, nil -} - -// Close closes the File. -// If the File was created using NewFile directly instead of Open, -// Close has no effect. -func (f *File) Close() error { - var err error - if f.closer != nil { - err = f.closer.Close() - f.closer = nil - } - return err -} - -// NewFile creates a new File for accessing a Mach-O binary in an underlying reader. -// The Mach-O binary is expected to start at position 0 in the ReaderAt. -func NewFile(r io.ReaderAt) (*File, error) { - f := new(File) - sr := io.NewSectionReader(r, 0, 1<<63-1) - - // Read and decode Mach magic to determine byte order, size. - // Magic32 and Magic64 differ only in the bottom bit. - var ident [4]byte - if _, err := r.ReadAt(ident[0:], 0); err != nil { - return nil, err - } - be := binary.BigEndian.Uint32(ident[0:]) - le := binary.LittleEndian.Uint32(ident[0:]) - switch Magic32 &^ 1 { - case be &^ 1: - f.ByteOrder = binary.BigEndian - f.Magic = be - case le &^ 1: - f.ByteOrder = binary.LittleEndian - f.Magic = le - default: - return nil, &FormatError{0, "invalid magic number", nil} - } - - // Read entire file header. - if err := binary.Read(sr, f.ByteOrder, &f.FileHeader); err != nil { - return nil, err - } - - // Then load commands. - offset := int64(fileHeaderSize32) - if f.Magic == Magic64 { - offset = fileHeaderSize64 - } - dat := make([]byte, f.Cmdsz) - if _, err := r.ReadAt(dat, offset); err != nil { - return nil, err - } - f.Loads = make([]Load, f.Ncmd) - bo := f.ByteOrder - for i := range f.Loads { - // Each load command begins with uint32 command and length. - if len(dat) < 8 { - return nil, &FormatError{offset, "command block too small", nil} - } - cmd, siz := LoadCmd(bo.Uint32(dat[0:4])), bo.Uint32(dat[4:8]) - if siz < 8 || siz > uint32(len(dat)) { - return nil, &FormatError{offset, "invalid command block size", nil} - } - var cmddat []byte - cmddat, dat = dat[0:siz], dat[siz:] - offset += int64(siz) - var s *Segment - switch cmd { - default: - f.Loads[i] = LoadBytes(cmddat) - - case LoadCmdDylib: - var hdr DylibCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - l := new(Dylib) - if hdr.Name >= uint32(len(cmddat)) { - return nil, &FormatError{offset, "invalid name in dynamic library command", hdr.Name} - } - l.Name = cstring(cmddat[hdr.Name:]) - l.Time = hdr.Time - l.CurrentVersion = hdr.CurrentVersion - l.CompatVersion = hdr.CompatVersion - l.LoadBytes = LoadBytes(cmddat) - f.Loads[i] = l - - case LoadCmdSymtab: - var hdr SymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - strtab := make([]byte, hdr.Strsize) - if _, err := r.ReadAt(strtab, int64(hdr.Stroff)); err != nil { - return nil, err - } - var symsz int - if f.Magic == Magic64 { - symsz = 16 - } else { - symsz = 12 - } - symdat := make([]byte, int(hdr.Nsyms)*symsz) - if _, err := r.ReadAt(symdat, int64(hdr.Symoff)); err != nil { - return nil, err - } - st, err := f.parseSymtab(symdat, strtab, cmddat, &hdr, offset) - if err != nil { - return nil, err - } - f.Loads[i] = st - f.Symtab = st - - case LoadCmdDysymtab: - var hdr DysymtabCmd - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &hdr); err != nil { - return nil, err - } - dat := make([]byte, hdr.Nindirectsyms*4) - if _, err := r.ReadAt(dat, int64(hdr.Indirectsymoff)); err != nil { - return nil, err - } - x := make([]uint32, hdr.Nindirectsyms) - if err := binary.Read(bytes.NewReader(dat), bo, x); err != nil { - return nil, err - } - st := new(Dysymtab) - st.LoadBytes = LoadBytes(cmddat) - st.DysymtabCmd = hdr - st.IndirectSyms = x - f.Loads[i] = st - f.Dysymtab = st - - case LoadCmdSegment: - var seg32 Segment32 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg32); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg32.Name[0:]) - s.Addr = uint64(seg32.Addr) - s.Memsz = uint64(seg32.Memsz) - s.Offset = uint64(seg32.Offset) - s.Filesz = uint64(seg32.Filesz) - s.Maxprot = seg32.Maxprot - s.Prot = seg32.Prot - s.Nsect = seg32.Nsect - s.Flag = seg32.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh32 Section32 - if err := binary.Read(b, bo, &sh32); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh32.Name[0:]) - sh.Seg = cstring(sh32.Seg[0:]) - sh.Addr = uint64(sh32.Addr) - sh.Size = uint64(sh32.Size) - sh.Offset = sh32.Offset - sh.Align = sh32.Align - sh.Reloff = sh32.Reloff - sh.Nreloc = sh32.Nreloc - sh.Flags = sh32.Flags - f.pushSection(sh, r) - } - - case LoadCmdSegment64: - var seg64 Segment64 - b := bytes.NewReader(cmddat) - if err := binary.Read(b, bo, &seg64); err != nil { - return nil, err - } - s = new(Segment) - s.LoadBytes = cmddat - s.Cmd = cmd - s.Len = siz - s.Name = cstring(seg64.Name[0:]) - s.Addr = seg64.Addr - s.Memsz = seg64.Memsz - s.Offset = seg64.Offset - s.Filesz = seg64.Filesz - s.Maxprot = seg64.Maxprot - s.Prot = seg64.Prot - s.Nsect = seg64.Nsect - s.Flag = seg64.Flag - f.Loads[i] = s - for i := 0; i < int(s.Nsect); i++ { - var sh64 Section64 - if err := binary.Read(b, bo, &sh64); err != nil { - return nil, err - } - sh := new(Section) - sh.Name = cstring(sh64.Name[0:]) - sh.Seg = cstring(sh64.Seg[0:]) - sh.Addr = sh64.Addr - sh.Size = sh64.Size - sh.Offset = sh64.Offset - sh.Align = sh64.Align - sh.Reloff = sh64.Reloff - sh.Nreloc = sh64.Nreloc - sh.Flags = sh64.Flags - f.pushSection(sh, r) - } - } - if s != nil { - s.sr = io.NewSectionReader(r, int64(s.Offset), int64(s.Filesz)) - s.ReaderAt = s.sr - } - } - return f, nil -} - -func (f *File) parseSymtab(symdat, strtab, cmddat []byte, hdr *SymtabCmd, offset int64) (*Symtab, error) { - bo := f.ByteOrder - symtab := make([]Symbol, hdr.Nsyms) - b := bytes.NewReader(symdat) - for i := range symtab { - var n Nlist64 - if f.Magic == Magic64 { - if err := binary.Read(b, bo, &n); err != nil { - return nil, err - } - } else { - var n32 Nlist32 - if err := binary.Read(b, bo, &n32); err != nil { - return nil, err - } - n.Name = n32.Name - n.Type = n32.Type - n.Sect = n32.Sect - n.Desc = n32.Desc - n.Value = uint64(n32.Value) - } - sym := &symtab[i] - if n.Name >= uint32(len(strtab)) { - return nil, &FormatError{offset, "invalid name in symbol table", n.Name} - } - sym.Name = cstring(strtab[n.Name:]) - sym.Type = n.Type - sym.Sect = n.Sect - sym.Desc = n.Desc - sym.Value = n.Value - } - st := new(Symtab) - st.LoadBytes = LoadBytes(cmddat) - st.Syms = symtab - return st, nil -} - -func (f *File) pushSection(sh *Section, r io.ReaderAt) { - f.Sections = append(f.Sections, sh) - sh.sr = io.NewSectionReader(r, int64(sh.Offset), int64(sh.Size)) - sh.ReaderAt = sh.sr -} - -func cstring(b []byte) string { - var i int - for i = 0; i < len(b) && b[i] != 0; i++ { - } - return string(b[0:i]) -} - -// Segment returns the first Segment with the given name, or nil if no such segment exists. -func (f *File) Segment(name string) *Segment { - for _, l := range f.Loads { - if s, ok := l.(*Segment); ok && s.Name == name { - return s - } - } - return nil -} - -// Section returns the first section with the given name, or nil if no such -// section exists. -func (f *File) Section(name string) *Section { - for _, s := range f.Sections { - if s.Name == name { - return s - } - } - return nil -} - -// DWARF returns the DWARF debug information for the Mach-O file. -func (f *File) DWARF() (*dwarf.Data, error) { - // There are many other DWARF sections, but these - // are the required ones, and the debug/dwarf package - // does not use the others, so don't bother loading them. - var names = [...]string{"abbrev", "info", "str"} - var dat [len(names)][]byte - for i, name := range names { - name = "__debug_" + name - s := f.Section(name) - if s == nil { - continue - } - b, err := s.Data() - if err != nil && uint64(len(b)) < s.Size { - return nil, err - } - dat[i] = b - } - - abbrev, info, str := dat[0], dat[1], dat[2] - return dwarf.New(abbrev, nil, nil, info, nil, nil, nil, str) -} - -// ImportedSymbols returns the names of all symbols -// referred to by the binary f that are expected to be -// satisfied by other libraries at dynamic load time. -func (f *File) ImportedSymbols() ([]string, error) { - if f.Dysymtab == nil || f.Symtab == nil { - return nil, &FormatError{0, "missing symbol table", nil} - } - - st := f.Symtab - dt := f.Dysymtab - var all []string - for _, s := range st.Syms[dt.Iundefsym : dt.Iundefsym+dt.Nundefsym] { - all = append(all, s.Name) - } - return all, nil -} - -// ImportedLibraries returns the paths of all libraries -// referred to by the binary f that are expected to be -// linked with the binary at dynamic link time. -func (f *File) ImportedLibraries() ([]string, error) { - var all []string - for _, l := range f.Loads { - if lib, ok := l.(*Dylib); ok { - all = append(all, lib.Name) - } - } - return all, nil -} diff --git a/src/pkg/debug/macho/file_test.go b/src/pkg/debug/macho/file_test.go deleted file mode 100644 index 4797780ce..000000000 --- a/src/pkg/debug/macho/file_test.go +++ /dev/null @@ -1,210 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package macho - -import ( - "reflect" - "testing" -) - -type fileTest struct { - file string - hdr FileHeader - segments []*SegmentHeader - sections []*SectionHeader -} - -var fileTests = []fileTest{ - { - "testdata/gcc-386-darwin-exec", - FileHeader{0xfeedface, Cpu386, 0x3, 0x2, 0xc, 0x3c0, 0x85}, - []*SegmentHeader{ - {LoadCmdSegment, 0x38, "__PAGEZERO", 0x0, 0x1000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - {LoadCmdSegment, 0xc0, "__TEXT", 0x1000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x2, 0x0}, - {LoadCmdSegment, 0xc0, "__DATA", 0x2000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x2, 0x0}, - {LoadCmdSegment, 0x7c, "__IMPORT", 0x3000, 0x1000, 0x2000, 0x1000, 0x7, 0x7, 0x1, 0x0}, - {LoadCmdSegment, 0x38, "__LINKEDIT", 0x4000, 0x1000, 0x3000, 0x12c, 0x7, 0x1, 0x0, 0x0}, - nil, - nil, - nil, - nil, - nil, - nil, - nil, - }, - []*SectionHeader{ - {"__text", "__TEXT", 0x1f68, 0x88, 0xf68, 0x2, 0x0, 0x0, 0x80000400}, - {"__cstring", "__TEXT", 0x1ff0, 0xd, 0xff0, 0x0, 0x0, 0x0, 0x2}, - {"__data", "__DATA", 0x2000, 0x14, 0x1000, 0x2, 0x0, 0x0, 0x0}, - {"__dyld", "__DATA", 0x2014, 0x1c, 0x1014, 0x2, 0x0, 0x0, 0x0}, - {"__jump_table", "__IMPORT", 0x3000, 0xa, 0x2000, 0x6, 0x0, 0x0, 0x4000008}, - }, - }, - { - "testdata/gcc-amd64-darwin-exec", - FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0x2, 0xb, 0x568, 0x85}, - []*SegmentHeader{ - {LoadCmdSegment64, 0x48, "__PAGEZERO", 0x0, 0x100000000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, - {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x1000, 0x7, 0x5, 0x5, 0x0}, - {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x1000, 0x1000, 0x7, 0x3, 0x3, 0x0}, - {LoadCmdSegment64, 0x48, "__LINKEDIT", 0x100002000, 0x1000, 0x2000, 0x140, 0x7, 0x1, 0x0, 0x0}, - nil, - nil, - nil, - nil, - nil, - nil, - nil, - }, - []*SectionHeader{ - {"__text", "__TEXT", 0x100000f14, 0x6d, 0xf14, 0x2, 0x0, 0x0, 0x80000400}, - {"__symbol_stub1", "__TEXT", 0x100000f81, 0xc, 0xf81, 0x0, 0x0, 0x0, 0x80000408}, - {"__stub_helper", "__TEXT", 0x100000f90, 0x18, 0xf90, 0x2, 0x0, 0x0, 0x0}, - {"__cstring", "__TEXT", 0x100000fa8, 0xd, 0xfa8, 0x0, 0x0, 0x0, 0x2}, - {"__eh_frame", "__TEXT", 0x100000fb8, 0x48, 0xfb8, 0x3, 0x0, 0x0, 0x6000000b}, - {"__data", "__DATA", 0x100001000, 0x1c, 0x1000, 0x3, 0x0, 0x0, 0x0}, - {"__dyld", "__DATA", 0x100001020, 0x38, 0x1020, 0x3, 0x0, 0x0, 0x0}, - {"__la_symbol_ptr", "__DATA", 0x100001058, 0x10, 0x1058, 0x2, 0x0, 0x0, 0x7}, - }, - }, - { - "testdata/gcc-amd64-darwin-exec-debug", - FileHeader{0xfeedfacf, CpuAmd64, 0x80000003, 0xa, 0x4, 0x5a0, 0}, - []*SegmentHeader{ - nil, - {LoadCmdSegment64, 0x1d8, "__TEXT", 0x100000000, 0x1000, 0x0, 0x0, 0x7, 0x5, 0x5, 0x0}, - {LoadCmdSegment64, 0x138, "__DATA", 0x100001000, 0x1000, 0x0, 0x0, 0x7, 0x3, 0x3, 0x0}, - {LoadCmdSegment64, 0x278, "__DWARF", 0x100002000, 0x1000, 0x1000, 0x1bc, 0x7, 0x3, 0x7, 0x0}, - }, - []*SectionHeader{ - {"__text", "__TEXT", 0x100000f14, 0x0, 0x0, 0x2, 0x0, 0x0, 0x80000400}, - {"__symbol_stub1", "__TEXT", 0x100000f81, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80000408}, - {"__stub_helper", "__TEXT", 0x100000f90, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0}, - {"__cstring", "__TEXT", 0x100000fa8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2}, - {"__eh_frame", "__TEXT", 0x100000fb8, 0x0, 0x0, 0x3, 0x0, 0x0, 0x6000000b}, - {"__data", "__DATA", 0x100001000, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0}, - {"__dyld", "__DATA", 0x100001020, 0x0, 0x0, 0x3, 0x0, 0x0, 0x0}, - {"__la_symbol_ptr", "__DATA", 0x100001058, 0x0, 0x0, 0x2, 0x0, 0x0, 0x7}, - {"__debug_abbrev", "__DWARF", 0x100002000, 0x36, 0x1000, 0x0, 0x0, 0x0, 0x0}, - {"__debug_aranges", "__DWARF", 0x100002036, 0x30, 0x1036, 0x0, 0x0, 0x0, 0x0}, - {"__debug_frame", "__DWARF", 0x100002066, 0x40, 0x1066, 0x0, 0x0, 0x0, 0x0}, - {"__debug_info", "__DWARF", 0x1000020a6, 0x54, 0x10a6, 0x0, 0x0, 0x0, 0x0}, - {"__debug_line", "__DWARF", 0x1000020fa, 0x47, 0x10fa, 0x0, 0x0, 0x0, 0x0}, - {"__debug_pubnames", "__DWARF", 0x100002141, 0x1b, 0x1141, 0x0, 0x0, 0x0, 0x0}, - {"__debug_str", "__DWARF", 0x10000215c, 0x60, 0x115c, 0x0, 0x0, 0x0, 0x0}, - }, - }, -} - -func TestOpen(t *testing.T) { - for i := range fileTests { - tt := &fileTests[i] - - f, err := Open(tt.file) - if err != nil { - t.Error(err) - continue - } - if !reflect.DeepEqual(f.FileHeader, tt.hdr) { - t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr) - continue - } - for i, l := range f.Loads { - if i >= len(tt.segments) { - break - } - sh := tt.segments[i] - s, ok := l.(*Segment) - if sh == nil { - if ok { - t.Errorf("open %s, section %d: skipping %#v\n", tt.file, i, &s.SegmentHeader) - } - continue - } - if !ok { - t.Errorf("open %s, section %d: not *Segment\n", tt.file, i) - continue - } - have := &s.SegmentHeader - want := sh - if !reflect.DeepEqual(have, want) { - t.Errorf("open %s, segment %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want) - } - } - tn := len(tt.segments) - fn := len(f.Loads) - if tn != fn { - t.Errorf("open %s: len(Loads) = %d, want %d", tt.file, fn, tn) - } - - for i, sh := range f.Sections { - if i >= len(tt.sections) { - break - } - have := &sh.SectionHeader - want := tt.sections[i] - if !reflect.DeepEqual(have, want) { - t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want) - } - } - tn = len(tt.sections) - fn = len(f.Sections) - if tn != fn { - t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn) - } - - } -} - -func TestOpenFailure(t *testing.T) { - filename := "file.go" // not a Mach-O file - _, err := Open(filename) // don't crash - if err == nil { - t.Errorf("open %s: succeeded unexpectedly", filename) - } -} - -func TestOpenFat(t *testing.T) { - ff, err := OpenFat("testdata/fat-gcc-386-amd64-darwin-exec") - if err != nil { - t.Fatal(err) - } - - if ff.Magic != MagicFat { - t.Errorf("OpenFat: got magic number %#x, want %#x", ff.Magic, MagicFat) - } - if len(ff.Arches) != 2 { - t.Errorf("OpenFat: got %d architectures, want 2", len(ff.Arches)) - } - - for i := range ff.Arches { - arch := &ff.Arches[i] - ftArch := &fileTests[i] - - if arch.Cpu != ftArch.hdr.Cpu || arch.SubCpu != ftArch.hdr.SubCpu { - t.Errorf("OpenFat: architecture #%d got cpu=%#x subtype=%#x, expected cpu=%#x, subtype=%#x", i, arch.Cpu, arch.SubCpu, ftArch.hdr.Cpu, ftArch.hdr.SubCpu) - } - - if !reflect.DeepEqual(arch.FileHeader, ftArch.hdr) { - t.Errorf("OpenFat header:\n\tgot %#v\n\twant %#v\n", arch.FileHeader, ftArch.hdr) - } - } -} - -func TestOpenFatFailure(t *testing.T) { - filename := "file.go" // not a Mach-O file - if _, err := OpenFat(filename); err == nil { - t.Errorf("OpenFat %s: succeeded unexpectedly", filename) - } - - filename = "testdata/gcc-386-darwin-exec" // not a fat Mach-O - ff, err := OpenFat(filename) - if err != ErrNotFat { - t.Errorf("OpenFat %s: got %v, want ErrNotFat", filename, err) - } - if ff != nil { - t.Errorf("OpenFat %s: got %v, want nil", filename, ff) - } -} diff --git a/src/pkg/debug/macho/macho.go b/src/pkg/debug/macho/macho.go deleted file mode 100644 index d9678c8ed..000000000 --- a/src/pkg/debug/macho/macho.go +++ /dev/null @@ -1,316 +0,0 @@ -// Copyright 2009 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Mach-O header data structures -// http://developer.apple.com/mac/library/documentation/DeveloperTools/Conceptual/MachORuntime/Reference/reference.html - -package macho - -import "strconv" - -// A FileHeader represents a Mach-O file header. -type FileHeader struct { - Magic uint32 - Cpu Cpu - SubCpu uint32 - Type Type - Ncmd uint32 - Cmdsz uint32 - Flags uint32 -} - -const ( - fileHeaderSize32 = 7 * 4 - fileHeaderSize64 = 8 * 4 -) - -const ( - Magic32 uint32 = 0xfeedface - Magic64 uint32 = 0xfeedfacf - MagicFat uint32 = 0xcafebabe -) - -// A Type is the Mach-O file type, e.g. an object file, executable, or dynamic library. -type Type uint32 - -const ( - TypeObj Type = 1 - TypeExec Type = 2 - TypeDylib Type = 6 - TypeBundle Type = 8 -) - -// A Cpu is a Mach-O cpu type. -type Cpu uint32 - -const cpuArch64 = 0x01000000 - -const ( - Cpu386 Cpu = 7 - CpuAmd64 Cpu = Cpu386 | cpuArch64 - CpuArm Cpu = 12 - CpuPpc Cpu = 18 - CpuPpc64 Cpu = CpuPpc | cpuArch64 -) - -var cpuStrings = []intName{ - {uint32(Cpu386), "Cpu386"}, - {uint32(CpuAmd64), "CpuAmd64"}, - {uint32(CpuArm), "CpuArm"}, - {uint32(CpuPpc), "CpuPpc"}, - {uint32(CpuPpc64), "CpuPpc64"}, -} - -func (i Cpu) String() string { return stringName(uint32(i), cpuStrings, false) } -func (i Cpu) GoString() string { return stringName(uint32(i), cpuStrings, true) } - -// A LoadCmd is a Mach-O load command. -type LoadCmd uint32 - -const ( - LoadCmdSegment LoadCmd = 1 - LoadCmdSymtab LoadCmd = 2 - LoadCmdThread LoadCmd = 4 - LoadCmdUnixThread LoadCmd = 5 // thread+stack - LoadCmdDysymtab LoadCmd = 11 - LoadCmdDylib LoadCmd = 12 - LoadCmdDylinker LoadCmd = 15 - LoadCmdSegment64 LoadCmd = 25 -) - -var cmdStrings = []intName{ - {uint32(LoadCmdSegment), "LoadCmdSegment"}, - {uint32(LoadCmdThread), "LoadCmdThread"}, - {uint32(LoadCmdUnixThread), "LoadCmdUnixThread"}, - {uint32(LoadCmdDylib), "LoadCmdDylib"}, - {uint32(LoadCmdSegment64), "LoadCmdSegment64"}, -} - -func (i LoadCmd) String() string { return stringName(uint32(i), cmdStrings, false) } -func (i LoadCmd) GoString() string { return stringName(uint32(i), cmdStrings, true) } - -// A Segment64 is a 64-bit Mach-O segment load command. -type Segment64 struct { - Cmd LoadCmd - Len uint32 - Name [16]byte - Addr uint64 - Memsz uint64 - Offset uint64 - Filesz uint64 - Maxprot uint32 - Prot uint32 - Nsect uint32 - Flag uint32 -} - -// A Segment32 is a 32-bit Mach-O segment load command. -type Segment32 struct { - Cmd LoadCmd - Len uint32 - Name [16]byte - Addr uint32 - Memsz uint32 - Offset uint32 - Filesz uint32 - Maxprot uint32 - Prot uint32 - Nsect uint32 - Flag uint32 -} - -// A DylibCmd is a Mach-O load dynamic library command. -type DylibCmd struct { - Cmd LoadCmd - Len uint32 - Name uint32 - Time uint32 - CurrentVersion uint32 - CompatVersion uint32 -} - -// A Section32 is a 32-bit Mach-O section header. -type Section32 struct { - Name [16]byte - Seg [16]byte - Addr uint32 - Size uint32 - Offset uint32 - Align uint32 - Reloff uint32 - Nreloc uint32 - Flags uint32 - Reserve1 uint32 - Reserve2 uint32 -} - -// A Section32 is a 64-bit Mach-O section header. -type Section64 struct { - Name [16]byte - Seg [16]byte - Addr uint64 - Size uint64 - Offset uint32 - Align uint32 - Reloff uint32 - Nreloc uint32 - Flags uint32 - Reserve1 uint32 - Reserve2 uint32 - Reserve3 uint32 -} - -// A SymtabCmd is a Mach-O symbol table command. -type SymtabCmd struct { - Cmd LoadCmd - Len uint32 - Symoff uint32 - Nsyms uint32 - Stroff uint32 - Strsize uint32 -} - -// A DysymtabCmd is a Mach-O dynamic symbol table command. -type DysymtabCmd struct { - Cmd LoadCmd - Len uint32 - Ilocalsym uint32 - Nlocalsym uint32 - Iextdefsym uint32 - Nextdefsym uint32 - Iundefsym uint32 - Nundefsym uint32 - Tocoffset uint32 - Ntoc uint32 - Modtaboff uint32 - Nmodtab uint32 - Extrefsymoff uint32 - Nextrefsyms uint32 - Indirectsymoff uint32 - Nindirectsyms uint32 - Extreloff uint32 - Nextrel uint32 - Locreloff uint32 - Nlocrel uint32 -} - -// An Nlist32 is a Mach-O 32-bit symbol table entry. -type Nlist32 struct { - Name uint32 - Type uint8 - Sect uint8 - Desc uint16 - Value uint32 -} - -// An Nlist64 is a Mach-O 64-bit symbol table entry. -type Nlist64 struct { - Name uint32 - Type uint8 - Sect uint8 - Desc uint16 - Value uint64 -} - -// A Symbol is a Mach-O 32-bit or 64-bit symbol table entry. -type Symbol struct { - Name string - Type uint8 - Sect uint8 - Desc uint16 - Value uint64 -} - -// A Thread is a Mach-O thread state command. -type Thread struct { - Cmd LoadCmd - Len uint32 - Type uint32 - Data []uint32 -} - -// Regs386 is the Mach-O 386 register structure. -type Regs386 struct { - AX uint32 - BX uint32 - CX uint32 - DX uint32 - DI uint32 - SI uint32 - BP uint32 - SP uint32 - SS uint32 - FLAGS uint32 - IP uint32 - CS uint32 - DS uint32 - ES uint32 - FS uint32 - GS uint32 -} - -// RegsAMD64 is the Mach-O AMD64 register structure. -type RegsAMD64 struct { - AX uint64 - BX uint64 - CX uint64 - DX uint64 - DI uint64 - SI uint64 - BP uint64 - SP uint64 - R8 uint64 - R9 uint64 - R10 uint64 - R11 uint64 - R12 uint64 - R13 uint64 - R14 uint64 - R15 uint64 - IP uint64 - FLAGS uint64 - CS uint64 - FS uint64 - GS uint64 -} - -type intName struct { - i uint32 - s string -} - -func stringName(i uint32, names []intName, goSyntax bool) string { - for _, n := range names { - if n.i == i { - if goSyntax { - return "macho." + n.s - } - return n.s - } - } - return strconv.FormatUint(uint64(i), 10) -} - -func flagName(i uint32, names []intName, goSyntax bool) string { - s := "" - for _, n := range names { - if n.i&i == n.i { - if len(s) > 0 { - s += "+" - } - if goSyntax { - s += "macho." - } - s += n.s - i -= n.i - } - } - if len(s) == 0 { - return "0x" + strconv.FormatUint(uint64(i), 16) - } - if i != 0 { - s += "+0x" + strconv.FormatUint(uint64(i), 16) - } - return s -} diff --git a/src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec b/src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec Binary files differdeleted file mode 100644 index 7efd19300..000000000 --- a/src/pkg/debug/macho/testdata/fat-gcc-386-amd64-darwin-exec +++ /dev/null diff --git a/src/pkg/debug/macho/testdata/gcc-386-darwin-exec b/src/pkg/debug/macho/testdata/gcc-386-darwin-exec Binary files differdeleted file mode 100755 index 03ba1bafa..000000000 --- a/src/pkg/debug/macho/testdata/gcc-386-darwin-exec +++ /dev/null diff --git a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec b/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec Binary files differdeleted file mode 100755 index 5155a5a26..000000000 --- a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec +++ /dev/null diff --git a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug b/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug Binary files differdeleted file mode 100644 index a47d3aef7..000000000 --- a/src/pkg/debug/macho/testdata/gcc-amd64-darwin-exec-debug +++ /dev/null diff --git a/src/pkg/debug/macho/testdata/hello.c b/src/pkg/debug/macho/testdata/hello.c deleted file mode 100644 index a689d3644..000000000 --- a/src/pkg/debug/macho/testdata/hello.c +++ /dev/null @@ -1,8 +0,0 @@ -#include <stdio.h> - -int -main(void) -{ - printf("hello, world\n"); - return 0; -} |