mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
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
This commit is contained in:
parent
fad69a7b77
commit
08033f9816
11 changed files with 448 additions and 387 deletions
92
src/cmd/internal/objfile/macho.go
Normal file
92
src/cmd/internal/objfile/macho.go
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
// 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/macho"
|
||||
"fmt"
|
||||
"os"
|
||||
"sort"
|
||||
)
|
||||
|
||||
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 {
|
||||
addrs = append(addrs, s.Value)
|
||||
}
|
||||
sort.Sort(uint64s(addrs))
|
||||
|
||||
var syms []Sym
|
||||
for _, s := range f.macho.Symtab.Syms {
|
||||
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
|
||||
}
|
||||
|
||||
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] }
|
||||
Loading…
Add table
Add a link
Reference in a new issue