Skip to content

Commit

Permalink
WIP: x64_*,arm64: Add decoders
Browse files Browse the repository at this point in the history
  • Loading branch information
wader committed Apr 1, 2022
1 parent 2a8104d commit 5e01085
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 7 deletions.
1 change: 1 addition & 0 deletions format/all/all.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
_ "github.com/wader/fq/format/icc"
_ "github.com/wader/fq/format/id3"
_ "github.com/wader/fq/format/inet"
_ "github.com/wader/fq/format/isa"
_ "github.com/wader/fq/format/jpeg"
_ "github.com/wader/fq/format/json"
_ "github.com/wader/fq/format/macho"
Expand Down
59 changes: 52 additions & 7 deletions format/elf/elf.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ import (
"github.com/wader/fq/pkg/scalar"
)

var x86_64Format decode.Group
var arm64Format decode.Group

func init() {
registry.MustRegister(decode.Format{
Name: format.ELF,
Description: "Executable and Linkable Format",
Groups: []string{format.PROBE},
DecodeFn: elfDecode,
Dependencies: []decode.Dependency{
// TODO: x86_32?
{Names: []string{format.X86_64}, Group: &x86_64Format},
{Names: []string{format.ARM64}, Group: &arm64Format},
},
})
}

Expand Down Expand Up @@ -131,6 +139,15 @@ var machineNames = scalar.UToScalar{
0x101: {Sym: "wdc_65C816", Description: "WDC 65C816"},
}

var machineToFormatFn = map[int]func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)){
EM_X86_64: func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)) {
d.Format(x86_64Format, format.X86_64In{Base: int64(base), SymLookup: symLookup})
},
EM_ARM64: func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)) {
d.Format(arm64Format, format.ARM64In{Base: int64(base), SymLookup: symLookup})
},
}

var phTypeNames = scalar.URangeToScalar{
{Range: [2]uint64{0x00000000, 0x00000000}, S: scalar.S{Sym: "null", Description: "Unused element"}},
{Range: [2]uint64{0x00000001, 0x00000001}, S: scalar.S{Sym: "load", Description: "Loadable segment"}},
Expand Down Expand Up @@ -767,6 +784,8 @@ func elfDecodeDynamicTags(d *decode.D, ec elfContext, dc dynamicContext) {
}

func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
var execInstr bool

shFlags := func(d *decode.D, archBits int) {
d.FieldStruct("flags", func(d *decode.D) {
if d.Endian == decode.LittleEndian {
Expand All @@ -775,7 +794,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
d.FieldBool("strings")
d.FieldBool("merge")
d.FieldU1("unused0")
d.FieldBool("execinstr")
execInstr = d.FieldBool("execinstr")
d.FieldBool("alloc")
d.FieldBool("write")
d.FieldBool("tls")
Expand Down Expand Up @@ -805,13 +824,14 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
d.FieldBool("strings")
d.FieldBool("merge")
d.FieldU1("unused2")
d.FieldBool("execinstr")
execInstr = d.FieldBool("execinstr")
d.FieldBool("alloc")
d.FieldBool("write")
}
})
}

var addr uint64
var offset int64
var size int64
var entSize int64
Expand All @@ -822,7 +842,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
d.FieldU32("name", strTable(ec.strTabMap[STRTAB_SHSTRTAB]))
typ = d.FieldU32("type", sectionHeaderTypeMap, scalar.Hex)
shFlags(d, ec.archBits)
d.FieldU("addr", ec.archBits, scalar.Hex)
addr = d.FieldU("addr", ec.archBits, scalar.Hex)
offset = int64(d.FieldU("offset", ec.archBits)) * 8
size = int64(d.FieldU32("size", scalar.Hex) * 8)
d.FieldU32("link")
Expand All @@ -833,7 +853,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
d.FieldU32("name", strTable(ec.strTabMap[STRTAB_SHSTRTAB]))
typ = d.FieldU32("type", sectionHeaderTypeMap, scalar.Hex)
shFlags(d, ec.archBits)
d.FieldU("addr", ec.archBits, scalar.Hex)
addr = d.FieldU("addr", ec.archBits, scalar.Hex)
offset = int64(d.FieldU("offset", ec.archBits, scalar.Hex) * 8)
size = int64(d.FieldU64("size") * 8)
d.FieldU32("link")
Expand Down Expand Up @@ -866,9 +886,34 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
elfDecodeSymbolTable(d, ec, int(size/entSize), ec.strTabMap[STRTAB_DYNSTR])
})
case SHT_PROGBITS:
// TODO: name progbits?
// TODO: decode opcodes
d.FieldRawLen("data", size)
// TODO: verify this, seems to result in strange relative addresses
symLookup := func(symAddr uint64) (string, uint64) {
var best *symbol

for _, sh := range ec.sections {
for i, s := range sh.symbols {
if symAddr >= s.value && (best == nil || symAddr-s.value < best.value-s.value) {
best = &sh.symbols[i]
}
}
}
if best == nil {
return "", 0
}
return strIndexNull(int(best.name), ec.strTabMap[STRTAB_STRTAB]), best.value
}

// TODO: name progbits? instructions?
if fn, ok := machineToFormatFn[ec.machine]; execInstr && ok {
d.FieldArray("code", func(d *decode.D) {
d.FramedFn(size, func(d *decode.D) {
fn(d, addr, symLookup)
})
})
} else {
d.FieldRawLen("data", size)
}

case SHT_GNU_HASH:
d.FieldStruct("gnu_hash", func(d *decode.D) {
elfDecodeGNUHash(d, ec, size, ec.strTabMap[STRTAB_DYNSTR])
Expand Down
4 changes: 4 additions & 0 deletions format/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ const (
AMF0 = "amf0"
APEV2 = "apev2"
AR = "ar"
ARM64 = "arm64"
ASN1_BER = "asn1_ber"
AV1_CCR = "av1_ccr"
AV1_FRAME = "av1_frame"
Expand Down Expand Up @@ -99,6 +100,9 @@ const (
VPX_CCR = "vpx_ccr"
WAV = "wav"
WEBP = "webp"
X86_16 = "x86_16"
X86_32 = "x86_32"
X86_64 = "x86_64"
XING = "xing"
ZIP = "zip"
)
Expand Down
55 changes: 55 additions & 0 deletions format/isa/arm64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package isa

import (
"strings"

"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
"golang.org/x/arch/arm64/arm64asm"
)

func init() {
registry.MustRegister(decode.Format{
Name: format.ARM64,
Description: "ARM64 instructions",
DecodeFn: decodeARM64,
RootArray: true,
RootName: "instructions",
})
}

func decodeARM64(d *decode.D, in interface{}) interface{} {
var symLookup func(uint64) (string, uint64)
var base int64
if xi, ok := in.(format.ARM64In); ok {
symLookup = xi.SymLookup
base = xi.Base
}

bb := d.BytesRange(0, int(d.BitsLeft()/8))
// TODO: uint64?
pc := base

for !d.End() {
d.FieldStruct("instruction", func(d *decode.D) {
i, err := arm64asm.Decode(bb)
if err != nil {
d.Fatalf("failed to decode arm64 instruction: %s", err)
}

// TODO: other syntax
d.FieldRawLen("opcode", int64(4)*8, scalar.Sym(arm64asm.GoSyntax(i, uint64(pc), symLookup, nil)), scalar.Hex)

// TODO: Enc?
d.FieldValueU("op", uint64(i.Enc), scalar.Sym(strings.ToLower(i.Op.String())), scalar.Hex)

bb = bb[4:]
pc += int64(4)
})

}

return nil
}
73 changes: 73 additions & 0 deletions format/isa/x86_64.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package isa

import (
"strings"

"github.com/wader/fq/format"
"github.com/wader/fq/format/registry"
"github.com/wader/fq/pkg/decode"
"github.com/wader/fq/pkg/scalar"
"golang.org/x/arch/x86/x86asm"
)

func init() {
// amd64?
registry.MustRegister(decode.Format{
Name: format.X86_64,
Description: "x86-64 instructions",
DecodeFn: func(d *decode.D, in interface{}) interface{} { return decodeX86(d, in, 64) },
RootArray: true,
RootName: "instructions",
})
registry.MustRegister(decode.Format{
Name: format.X86_32,
Description: "x86-32 instructions",
DecodeFn: func(d *decode.D, in interface{}) interface{} { return decodeX86(d, in, 32) },
RootArray: true,
RootName: "instructions",
})
registry.MustRegister(decode.Format{
Name: format.X86_16,
Description: "x86-16 instructions",
DecodeFn: func(d *decode.D, in interface{}) interface{} { return decodeX86(d, in, 16) },
RootArray: true,
RootName: "instructions",
})
}

func decodeX86(d *decode.D, in interface{}, mode int) interface{} {
var symLookup func(uint64) (string, uint64)
var base int64
if xi, ok := in.(format.X86_64In); ok {
symLookup = xi.SymLookup
base = xi.Base
}

bb := d.BytesRange(0, int(d.BitsLeft()/8))
// TODO: uint64?
pc := base

for !d.End() {
d.FieldStruct("instruction", func(d *decode.D) {
i, err := x86asm.Decode(bb, mode)
if err != nil {
d.Fatalf("failed to decode x86 instruction: %s", err)
}

d.FieldRawLen("opcode", int64(i.Len)*8, scalar.Sym(x86asm.IntelSyntax(i, uint64(pc), symLookup)), scalar.Hex)

// log.Printf("i.Len: %#+v\n", i.Len)
// log.Printf("i.Opcode: %x\n", i.Opcode)
// log.Printf("i: %#+v\n", i)

// TODO: rebuild op lower?
d.FieldValueU("op", uint64(i.Opcode), scalar.Sym(strings.ToLower(i.Op.String())), scalar.Hex)

bb = bb[i.Len:]
pc += int64(i.Len)
})

}

return nil
}
2 changes: 2 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ require (
golang.org/x/text v0.3.7
)

require golang.org/x/arch v0.0.0-20220401014709-5424468ecbac

require (
github.com/itchyny/timefmt-go v0.1.3 // indirect
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
Expand Down
3 changes: 3 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ github.com/wader/gojq v0.12.1-0.20220328204148-c4e42b829bf0 h1:rj+NshD1TyRazsy+H
github.com/wader/gojq v0.12.1-0.20220328204148-c4e42b829bf0/go.mod h1:Pq2wrnwmiGxsaT62vOTEXkH3J3tI81VHJ2K2ZePP6oI=
github.com/wader/readline v0.0.0-20220117233529-692d84ca36e2 h1:AK4wt6mSypGEVAzUcCfrJqVD5hju+w81b9J/k0swV/8=
github.com/wader/readline v0.0.0-20220117233529-692d84ca36e2/go.mod h1:TJUJCkylZhI0Z07t2Nw6l6Ck7NiZqUpnMlkjEzN7+yM=
golang.org/x/arch v0.0.0-20220401014709-5424468ecbac h1:05z6X/pDgf2qll8x7kbRRVdr33GjdV/GOCGiQfnaJS8=
golang.org/x/arch v0.0.0-20220401014709-5424468ecbac/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
Expand All @@ -37,3 +39,4 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

0 comments on commit 5e01085

Please sign in to comment.