github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/disas/main.go (about)

     1  // Copyright 2015 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package main
     6  
     7  import (
     8  	"flag"
     9  	"fmt"
    10  	"io/ioutil"
    11  	"log"
    12  	"os"
    13  	"os/exec"
    14  	"strings"
    15  
    16  	"cmd/internal/goobj"
    17  	"cmd/internal/obj"
    18  )
    19  
    20  func getobjdumpcmd(fname string) (*exec.Cmd, error) {
    21  	switch obj.GOARCH {
    22  	case "arm":
    23  		return exec.Command(
    24  				"arm-none-eabi-objdump",
    25  				"-b", "binary",
    26  				"-m", "arm",
    27  				"-EL",
    28  				"-D", fname),
    29  			nil
    30  	case "riscv":
    31  		return exec.Command(
    32  				"riscv64-unknown-elf-objdump",
    33  				"-b", "binary",
    34  				"-m", "riscv:rv64",
    35  				"-EL",
    36  				"-D", fname),
    37  			nil
    38  	default:
    39  		return nil, fmt.Errorf("unsupported architecture %s", obj.GOARCH)
    40  	}
    41  }
    42  
    43  func disas1(sym *goobj.Sym, data []byte) {
    44  	f, err := ioutil.TempFile("/tmp", "go_disas")
    45  	if err != nil {
    46  		log.Println(err)
    47  		return
    48  	}
    49  	defer os.Remove(f.Name())
    50  	defer f.Close()
    51  
    52  	_, err = f.Write(data)
    53  	if err != nil {
    54  		log.Println(err)
    55  		return
    56  	}
    57  
    58  	objdumpcmd, err := getobjdumpcmd(f.Name())
    59  	if err != nil {
    60  		log.Println(err)
    61  		return
    62  	}
    63  	objdumpout, err := objdumpcmd.Output()
    64  	if err != nil {
    65  		log.Println(err)
    66  		return
    67  	}
    68  	objdumplines := strings.Split(string(objdumpout[:]), "\n")
    69  	fmt.Printf("%s:\n", sym.Name)
    70  	for _, line := range objdumplines[7:] {
    71  		fmt.Println(line)
    72  	}
    73  }
    74  
    75  func disas(file string, pkgpath string) {
    76  	f, err := os.Open(file)
    77  	if err != nil {
    78  		log.Fatal(err)
    79  	}
    80  	defer f.Close()
    81  
    82  	obj, err := goobj.Parse(f, pkgpath)
    83  	if err != nil {
    84  		log.Fatal(err)
    85  	}
    86  
    87  	for _, sym := range obj.Syms {
    88  		data := make([]byte, sym.Data.Size)
    89  
    90  		_, err = f.Seek(sym.Data.Offset, 0)
    91  		if err != nil {
    92  			log.Println(err)
    93  			continue
    94  		}
    95  
    96  		_, err = f.Read(data)
    97  		if err != nil {
    98  			log.Println(err)
    99  			continue
   100  		}
   101  
   102  		disas1(sym, data)
   103  	}
   104  }
   105  
   106  func main() {
   107  	log.SetFlags(0)
   108  	log.SetPrefix("disas: ")
   109  
   110  	// Ensure that we actually support this architecture.
   111  	_, err := getobjdumpcmd("dummy")
   112  	if err != nil {
   113  		log.Fatal(err)
   114  	}
   115  
   116  	flag.Parse()
   117  	if flag.NArg() != 1 {
   118  		fmt.Fprintf(os.Stderr, "usage: disas file.o\n")
   119  		os.Exit(2)
   120  	}
   121  
   122  	disas(flag.Arg(0), "main")
   123  }