aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/addr2line
diff options
context:
space:
mode:
authorRuss Cox <rsc@golang.org>2014-08-07 12:33:06 -0400
committerRuss Cox <rsc@golang.org>2014-08-07 12:33:06 -0400
commit08033f9816e1e33092c93c050dc34514d8e3e926 (patch)
treee7442db7fd5cbf52364c7617d437f30374e1117e /src/cmd/addr2line
parentfad69a7b77a7996b0308bdbcd559b78b32046bb3 (diff)
downloadgo-08033f9816e1e33092c93c050dc34514d8e3e926.tar.gz
go-08033f9816e1e33092c93c050dc34514d8e3e926.zip
cmd/addr2line, cmd/nm: factor object reading into cmd/internal/objfile
To do in another CL: make cmd/objdump use cmd/internal/objfile too. There is a package placement decision in this CL: cmd/internal/objfile instead of internal/objfile. I chose to put internal under cmd to make clear (and enforce) that no standard library packages should use this (it's a bit dependency-heavy). LGTM=r R=r CC=golang-codereviews https://golang.org/cl/123910043
Diffstat (limited to 'src/cmd/addr2line')
-rw-r--r--src/cmd/addr2line/main.go159
1 files changed, 4 insertions, 155 deletions
diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go
index 3802f764f9..267f4170a8 100644
--- a/src/cmd/addr2line/main.go
+++ b/src/cmd/addr2line/main.go
@@ -19,17 +19,14 @@ package main
import (
"bufio"
- "debug/elf"
- "debug/gosym"
- "debug/macho"
- "debug/pe"
- "debug/plan9obj"
"flag"
"fmt"
"log"
"os"
"strconv"
"strings"
+
+ "cmd/internal/objfile"
)
func printUsage(w *os.File) {
@@ -60,18 +57,12 @@ func main() {
usage()
}
- f, err := os.Open(flag.Arg(0))
+ f, err := objfile.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
- textStart, symtab, pclntab, err := loadTables(f)
- if err != nil {
- log.Fatalf("reading %s: %v", flag.Arg(0), err)
- }
-
- pcln := gosym.NewLineTable(pclntab, textStart)
- tab, err := gosym.NewTable(symtab, pcln)
+ tab, err := f.PCLineTable()
if err != nil {
log.Fatalf("reading %s: %v", flag.Arg(0), err)
}
@@ -102,145 +93,3 @@ func main() {
}
stdout.Flush()
}
-
-func loadTables(f *os.File) (textStart uint64, symtab, pclntab []byte, err error) {
- if obj, err := elf.NewFile(f); err == nil {
- if sect := obj.Section(".text"); sect != nil {
- textStart = sect.Addr
- }
- if sect := obj.Section(".gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- if sect := obj.Section(".gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := macho.NewFile(f); err == nil {
- if sect := obj.Section("__text"); sect != nil {
- textStart = sect.Addr
- }
- if sect := obj.Section("__gosymtab"); sect != nil {
- if symtab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- if sect := obj.Section("__gopclntab"); sect != nil {
- if pclntab, err = sect.Data(); err != nil {
- return 0, nil, nil, err
- }
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := pe.NewFile(f); err == nil {
- var imageBase uint64
- switch oh := obj.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 := obj.Section(".text"); sect != nil {
- textStart = imageBase + uint64(sect.VirtualAddress)
- }
- if pclntab, err = loadPETable(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, err
- }
- if symtab, err = loadPETable(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, err
- }
- return textStart, symtab, pclntab, nil
- }
-
- if obj, err := plan9obj.NewFile(f); err == nil {
- textStart = obj.LoadAddress + obj.HdrSize
- if pclntab, err = loadPlan9Table(obj, "pclntab", "epclntab"); err != nil {
- return 0, nil, nil, err
- }
- if symtab, err = loadPlan9Table(obj, "symtab", "esymtab"); err != nil {
- return 0, nil, nil, err
- }
- return textStart, symtab, pclntab, nil
- }
-
- return 0, nil, nil, fmt.Errorf("unrecognized binary format")
-}
-
-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 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
-}