mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/internal/objfile: break out dissassemblers to another package
Currently, cmd/internal/objfile provides dissassembly routines for
various architectures, which depend on dissassemblers from x/arch.
cmd/internal/objfile is imported in tools that need dissassembly
(objdump, pprof) and tools that don't need dissassembly (nm,
addr2line). Adding/improving disassembly support for more
architectures can cause binary size increase, and for some tools
(nm, addr2line) it is not necessary.
This CL breaks out dissassembly routines to a different package,
which is only imported in tools that need dissassembly. Other
tools can depend on cmd/internal/objfile without the disassembly
code from x/arch.
This reduces binary sizes for those tools. On darwin/arm64,
old new
cmd/addr2line 4554418 3648882 -20%
cmd/addr2line (-ldflags=-w) 3464626 2641650 -24%
cmd/nm 4503874 3616722 -20%
cmd/nm (-ldflags=-w) 3430594 2609490 -24%
For #70699.
Change-Id: Ie45d5d5c5500c5f3882e8b3c4e6eb81f0d815292
Reviewed-on: https://go-review.googlesource.com/c/go/+/634916
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: David Chase <drchase@google.com>
This commit is contained in:
parent
e0c76d95ab
commit
6c25cf1c5f
4 changed files with 28 additions and 22 deletions
|
|
@ -2,13 +2,16 @@
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package objfile
|
// Package disasm provides disassembly routines.
|
||||||
|
//
|
||||||
|
// It is broken out from cmd/internal/objfile so tools that don't need
|
||||||
|
// disassembling don't need to depend on x/arch disassembler code.
|
||||||
|
package disasm
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"container/list"
|
"container/list"
|
||||||
"debug/gosym"
|
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
@ -19,6 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"text/tabwriter"
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"cmd/internal/objfile"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
|
|
||||||
"golang.org/x/arch/arm/armasm"
|
"golang.org/x/arch/arm/armasm"
|
||||||
|
|
@ -32,8 +36,8 @@ import (
|
||||||
|
|
||||||
// Disasm is a disassembler for a given File.
|
// Disasm is a disassembler for a given File.
|
||||||
type Disasm struct {
|
type Disasm struct {
|
||||||
syms []Sym //symbols in file, sorted by address
|
syms []objfile.Sym // symbols in file, sorted by address
|
||||||
pcln Liner // pcln table
|
pcln objfile.Liner // pcln table
|
||||||
text []byte // bytes of text segment (actual instructions)
|
text []byte // bytes of text segment (actual instructions)
|
||||||
textStart uint64 // start PC of text
|
textStart uint64 // start PC of text
|
||||||
textEnd uint64 // end PC of text
|
textEnd uint64 // end PC of text
|
||||||
|
|
@ -42,8 +46,12 @@ type Disasm struct {
|
||||||
byteOrder binary.ByteOrder // byte order for goarch
|
byteOrder binary.ByteOrder // byte order for goarch
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disasm returns a disassembler for the file f.
|
// DisasmForFile returns a disassembler for the file f.
|
||||||
func (e *Entry) Disasm() (*Disasm, error) {
|
func DisasmForFile(f *objfile.File) (*Disasm, error) {
|
||||||
|
return disasmForEntry(f.Entries()[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
func disasmForEntry(e *objfile.Entry) (*Disasm, error) {
|
||||||
syms, err := e.Symbols()
|
syms, err := e.Symbols()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -269,7 +277,7 @@ func (d *Disasm) Print(w io.Writer, filter *regexp.Regexp, start, end uint64, pr
|
||||||
}
|
}
|
||||||
|
|
||||||
// Decode disassembles the text segment range [start, end), calling f for each instruction.
|
// Decode disassembles the text segment range [start, end), calling f for each instruction.
|
||||||
func (d *Disasm) Decode(start, end uint64, relocs []Reloc, gnuAsm bool, f func(pc, size uint64, file string, line int, text string)) {
|
func (d *Disasm) Decode(start, end uint64, relocs []objfile.Reloc, gnuAsm bool, f func(pc, size uint64, file string, line int, text string)) {
|
||||||
if start < d.textStart {
|
if start < d.textStart {
|
||||||
start = d.textStart
|
start = d.textStart
|
||||||
}
|
}
|
||||||
|
|
@ -452,9 +460,3 @@ var byteOrders = map[string]binary.ByteOrder{
|
||||||
"riscv64": binary.LittleEndian,
|
"riscv64": binary.LittleEndian,
|
||||||
"s390x": binary.BigEndian,
|
"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)
|
|
||||||
}
|
|
||||||
|
|
@ -119,10 +119,6 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
||||||
return f.entries[0].DWARF()
|
return f.entries[0].DWARF()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *File) Disasm() (*Disasm, error) {
|
|
||||||
return f.entries[0].Disasm()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (e *Entry) Name() string {
|
func (e *Entry) Name() string {
|
||||||
return e.name
|
return e.name
|
||||||
}
|
}
|
||||||
|
|
@ -181,3 +177,9 @@ func (e *Entry) LoadAddress() (uint64, error) {
|
||||||
func (e *Entry) DWARF() (*dwarf.Data, error) {
|
func (e *Entry) DWARF() (*dwarf.Data, error) {
|
||||||
return e.raw.dwarf()
|
return e.raw.dwarf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"cmd/internal/disasm"
|
||||||
"cmd/internal/objfile"
|
"cmd/internal/objfile"
|
||||||
"cmd/internal/telemetry/counter"
|
"cmd/internal/telemetry/counter"
|
||||||
)
|
)
|
||||||
|
|
@ -82,7 +83,7 @@ func main() {
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
dis, err := f.Disasm()
|
dis, err := disasm.DisasmForFile(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("disassemble %s: %v", flag.Arg(0), err)
|
log.Fatalf("disassemble %s: %v", flag.Arg(0), err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"cmd/internal/disasm"
|
||||||
"cmd/internal/objfile"
|
"cmd/internal/objfile"
|
||||||
"cmd/internal/telemetry/counter"
|
"cmd/internal/telemetry/counter"
|
||||||
|
|
||||||
|
|
@ -162,7 +163,7 @@ func adjustURL(source string, duration, timeout time.Duration) (string, time.Dur
|
||||||
// (instead of invoking GNU binutils).
|
// (instead of invoking GNU binutils).
|
||||||
type objTool struct {
|
type objTool struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
disasmCache map[string]*objfile.Disasm
|
disasmCache map[string]*disasm.Disasm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*objTool) Open(name string, start, limit, offset uint64, relocationSymbol string) (driver.ObjFile, error) {
|
func (*objTool) Open(name string, start, limit, offset uint64, relocationSymbol string) (driver.ObjFile, error) {
|
||||||
|
|
@ -202,11 +203,11 @@ func (t *objTool) Disasm(file string, start, end uint64, intelSyntax bool) ([]dr
|
||||||
return asm, nil
|
return asm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *objTool) cachedDisasm(file string) (*objfile.Disasm, error) {
|
func (t *objTool) cachedDisasm(file string) (*disasm.Disasm, error) {
|
||||||
t.mu.Lock()
|
t.mu.Lock()
|
||||||
defer t.mu.Unlock()
|
defer t.mu.Unlock()
|
||||||
if t.disasmCache == nil {
|
if t.disasmCache == nil {
|
||||||
t.disasmCache = make(map[string]*objfile.Disasm)
|
t.disasmCache = make(map[string]*disasm.Disasm)
|
||||||
}
|
}
|
||||||
d := t.disasmCache[file]
|
d := t.disasmCache[file]
|
||||||
if d != nil {
|
if d != nil {
|
||||||
|
|
@ -216,7 +217,7 @@ func (t *objTool) cachedDisasm(file string) (*objfile.Disasm, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
d, err = f.Disasm()
|
d, err = disasm.DisasmForFile(f)
|
||||||
f.Close()
|
f.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue