cmd/irdump: formatted disassembly
This commit is contained in:
@@ -18,6 +18,7 @@ func main() {
|
|||||||
flagReal bool
|
flagReal bool
|
||||||
flagHeader bool
|
flagHeader bool
|
||||||
flagForce bool
|
flagForce bool
|
||||||
|
flagRaw bool
|
||||||
)
|
)
|
||||||
c := command.New(os.Stderr, log.Printf, "irdump", func(args []string) (err error) {
|
c := command.New(os.Stderr, log.Printf, "irdump", func(args []string) (err error) {
|
||||||
var input *os.File
|
var input *os.File
|
||||||
@@ -40,7 +41,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var out string
|
var out string
|
||||||
if out, err = pkg.Disassemble(input, flagReal, flagHeader, flagForce); err != nil {
|
if out, err = pkg.Disassemble(input, flagReal, flagHeader, flagForce, flagRaw); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err = output.WriteString(out); err != nil {
|
if _, err = output.WriteString(out); err != nil {
|
||||||
@@ -57,12 +58,16 @@ func main() {
|
|||||||
"skip label generation; idents print real value",
|
"skip label generation; idents print real value",
|
||||||
).Flag(
|
).Flag(
|
||||||
&flagHeader,
|
&flagHeader,
|
||||||
"h", command.BoolFlag(false),
|
"H", command.BoolFlag(false),
|
||||||
"display artifact headers",
|
"display artifact headers",
|
||||||
).Flag(
|
).Flag(
|
||||||
&flagForce,
|
&flagForce,
|
||||||
"f", command.BoolFlag(false),
|
"f", command.BoolFlag(false),
|
||||||
"force display (skip validations)",
|
"force display (skip validations)",
|
||||||
|
).Flag(
|
||||||
|
&flagRaw,
|
||||||
|
"R", command.BoolFlag(false),
|
||||||
|
"don't format output",
|
||||||
)
|
)
|
||||||
|
|
||||||
c.MustParse(os.Args[1:], func(err error) {
|
c.MustParse(os.Args[1:], func(err error) {
|
||||||
|
|||||||
@@ -8,144 +8,209 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Disassemble(r io.Reader, real bool, showHeader bool, force bool) (s string, err error) {
|
type asmOutLine struct {
|
||||||
var values [][2]string
|
pos int
|
||||||
|
word int
|
||||||
|
kindData int64
|
||||||
|
valueData []byte
|
||||||
|
indent int
|
||||||
|
kind string
|
||||||
|
value string
|
||||||
|
}
|
||||||
|
|
||||||
|
var spacingLine = asmOutLine{
|
||||||
|
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 []asmOutLine
|
||||||
sb := new(strings.Builder)
|
sb := new(strings.Builder)
|
||||||
header := true
|
header := true
|
||||||
|
pos := new(int)
|
||||||
|
|
||||||
for err == nil {
|
for err == nil {
|
||||||
if header {
|
if header {
|
||||||
var kind uint64
|
var kind uint64
|
||||||
var size uint64
|
var size uint64
|
||||||
hsb := new(strings.Builder)
|
var bsize []byte
|
||||||
|
p := *pos
|
||||||
if kind, err = nextUint64(r); err != nil {
|
if _, kind, err = nextUint64(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if size, err = nextUint64(r); err != nil {
|
if bsize, size, err = nextUint64(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if showHeader {
|
||||||
|
lines = append(lines, asmOutLine{p, 8, int64(kind), bsize, 0, "head " + intToKind(kind), ""})
|
||||||
|
}
|
||||||
for i := 0; uint64(i) < size; i++ {
|
for i := 0; uint64(i) < size; i++ {
|
||||||
var did Checksum
|
var did Checksum
|
||||||
var dkind uint64
|
var dkind uint64
|
||||||
if dkind, err = nextUint64(r); err != nil {
|
p := *pos
|
||||||
|
if _, dkind, err = nextUint64(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if did, err = nextIdent(r); err != nil {
|
if _, did, err = nextIdent(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
if showHeader {
|
||||||
hsb.WriteString(fmt.Sprintf("\t\t\t%s\t%s\n", intToKind(dkind), Encode(did)))
|
lines = append(lines, asmOutLine{p, 8, int64(dkind), nil, 1, intToKind(dkind), Encode(did)})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
header = false
|
header = false
|
||||||
if showHeader {
|
|
||||||
values = append(values, [2]string{"head", fmt.Sprintf("%s [\n%s]", intToKind(kind), hsb.String())})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
var k uint32
|
var k uint32
|
||||||
if k, err = nextUint32(r); err != nil {
|
p := *pos
|
||||||
|
if _, k, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
kind := IRValueKind(k)
|
kind := IRValueKind(k)
|
||||||
switch kind {
|
switch kind {
|
||||||
case IRKindEnd:
|
case IRKindEnd:
|
||||||
var a uint32
|
var a uint32
|
||||||
if a, err = nextUint32(r); err != nil {
|
var ba []byte
|
||||||
|
if ba, a, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if a&1 != 0 {
|
if a&1 != 0 {
|
||||||
var sum Checksum
|
var sum Checksum
|
||||||
if sum, err = nextIdent(r); err != nil {
|
if _, sum, err = nextIdent(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
values = append(values, [2]string{"end", Encode(sum)})
|
lines = append(lines, asmOutLine{p, 4, int64(kind), ba, 1, "end ", Encode(sum)})
|
||||||
} else {
|
} else {
|
||||||
values = append(values, [2]string{"end", ""})
|
lines = append(lines, asmOutLine{p, 4, int64(kind), []byte{0, 0, 0, 0}, 1, "end ", ""})
|
||||||
}
|
}
|
||||||
|
lines = append(lines, spacingLine)
|
||||||
header = true
|
header = true
|
||||||
continue
|
continue
|
||||||
|
|
||||||
case IRKindIdent:
|
case IRKindIdent:
|
||||||
|
var a []byte
|
||||||
// discard ancillary
|
// discard ancillary
|
||||||
if _, err = nextUint32(r); err != nil {
|
if a, _, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
var sum Checksum
|
var sum Checksum
|
||||||
if sum, err = nextIdent(r); err != nil {
|
if _, sum, err = nextIdent(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
values = append(values, [2]string{"id", Encode(sum)})
|
lines = append(lines, asmOutLine{p, 4, int64(kind), a, 1, "id ", Encode(sum)})
|
||||||
continue
|
continue
|
||||||
case IRKindUint32:
|
case IRKindUint32:
|
||||||
var i uint32
|
var i uint32
|
||||||
if i, err = nextUint32(r); err != nil {
|
var bi []byte
|
||||||
|
if bi, i, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
values = append(values, [2]string{"int", strconv.FormatUint(uint64(i), 10)})
|
lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "int ", strconv.FormatUint(uint64(i), 10)})
|
||||||
case IRKindString:
|
case IRKindString:
|
||||||
var l uint32
|
var l uint32
|
||||||
if l, err = nextUint32(r); err != nil {
|
var bl []byte
|
||||||
|
if bl, l, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize)
|
s := make([]byte, l+(wordSize-(l)%wordSize)%wordSize)
|
||||||
if _, err = r.Read(s); err != nil {
|
var n int
|
||||||
|
if n, err = r.Read(s); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
values = append(values, [2]string{"str", fmt.Sprintf("\"%s\"", string(s[:l]))})
|
*pos = *pos + n
|
||||||
|
|
||||||
|
lines = append(lines, asmOutLine{p, 4, int64(kind), bl, 1, "str ", strconv.Quote(string(s[:l]))})
|
||||||
continue
|
continue
|
||||||
default:
|
default:
|
||||||
var i uint32
|
var bi []byte
|
||||||
if i, err = nextUint32(r); err != nil {
|
if bi, _, err = nextUint32(r, pos); err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
values = append(values, [2]string{fmt.Sprintf("$%x", uint32(kind)), strconv.FormatUint(uint64(i), 10)})
|
lines = append(lines, asmOutLine{p, 4, int64(kind), bi, 1, "????", ""})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err != io.EOF {
|
if err != io.EOF {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = nil
|
err = nil
|
||||||
for i := 0; i < len(values); i++ {
|
for _, line := range lines {
|
||||||
sb.WriteString(fmt.Sprintf("%s\t\t%s\n", values[i][0], values[i][1]))
|
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
|
return sb.String(), err
|
||||||
}
|
}
|
||||||
func nextUint32(r io.Reader) (uint32, error) {
|
func nextUint32(r io.Reader, pos *int) ([]byte, uint32, error) {
|
||||||
i := make([]byte, 4)
|
i := make([]byte, 4)
|
||||||
_, err := r.Read(i)
|
_, err := r.Read(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return i, 0, err
|
||||||
}
|
}
|
||||||
return binary.LittleEndian.Uint32(i), nil
|
p := *pos + 4
|
||||||
|
*pos = p
|
||||||
|
return i, binary.LittleEndian.Uint32(i), nil
|
||||||
}
|
}
|
||||||
func nextUint64(r io.Reader) (uint64, error) {
|
func nextUint64(r io.Reader, pos *int) ([]byte, uint64, error) {
|
||||||
i := make([]byte, 8)
|
i := make([]byte, 8)
|
||||||
_, err := r.Read(i)
|
_, err := r.Read(i)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, err
|
return i, 0, err
|
||||||
}
|
}
|
||||||
return binary.LittleEndian.Uint64(i), nil
|
p := *pos + 8
|
||||||
|
*pos = p
|
||||||
|
return i, binary.LittleEndian.Uint64(i), nil
|
||||||
}
|
}
|
||||||
func nextIdent(r io.Reader) (Checksum, error) {
|
func nextIdent(r io.Reader, pos *int) ([]byte, Checksum, error) {
|
||||||
i := make([]byte, 48)
|
i := make([]byte, 48)
|
||||||
if _, err := r.Read(i); err != nil {
|
if _, err := r.Read(i); err != nil {
|
||||||
return Checksum{}, err
|
return i, Checksum{}, err
|
||||||
}
|
}
|
||||||
return Checksum(i), nil
|
p := *pos + 48
|
||||||
|
*pos = p
|
||||||
|
return i, Checksum(i), nil
|
||||||
}
|
}
|
||||||
func intToKind(i uint64) string {
|
func intToKind(i uint64) string {
|
||||||
switch Kind(i) {
|
switch Kind(i) {
|
||||||
case KindHTTPGet:
|
case KindHTTPGet:
|
||||||
return "http_get"
|
return "http"
|
||||||
case KindTar:
|
case KindTar:
|
||||||
return "tar"
|
return "tar "
|
||||||
case KindExec:
|
case KindExec:
|
||||||
return "exec"
|
return "exec"
|
||||||
case KindExecNet:
|
case KindExecNet:
|
||||||
return "exec_net"
|
return "exen"
|
||||||
case KindFile:
|
case KindFile:
|
||||||
return "file"
|
return "file"
|
||||||
default:
|
default:
|
||||||
return fmt.Sprintf("$%d", i-KindCustomOffset)
|
return fmt.Sprintf("$%d ", i-KindCustomOffset)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func headerSpacing(showHeader bool) string {
|
||||||
|
if showHeader {
|
||||||
|
return " "
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user