github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/disasm/mips/disasm.go (about)

     1  // Package mips implements a disassembler for the MIPS architecture.
     2  package mips
     3  
     4  import (
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  
     9  	"github.com/decomp/exp/bin"
    10  	"github.com/decomp/exp/disasm"
    11  	"github.com/mewkiz/pkg/jsonutil"
    12  	"github.com/mewkiz/pkg/osutil"
    13  	"github.com/mewkiz/pkg/term"
    14  	"github.com/pkg/errors"
    15  )
    16  
    17  // TODO: Remove loggers once the library matures.
    18  
    19  // Loggers.
    20  var (
    21  	// dbg represents a logger with the "mips:" prefix, which logs debug messages
    22  	// to standard error.
    23  	dbg = log.New(os.Stderr, term.BlueBold("mips:")+" ", 0)
    24  	// warn represents a logger with the "warning:" prefix, which logs warning
    25  	// messages to standard error.
    26  	warn = log.New(os.Stderr, term.RedBold("warning:")+" ", 0)
    27  )
    28  
    29  // A Disasm tracks information required to disassemble a binary executable.
    30  //
    31  // Data should only be written to this structure during initialization. After
    32  // initialization the structure is considered in read-only mode to allow for
    33  // concurrent decoding of functions.
    34  type Disasm struct {
    35  	*disasm.Disasm
    36  	// Processor mode.
    37  	Mode int
    38  }
    39  
    40  // NewDisasm creates a new Disasm for accessing the assembly instructions of the
    41  // given binary executable.
    42  //
    43  // Associated files of the generic disassembler.
    44  //
    45  //    funcs.json
    46  //    blocks.json
    47  //    tables.json
    48  //    chunks.json
    49  //    data.json
    50  //
    51  // Associated files of the MIPS disassembler.
    52  //
    53  //    contexts.json
    54  func NewDisasm(file *bin.File) (*Disasm, error) {
    55  	// Prepare MIPS disassembler.
    56  	d, err := disasm.New(file)
    57  	if err != nil {
    58  		return nil, errors.WithStack(err)
    59  	}
    60  	dis := &Disasm{
    61  		Disasm: d,
    62  	}
    63  
    64  	// Parse processor mode.
    65  	switch dis.File.Arch {
    66  	case bin.ArchMIPS_32:
    67  		dis.Mode = 32
    68  	default:
    69  		panic(fmt.Errorf("support for machine architecture %v not yet implemented", dis.File.Arch))
    70  	}
    71  
    72  	// Parse CPU contexts.
    73  	//if err := parseJSON("contexts.json", &dis.Contexts); err != nil {
    74  	//	return nil, errors.WithStack(err)
    75  	//}
    76  
    77  	return dis, nil
    78  }
    79  
    80  // ### [ Helper functions ] ####################################################
    81  
    82  // parseJSON parses the given JSON file and stores the result into v.
    83  func parseJSON(jsonPath string, v interface{}) error {
    84  	if !osutil.Exists(jsonPath) {
    85  		warn.Printf("unable to locate JSON file %q", jsonPath)
    86  		return nil
    87  	}
    88  	return jsonutil.ParseFile(jsonPath, v)
    89  }