forked from rosa/hakurei
cmd/irdump: remove old implementation
This commit is contained in:
@@ -1,293 +0,0 @@
|
|||||||
package pkg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"unique"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AsmMessage struct {
|
|
||||||
data AsmData
|
|
||||||
sig AsmSig
|
|
||||||
}
|
|
||||||
type AsmGenerator struct {
|
|
||||||
i uintptr
|
|
||||||
as chan AsmMessage
|
|
||||||
lbl []uintptr
|
|
||||||
}
|
|
||||||
type AsmSig int
|
|
||||||
|
|
||||||
const (
|
|
||||||
AsmSigEnd AsmSig = iota
|
|
||||||
AsmSigLbl
|
|
||||||
AsmSigHead
|
|
||||||
AsmSigVal
|
|
||||||
)
|
|
||||||
|
|
||||||
// GenerateAll collects all asm sent to this generator and outputs formatted data to the given [io.Writer].
|
|
||||||
func (g *AsmGenerator) GenerateAll(w io.Writer) error {
|
|
||||||
for a := <-g.as; a.sig != AsmSigEnd; a = <-g.as {
|
|
||||||
switch a.sig {
|
|
||||||
case AsmSigLbl:
|
|
||||||
|
|
||||||
break
|
|
||||||
case AsmSigHead:
|
|
||||||
|
|
||||||
break
|
|
||||||
case AsmSigVal:
|
|
||||||
_, err := w.Write([]byte(a.data.Line(g)))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
break
|
|
||||||
default:
|
|
||||||
panic("invalid asm signal")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type AsmFormatter struct {
|
|
||||||
// if false, generate labels. if true, bare idents will be shown.
|
|
||||||
Real bool
|
|
||||||
// if true, header data and the dependencies list will be shown.
|
|
||||||
ShowHeader bool
|
|
||||||
// if true, don't generate raw byte data (only generate raw assembly).
|
|
||||||
Raw bool
|
|
||||||
}
|
|
||||||
type AsmData interface {
|
|
||||||
Line(*AsmGenerator) string
|
|
||||||
Offset(int)
|
|
||||||
}
|
|
||||||
|
|
||||||
type AsmDataNone struct{}
|
|
||||||
|
|
||||||
func (a AsmDataNone) Line(*AsmGenerator) string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (a AsmDataNone) Offset(int) {}
|
|
||||||
|
|
||||||
type AsmLine struct {
|
|
||||||
pos int
|
|
||||||
word int
|
|
||||||
kindData int64
|
|
||||||
valueData []byte
|
|
||||||
indent int
|
|
||||||
kind string
|
|
||||||
value string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l AsmLine) Line(gen *AsmGenerator) string {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
func (l AsmLine) Offset(offset int) {
|
|
||||||
l.pos += offset
|
|
||||||
}
|
|
||||||
|
|
||||||
type AsmHeaderLine struct {
|
|
||||||
pos int
|
|
||||||
kind string
|
|
||||||
kindData int64
|
|
||||||
label string
|
|
||||||
id unique.Handle[ID]
|
|
||||||
}
|
|
||||||
|
|
||||||
var spacingLine = AsmLine{
|
|
||||||
pos: -1,
|
|
||||||
kindData: -1,
|
|
||||||
valueData: nil,
|
|
||||||
indent: 0,
|
|
||||||
kind: "",
|
|
||||||
value: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
func Disassemble(r io.Reader, real bool, showHeader bool, force bool, raw bool) (s string, err error) {
|
|
||||||
var lines []AsmLine
|
|
||||||
sb := new(strings.Builder)
|
|
||||||
header := true
|
|
||||||
pos := new(int)
|
|
||||||
|
|
||||||
for err == nil {
|
|
||||||
if header {
|
|
||||||
var kind uint64
|
|
||||||
var size uint64
|
|
||||||
var bsize []byte
|
|
||||||
p := *pos
|
|
||||||
if _, kind, err = nextUint64(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if bsize, size, err = nextUint64(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if showHeader {
|
|
||||||
lines = append(lines, AsmLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""})
|
|
||||||
}
|
|
||||||
for i := 0; uint64(i) < size; i++ {
|
|
||||||
var did ID
|
|
||||||
var dkind uint64
|
|
||||||
p := *pos
|
|
||||||
if _, dkind, err = nextUint64(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if _, did, err = nextIdent(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if showHeader {
|
|
||||||
lines = append(lines, AsmLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
header = false
|
|
||||||
}
|
|
||||||
var k uint32
|
|
||||||
p := *pos
|
|
||||||
if _, k, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
kind := IRValueKind(k)
|
|
||||||
switch kind {
|
|
||||||
case IRKindEnd:
|
|
||||||
var a uint32
|
|
||||||
var ba []byte
|
|
||||||
if ba, a, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if a&1 != 0 {
|
|
||||||
var sum Checksum
|
|
||||||
if _, sum, err = nextIdent(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)})
|
|
||||||
} else {
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""})
|
|
||||||
}
|
|
||||||
lines = append(lines, spacingLine)
|
|
||||||
header = true
|
|
||||||
continue
|
|
||||||
|
|
||||||
case IRKindIdent:
|
|
||||||
var a []byte
|
|
||||||
// discard ancillary
|
|
||||||
if a, _, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
var id ID
|
|
||||||
if _, id, err = nextIdent(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), a, 1, "id ", Encode(id)})
|
|
||||||
continue
|
|
||||||
case IRKindUint32:
|
|
||||||
var i uint32
|
|
||||||
var bi []byte
|
|
||||||
if bi, i, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)})
|
|
||||||
case IRKindString:
|
|
||||||
var l uint32
|
|
||||||
var bl []byte
|
|
||||||
if bl, l, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize)
|
|
||||||
var n int
|
|
||||||
if n, err = r.Read(s); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
*pos = *pos + n
|
|
||||||
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))})
|
|
||||||
continue
|
|
||||||
default:
|
|
||||||
var bi []byte
|
|
||||||
if bi, _, err = nextUint32(r, pos); err != nil {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
lines = append(lines, AsmLine{p, 4, int64(kind), bi, 1, "????", ""})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if err != io.EOF {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
err = nil
|
|
||||||
for _, line := range lines {
|
|
||||||
if raw {
|
|
||||||
if line.pos != -1 {
|
|
||||||
sb.WriteString(fmt.Sprintf("%s\t%s\n", line.kind, line.value))
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if line.pos == -1 {
|
|
||||||
sb.WriteString("\n")
|
|
||||||
} else if line.word == 4 {
|
|
||||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x%s %s %s\n", line.pos, binary.LittleEndian.AppendUint32(nil, uint32(line.kindData)), line.valueData, headerSpacing(showHeader), line.kind, line.value))
|
|
||||||
} else {
|
|
||||||
kind := binary.LittleEndian.AppendUint64(nil, uint64(line.kindData))
|
|
||||||
value := line.valueData
|
|
||||||
if len(value) == 8 {
|
|
||||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], value[:4], value[4:], line.kind, line.value))
|
|
||||||
} else {
|
|
||||||
sb.WriteString(fmt.Sprintf("%06x: %04x %04x %s %s\n", line.pos, kind[:4], kind[4:], line.kind, line.value))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
return sb.String(), err
|
|
||||||
}
|
|
||||||
func nextUint32(r io.Reader, pos *int) ([]byte, uint32, error) {
|
|
||||||
i := make([]byte, 4)
|
|
||||||
_, err := r.Read(i)
|
|
||||||
if err != nil {
|
|
||||||
return i, 0, err
|
|
||||||
}
|
|
||||||
p := *pos + 4
|
|
||||||
*pos = p
|
|
||||||
return i, binary.LittleEndian.Uint32(i), nil
|
|
||||||
}
|
|
||||||
func nextUint64(r io.Reader, pos *int) ([]byte, uint64, error) {
|
|
||||||
i := make([]byte, 8)
|
|
||||||
_, err := r.Read(i)
|
|
||||||
if err != nil {
|
|
||||||
return i, 0, err
|
|
||||||
}
|
|
||||||
p := *pos + 8
|
|
||||||
*pos = p
|
|
||||||
return i, binary.LittleEndian.Uint64(i), nil
|
|
||||||
}
|
|
||||||
func nextIdent(r io.Reader, pos *int) ([]byte, ID, error) {
|
|
||||||
i := make([]byte, 48)
|
|
||||||
if _, err := r.Read(i); err != nil {
|
|
||||||
return i, ID{}, err
|
|
||||||
}
|
|
||||||
p := *pos + 48
|
|
||||||
*pos = p
|
|
||||||
return i, ID(i), nil
|
|
||||||
}
|
|
||||||
func intToKind(i uint64) string {
|
|
||||||
switch Kind(i) {
|
|
||||||
case KindHTTPGet:
|
|
||||||
return "http"
|
|
||||||
case KindTar:
|
|
||||||
return "tar "
|
|
||||||
case KindExec:
|
|
||||||
return "exec"
|
|
||||||
case KindExecNet:
|
|
||||||
return "exen"
|
|
||||||
case KindFile:
|
|
||||||
return "file"
|
|
||||||
default:
|
|
||||||
return fmt.Sprintf("$%d ", i-KindCustomOffset)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func headerSpacing(showHeader bool) string {
|
|
||||||
if showHeader {
|
|
||||||
return " "
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user