summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/google/gops/internal/objfile
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/google/gops/internal/objfile')
-rw-r--r--vendor/github.com/google/gops/internal/objfile/disasm.go283
-rw-r--r--vendor/github.com/google/gops/internal/objfile/elf.go124
-rw-r--r--vendor/github.com/google/gops/internal/objfile/goobj.go160
-rw-r--r--vendor/github.com/google/gops/internal/objfile/macho.go134
-rw-r--r--vendor/github.com/google/gops/internal/objfile/objfile.go129
-rw-r--r--vendor/github.com/google/gops/internal/objfile/pe.go208
-rw-r--r--vendor/github.com/google/gops/internal/objfile/plan9obj.go156
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")
-}