github.com/decomp/exp@v0.0.0-20210624183419-6d058f5e1da6/cmd/bin2asm/header.go (about)

     1  package main
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"github.com/mewkiz/pkg/goutil"
    11  	"github.com/mewrev/pe"
    12  	"github.com/pkg/errors"
    13  )
    14  
    15  // bin2asmDir specifies the source directory of the bin2asm command.
    16  var bin2asmDir string
    17  
    18  func init() {
    19  	var err error
    20  	bin2asmDir, err = goutil.SrcDir("github.com/decomp/exp/cmd/bin2asm")
    21  	if err != nil {
    22  		panic(fmt.Errorf("unable to locate source directory of bin2asm; %v", err))
    23  	}
    24  }
    25  
    26  // dumpCommon dumps a common include file of the executable.
    27  func dumpCommon(file *pe.File) error {
    28  	buf := &bytes.Buffer{}
    29  	const commonFormat = `
    30  %%ifndef __COMMON_INC__
    31  %%define __COMMON_INC__
    32  
    33  %%define IMAGE_BASE      0x%08X
    34  %%define CODE_BASE       0x%08X
    35  %%define DATA_BASE       0x%08X
    36  
    37     hdr_vstart           equ     IMAGE_BASE
    38  `
    39  	optHdr, err := file.OptHeader()
    40  	if err != nil {
    41  		return errors.WithStack(err)
    42  	}
    43  	sectHdrs, err := file.SectHeaders()
    44  	if err != nil {
    45  		return errors.WithStack(err)
    46  	}
    47  	fmt.Fprintf(buf, commonFormat[1:], optHdr.ImageBase, optHdr.CodeBase, optHdr.DataBase)
    48  
    49  	for _, sectHdr := range sectHdrs {
    50  		rawName := sectHdr.Name
    51  		sectName := strings.Replace(rawName, ".", "_", -1)
    52  		fmt.Fprintf(buf, "   %s_vstart         equ     IMAGE_BASE + 0x%08X\n", sectName, sectHdr.RelAddr)
    53  	}
    54  	buf.WriteString("\n")
    55  	for _, sectHdr := range sectHdrs {
    56  		if sectHdr.VirtSize > sectHdr.Size {
    57  			// Section with uninitialized data.
    58  			buf.WriteString(";")
    59  		}
    60  		rawName := sectHdr.Name
    61  		sectName := strings.Replace(rawName, ".", "_", -1)
    62  		fmt.Fprintf(buf, "   %s_size           equ     0x%08X\n", sectName, sectHdr.Size)
    63  	}
    64  	buf.WriteString("\n")
    65  	for _, sectHdr := range sectHdrs {
    66  		if sectHdr.VirtSize <= sectHdr.Size {
    67  			// Section with padding.
    68  			buf.WriteString(";")
    69  		}
    70  		rawName := sectHdr.Name
    71  		sectName := strings.Replace(rawName, ".", "_", -1)
    72  		fmt.Fprintf(buf, "   %s_vsize          equ     0x%08X\n", sectName, sectHdr.VirtSize)
    73  	}
    74  	buf.WriteString("\n")
    75  
    76  	const bitsHeader = `
    77  BITS 32
    78  
    79  SECTION hdr    vstart=hdr_vstart
    80  `
    81  	buf.WriteString(bitsHeader[1:])
    82  
    83  	prev := "hdr"
    84  	for _, sectHdr := range sectHdrs {
    85  		rawName := sectHdr.Name
    86  		sectName := strings.Replace(rawName, ".", "_", -1)
    87  		fmt.Fprintf(buf, "SECTION %s  vstart=%s_vstart  follows=%s\n", rawName, sectName, prev)
    88  		prev = rawName
    89  	}
    90  	buf.WriteString("\n")
    91  	buf.WriteString("%endif ; %ifndef __COMMON_INC__\n")
    92  
    93  	// Store output.
    94  	outPath := filepath.Join(outDir, "common.inc")
    95  	dbg.Printf("creating %q\n", outPath)
    96  	if err := ioutil.WriteFile(outPath, buf.Bytes(), 0644); err != nil {
    97  		return errors.WithStack(err)
    98  	}
    99  	return nil
   100  }