Commit 0d441a08 authored by Russ Cox's avatar Russ Cox

cmd/objdump: rewrite in Go

Update cmd/dist not to build the C version.
Update cmd/go to install the Go version to the tool directory.

Update #7452

This is the basic logic needed for objdump, and it works well enough
to support the pprof list and weblist commands. A real disassembler
needs to be added in order to support the pprof disasm command
and the per-line assembly displays in weblist. That's still to come.

Probably objdump will move to go.tools when the disassembler
is added, but it can stay here for now.

LGTM=minux.ma
R=golang-codereviews, minux.ma
CC=golang-codereviews, iant, r
https://golang.org/cl/87580043
parent c48db9a4
......@@ -1332,7 +1332,6 @@ static char *buildorder[] = {
"misc/pprof",
"cmd/objdump",
"cmd/prof",
"cmd/cc", // must be before c
......@@ -1409,7 +1408,6 @@ static char *cleantab[] = {
"cmd/cc",
"cmd/gc",
"cmd/go",
"cmd/objdump",
"cmd/prof",
"lib9",
"libbio",
......
......@@ -313,6 +313,7 @@ var goTools = map[string]targetDir{
"cmd/fix": toTool,
"cmd/link": toTool,
"cmd/nm": toTool,
"cmd/objdump": toTool,
"cmd/pack": toTool,
"cmd/yacc": toTool,
"code.google.com/p/go.tools/cmd/cover": toTool,
......
// Copyright 2012 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.
/*
* objdump simulation - only enough to make pprof work on Macs
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <mach.h>
void
usage(void)
{
fprint(2, "usage: objdump binary start stop\n");
fprint(2, "Disassembles binary from PC start up to stop.\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int fd, n;
uvlong pc, start, stop;
Fhdr fhdr;
Biobuf bout;
char buf[1024];
Map *text;
ARGBEGIN{
default:
usage();
}ARGEND
if(argc != 3)
usage();
start = strtoull(argv[1], 0, 16);
stop = strtoull(argv[2], 0, 16);
fd = open(argv[0], OREAD);
if(fd < 0)
sysfatal("open %s: %r", argv[0]);
if(crackhdr(fd, &fhdr) <= 0)
sysfatal("crackhdr: %r");
machbytype(fhdr.type);
if(syminit(fd, &fhdr) <= 0)
sysfatal("syminit: %r");
text = loadmap(nil, fd, &fhdr);
if(text == nil)
sysfatal("loadmap: %r");
Binit(&bout, 1, OWRITE);
for(pc=start; pc<stop; ) {
if(fileline(buf, sizeof buf, pc))
Bprint(&bout, "%s\n", buf);
buf[0] = '\0';
machdata->das(text, pc, 0, buf, sizeof buf);
Bprint(&bout, " %llx: %s\n", pc, buf);
n = machdata->instsize(text, pc);
if(n <= 0)
break;
pc += n;
}
Bflush(&bout);
exits(0);
}
// Copyright 2012 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.
// objdump simulation - only enough to make pprof work on Macs
package main
import (
"bufio"
"debug/elf"
"debug/gosym"
"debug/macho"
"debug/pe"
"flag"
"fmt"
"log"
"os"
"strconv"
)
func printUsage(w *os.File) {
fmt.Fprintf(w, "usage: objdump binary start end\n")
fmt.Fprintf(w, "disassembles binary from start PC to end PC.\n")
}
func usage() {
printUsage(os.Stderr)
os.Exit(2)
}
func main() {
log.SetFlags(0)
log.SetPrefix("objdump: ")
flag.Usage = usage
flag.Parse()
if flag.NArg() != 3 {
usage()
}
f, err := os.Open(flag.Arg(0))
if err != nil {
log.Fatal(err)
}
textStart, textData, 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)
if err != nil {
log.Fatalf("reading %s: %v", flag.Arg(0), err)
}
start, err := strconv.ParseUint(flag.Arg(1), 0, 64)
if err != nil {
log.Fatalf("invalid start PC: %v", err)
}
end, err := strconv.ParseUint(flag.Arg(2), 0, 64)
if err != nil {
log.Fatalf("invalid end PC: %v", err)
}
stdout := bufio.NewWriter(os.Stdout)
// For now, find spans of same PC/line/fn and
// emit them as having dummy instructions.
var (
spanPC uint64
spanFile string
spanLine int
spanFn *gosym.Func
)
flush := func(endPC uint64) {
if spanPC == 0 {
return
}
fmt.Fprintf(stdout, "%s:%d\n", spanFile, spanLine)
for pc := spanPC; pc < endPC; pc++ {
// TODO(rsc): Disassemble instructions here.
if textStart <= pc && pc-textStart < uint64(len(textData)) {
fmt.Fprintf(stdout, " %x: byte %#x\n", pc, textData[pc-textStart])
} else {
fmt.Fprintf(stdout, " %x: ?\n", pc)
}
}
spanPC = 0
}
for pc := start; pc < end; pc++ {
file, line, fn := tab.PCToLine(pc)
if file != spanFile || line != spanLine || fn != spanFn {
flush(pc)
spanPC, spanFile, spanLine, spanFn = pc, file, line, fn
}
}
flush(end)
stdout.Flush()
}
func loadTables(f *os.File) (textStart uint64, textData, symtab, pclntab []byte, err error) {
if obj, err := elf.NewFile(f); err == nil {
if sect := obj.Section(".text"); sect != nil {
textStart = sect.Addr
textData, _ = sect.Data()
}
if sect := obj.Section(".gosymtab"); sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
if sect := obj.Section(".gopclntab"); sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
return textStart, textData, symtab, pclntab, nil
}
if obj, err := macho.NewFile(f); err == nil {
if sect := obj.Section("__text"); sect != nil {
textStart = sect.Addr
textData, _ = sect.Data()
}
if sect := obj.Section("__gosymtab"); sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
if sect := obj.Section("__gopclntab"); sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
return textStart, textData, symtab, pclntab, nil
}
if obj, err := pe.NewFile(f); err == nil {
if sect := obj.Section(".text"); sect != nil {
textStart = uint64(sect.VirtualAddress)
textData, _ = sect.Data()
}
if sect := obj.Section(".gosymtab"); sect != nil {
if symtab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
if sect := obj.Section(".gopclntab"); sect != nil {
if pclntab, err = sect.Data(); err != nil {
return 0, nil, nil, nil, err
}
}
return textStart, textData, symtab, pclntab, nil
}
return 0, nil, nil, nil, fmt.Errorf("unrecognized binary format")
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment