diff options
author | Russ Cox <rsc@golang.org> | 2014-10-29 18:07:24 -0400 |
---|---|---|
committer | Russ Cox <rsc@golang.org> | 2014-10-29 18:07:24 -0400 |
commit | 7c37155e4f8fedaff6857cf9ddf74878500b3324 (patch) | |
tree | 4f430a02836821dbffdabb8a38c4b7dd674b0280 /src/cmd/internal | |
parent | 1cba7318285036b440adcb10e1a8a478bf4da498 (diff) | |
download | go-7c37155e4f8fedaff6857cf9ddf74878500b3324.tar.gz |
cmd/objdump: use cmd/internal/objfile
This removes a bunch of ugly duplicate code.
The end goal is to factor the disassembly code
into cmd/internal/objfile too, so that pprof can use it,
but one step at a time.
LGTM=r, iant
R=r, alex.brainman, iant
CC=golang-codereviews
https://codereview.appspot.com/149400043
Diffstat (limited to 'src/cmd/internal')
-rw-r--r-- | src/cmd/internal/objfile/elf.go | 25 | ||||
-rw-r--r-- | src/cmd/internal/objfile/goobj.go | 12 | ||||
-rw-r--r-- | src/cmd/internal/objfile/macho.go | 24 | ||||
-rw-r--r-- | src/cmd/internal/objfile/objfile.go | 10 | ||||
-rw-r--r-- | src/cmd/internal/objfile/pe.go | 31 | ||||
-rw-r--r-- | src/cmd/internal/objfile/plan9obj.go | 22 |
6 files changed, 124 insertions, 0 deletions
diff --git a/src/cmd/internal/objfile/elf.go b/src/cmd/internal/objfile/elf.go index 8495fa753..17755b84d 100644 --- a/src/cmd/internal/objfile/elf.go +++ b/src/cmd/internal/objfile/elf.go @@ -8,6 +8,7 @@ package objfile import ( "debug/elf" + "fmt" "os" ) @@ -77,3 +78,27 @@ func (f *elfFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { } 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: + return "power64" + } + return "" +} diff --git a/src/cmd/internal/objfile/goobj.go b/src/cmd/internal/objfile/goobj.go index a4f49ebe4..a1d773023 100644 --- a/src/cmd/internal/objfile/goobj.go +++ b/src/cmd/internal/objfile/goobj.go @@ -79,3 +79,15 @@ func (f *goobjFile) symbols() ([]Sym, error) { func (f *goobjFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { return 0, nil, nil, fmt.Errorf("pcln not available in go object file") } + +// text does not make sense for Go object files, because +// each function has a separate section. +func (f *goobjFile) text() (textStart uint64, text []byte, err error) { + return 0, nil, fmt.Errorf("text not available in go object file") +} + +// goarch makes sense but is not exposed in debug/goobj's API, +// and we don't need it yet for any users of internal/objfile. +func (f *goobjFile) goarch() string { + return "GOARCH unimplemented for debug/goobj files" +} diff --git a/src/cmd/internal/objfile/macho.go b/src/cmd/internal/objfile/macho.go index f845792ff..7dd84a339 100644 --- a/src/cmd/internal/objfile/macho.go +++ b/src/cmd/internal/objfile/macho.go @@ -85,6 +85,30 @@ func (f *machoFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) 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 "power64" + } + return "" +} + type uint64s []uint64 func (x uint64s) Len() int { return len(x) } diff --git a/src/cmd/internal/objfile/objfile.go b/src/cmd/internal/objfile/objfile.go index 09fa63e60..3d4a5d27c 100644 --- a/src/cmd/internal/objfile/objfile.go +++ b/src/cmd/internal/objfile/objfile.go @@ -14,6 +14,8 @@ import ( 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 } // A File is an opened executable file. @@ -70,3 +72,11 @@ func (f *File) PCLineTable() (*gosym.Table, error) { } 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() +} diff --git a/src/cmd/internal/objfile/pe.go b/src/cmd/internal/objfile/pe.go index 868709eaf..67e59c226 100644 --- a/src/cmd/internal/objfile/pe.go +++ b/src/cmd/internal/objfile/pe.go @@ -133,6 +133,25 @@ func (f *peFile) pcln() (textStart uint64, symtab, pclntab []byte, err error) { 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 { @@ -168,3 +187,15 @@ func loadPETable(f *pe.File, sname, ename string) ([]byte, error) { } 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 "" +} diff --git a/src/cmd/internal/objfile/plan9obj.go b/src/cmd/internal/objfile/plan9obj.go index 80744f82a..eb6cba5eb 100644 --- a/src/cmd/internal/objfile/plan9obj.go +++ b/src/cmd/internal/objfile/plan9obj.go @@ -88,6 +88,16 @@ func (f *plan9File) pcln() (textStart uint64, symtab, pclntab []byte, err error) 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 { @@ -122,3 +132,15 @@ func loadPlan9Table(f *plan9obj.File, sname, ename string) ([]byte, error) { 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 "" +} |