commit 9f3ba4948a2d0219cbddfd5654ab40727682f20f
parent 029f0e11d30363a1f6617bb4236a91681e98789f
Author: Tizian Leonhardt <tizianleonhardt@web.de>
Date: Fri, 5 Feb 2021 13:07:42 +0100
Merging
Diffstat:
2 files changed, 59 insertions(+), 8 deletions(-)
diff --git a/project/extract_sizeret.py b/project/extract_sizeret.py
@@ -9,11 +9,20 @@ break_arg = {
"kmem_cache_alloc_trace": "rdx",
"kmalloc_order": "rdi",
"__kmalloc": "rdi",
+ "vmalloc": "rdi",
+ "vzalloc": "rdi",
+ "vmalloc_user": "rdi",
+ "vmalloc_node": "rdi",
+ "vzalloc_node": "rdi",
+ "vmalloc_exec": "rdi",
+ "vmalloc_32": "rdi",
+ "vmalloc_32_user": "rdi",
}
free_funcs = {
+ # *v*free variants all call kfree
"kfree": "rdi",
- "kmem_cache_free" : "rsi"
+ "kmem_cache_free" : "rsi",
}
entries = set()
@@ -69,6 +78,7 @@ class EntryExitBreakpoint(gdb.Breakpoint):
(size, address) = extret
mem_map[address] = (type, size, caller)
+ print("Allocating ", (type, size, caller))
return False
def extract(self, frame):
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,26 +43,27 @@ 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 = ["*", "->", "(", ")", "[", "]"]
-
for line in self.inf.readlines():
# Insert ./ to reflect the frame representation of source file in gdb
- l = "./" + line
+ l = ("./" + line).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:
@@ -70,11 +72,50 @@ 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]
+ field = re.sub('\[.*?\]', '', field)
+
+ # obtain the fields of the compound type to search through
+ 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
+ bitfield = f.rfind(':')
+ if bitfield > 0:
+ f = f[:bitfield]
+
+ # account for possible array
+ f = re.sub('\[.*?\]', '', f)
+
+ # match on field name, everything preceding it is its type
+ name = re.search(f"[^_A-Za-z]({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()