Skip to content

Commit 6e76622

Browse files
committed
WIP: x64_*,arm64: Add decoders
1 parent 94834c0 commit 6e76622

File tree

6 files changed

+132
-9
lines changed

6 files changed

+132
-9
lines changed

format/all/all.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
_ "github.com/wader/fq/format/icc"
2828
_ "github.com/wader/fq/format/id3"
2929
_ "github.com/wader/fq/format/inet"
30+
_ "github.com/wader/fq/format/isa"
3031
_ "github.com/wader/fq/format/jpeg"
3132
_ "github.com/wader/fq/format/json"
3233
_ "github.com/wader/fq/format/markdown"

format/elf/elf.go

Lines changed: 54 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,23 @@ import (
1616
"github.com/wader/fq/pkg/scalar"
1717
)
1818

19+
var x86_64Group decode.Group
20+
var arm64Group decode.Group
21+
1922
func init() {
2023
interp.RegisterFormat(
2124
format.Elf,
2225
&decode.Format{
2326
Description: "Executable and Linkable Format",
2427
Groups: []*decode.Group{format.Probe},
2528
DecodeFn: elfDecode,
26-
})
29+
Dependencies: []decode.Dependency{
30+
// TODO: x86 32/16?
31+
{Groups: []*decode.Group{format.X86_64}, Out: &x86_64Group},
32+
{Groups: []*decode.Group{format.Arm64}, Out: &arm64Group},
33+
},
34+
},
35+
)
2736
}
2837

2938
const (
@@ -167,6 +176,15 @@ var phTypeNames = scalar.UintRangeToScalar{
167176
{Range: [2]uint64{0x70000000, 0x7fffffff}, S: scalar.Uint{Sym: "proc", Description: "Processor-specific"}},
168177
}
169178

179+
var machineToFormatFn = map[int]func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)){
180+
EM_X86_64: func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)) {
181+
d.Format(&x86_64Group, format.X86_64In{Base: int64(base), SymLookup: symLookup})
182+
},
183+
EM_ARM64: func(d *decode.D, base uint64, symLookup func(uint64) (string, uint64)) {
184+
d.Format(&arm64Group, format.ARM64In{Base: int64(base), SymLookup: symLookup})
185+
},
186+
}
187+
170188
const (
171189
NT_PRSTATUS = 1
172190
NT_PRFPREG = 2
@@ -980,6 +998,8 @@ func elfDecodeDynamicTags(d *decode.D, ec elfContext, dc dynamicContext) {
980998
}
981999

9821000
func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
1001+
var execInstr bool
1002+
9831003
shFlags := func(d *decode.D, archBits int) {
9841004
d.FieldStruct("flags", func(d *decode.D) {
9851005
if d.Endian == decode.LittleEndian {
@@ -988,7 +1008,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
9881008
d.FieldBool("strings")
9891009
d.FieldBool("merge")
9901010
d.FieldU1("unused0")
991-
d.FieldBool("execinstr")
1011+
execInstr = d.FieldBool("execinstr")
9921012
d.FieldBool("alloc")
9931013
d.FieldBool("write")
9941014
d.FieldBool("tls")
@@ -1018,13 +1038,14 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10181038
d.FieldBool("strings")
10191039
d.FieldBool("merge")
10201040
d.FieldU1("unused2")
1021-
d.FieldBool("execinstr")
1041+
execInstr = d.FieldBool("execinstr")
10221042
d.FieldBool("alloc")
10231043
d.FieldBool("write")
10241044
}
10251045
})
10261046
}
10271047

1048+
var addr uint64
10281049
var offset int64
10291050
var size int64
10301051
var entSize int64
@@ -1035,7 +1056,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10351056
d.FieldU32("name", strTable(ec.strTabMap[STRTAB_SHSTRTAB]))
10361057
typ = d.FieldU32("type", sectionHeaderTypeMap, scalar.UintHex)
10371058
shFlags(d, ec.archBits)
1038-
d.FieldU("addr", ec.archBits, scalar.UintHex)
1059+
addr = d.FieldU("addr", ec.archBits, scalar.UintHex)
10391060
offset = int64(d.FieldU("offset", ec.archBits)) * 8
10401061
size = int64(d.FieldU32("size", scalar.UintHex) * 8)
10411062
d.FieldU32("link")
@@ -1046,7 +1067,7 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10461067
d.FieldU32("name", strTable(ec.strTabMap[STRTAB_SHSTRTAB]))
10471068
typ = d.FieldU32("type", sectionHeaderTypeMap, scalar.UintHex)
10481069
shFlags(d, ec.archBits)
1049-
d.FieldU("addr", ec.archBits, scalar.UintHex)
1070+
addr = d.FieldU("addr", ec.archBits, scalar.UintHex)
10501071
offset = int64(d.FieldU("offset", ec.archBits, scalar.UintHex) * 8)
10511072
size = int64(d.FieldU64("size") * 8)
10521073
d.FieldU32("link")
@@ -1079,9 +1100,34 @@ func elfDecodeSectionHeader(d *decode.D, ec elfContext, sh sectionHeader) {
10791100
elfDecodeSymbolTable(d, ec, int(size/entSize), ec.strTabMap[STRTAB_DYNSTR])
10801101
})
10811102
case SHT_PROGBITS:
1082-
// TODO: name progbits?
1083-
// TODO: decode opcodes
1084-
d.FieldRawLen("data", size)
1103+
// TODO: verify this, seems to result in strange relative addresses
1104+
symLookup := func(symAddr uint64) (string, uint64) {
1105+
var best *symbol
1106+
1107+
for _, sh := range ec.sections {
1108+
for i, s := range sh.symbols {
1109+
if symAddr >= s.value && (best == nil || symAddr-s.value < best.value-s.value) {
1110+
best = &sh.symbols[i]
1111+
}
1112+
}
1113+
}
1114+
if best == nil {
1115+
return "", 0
1116+
}
1117+
return strIndexNull(int(best.name), ec.strTabMap[STRTAB_STRTAB]), best.value
1118+
}
1119+
1120+
// TODO: name progbits? instructions?
1121+
if fn, ok := machineToFormatFn[ec.machine]; execInstr && ok {
1122+
d.FieldArray("code", func(d *decode.D) {
1123+
d.FramedFn(size, func(d *decode.D) {
1124+
fn(d, addr, symLookup)
1125+
})
1126+
})
1127+
} else {
1128+
d.FieldRawLen("data", size)
1129+
}
1130+
10851131
case SHT_GNU_HASH:
10861132
d.FieldStruct("gnu_hash", func(d *decode.D) {
10871133
elfDecodeGNUHash(d, ec, size, ec.strTabMap[STRTAB_DYNSTR])

format/format.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ var (
3535
Apev2 = &decode.Group{Name: "apev2"}
3636
AppleBookmark = &decode.Group{Name: "apple_bookmark"}
3737
Ar = &decode.Group{Name: "ar"}
38+
Arm64 = &decode.Group{Name: "arm64"}
3839
Asn1Ber = &decode.Group{Name: "asn1_ber"}
3940
Av1Ccr = &decode.Group{Name: "av1_ccr"}
4041
Av1Frame = &decode.Group{Name: "av1_frame"}
@@ -120,8 +121,8 @@ var (
120121
ProtobufWidevine = &decode.Group{Name: "protobuf_widevine"}
121122
PsshPlayready = &decode.Group{Name: "pssh_playready"}
122123
Rtmp = &decode.Group{Name: "rtmp"}
123-
SllPacket = &decode.Group{Name: "sll_packet"}
124124
Sll2Packet = &decode.Group{Name: "sll2_packet"}
125+
SllPacket = &decode.Group{Name: "sll_packet"}
125126
Tar = &decode.Group{Name: "tar"}
126127
TcpSegment = &decode.Group{Name: "tcp_segment"}
127128
Tiff = &decode.Group{Name: "tiff"}
@@ -138,6 +139,9 @@ var (
138139
Wasm = &decode.Group{Name: "wasm"}
139140
Wav = &decode.Group{Name: "wav"}
140141
Webp = &decode.Group{Name: "webp"}
142+
X86_16 = &decode.Group{Name: "x86_16"}
143+
X86_32 = &decode.Group{Name: "x86_32"}
144+
X86_64 = &decode.Group{Name: "x86_64"}
141145
Xml = &decode.Group{Name: "xml"}
142146
Yaml = &decode.Group{Name: "yaml"}
143147
Zip = &decode.Group{Name: "zip"}
@@ -341,3 +345,13 @@ type BitCoinBlockIn struct {
341345
type TLSIn struct {
342346
Keylog string `doc:"NSS Key Log content"`
343347
}
348+
349+
type X86_64In struct {
350+
SymLookup func(symAddr uint64) (string, uint64)
351+
Base int64
352+
}
353+
354+
type ARM64In struct {
355+
SymLookup func(symAddr uint64) (string, uint64)
356+
Base int64
357+
}

format/isa/arm64.go

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package isa
2+
3+
import (
4+
"strings"
5+
6+
"github.com/wader/fq/format"
7+
"github.com/wader/fq/pkg/decode"
8+
"github.com/wader/fq/pkg/interp"
9+
"github.com/wader/fq/pkg/scalar"
10+
"golang.org/x/arch/arm64/arm64asm"
11+
)
12+
13+
func init() {
14+
interp.RegisterFormat(
15+
format.Arm64,
16+
&decode.Format{
17+
Description: "ARM64 instructions",
18+
DecodeFn: decodeARM64,
19+
RootArray: true,
20+
RootName: "instructions",
21+
})
22+
}
23+
24+
func decodeARM64(d *decode.D) any {
25+
var symLookup func(uint64) (string, uint64)
26+
var base int64
27+
var ai format.ARM64In
28+
29+
if d.ArgAs(&ai) {
30+
symLookup = ai.SymLookup
31+
base = ai.Base
32+
}
33+
34+
bb := d.BytesRange(0, int(d.BitsLeft()/8))
35+
// TODO: uint64?
36+
pc := base
37+
38+
for !d.End() {
39+
d.FieldStruct("instruction", func(d *decode.D) {
40+
i, err := arm64asm.Decode(bb)
41+
if err != nil {
42+
d.Fatalf("failed to decode arm64 instruction: %s", err)
43+
}
44+
45+
// TODO: other syntax
46+
d.FieldRawLen("opcode", int64(4)*8, scalar.BitBufSym(arm64asm.GoSyntax(i, uint64(pc), symLookup, nil)), scalar.RawHex)
47+
48+
// TODO: Enc?
49+
d.FieldValueUint("op", uint64(i.Enc), scalar.UintSym(strings.ToLower(i.Op.String())), scalar.UintHex)
50+
51+
bb = bb[4:]
52+
pc += int64(4)
53+
})
54+
55+
}
56+
57+
return nil
58+
}

go.mod

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,8 @@ require (
7474
gopkg.in/yaml.v3 v3.0.1
7575
)
7676

77+
require golang.org/x/arch v0.0.0-20220401014709-5424468ecbac
78+
7779
require (
7880
github.com/itchyny/timefmt-go v0.1.5 // indirect
7981
github.com/mitchellh/reflectwalk v1.0.2 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ github.com/wader/gojq v0.12.1-0.20230308145020-2de2194791c0 h1:OjBLxUJRtmoYbNtgB
2727
github.com/wader/gojq v0.12.1-0.20230308145020-2de2194791c0/go.mod h1:jQY39j9tgky+JYcJrKNz5OYTe/sPDAw7FvVj13JGqVk=
2828
github.com/wader/readline v0.0.0-20230307172220-bcb7158e7448 h1:AzpBtmgdXa3uznrb3esNeEoaLqtNEwckRmaUH0qWD6w=
2929
github.com/wader/readline v0.0.0-20230307172220-bcb7158e7448/go.mod h1:Zgz8IJWvJoe7NK23CCPpC109XMCqJCpUhpHcnnA4XaM=
30+
golang.org/x/arch v0.0.0-20220401014709-5424468ecbac h1:05z6X/pDgf2qll8x7kbRRVdr33GjdV/GOCGiQfnaJS8=
31+
golang.org/x/arch v0.0.0-20220401014709-5424468ecbac/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
3032
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
3133
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
3234
golang.org/x/exp v0.0.0-20230131160201-f062dba9d201 h1:BEABXpNXLEz0WxtA+6CQIz2xkg80e+1zrhWyMcq8VzE=

0 commit comments

Comments
 (0)