This repository has been archived by the owner on Jan 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 3
/
arm64.go
131 lines (105 loc) · 2.72 KB
/
arm64.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package arm64
import (
"encoding/binary"
"fmt"
"io"
)
// Options Disassemble options
type Options struct {
StartAddress int64
DecimalImm bool
}
// Result Disassemble instruction result
type Result struct {
StrRepr string
Instruction *Instruction
Error error
}
// Disassemble will output the disassembly of the data of a given io.ReadSeeker
func Disassemble(r io.ReadSeeker, options Options) <-chan Result {
out := make(chan Result)
go func() {
var err error
var instrValue uint32
for {
addr, _ := r.Seek(0, io.SeekCurrent)
err = binary.Read(r, binary.LittleEndian, &instrValue)
if err == io.EOF {
close(out)
break
}
if err != nil {
out <- Result{
Error: fmt.Errorf("failed to read instruction: %v", err),
}
close(out)
break
}
if options.StartAddress != 0 {
addr += options.StartAddress
} else {
addr = 0
}
i, err := decompose(instrValue, uint64(addr))
if err != nil {
if err == failedToDecodeInstruction {
out <- Result{
StrRepr: fmt.Sprintf("%#08x: %s\t<unknown>", uint64(addr), getOpCodeByteString(instrValue)),
Error: fmt.Errorf("failed to decode instruction: 0x%08x; %v", instrValue, err),
}
} else {
out <- Result{
StrRepr: fmt.Sprintf("%#08x: %s\t💥 ERROR 💥", uint64(addr), getOpCodeByteString(instrValue)),
Error: fmt.Errorf("failed to decode instruction: 0x%08x; %v", instrValue, err),
}
}
continue
}
instruction, err := i.disassemble(options.DecimalImm)
if err != nil {
out <- Result{
StrRepr: fmt.Sprintf("%#08x: %s\t<unknown>", uint64(addr), getOpCodeByteString(instrValue)),
Error: fmt.Errorf("failed to disassemble instruction: 0x%08x; %v", instrValue, err),
}
continue
}
out <- Result{
StrRepr: fmt.Sprintf("%#08x: %s\t%s", uint64(addr), getOpCodeByteString(instrValue), instruction),
Instruction: i,
Error: nil,
}
}
return
}()
return out
}
// Instructions will output the decoded instructions of the data of a given io.ReadSeeker
func Instructions(r io.ReadSeeker, startAddr int64) (<-chan *Instruction, error) {
out := make(chan *Instruction)
go func() error {
var instrValue uint32
for {
addr, _ := r.Seek(0, io.SeekCurrent)
err := binary.Read(r, binary.LittleEndian, &instrValue)
if err == io.EOF {
break
}
if err != nil {
return fmt.Errorf("failed to read instruction: %v", err)
}
if startAddr > 0 {
addr += startAddr
} else {
addr = 0
}
i, err := decompose(instrValue, 0)
if err != nil {
return fmt.Errorf("failed to decompose instruction: 0x%08x; %v", instrValue, err)
}
out <- i
}
close(out)
return nil
}()
return out, nil
}