summaryrefslogtreecommitdiff
path: root/python/examples/debug_info.py
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2022-01-27 22:43:28 -0500
committerKyleMiles <krm504@nyu.edu>2022-01-28 00:24:06 -0500
commit6812c973c9fa9b4ad642ab81856c05f87bd6fcc4 (patch)
treedace4156d03148bcaf02df138ab4e0d93e61bc6f /python/examples/debug_info.py
parent519c9db22367f2659d1a54599fab47e6313be06e (diff)
Format All Files
Diffstat (limited to 'python/examples/debug_info.py')
-rwxr-xr-xpython/examples/debug_info.py151
1 files changed, 87 insertions, 64 deletions
diff --git a/python/examples/debug_info.py b/python/examples/debug_info.py
index 8f379544..28175ba1 100755
--- a/python/examples/debug_info.py
+++ b/python/examples/debug_info.py
@@ -29,7 +29,6 @@
# bv.apply_debug_info(debug_info)
# ```
-
# The rest of this file serves as a test and example of implementing debug info parsers, and the resultant debug info.
#
# All that is required is to provide functions similar to "is_valid" and "parse_info" below, and call
@@ -98,50 +97,56 @@
# }
# ```
-
import binaryninja as bn
import os
-
filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), "test_debug_info")
-
# Some setup code not just for informative printing
-
print = print
if __name__ != "__main__":
- print = bn.log_error
+ print = bn.log_error
-def pretty_print_add_data_variable(debug_info: bn.debuginfo.DebugInfo, address: int, t: bn.types.Type, name: str = None) -> None:
- print(f" Adding data variable of type `{t}` at {hex(address)} : {debug_info.add_data_variable(address, t, name)}")
+def pretty_print_add_data_variable(
+ debug_info: bn.debuginfo.DebugInfo, address: int, t: bn.types.Type, name: str = None
+) -> None:
+ print(f" Adding data variable of type `{t}` at {hex(address)} : {debug_info.add_data_variable(address, t, name)}")
-def pretty_print_add_function(debug_info: bn.debuginfo.DebugInfo, address: int, short_name: str = None, full_name: str = None, raw_name: str = None, return_type = None, parameters = None) -> None:
- function_info = bn.debuginfo.DebugFunctionInfo(address, short_name, full_name, raw_name, return_type, parameters)
- if parameters is not None:
- print(f" Adding function `{return_type} {short_name}({', '.join(f'{t} {name}' for name, t in parameters)})` at {hex(address)} : {debug_info.add_function(function_info)}")
- else:
- print(f" Adding function `{return_type} {short_name}()` at {hex(address)} : {debug_info.add_function(function_info)}")
+def pretty_print_add_function(
+ debug_info: bn.debuginfo.DebugInfo, address: int, short_name: str = None, full_name: str = None, raw_name: str = None,
+ return_type=None, parameters=None
+) -> None:
+ function_info = bn.debuginfo.DebugFunctionInfo(address, short_name, full_name, raw_name, return_type, parameters)
+ if parameters is not None:
+ print(
+ f" Adding function `{return_type} {short_name}({', '.join(f'{t} {name}' for name, t in parameters)})` at {hex(address)} : {debug_info.add_function(function_info)}"
+ )
+ else:
+ print(
+ f" Adding function `{return_type} {short_name}()` at {hex(address)} : {debug_info.add_function(function_info)}"
+ )
# The beginning of the actual debug info plugin
def is_valid(bv: bn.binaryview.BinaryView):
- sym = bv.get_symbol_by_raw_name("__elf_interp")
- if sym is None:
- return False
- else:
- var = bv.get_data_var_at(sym.address)
- return b"test_debug_info_parsing" == bv.read(sym.address, var.type.width-1)
+ sym = bv.get_symbol_by_raw_name("__elf_interp")
+ if sym is None:
+ return False
+ else:
+ var = bv.get_data_var_at(sym.address)
+ return b"test_debug_info_parsing" == bv.read(sym.address, var.type.width - 1)
def parse_info(debug_info: bn.debuginfo.DebugInfo, bv: bn.binaryview.BinaryView):
- print("Adding types")
- types = []
- for name, t in bv.parse_types_from_string("""
+ print("Adding types")
+ types = []
+ for name, t in bv.parse_types_from_string(
+ """
struct test_type_1 {
int a;
char b[4];
@@ -153,62 +158,81 @@ def parse_info(debug_info: bn.debuginfo.DebugInfo, bv: bn.binaryview.BinaryView)
struct test_type_1 a;
struct test_type_1* b;
struct test_type_2* c;
- };""").types.items():
- print(f" Adding type \"{name}\" `{t}` : {debug_info.add_type(str(name), t)}")
- types.append(t)
+ };"""
+ ).types.items():
+ print(f" Adding type \"{name}\" `{t}` : {debug_info.add_type(str(name), t)}")
+ types.append(t)
- print("Adding data variables")
- pretty_print_add_data_variable(debug_info, 0x4030, types[0], "test_var_1")
- pretty_print_add_data_variable(debug_info, 0x4010, bn.types.Type.int(4, True), "test_var_2")
- # Names are optional
- pretty_print_add_data_variable(debug_info, 0x4014, bn.types.Type.int(4, True))
+ print("Adding data variables")
+ pretty_print_add_data_variable(debug_info, 0x4030, types[0], "test_var_1")
+ pretty_print_add_data_variable(debug_info, 0x4010, bn.types.Type.int(4, True), "test_var_2")
+ # Names are optional
+ pretty_print_add_data_variable(debug_info, 0x4014, bn.types.Type.int(4, True))
- t = bn.types.Type.int(4, True)
- t.const = True
- pretty_print_add_data_variable(debug_info, 0x2004, t, "test_var_3")
+ t = bn.types.Type.int(4, True)
+ t.const = True
+ pretty_print_add_data_variable(debug_info, 0x2004, t, "test_var_3")
- print("Adding functions")
- char_star = bv.parse_type_string("char*")[0]
- pretty_print_add_function(debug_info, 0x1129, "no_return_type_no_parameters", None, None, bn.types.Type.void(), None)
- pretty_print_add_function(debug_info, 0x1134, "used_parameter", None, None, bn.types.Type.bool(), [("value", bn.types.Type.bool())])
- pretty_print_add_function(debug_info, 0x1155, "unused_parameters", None, None, bn.types.Type.int(4, True), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star)])
- pretty_print_add_function(debug_info, 0x1170, "used_and_unused_parameters_1", None, None, bn.types.Type.int(4, True), [("value_1", bn.types.Type.int(4, True)), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star), ("value_4", bn.types.Type.bool())])
- pretty_print_add_function(debug_info, 0x1191, "used_and_unused_parameters_2", None, None, bn.types.Type.int(1, False), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(1, False)), ("value_3", char_star), ("value_4", bn.types.Type.int(1, False)), ("value_5", bn.types.Type.char())])
- pretty_print_add_function(debug_info, 0x11c0, "local_parameters", None, None, bn.types.Type.void(), [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(1, False)), ("value_3", char_star), ("value_4", bn.types.Type.int(1, False)), ("value_5", bn.types.Type.char())])
+ print("Adding functions")
+ char_star = bv.parse_type_string("char*")[0]
+ pretty_print_add_function(debug_info, 0x1129, "no_return_type_no_parameters", None, None, bn.types.Type.void(), None)
+ pretty_print_add_function(
+ debug_info, 0x1134, "used_parameter", None, None, bn.types.Type.bool(), [("value", bn.types.Type.bool())]
+ )
+ pretty_print_add_function(
+ debug_info, 0x1155, "unused_parameters", None, None, bn.types.Type.int(4, True),
+ [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star)]
+ )
+ pretty_print_add_function(
+ debug_info, 0x1170, "used_and_unused_parameters_1", None, None, bn.types.Type.int(4, True),
+ [("value_1", bn.types.Type.int(4, True)), ("value_2", bn.types.Type.int(4, True)), ("value_3", char_star),
+ ("value_4", bn.types.Type.bool())]
+ )
+ pretty_print_add_function(
+ debug_info, 0x1191, "used_and_unused_parameters_2", None, None, bn.types.Type.int(1, False),
+ [("value_1", bn.types.Type.bool()), ("value_2", bn.types.Type.int(1, False)), ("value_3", char_star),
+ ("value_4", bn.types.Type.int(1, False)), ("value_5", bn.types.Type.char())]
+ )
+ pretty_print_add_function(
+ debug_info, 0x11c0, "local_parameters", None, None, bn.types.Type.void(), [("value_1", bn.types.Type.bool()),
+ ("value_2", bn.types.Type.int(1, False)),
+ ("value_3", char_star),
+ ("value_4", bn.types.Type.int(1, False)),
+ ("value_5", bn.types.Type.char())]
+ )
parser = bn.debuginfo.DebugInfoParser.register("test debug info parser", is_valid, parse_info)
print(f"Registered parser: {parser.name}")
-
# The above is all that is needed for a DebugInfo plugin
# The below serves to test the correctness of (the Python bindings' implementation of) debug info parsers' functionality.
-
bn.debuginfo.DebugInfoParser.register("dummy extra debug parser 1", lambda bv: False, lambda di, bv: None)
-bn.debuginfo.DebugInfoParser.register("dummy extra debug parser 2", lambda bv: bv.view_type != "Raw", lambda di, bv: None)
+bn.debuginfo.DebugInfoParser.register(
+ "dummy extra debug parser 2", lambda bv: bv.view_type != "Raw", lambda di, bv: None
+)
# Test fetching parser list and fetching by name
print(f"Availible parsers: {len(list(bn.debuginfo.DebugInfoParser))}")
for p in bn.debuginfo.DebugInfoParser:
- if p == parser:
- print(f" {bn.debuginfo.DebugInfoParser[p.name].name} (the one we just registered)")
- else:
- print(f" {bn.debuginfo.DebugInfoParser[p.name].name}")
+ if p == parser:
+ print(f" {bn.debuginfo.DebugInfoParser[p.name].name} (the one we just registered)")
+ else:
+ print(f" {bn.debuginfo.DebugInfoParser[p.name].name}")
# Test calling our `is_valid` callback
bv = bn.open_view(filename, options={"analysis.experimental.parseDebugInfo": False})
if parser.is_valid_for_view(bv):
- print("Parser is valid")
+ print("Parser is valid")
else:
- print("Parser is NOT valid!")
- quit()
-
+ print("Parser is NOT valid!")
+ quit()
# Test getting list of valid parsers, and DebugInfoParser's repr
print("")
for p in bn.debuginfo.DebugInfoParser.get_parsers_for_view(bv):
- print(f"`{p.name}` is valid for `{bv}`")
+ print(f"`{p.name}` is valid for `{bv}`")
print("")
# Test calling our `parse_info` callback
@@ -219,32 +243,31 @@ print("\nEach of the following pairs of prints should be the same\n")
print("All types:")
for name, t in debug_info.types:
- print(f" \"{name}\": `{t}`")
+ print(f" \"{name}\": `{t}`")
print("Types from parser:")
for name, t in debug_info.types_from_parser(parser.name):
- print(f" \"{name}\": `{t}`")
+ print(f" \"{name}\": `{t}`")
print("")
print("All functions:")
for func in debug_info.functions:
- print(f" {func}")
+ print(f" {func}")
print("Functions from parser:")
for func in debug_info.functions_from_parser(parser.name):
- print(f" {func}")
+ print(f" {func}")
print("")
print("All data variables:")
for data_var in debug_info.data_variables:
- print(f" {data_var}")
+ print(f" {data_var}")
print("Data variables from parser:")
for data_var in debug_info.data_variables_from_parser(parser.name):
- print(f" {data_var}")
-
+ print(f" {data_var}")
print("Appling debug info!")
bv.apply_debug_info(debug_info)
@@ -254,16 +277,16 @@ bv.update_analysis_and_wait()
print("")
print("Types:")
for name, t in debug_info.types:
- print(f" {bv.get_type_by_name(name)}")
+ print(f" {bv.get_type_by_name(name)}")
print("")
print("Functions:")
for func in debug_info.functions:
- print(f" {bv.get_function_at(func.address)}")
+ print(f" {bv.get_function_at(func.address)}")
print("")
print("Data variables:")
for data_var in debug_info.data_variables:
- print(f" {bv.get_data_var_at(data_var.address)}")
+ print(f" {bv.get_data_var_at(data_var.address)}")