-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhdec.py
155 lines (127 loc) · 4.4 KB
/
hdec.py
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import sys
import bitstring # sudo pip install bitstring
from bitstring import BitStream, Bits
import struct
class Field:
def __init__(self, name, bits, types, prefix = "", condition = "True"):
self.name = name
self.bits = bits
self.types = types
self.prefix = prefix
self.condition = condition
def __repr__(self):
return self.name + " (" + str(self.bits) + ")"
def getBits(self):
return self.bits
def getName(self):
return self.name
def getTypes(self):
t = []
for ty in self.types:
if ty[-1] == 'E':
t.append((ty[:-1], True))
else:
t.append((ty, False))
return t
def getPrefix(self):
return self.prefix
def getCondition(self):
return self.condition
def parseDefinition(definition, bits = []):
with open(definition) as df:
d = df.readlines()
for l in d:
p = l.split(":")
name = p[0].strip()
bitlen = p[1].strip()
ptypes = ["hex", "int", "bin"]
cond = "True"
if len(p) >= 3:
ptypes = list(map(lambda x: x.strip(), p[2].strip().split(",")))
if len(p) == 4:
cond = p[3].strip()
bits.append(Field(name, bitlen, ptypes, definition, cond))
return bits
def endianness(x, endian, bits):
if endian:
if bits == 32:
return (((x << 24) & 0xFF000000) | ((x << 8) & 0x00FF0000) | ((x >> 8) & 0x0000FF00) | ((x >> 24) & 0x000000FF))
elif bits == 16:
return (((x << 8) & 0xFF00) | ((x >> 8) & 0x00FF))
else:
return x
else:
return x
def main(argv):
if len(argv) < 4:
print("Usage: " + argv[0] + " <header dump> <type (hex|bin|raw)> <definition>")
return
filename = argv[1]
typ = argv[2]
definition = []
for argc in range(3, len(argv)):
definition.append(argv[argc])
print("File: " + filename)
print("Definition: " + ", ".join(definition))
print("Type: " + typ)
bits = []
for d in definition:
bits = parseDefinition(d, bits)
content = None
field = None
with open(filename) as f:
if typ == "hex":
content = f.read().strip()
field = BitStream("0x" + content)
if typ == "bin":
content = f.read().strip()
field = BitStream("0b" + content)
if typ == "raw":
field = BitStream(f)
parsed = {}
pos = 0
last_header = None
for bit in bits:
field.pos = pos
bitlen = 0
lenexpr = bit.getBits()
condexpr = bit.getCondition()
for p in sorted(parsed.keys(), key=len, reverse=True):
lenexpr = lenexpr.replace(p, str(parsed[p]))
condexpr = condexpr.replace(p, str(parsed[p]))
try:
bitlen = eval(lenexpr)
except:
print("Error: " + str(bit.getBits()) + " is not a valid size!")
return
try:
cond = eval(condexpr)
except:
print("Error: " + str(bit.getCondition()) + " is not a valid condition! (Parsed to " + condexpr + ")")
return
if cond:
try:
val = field.read(bitlen)
except:
print("Could not read field " + str(bit.getName()) + " with " + str(bitlen) + " bits!")
continue
parsed[bit.getName()] = val.uint
pos += bitlen
if last_header is not bit.getPrefix():
last_header = bit.getPrefix()
print("")
out = bit.getName() + ": "
for t, endian in bit.getTypes():
if t == "hex":
out += "0x" + val.hex + " "
if t == "int":
out += str(endianness(val.uint, endian, int(bitlen))) + " "
if t == "bin":
out += "0b" + val.bin + " "
if t == "str":
s = ""
for si in range(0, len(str(val)[2:]), 2):
out += str(chr(int(str(val)[si + 2:si + 4], 16)))
print(out)
if __name__ == "__main__":
main(sys.argv)