diff options
Diffstat (limited to 'vendor/github.com/google/gops/internal/objfile')
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/disasm.go | 283 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/elf.go | 124 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/goobj.go | 160 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/macho.go | 134 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/objfile.go | 129 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/pe.go | 208 | ||||
-rw-r--r-- | vendor/github.com/google/gops/internal/objfile/plan9obj.go | 156 |
7 files changed, 0 insertions, 1194 deletions
diff --git a/vendor/github.com/google/gops/internal/objfile/disasm.go b/vendor/github.com/google/gops/internal/objfile/disasm.go deleted file mode 100644 index 8af0c8f8..00000000 --- a/vendor/github.com/google/gops/internal/objfile/disasm.go +++ /dev/null @@ -1,283 +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 objfile - -import ( - "bufio" - "debug/gosym" - "encoding/binary" - "fmt" - "io" - "regexp" - "sort" - "strings" - "text/tabwriter" - - "golang.org/x/arch/arm/armasm" - "golang.org/x/arch/ppc64/ppc64asm" - "golang.org/x/arch/x86/x86asm" -) - -// Disasm is a disassembler for a given File. -type Disasm struct { - syms []Sym //symbols in file, sorted by address - pcln Liner // pcln table - text []byte // bytes of text segment (actual instructions) - textStart uint64 // start PC of text - textEnd uint64 // end PC of text - goarch string // GOARCH string - disasm disasmFunc // disassembler function for goarch - byteOrder binary.ByteOrder // byte order for goarch -} - -// Disasm returns a disassembler for the file f. -func (f *File) Disasm() (*Disasm, error) { - syms, err := f.Symbols() - if err != nil { - return nil, err - } - - pcln, err := f.PCLineTable() - if err != nil { - return nil, err - } - - textStart, textBytes, err := f.Text() - if err != nil { - return nil, err - } - - goarch := f.GOARCH() - disasm := disasms[goarch] - byteOrder := byteOrders[goarch] - if disasm == nil || byteOrder == nil { - return nil, fmt.Errorf("unsupported architecture") - } - - // Filter out section symbols, overwriting syms in place. - keep := syms[:0] - for _, sym := range syms { - switch sym.Name { - case "runtime.text", "text", "_text", "runtime.etext", "etext", "_etext": - // drop - default: - keep = append(keep, sym) - } - } - syms = keep - d := &Disasm{ - syms: syms, - pcln: pcln, - text: textBytes, - textStart: textStart, - textEnd: textStart + uint64(len(textBytes)), - goarch: goarch, - disasm: disasm, - byteOrder: byteOrder, - } - - return d, nil -} - -// lookup finds the symbol name containing addr. -func (d *Disasm) lookup(addr uint64) (name string, base uint64) { - i := sort.Search(len(d.syms), func(i int) bool { return addr < d.syms[i].Addr }) - if i > 0 { - s := d.syms[i-1] - if s.Addr != 0 && s.Addr <= addr && addr < s.Addr+uint64(s.Size) { - return s.Name, s.Addr - } - } - return "", 0 -} - -// base returns the final element in the path. -// It works on both Windows and Unix paths, -// regardless of host operating system. -func base(path string) string { - path = path[strings.LastIndex(path, "/")+1:] - path = path[strings.LastIndex(path, `\`)+1:] - return path -} - -// Print prints a disassembly of the file to w. -// If filter is non-nil, the disassembly only includes functions with names matching filter. -// The disassembly only includes functions that overlap the range [start, end). -func (d *Disasm) Print(w io.Writer, filter *regexp.Regexp, start, end uint64) { - if start < d.textStart { - start = d.textStart - } - if end > d.textEnd { - end = d.textEnd - } - printed := false - bw := bufio.NewWriter(w) - for _, sym := range d.syms { - symStart := sym.Addr - symEnd := sym.Addr + uint64(sym.Size) - relocs := sym.Relocs - if sym.Code != 'T' && sym.Code != 't' || - symStart < d.textStart || - symEnd <= start || end <= symStart || - filter != nil && !filter.MatchString(sym.Name) { - continue - } - if printed { - fmt.Fprintf(bw, "\n") - } - printed = true - - file, _, _ := d.pcln.PCToLine(sym.Addr) - fmt.Fprintf(bw, "TEXT %s(SB) %s\n", sym.Name, file) - - tw := tabwriter.NewWriter(bw, 1, 8, 1, '\t', 0) - if symEnd > end { - symEnd = end - } - code := d.text[:end-d.textStart] - d.Decode(symStart, symEnd, relocs, func(pc, size uint64, file string, line int, text string) { - i := pc - d.textStart - fmt.Fprintf(tw, "\t%s:%d\t%#x\t", base(file), line, pc) - if size%4 != 0 || d.goarch == "386" || d.goarch == "amd64" { - // Print instruction as bytes. - fmt.Fprintf(tw, "%x", code[i:i+size]) - } else { - // Print instruction as 32-bit words. - for j := uint64(0); j < size; j += 4 { - if j > 0 { - fmt.Fprintf(tw, " ") - } - fmt.Fprintf(tw, "%08x", d.byteOrder.Uint32(code[i+j:])) - } - } - fmt.Fprintf(tw, "\t%s\n", text) - }) - tw.Flush() - } - bw.Flush() -} - -// Decode disassembles the text segment range [start, end), calling f for each instruction. -func (d *Disasm) Decode(start, end uint64, relocs []Reloc, f func(pc, size uint64, file string, line int, text string)) { - if start < d.textStart { - start = d.textStart - } - if end > d.textEnd { - end = d.textEnd - } - code := d.text[:end-d.textStart] - lookup := d.lookup - for pc := start; pc < end; { - i := pc - d.textStart - text, size := d.disasm(code[i:], pc, lookup, d.byteOrder) - file, line, _ := d.pcln.PCToLine(pc) - text += "\t" - first := true - for len(relocs) > 0 && relocs[0].Addr < i+uint64(size) { - if first { - first = false - } else { - text += " " - } - text += relocs[0].Stringer.String(pc - start) - relocs = relocs[1:] - } - f(pc, uint64(size), file, line, text) - pc += uint64(size) - } -} - -type lookupFunc func(addr uint64) (sym string, base uint64) -type disasmFunc func(code []byte, pc uint64, lookup lookupFunc, ord binary.ByteOrder) (text string, size int) - -func disasm_386(code []byte, pc uint64, lookup lookupFunc, _ binary.ByteOrder) (string, int) { - return disasm_x86(code, pc, lookup, 32) -} - -func disasm_amd64(code []byte, pc uint64, lookup lookupFunc, _ binary.ByteOrder) (string, int) { - return disasm_x86(code, pc, lookup, 64) -} - -func disasm_x86(code []byte, pc uint64, lookup lookupFunc, arch int) (string, int) { - inst, err := x86asm.Decode(code, 64) - var text string - size := inst.Len - if err != nil || size == 0 || inst.Op == 0 { - size = 1 - text = "?" - } else { - text = x86asm.GoSyntax(inst, pc, lookup) - } - return text, size -} - -type textReader struct { - code []byte - pc uint64 -} - -func (r textReader) ReadAt(data []byte, off int64) (n int, err error) { - if off < 0 || uint64(off) < r.pc { - return 0, io.EOF - } - d := uint64(off) - r.pc - if d >= uint64(len(r.code)) { - return 0, io.EOF - } - n = copy(data, r.code[d:]) - if n < len(data) { - err = io.ErrUnexpectedEOF - } - return -} - -func disasm_arm(code []byte, pc uint64, lookup lookupFunc, _ binary.ByteOrder) (string, int) { - inst, err := armasm.Decode(code, armasm.ModeARM) - var text string - size := inst.Len - if err != nil || size == 0 || inst.Op == 0 { - size = 4 - text = "?" - } else { - text = armasm.GoSyntax(inst, pc, lookup, textReader{code, pc}) - } - return text, size -} - -func disasm_ppc64(code []byte, pc uint64, lookup lookupFunc, byteOrder binary.ByteOrder) (string, int) { - inst, err := ppc64asm.Decode(code, byteOrder) - var text string - size := inst.Len - if err != nil || size == 0 || inst.Op == 0 { - size = 4 - text = "?" - } else { - text = ppc64asm.GoSyntax(inst, pc, lookup) - } - return text, size -} - -var disasms = map[string]disasmFunc{ - "386": disasm_386, - "amd64": disasm_amd64, - "arm": disasm_arm, - "ppc64": disasm_ppc64, - "ppc64le": disasm_ppc64, -} - -var byteOrders = map[string]binary.ByteOrder{ - "386": binary.LittleEndian, - "amd64": binary.LittleEndian, - "arm": binary.LittleEndian, - "ppc64": binary.BigEndian, - "ppc64le": binary.LittleEndian, - "s390x": binary.BigEndian, -} - -type Liner interface { - // Given a pc, returns the corresponding file, line, and function data. - // If unknown, returns "",0,nil. - PCToLine(uint64) (string, int, *gosym.Func) -} diff --git a/vendor/github.com/google/gops/internal/objfile/elf.go b/vendor/github.com/google/gops/internal/objfile/elf.go deleted file mode 100644 index 4ab7e6de..00000000 --- a/vendor/github.com/google/gops/internal/objfile/elf.go +++ /dev/null @@ -1,124 +0,0 @@ -// Copyright 2013 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. - -// Parsing of ELF executables (Linux, FreeBSD, and so on). - -package objfile - -import ( - "debug/dwarf" - "debug/elf" - "encoding/binary" - "fmt" - "os" -) - -type elfFile struct { - elf *elf.File -} - -func openElf(r *os.File) (rawFile, error) { - f, err := elf.NewFile(r) - if err != nil { - return nil, err - } - return &elfFile{f}, nil -} - -func (f *elfFile) symbols() ([]Sym, error) { - elfSyms, err := f.elf.Symbols() - if err != nil { - return nil, err - } - - var syms []Sym - for _, s := range elfSyms { - sym := Sym{Addr: s.Value, Name: s.Name, Size: int64(s.Size), Code: '?'} - switch s.Section { - case elf.SHN_UNDEF: - sym.Code = 'U' - case elf.SHN_COMMON: - sym.Code = 'B' - default: - i := int(s.Section) - if i < 0 || i >= len(f.elf.Sections) { - break - } - sect := f.elf.Sections[i] - switch sect.Flags & (elf.SHF_WRITE | elf.SHF_ALLOC | elf.SHF_EXECINSTR) { - case elf.SHF_ALLOC | elf.SHF_EXECINSTR: - sym.Code = 'T' - case elf.SHF_ALLOC: - sym.Code = 'R' - case elf.SHF_ALLOC | elf.SHF_WRITE: - sym.Code = 'D' - } - } - if elf.ST_BIND(s.Info) == elf.STB_LOCAL { - sym.Code += 'a' - 'A' - } - syms = append(syms, sym) - } - - return syms, nil -} - -func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { - if sect := f.elf.Section(".text"); sect != nil { - textStart = sect.Addr - } - if sect := f.elf.Section(".gosymtab"); sect != nil { - if symtab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - if sect := f.elf.Section(".gopclntab"); sect != nil { - if pclntab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil -} - -func (f *elfFile) text() (textStart uint64, text []byte, err error) { - sect := f.elf.Section(".text") - if sect == nil { - return 0, nil, fmt.Errorf("text section not found") - } - textStart = sect.Addr - text, err = sect.Data() - return -} - -func (f *elfFile) goarch() string { - switch f.elf.Machine { - case elf.EM_386: - return "386" - case elf.EM_X86_64: - return "amd64" - case elf.EM_ARM: - return "arm" - case elf.EM_PPC64: - if f.elf.ByteOrder == binary.LittleEndian { - return "ppc64le" - } - return "ppc64" - case elf.EM_S390: - return "s390x" - } - return "" -} - -func (f *elfFile) loadAddress() (uint64, error) { - for _, p := range f.elf.Progs { - if p.Type == elf.PT_LOAD { - return p.Vaddr, nil - } - } - return 0, fmt.Errorf("unknown load address") -} - -func (f *elfFile) dwarf() (*dwarf.Data, error) { - return f.elf.DWARF() -} diff --git a/vendor/github.com/google/gops/internal/objfile/goobj.go b/vendor/github.com/google/gops/internal/objfile/goobj.go deleted file mode 100644 index 5a8ec53d..00000000 --- a/vendor/github.com/google/gops/internal/objfile/goobj.go +++ /dev/null @@ -1,160 +0,0 @@ -// Copyright 2013 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. - -// Parsing of Go intermediate object files and archives. - -package objfile - -/* - - -import ( - "debug/dwarf" - "debug/gosym" - "errors" - "fmt" - "os" - - "github.com/google/gops/internal/sys" - - "github.com/google/gops/internal/goobj" -) - -type goobjFile struct { - goobj *goobj.Package - f *os.File // the underlying .o or .a file -} - -func openGoobj(r *os.File) (rawFile, error) { - f, err := goobj.Parse(r, `""`) - if err != nil { - return nil, err - } - return &goobjFile{goobj: f, f: r}, nil -} - -func goobjName(id goobj.SymID) string { - if id.Version == 0 { - return id.Name - } - return fmt.Sprintf("%s<%d>", id.Name, id.Version) -} - -func (f *goobjFile) symbols() ([]Sym, error) { - seen := make(map[goobj.SymID]bool) - - var syms []Sym - for _, s := range f.goobj.Syms { - seen[s.SymID] = true - sym := Sym{Addr: uint64(s.Data.Offset), Name: goobjName(s.SymID), Size: int64(s.Size), Type: s.Type.Name, Code: '?'} - switch s.Kind { - case goobj.STEXT, goobj.SELFRXSECT: - sym.Code = 'T' - case goobj.STYPE, goobj.SSTRING, goobj.SGOSTRING, goobj.SGOFUNC, goobj.SRODATA, goobj.SFUNCTAB, goobj.STYPELINK, goobj.SITABLINK, goobj.SSYMTAB, goobj.SPCLNTAB, goobj.SELFROSECT: - sym.Code = 'R' - case goobj.SMACHOPLT, goobj.SELFSECT, goobj.SMACHO, goobj.SMACHOGOT, goobj.SNOPTRDATA, goobj.SINITARR, goobj.SDATA, goobj.SWINDOWS: - sym.Code = 'D' - case goobj.SBSS, goobj.SNOPTRBSS, goobj.STLSBSS: - sym.Code = 'B' - case goobj.SXREF, goobj.SMACHOSYMSTR, goobj.SMACHOSYMTAB, goobj.SMACHOINDIRECTPLT, goobj.SMACHOINDIRECTGOT, goobj.SFILE, goobj.SFILEPATH, goobj.SCONST, goobj.SDYNIMPORT, goobj.SHOSTOBJ: - sym.Code = 'X' // should not see - } - if s.Version != 0 { - sym.Code += 'a' - 'A' - } - for i, r := range s.Reloc { - sym.Relocs = append(sym.Relocs, Reloc{Addr: uint64(s.Data.Offset) + uint64(r.Offset), Size: uint64(r.Size), Stringer: &s.Reloc[i]}) - } - syms = append(syms, sym) - } - - for _, s := range f.goobj.Syms { - for _, r := range s.Reloc { - if !seen[r.Sym] { - seen[r.Sym] = true - sym := Sym{Name: goobjName(r.Sym), Code: 'U'} - if s.Version != 0 { - // should not happen but handle anyway - sym.Code = 'u' - } - syms = append(syms, sym) - } - } - } - - return syms, nil -} - -func (f *goobjFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { - // Should never be called. We implement Liner below, callers - // should use that instead. - return 0, nil, nil, fmt.Errorf("pcln not available in go object file") -} - -// Find returns the file name, line, and function data for the given pc. -// Returns "",0,nil if unknown. -// This function implements the Liner interface in preference to pcln() above. -func (f *goobjFile) PCToLine(pc uint64) (string, int, *gosym.Func) { - // TODO: this is really inefficient. Binary search? Memoize last result? - var arch *sys.Arch - for _, a := range sys.Archs { - if a.Name == f.goobj.Arch { - arch = a - break - } - } - if arch == nil { - return "", 0, nil - } - for _, s := range f.goobj.Syms { - if pc < uint64(s.Data.Offset) || pc >= uint64(s.Data.Offset+s.Data.Size) { - continue - } - if s.Func == nil { - return "", 0, nil - } - pcfile := make([]byte, s.Func.PCFile.Size) - _, err := f.f.ReadAt(pcfile, s.Func.PCFile.Offset) - if err != nil { - return "", 0, nil - } - fileID := gosym.PCValue(pcfile, pc-uint64(s.Data.Offset), arch.MinLC) - fileName := s.Func.File[fileID] - pcline := make([]byte, s.Func.PCLine.Size) - _, err = f.f.ReadAt(pcline, s.Func.PCLine.Offset) - if err != nil { - return "", 0, nil - } - line := gosym.PCValue(pcline, pc-uint64(s.Data.Offset), arch.MinLC) - // Note: we provide only the name in the Func structure. - // We could provide more if needed. - return fileName, line, &gosym.Func{Sym: &gosym.Sym{Name: s.Name}} - } - return "", 0, nil -} - -// We treat the whole object file as the text section. -func (f *goobjFile) text() (textStart uint64, text []byte, err error) { - var info os.FileInfo - info, err = f.f.Stat() - if err != nil { - return - } - text = make([]byte, info.Size()) - _, err = f.f.ReadAt(text, 0) - return -} - -func (f *goobjFile) goarch() string { - return f.goobj.Arch -} - -func (f *goobjFile) loadAddress() (uint64, error) { - return 0, fmt.Errorf("unknown load address") -} - -func (f *goobjFile) dwarf() (*dwarf.Data, error) { - return nil, errors.New("no DWARF data in go object file") -} -*/ diff --git a/vendor/github.com/google/gops/internal/objfile/macho.go b/vendor/github.com/google/gops/internal/objfile/macho.go deleted file mode 100644 index 1d22a09b..00000000 --- a/vendor/github.com/google/gops/internal/objfile/macho.go +++ /dev/null @@ -1,134 +0,0 @@ -// Copyright 2013 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. - -// Parsing of Mach-O executables (OS X). - -package objfile - -import ( - "debug/dwarf" - "debug/macho" - "fmt" - "os" - "sort" -) - -const stabTypeMask = 0xe0 - -type machoFile struct { - macho *macho.File -} - -func openMacho(r *os.File) (rawFile, error) { - f, err := macho.NewFile(r) - if err != nil { - return nil, err - } - return &machoFile{f}, nil -} - -func (f *machoFile) symbols() ([]Sym, error) { - if f.macho.Symtab == nil { - return nil, fmt.Errorf("missing symbol table") - } - - // Build sorted list of addresses of all symbols. - // We infer the size of a symbol by looking at where the next symbol begins. - var addrs []uint64 - for _, s := range f.macho.Symtab.Syms { - // Skip stab debug info. - if s.Type&stabTypeMask == 0 { - addrs = append(addrs, s.Value) - } - } - sort.Sort(uint64s(addrs)) - - var syms []Sym - for _, s := range f.macho.Symtab.Syms { - if s.Type&stabTypeMask != 0 { - // Skip stab debug info. - continue - } - sym := Sym{Name: s.Name, Addr: s.Value, Code: '?'} - i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) - if i < len(addrs) { - sym.Size = int64(addrs[i] - s.Value) - } - if s.Sect == 0 { - sym.Code = 'U' - } else if int(s.Sect) <= len(f.macho.Sections) { - sect := f.macho.Sections[s.Sect-1] - switch sect.Seg { - case "__TEXT": - sym.Code = 'R' - case "__DATA": - sym.Code = 'D' - } - switch sect.Seg + " " + sect.Name { - case "__TEXT __text": - sym.Code = 'T' - case "__DATA __bss", "__DATA __noptrbss": - sym.Code = 'B' - } - } - syms = append(syms, sym) - } - - return syms, nil -} - -func (f *machoFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { - if sect := f.macho.Section("__text"); sect != nil { - textStart = sect.Addr - } - if sect := f.macho.Section("__gosymtab"); sect != nil { - if symtab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - if sect := f.macho.Section("__gopclntab"); sect != nil { - if pclntab, err = sect.Data(); err != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil -} - -func (f *machoFile) text() (textStart uint64, text []byte, err error) { - sect := f.macho.Section("__text") - if sect == nil { - return 0, nil, fmt.Errorf("text section not found") - } - textStart = sect.Addr - text, err = sect.Data() - return -} - -func (f *machoFile) goarch() string { - switch f.macho.Cpu { - case macho.Cpu386: - return "386" - case macho.CpuAmd64: - return "amd64" - case macho.CpuArm: - return "arm" - case macho.CpuPpc64: - return "ppc64" - } - return "" -} - -type uint64s []uint64 - -func (x uint64s) Len() int { return len(x) } -func (x uint64s) Swap(i, j int) { x[i], x[j] = x[j], x[i] } -func (x uint64s) Less(i, j int) bool { return x[i] < x[j] } - -func (f *machoFile) loadAddress() (uint64, error) { - return 0, fmt.Errorf("unknown load address") -} - -func (f *machoFile) dwarf() (*dwarf.Data, error) { - return f.macho.DWARF() -} diff --git a/vendor/github.com/google/gops/internal/objfile/objfile.go b/vendor/github.com/google/gops/internal/objfile/objfile.go deleted file mode 100644 index a884a20d..00000000 --- a/vendor/github.com/google/gops/internal/objfile/objfile.go +++ /dev/null @@ -1,129 +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 objfile implements portable access to OS-specific executable files. -package objfile - -import ( - "debug/dwarf" - "debug/gosym" - "fmt" - "os" - "sort" -) - -type rawFile interface { - symbols() (syms []Sym, err error) - pcln() (textStart uint64, symtab, pclntab []byte, err error) - text() (textStart uint64, text []byte, err error) - goarch() string - loadAddress() (uint64, error) - dwarf() (*dwarf.Data, error) -} - -// A File is an opened executable file. -type File struct { - r *os.File - raw rawFile -} - -// A Sym is a symbol defined in an executable file. -type Sym struct { - Name string // symbol name - Addr uint64 // virtual address of symbol - Size int64 // size in bytes - Code rune // nm code (T for text, D for data, and so on) - Type string // XXX? - Relocs []Reloc // in increasing Addr order -} - -type Reloc struct { - Addr uint64 // Address of first byte that reloc applies to. - Size uint64 // Number of bytes - Stringer RelocStringer -} - -type RelocStringer interface { - // insnOffset is the offset of the instruction containing the relocation - // from the start of the symbol containing the relocation. - String(insnOffset uint64) string -} - -var openers = []func(*os.File) (rawFile, error){ - openElf, - // openGoobj, // TODO(jbd): Bring it back when 1.8 is popular. - openMacho, - openPE, - openPlan9, -} - -// Open opens the named file. -// The caller must call f.Close when the file is no longer needed. -func Open(name string) (*File, error) { - r, err := os.Open(name) - if err != nil { - return nil, err - } - for _, try := range openers { - if raw, err := try(r); err == nil { - return &File{r, raw}, nil - } - } - r.Close() - return nil, fmt.Errorf("open %s: unrecognized object file", name) -} - -func (f *File) Close() error { - return f.r.Close() -} - -func (f *File) Symbols() ([]Sym, error) { - syms, err := f.raw.symbols() - if err != nil { - return nil, err - } - sort.Sort(byAddr(syms)) - return syms, nil -} - -type byAddr []Sym - -func (x byAddr) Less(i, j int) bool { return x[i].Addr < x[j].Addr } -func (x byAddr) Len() int { return len(x) } -func (x byAddr) Swap(i, j int) { x[i], x[j] = x[j], x[i] } - -func (f *File) PCLineTable() (Liner, error) { - // If the raw file implements Liner directly, use that. - // Currently, only Go intermediate objects and archives (goobj) use this path. - if pcln, ok := f.raw.(Liner); ok { - return pcln, nil - } - // Otherwise, read the pcln tables and build a Liner out of that. - textStart, symtab, pclntab, err := f.raw.pcln() - if err != nil { - return nil, err - } - return gosym.NewTable(symtab, gosym.NewLineTable(pclntab, textStart)) -} - -func (f *File) Text() (uint64, []byte, error) { - return f.raw.text() -} - -func (f *File) GOARCH() string { - return f.raw.goarch() -} - -// LoadAddress returns the expected load address of the file. -// This differs from the actual load address for a position-independent -// executable. -func (f *File) LoadAddress() (uint64, error) { - return f.raw.loadAddress() -} - -// DWARF returns DWARF debug data for the file, if any. -// This is for cmd/pprof to locate cgo functions. -func (f *File) DWARF() (*dwarf.Data, error) { - return f.raw.dwarf() -} diff --git a/vendor/github.com/google/gops/internal/objfile/pe.go b/vendor/github.com/google/gops/internal/objfile/pe.go deleted file mode 100644 index 46b23172..00000000 --- a/vendor/github.com/google/gops/internal/objfile/pe.go +++ /dev/null @@ -1,208 +0,0 @@ -// Copyright 2013 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. - -// Parsing of PE executables (Microsoft Windows). - -package objfile - -import ( - "debug/dwarf" - "debug/pe" - "fmt" - "os" - "sort" -) - -type peFile struct { - pe *pe.File -} - -func openPE(r *os.File) (rawFile, error) { - f, err := pe.NewFile(r) - if err != nil { - return nil, err - } - switch f.OptionalHeader.(type) { - case *pe.OptionalHeader32, *pe.OptionalHeader64: - // ok - default: - return nil, fmt.Errorf("unrecognized PE format") - } - return &peFile{f}, nil -} - -func (f *peFile) symbols() ([]Sym, error) { - // Build sorted list of addresses of all symbols. - // We infer the size of a symbol by looking at where the next symbol begins. - var addrs []uint64 - - var imageBase uint64 - switch oh := f.pe.OptionalHeader.(type) { - case *pe.OptionalHeader32: - imageBase = uint64(oh.ImageBase) - case *pe.OptionalHeader64: - imageBase = oh.ImageBase - } - - var syms []Sym - for _, s := range f.pe.Symbols { - const ( - N_UNDEF = 0 // An undefined (extern) symbol - N_ABS = -1 // An absolute symbol (e_value is a constant, not an address) - N_DEBUG = -2 // A debugging symbol - ) - sym := Sym{Name: s.Name, Addr: uint64(s.Value), Code: '?'} - switch s.SectionNumber { - case N_UNDEF: - sym.Code = 'U' - case N_ABS: - sym.Code = 'C' - case N_DEBUG: - sym.Code = '?' - default: - if s.SectionNumber < 0 || len(f.pe.Sections) < int(s.SectionNumber) { - return nil, fmt.Errorf("invalid section number in symbol table") - } - sect := f.pe.Sections[s.SectionNumber-1] - const ( - text = 0x20 - data = 0x40 - bss = 0x80 - permW = 0x80000000 - ) - ch := sect.Characteristics - switch { - case ch&text != 0: - sym.Code = 'T' - case ch&data != 0: - if ch&permW == 0 { - sym.Code = 'R' - } else { - sym.Code = 'D' - } - case ch&bss != 0: - sym.Code = 'B' - } - sym.Addr += imageBase + uint64(sect.VirtualAddress) - } - syms = append(syms, sym) - addrs = append(addrs, sym.Addr) - } - - sort.Sort(uint64s(addrs)) - for i := range syms { - j := sort.Search(len(addrs), func(x int) bool { return addrs[x] > syms[i].Addr }) - if j < len(addrs) { - syms[i].Size = int64(addrs[j] - syms[i].Addr) - } - } - - return syms, nil -} - -func (f *peFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { - var imageBase uint64 - switch oh := f.pe.OptionalHeader.(type) { - case *pe.OptionalHeader32: - imageBase = uint64(oh.ImageBase) - case *pe.OptionalHeader64: - imageBase = oh.ImageBase - default: - return 0, nil, nil, fmt.Errorf("pe file format not recognized") - } - if sect := f.pe.Section(".text"); sect != nil { - textStart = imageBase + uint64(sect.VirtualAddress) - } - if pclntab, err = loadPETable(f.pe, "runtime.pclntab", "runtime.epclntab"); err != nil { - // We didn't find the symbols, so look for the names used in 1.3 and earlier. - // TODO: Remove code looking for the old symbols when we no longer care about 1.3. - var err2 error - if pclntab, err2 = loadPETable(f.pe, "pclntab", "epclntab"); err2 != nil { - return 0, nil, nil, err - } - } - if symtab, err = loadPETable(f.pe, "runtime.symtab", "runtime.esymtab"); err != nil { - // Same as above. - var err2 error - if symtab, err2 = loadPETable(f.pe, "symtab", "esymtab"); err2 != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil -} - -func (f *peFile) text() (textStart uint64, text []byte, err error) { - var imageBase uint64 - switch oh := f.pe.OptionalHeader.(type) { - case *pe.OptionalHeader32: - imageBase = uint64(oh.ImageBase) - case *pe.OptionalHeader64: - imageBase = oh.ImageBase - default: - return 0, nil, fmt.Errorf("pe file format not recognized") - } - sect := f.pe.Section(".text") - if sect == nil { - return 0, nil, fmt.Errorf("text section not found") - } - textStart = imageBase + uint64(sect.VirtualAddress) - text, err = sect.Data() - return -} - -func findPESymbol(f *pe.File, name string) (*pe.Symbol, error) { - for _, s := range f.Symbols { - if s.Name != name { - continue - } - if s.SectionNumber <= 0 { - return nil, fmt.Errorf("symbol %s: invalid section number %d", name, s.SectionNumber) - } - if len(f.Sections) < int(s.SectionNumber) { - return nil, fmt.Errorf("symbol %s: section number %d is larger than max %d", name, s.SectionNumber, len(f.Sections)) - } - return s, nil - } - return nil, fmt.Errorf("no %s symbol found", name) -} - -func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { - ssym, err := findPESymbol(f, sname) - if err != nil { - return nil, err - } - esym, err := findPESymbol(f, ename) - if err != nil { - return nil, err - } - if ssym.SectionNumber != esym.SectionNumber { - return nil, fmt.Errorf("%s and %s symbols must be in the same section", sname, ename) - } - sect := f.Sections[ssym.SectionNumber-1] - data, err := sect.Data() - if err != nil { - return nil, err - } - return data[ssym.Value:esym.Value], nil -} - -func (f *peFile) goarch() string { - // Not sure how to get the info we want from PE header. - // Look in symbol table for telltale rt0 symbol. - if _, err := findPESymbol(f.pe, "_rt0_386_windows"); err == nil { - return "386" - } - if _, err := findPESymbol(f.pe, "_rt0_amd64_windows"); err == nil { - return "amd64" - } - return "" -} - -func (f *peFile) loadAddress() (uint64, error) { - return 0, fmt.Errorf("unknown load address") -} - -func (f *peFile) dwarf() (*dwarf.Data, error) { - return f.pe.DWARF() -} diff --git a/vendor/github.com/google/gops/internal/objfile/plan9obj.go b/vendor/github.com/google/gops/internal/objfile/plan9obj.go deleted file mode 100644 index 3e34f65a..00000000 --- a/vendor/github.com/google/gops/internal/objfile/plan9obj.go +++ /dev/null @@ -1,156 +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. - -// Parsing of Plan 9 a.out executables. - -package objfile - -import ( - "debug/dwarf" - "debug/plan9obj" - "errors" - "fmt" - "os" - "sort" -) - -var validSymType = map[rune]bool{ - 'T': true, - 't': true, - 'D': true, - 'd': true, - 'B': true, - 'b': true, -} - -type plan9File struct { - plan9 *plan9obj.File -} - -func openPlan9(r *os.File) (rawFile, error) { - f, err := plan9obj.NewFile(r) - if err != nil { - return nil, err - } - return &plan9File{f}, nil -} - -func (f *plan9File) symbols() ([]Sym, error) { - plan9Syms, err := f.plan9.Symbols() - if err != nil { - return nil, err - } - - // Build sorted list of addresses of all symbols. - // We infer the size of a symbol by looking at where the next symbol begins. - var addrs []uint64 - for _, s := range plan9Syms { - if !validSymType[s.Type] { - continue - } - addrs = append(addrs, s.Value) - } - sort.Sort(uint64s(addrs)) - - var syms []Sym - - for _, s := range plan9Syms { - if !validSymType[s.Type] { - continue - } - sym := Sym{Addr: s.Value, Name: s.Name, Code: s.Type} - i := sort.Search(len(addrs), func(x int) bool { return addrs[x] > s.Value }) - if i < len(addrs) { - sym.Size = int64(addrs[i] - s.Value) - } - syms = append(syms, sym) - } - - return syms, nil -} - -func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) { - textStart = f.plan9.LoadAddress + f.plan9.HdrSize - if pclntab, err = loadPlan9Table(f.plan9, "runtime.pclntab", "runtime.epclntab"); err != nil { - // We didn't find the symbols, so look for the names used in 1.3 and earlier. - // TODO: Remove code looking for the old symbols when we no longer care about 1.3. - var err2 error - if pclntab, err2 = loadPlan9Table(f.plan9, "pclntab", "epclntab"); err2 != nil { - return 0, nil, nil, err - } - } - if symtab, err = loadPlan9Table(f.plan9, "runtime.symtab", "runtime.esymtab"); err != nil { - // Same as above. - var err2 error - if symtab, err2 = loadPlan9Table(f.plan9, "symtab", "esymtab"); err2 != nil { - return 0, nil, nil, err - } - } - return textStart, symtab, pclntab, nil -} - -func (f *plan9File) text() (textStart uint64, text []byte, err error) { - sect := f.plan9.Section("text") - if sect == nil { - return 0, nil, fmt.Errorf("text section not found") - } - textStart = f.plan9.LoadAddress + f.plan9.HdrSize - text, err = sect.Data() - return -} - -func findPlan9Symbol(f *plan9obj.File, name string) (*plan9obj.Sym, error) { - syms, err := f.Symbols() - if err != nil { - return nil, err - } - for _, s := range syms { - if s.Name != name { - continue - } - return &s, nil - } - return nil, fmt.Errorf("no %s symbol found", name) -} - -func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { - ssym, err := findPlan9Symbol(f, sname) - if err != nil { - return nil, err - } - esym, err := findPlan9Symbol(f, ename) - if err != nil { - return nil, err - } - sect := f.Section("text") - if sect == nil { - return nil, err - } - data, err := sect.Data() - if err != nil { - return nil, err - } - textStart := f.LoadAddress + f.HdrSize - return data[ssym.Value-textStart : esym.Value-textStart], nil -} - -func (f *plan9File) goarch() string { - switch f.plan9.Magic { - case plan9obj.Magic386: - return "386" - case plan9obj.MagicAMD64: - return "amd64" - case plan9obj.MagicARM: - return "arm" - } - return "" -} - -func (f *plan9File) loadAddress() (uint64, error) { - return 0, fmt.Errorf("unknown load address") -} - -func (f *plan9File) dwarf() (*dwarf.Data, error) { - return nil, errors.New("no DWARF data in Plan 9 file") -} |