commit 925e7542e4c345ff0ce0efe619b8d594be6978d5
parent f34236640594648fceaea94eb5d760eb061c5156
Author: deurzen <m.deurzen@tum.de>
Date: Fri, 5 Feb 2021 00:57:45 +0100
adds recursive field access type resolution, array handling
Diffstat:
1 file changed, 44 insertions(+), 6 deletions(-)
diff --git a/project/type_dict.py b/project/type_dict.py
@@ -15,6 +15,7 @@
import json
import os, errno
import gdb
+import re
def delfile(name):
try:
@@ -42,15 +43,13 @@ class CodeDict():
try:
self.inf = open(self.in_n, "r")
except:
- print(f"No file {in_n} found! Run occ.sh first")
+ print(f"{in_n} file not found, run `occ.sh` first")
raise
delfile(self.out_n)
self.outf = open(self.out_n, "w+")
def parse(self):
- ignore = ["*", "->", "(", ")", "[", "]"]
-
line = self.inf.readline()
dir = len(line) - 1 if line[-1] == "/" else len(line)
@@ -58,13 +57,16 @@ class CodeDict():
# Remove directory prefix, insert ./ to reflect the frame representation of source file in gdb
l = ("./" + (line[dir:])).split(" ")
+ if len(l) < 5 or l[4] != "=":
+ continue
+
src = l[0]
fn = l[1]
lnr = l[2]
var = l[3]
- if any(s in var for s in ignore):
- continue
+ var = re.split('\-\>|\.', var)
+ var[0] = re.sub('[.*?]', '', var[0])
if fn == "<global>":
try:
@@ -73,11 +75,47 @@ class CodeDict():
continue
else:
try:
- type_info = gdb.execute(f"whatis '{fn}'::{var}", to_string = True)
+ type_info = gdb.execute(f"whatis '{fn}'::{var[0]}", to_string = True)
except:
continue
+ if len(var) > 1:
+ print("looking in", type_info[7:].strip(), "for", var[1:])
+ type_info = self.parse_chain(type_info[7:], var, 1)
+ print("FOUND:", type_info)
+
if type_info is not None:
key = f"{src}:{lnr}"
self.dict[key] = type_info.replace('\n','')
+
+ def parse_chain(self, next_type, chain, index):
+ # we're at the final field access, return its type
+ if index >= len(chain):
+ return next_type
+
+ # we need to look for the type of the next field in the field access chain
+ field = chain[index]
+ ptype = gdb.execute(f"ptype {next_type}", to_string = True).split("\n")[1:-2]
+
+ # loop over the compound type's fields, attempt to match field we're looking for
+ for f in ptype:
+ # account for possible bit field
+ bitmask = f.rfind(':')
+ if bitmask > 0:
+ f = f[:bitmask]
+
+ # account for possible array
+ f = re.sub('\[.*?\]', '', f)
+
+ # match on field name, everything preceding it is its type
+ name = re.search(f"[^_A-Za-z0-9]({field})[^_A-Za-z0-9]", f)
+
+ # field name was found, extract type and recurse if necessary
+ if bool(name):
+ return self.parse_chain(f[:name.start(1)], chain, index + 1)
+
+ # field not found
+ return None
+
+
CodeDict()