summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKyleMiles <krm504@nyu.edu>2022-09-28 18:21:13 -0400
committerKyleMiles <krm504@nyu.edu>2022-10-04 15:36:26 -0400
commit3104042adab833e73a71738f57070ab881ade615 (patch)
tree4e5280c162a3f681dab5be6c15dba749d5c30115
parented820d2ab81470b3e5ac543d75211e87ff3bc738 (diff)
Rename and move `Analysis/Database Merge Tool` to `File/Merge Databases`; Add API bindings for `BinaryView::GetDebugInfo()`, `BinaryView::ApplyDebugInfo()`, and `BinaryView::SetDebugInfo()`; Remove `analysis.experimental.parseDebugInfo`
(in favor of `loader.debugInfoInternal` and `loader.debugInfoExternal`)
-rw-r--r--binaryninjaapi.h5
-rw-r--r--binaryview.cpp21
-rw-r--r--docs/getting-started.md1
-rw-r--r--python/debuginfo.py2
-rwxr-xr-xpython/examples/debug_info.py2
-rw-r--r--python/examples/mappedview.py6
-rw-r--r--rust/src/debuginfo.rs2
-rw-r--r--suite/api_test.py242
-rw-r--r--ui/settingsview.h1
9 files changed, 155 insertions, 127 deletions
diff --git a/binaryninjaapi.h b/binaryninjaapi.h
index 91395a90..b58db5cb 100644
--- a/binaryninjaapi.h
+++ b/binaryninjaapi.h
@@ -2480,6 +2480,7 @@ namespace BinaryNinja {
class NamedTypeReference;
struct TypeParserResult;
class Component;
+ class DebugInfo;
class QueryMetadataException : public std::exception
{
@@ -3631,6 +3632,10 @@ namespace BinaryNinja {
*/
void DefineImportedFunction(Ref<Symbol> importAddressSym, Ref<Function> func, Ref<Type> type = nullptr);
+ Ref<DebugInfo> GetDebugInfo();
+ void ApplyDebugInfo(Ref<DebugInfo> newDebugInfo);
+ void SetDebugInfo(Ref<DebugInfo> newDebugInfo);
+
void BeginBulkModifySymbols();
void EndBulkModifySymbols();
diff --git a/binaryview.cpp b/binaryview.cpp
index dba92d7c..b8dd7c1a 100644
--- a/binaryview.cpp
+++ b/binaryview.cpp
@@ -2560,6 +2560,27 @@ void BinaryView::DefineImportedFunction(Ref<Symbol> importAddressSym, Ref<Functi
}
+Ref<DebugInfo> BinaryView::GetDebugInfo()
+{
+ BNDebugInfo* result = BNGetDebugInfo(m_object);
+ if (!result)
+ return nullptr;
+ return new DebugInfo(result);
+}
+
+
+void BinaryView::ApplyDebugInfo(Ref<DebugInfo> newDebugInfo)
+{
+ BNApplyDebugInfo(m_object, newDebugInfo->GetObject());
+}
+
+
+void BinaryView::SetDebugInfo(Ref<DebugInfo> newDebugInfo)
+{
+ BNSetDebugInfo(m_object, newDebugInfo->GetObject());
+}
+
+
void BinaryView::BeginBulkModifySymbols()
{
BNBeginBulkModifySymbols(m_object);
diff --git a/docs/getting-started.md b/docs/getting-started.md
index f99dbd2d..a343e995 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -687,7 +687,6 @@ Here's a list of all built-in settings currently available from the UI:
|analysis|Gratuitous Function Update|Force the function update cycle to always end with an IncrementalAutoFunctionUpdate type.|`boolean`|`False`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.experimental.gratuitousFunctionUpdate'>analysis.experimental.gratuitousFunctionUpdate</a>|
|analysis|Heuristic Value Range Clamping|Use DataVariable state inferencing to help determine the possible size of a lookup table.|`boolean`|`True`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.experimental.heuristicRangeClamp'>analysis.experimental.heuristicRangeClamp</a>|
|analysis|Keep Dead Code Branches|Keep unreachable code branches and associated basic blocks in HLIL.|`boolean`|`False`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.experimental.keepDeadCodeBranches'>analysis.experimental.keepDeadCodeBranches</a>|
-|analysis|Parse and Apply Debug Info|Attempt to parse debug info with supplied debug info plugins for utilization during analysis.|`boolean`|`False`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.experimental.parseDebugInfo'>analysis.experimental.parseDebugInfo</a>|
|analysis|Always Analyze Indirect Branches|When using faster analysis modes, perform full analysis of functions containing indirect branches.|`boolean`|`True`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.forceIndirectBranches'>analysis.forceIndirectBranches</a>|
|analysis|Aggressive Condition Complexity Removal Threshold|High Level IL tuning parameter.|`number`|`64`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.hlil.aggressiveConditionComplexityRemovalThreshold'>analysis.hlil.aggressiveConditionComplexityRemovalThreshold</a>|
|analysis|Max Condition Complexity|High Level IL tuning parameter.|`number`|`1024`|[`SettingsProjectScope`, `SettingsResourceScope`, `SettingsUserScope`]|<a id='analysis.hlil.maxConditionComplexity'>analysis.hlil.maxConditionComplexity</a>|
diff --git a/python/debuginfo.py b/python/debuginfo.py
index fc434bfd..153e450d 100644
--- a/python/debuginfo.py
+++ b/python/debuginfo.py
@@ -177,7 +177,7 @@ class DebugInfoParser(object, metaclass=_DebugInfoParserMetaClass):
bn.debuginfo.DebugInfoParser.register("debug info parser", is_valid, parse_info)
- :py:class:`DebugInfo` can then be automatically applied to valid binary views (via the "Parse and Apply Debug Info" setting), or manually fetched/applied as bellow::
+ :py:class:`DebugInfo` will then be automatically applied to binary views that contain debug information (via the load setting `loader.debugInfoInternal`), binary views that provide valid external debug info files (`loader.debugInfoExternal`), or manually fetched/applied as below::
valid_parsers = bn.debuginfo.DebugInfoParser.get_parsers_for_view(bv)
parser = valid_parsers[0]
diff --git a/python/examples/debug_info.py b/python/examples/debug_info.py
index 28175ba1..0dd25786 100755
--- a/python/examples/debug_info.py
+++ b/python/examples/debug_info.py
@@ -222,7 +222,7 @@ for p in bn.debuginfo.DebugInfoParser:
print(f" {bn.debuginfo.DebugInfoParser[p.name].name}")
# Test calling our `is_valid` callback
-bv = bn.open_view(filename, options={"analysis.experimental.parseDebugInfo": False})
+bv = bn.open_view(filename, options={"loader.debugInfoInternal": False})
if parser.is_valid_for_view(bv):
print("Parser is valid")
else:
diff --git a/python/examples/mappedview.py b/python/examples/mappedview.py
index 645096f5..cfefa87a 100644
--- a/python/examples/mappedview.py
+++ b/python/examples/mappedview.py
@@ -53,7 +53,7 @@ class MappedView(BinaryView):
def get_load_settings_for_data(cls, data):
# This method is optional. If provided this is where the Load Settings for a BinaryViewType are specified. Binary Ninja provides
# some default read-only load settings which are:
- # ["loader.architecture", "loader.platform", "loader.entryPointOffset", "loader.imageBase", "loader.segments", "loader.sections"]
+ # ["loader.architecture", "loader.platform", "loader.entryPointOffset", "loader.imageBase", "loader.segments", "loader.sections", "loader.debugInfoInternal", "loader.debugInfoExternal"]
# The default load settings are provided for consistency and convenience.
# The default load settings are always generated with a read-only indication which is respected by the UI.
# The read-only indication is a property that consists of a JSON name/value pair ("readOnly" : true).
@@ -76,8 +76,8 @@ class MappedView(BinaryView):
# Specify default load settings that can be overridden (from the UI).
overrides = [
- "loader.architecture", "loader.platform", "loader.entryPointOffset", "loader.imageBase", "loader.segments",
- "loader.sections"
+ "loader.architecture", "loader.platform", "loader.entryPointOffset", "loader.imageBase",
+ "loader.segments", "loader.sections", "loader.debugInfoInternal", "loader.debugInfoExternal"
]
for override in overrides:
if load_settings.contains(override):
diff --git a/rust/src/debuginfo.rs b/rust/src/debuginfo.rs
index 57e40f71..1f0089fe 100644
--- a/rust/src/debuginfo.rs
+++ b/rust/src/debuginfo.rs
@@ -52,7 +52,7 @@
//! }
//! ```
//!
-//! `DebugInfo` can then be automatically applied to valid binary views (via the "Parse and Apply Debug Info" setting), or manually fetched/applied as bellow:
+//! `DebugInfo` will then be automatically applied to binary views that contain debug information (via the load setting `loader.debugInfoInternal`), binary views that provide valid external debug info files (`loader.debugInfoExternal`), or manually fetched/applied as below:
//! ```
//! let valid_parsers = DebugInfoParser::parsers_for_view(bv);
//! let parser = valid_parsers[0];
diff --git a/suite/api_test.py b/suite/api_test.py
index 7ff5ec00..2a544f7c 100644
--- a/suite/api_test.py
+++ b/suite/api_test.py
@@ -15,9 +15,9 @@ from binaryninja.enums import (
)
from binaryninja.types import (
- QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, OffsetWithConfidence, BoolWithConfidence,
- EnumerationBuilder, NamedTypeReferenceBuilder, StructureBuilder, StructureMember, IntegerType, StructureType,
- Symbol, NameSpace, MutableTypeBuilder, NamedTypeReferenceType, QualifiedNameType, TypeDefinitionLine
+ QualifiedName, Type, TypeBuilder, EnumerationMember, FunctionParameter, OffsetWithConfidence, BoolWithConfidence,
+ EnumerationBuilder, NamedTypeReferenceBuilder, StructureBuilder, StructureMember, IntegerType, StructureType,
+ Symbol, NameSpace, MutableTypeBuilder, NamedTypeReferenceType, QualifiedNameType, TypeDefinitionLine
)
from binaryninja.architecture import *
from binaryninja.function import *
@@ -318,6 +318,8 @@ class SettingsAPI(unittest.TestCase):
assert load_settings.contains("loader.platform"), "test_load_settings failed"
assert load_settings.contains("loader.imageBase"), "test_load_settings failed"
assert load_settings.contains("loader.entryPointOffset"), "test_load_settings failed"
+ assert load_settings.contains("loader.debugInfoInternal"), "test_load_settings failed"
+ assert load_settings.contains("loader.debugInfoExternal"), "test_load_settings failed"
load_settings.set_string("loader.architecture", 'x86_64')
load_settings.set_integer("loader.imageBase", 0x500000)
load_settings.set_integer("loader.entryPointOffset", 0)
@@ -523,9 +525,9 @@ class TypeParserTest(unittest.TestCase):
if types is None:
raise SyntaxError('\n'.join(str(e) for e in errors))
return BasicTypeParserResult(
- types=dict(zip([t.name for t in types.types], [t.type for t in types.types])),
- variables=dict(zip([t.name for t in types.variables], [t.type for t in types.variables])),
- functions=dict(zip([t.name for t in types.functions], [t.type for t in types.functions])),
+ types=dict(zip([t.name for t in types.types], [t.type for t in types.types])),
+ variables=dict(zip([t.name for t in types.variables], [t.type for t in types.variables])),
+ functions=dict(zip([t.name for t in types.functions], [t.type for t in types.functions])),
)
def test_integers(self):
@@ -688,7 +690,7 @@ class TypeParserTest(unittest.TestCase):
# Clang says (TIL):
# "Class 'foo' was previously declared as a struct; this is valid, but may result in linker errors under the Microsoft C++ ABI"
valid = [
- r'''
+ r'''
class foo
{
int a;
@@ -715,27 +717,27 @@ class TypeParserTest(unittest.TestCase):
def test_parse_empty(self):
valid = [
- # Forward declarations
- 'struct foo;',
- 'class foo;',
- 'union foo;',
- # Definition with no members
- 'struct foo {};',
- 'class foo {};',
- 'union foo {};',
- 'enum foo {};',
- # Inner structure is empty
- 'struct foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
- 'class foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
- 'union foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
+ # Forward declarations
+ 'struct foo;',
+ 'class foo;',
+ 'union foo;',
+ # Definition with no members
+ 'struct foo {};',
+ 'class foo {};',
+ 'union foo {};',
+ 'enum foo {};',
+ # Inner structure is empty
+ 'struct foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
+ 'class foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
+ 'union foo { struct {} bar; class {} baz; union {} alpha; enum {} bravo; };',
]
for source in valid:
with self.subTest():
types = self.parse_types_from_source(source)
invalid = [
- # Forward declaration of enum is not allowed
- 'enum foo;'
+ # Forward declaration of enum is not allowed
+ 'enum foo;'
]
for source in invalid:
with self.subTest():
@@ -813,52 +815,52 @@ class TypeParserTest(unittest.TestCase):
name = "MyTypeParser"
def preprocess_source(
- self, source: str, file_name: str, platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]],
- options: Optional[List[str]], include_dirs: Optional[List[str]]
+ self, source: str, file_name: str, platform: binaryninja.Platform,
+ existing_types: Optional[List[QualifiedNameTypeAndId]],
+ options: Optional[List[str]], include_dirs: Optional[List[str]]
) -> Tuple[Optional[str], List[TypeParserError]]:
return (
- source,
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
+ source,
+ [
+ TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
+ ]
)
def parse_types_from_source(
- self,
- source: str,
- file_name: str,
- platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]],
- options: Optional[List[str]],
- include_dirs: Optional[List[str]],
- auto_type_source: str = ""
+ self,
+ source: str,
+ file_name: str,
+ platform: binaryninja.Platform,
+ existing_types: Optional[List[QualifiedNameTypeAndId]],
+ options: Optional[List[str]],
+ include_dirs: Optional[List[str]],
+ auto_type_source: str = ""
) -> Tuple[Optional[TypeParserResult], List[TypeParserError]]:
return (
- TypeParserResult(
- [
- ParsedType("my_type", Type.int(4, False), True)
- ], [
- ParsedType("my_variable", Type.int(4, False), True)
- ], [
- ParsedType("my_function", Type.function(Type.void(), []), True)
- ]
- ),
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
+ TypeParserResult(
+ [
+ ParsedType("my_type", Type.int(4, False), True)
+ ], [
+ ParsedType("my_variable", Type.int(4, False), True)
+ ], [
+ ParsedType("my_function", Type.function(Type.void(), []), True)
+ ]
+ ),
+ [
+ TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
+ ]
)
def parse_type_string(
- self, source: str, platform: binaryninja.Platform,
- existing_types: Optional[List[QualifiedNameTypeAndId]]
+ self, source: str, platform: binaryninja.Platform,
+ existing_types: Optional[List[QualifiedNameTypeAndId]]
) -> Tuple[Optional[Tuple[QualifiedNameType, binaryninja.Type]],
- List[TypeParserError]]:
+ List[TypeParserError]]:
return (
- ("my_type", Type.int(4, False)),
- [
- TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
- ]
+ ("my_type", Type.int(4, False)),
+ [
+ TypeParserError(TypeParserErrorSeverity.WarningSeverity, "Test Warning", "sources.hpp", 1, 1)
+ ]
)
MyTypeParser().register()
@@ -927,49 +929,49 @@ class TestTypePrinter(unittest.TestCase):
bv.platform = platform
types = [
- (Type.int(4), 'basic_int', 'typedef int32_t basic_int;\n'),
- (Type.array(Type.int(4), 4), 'basic_array', 'typedef int32_t basic_array[0x4];\n'),
- (Type.pointer(platform.arch, Type.array(
- Type.int(4), 4
- )), 'pointer_array', 'typedef int32_t (* pointer_array)[0x4];\n'),
- (Type.array(
- Type.pointer(platform.arch, Type.int(4)), 4
- ), 'array_pointer', 'typedef int32_t* array_pointer[0x4];\n'),
- (Type.function(
- Type.int(4), []
- ), 'basic_func', 'typedef int32_t basic_func();\n'),
- (Type.function(
- Type.int(4), [], platform.fastcall_calling_convention
- ), 'convention_func', 'typedef int32_t __fastcall convention_func();\n'),
- (Type.pointer(platform.arch, Type.function(
- Type.int(4), []
- ), True), 'const_func_pointer', 'typedef int32_t (* const const_func_pointer)();\n'),
- (Type.pointer(platform.arch, Type.function(
- Type.int(4), []
- )), 'basic_func_pointer', 'typedef int32_t (* basic_func_pointer)();\n'),
- (Type.function(
- Type.pointer(platform.arch, Type.int(4)), []
- ), 'func_returning_ptr', 'typedef int32_t* func_returning_ptr();\n'),
- (Type.structure([
- (Type.int(4), 'foo')
- ]), 'basic_struct', 'struct basic_struct\n{\n int32_t foo;\n};\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.int(4), 'foo')
- ])), 'pointer_struct', 'typedef struct { int32_t foo; }* pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.int(4)), 'foo')
- ])), 'pointer_in_pointer_struct', 'typedef struct { int32_t* foo; }* pointer_in_pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.int(4)), 'foo')
- ])), 'foo')
- ])), 'nested_pointer_struct', 'typedef struct { struct { int32_t* foo; }* foo; }* nested_pointer_struct;\n'),
- (Type.pointer(platform.arch, Type.structure([
- (Type.pointer(platform.arch, Type.function(Type.int(4), [('param', Type.int(4))])), 'foo')
- ])), 'pointer_function_struct', 'typedef struct { int32_t (* foo)(int32_t param); }* pointer_function_struct;\n'),
- (Type.pointer(platform.arch, Type.enumeration(platform.arch, [
- ('one', 1)
- ])), 'pointer_enumeration', 'typedef enum {}* pointer_enumeration;\n'),
+ (Type.int(4), 'basic_int', 'typedef int32_t basic_int;\n'),
+ (Type.array(Type.int(4), 4), 'basic_array', 'typedef int32_t basic_array[0x4];\n'),
+ (Type.pointer(platform.arch, Type.array(
+ Type.int(4), 4
+ )), 'pointer_array', 'typedef int32_t (* pointer_array)[0x4];\n'),
+ (Type.array(
+ Type.pointer(platform.arch, Type.int(4)), 4
+ ), 'array_pointer', 'typedef int32_t* array_pointer[0x4];\n'),
+ (Type.function(
+ Type.int(4), []
+ ), 'basic_func', 'typedef int32_t basic_func();\n'),
+ (Type.function(
+ Type.int(4), [], platform.fastcall_calling_convention
+ ), 'convention_func', 'typedef int32_t __fastcall convention_func();\n'),
+ (Type.pointer(platform.arch, Type.function(
+ Type.int(4), []
+ ), True), 'const_func_pointer', 'typedef int32_t (* const const_func_pointer)();\n'),
+ (Type.pointer(platform.arch, Type.function(
+ Type.int(4), []
+ )), 'basic_func_pointer', 'typedef int32_t (* basic_func_pointer)();\n'),
+ (Type.function(
+ Type.pointer(platform.arch, Type.int(4)), []
+ ), 'func_returning_ptr', 'typedef int32_t* func_returning_ptr();\n'),
+ (Type.structure([
+ (Type.int(4), 'foo')
+ ]), 'basic_struct', 'struct basic_struct\n{\n int32_t foo;\n};\n'),
+ (Type.pointer(platform.arch, Type.structure([
+ (Type.int(4), 'foo')
+ ])), 'pointer_struct', 'typedef struct { int32_t foo; }* pointer_struct;\n'),
+ (Type.pointer(platform.arch, Type.structure([
+ (Type.pointer(platform.arch, Type.int(4)), 'foo')
+ ])), 'pointer_in_pointer_struct', 'typedef struct { int32_t* foo; }* pointer_in_pointer_struct;\n'),
+ (Type.pointer(platform.arch, Type.structure([
+ (Type.pointer(platform.arch, Type.structure([
+ (Type.pointer(platform.arch, Type.int(4)), 'foo')
+ ])), 'foo')
+ ])), 'nested_pointer_struct', 'typedef struct { struct { int32_t* foo; }* foo; }* nested_pointer_struct;\n'),
+ (Type.pointer(platform.arch, Type.structure([
+ (Type.pointer(platform.arch, Type.function(Type.int(4), [('param', Type.int(4))])), 'foo')
+ ])), 'pointer_function_struct', 'typedef struct { int32_t (* foo)(int32_t param); }* pointer_function_struct;\n'),
+ (Type.pointer(platform.arch, Type.enumeration(platform.arch, [
+ ('one', 1)
+ ])), 'pointer_enumeration', 'typedef enum {}* pointer_enumeration;\n'),
]
for t in types:
@@ -988,46 +990,46 @@ class TestTypePrinter(unittest.TestCase):
name = "MyTypePrinter"
def get_type_tokens(self, type: types.Type, platform: Optional[Platform], name: types.QualifiedName,
- base_confidence: int, escaping: TokenEscapingType) -> List[InstructionTextToken]:
+ base_confidence: int, escaping: TokenEscapingType) -> List[InstructionTextToken]:
return [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
- InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
+ InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
+ InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
+ InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
]
def get_type_tokens_before_name(self, type: types.Type, platform: Optional[Platform], base_confidence: int,
- parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[
- InstructionTextToken]:
+ parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[
+ InstructionTextToken]:
return [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
+ InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
]
def get_type_tokens_after_name(self, type: types.Type, platform: Optional[Platform], base_confidence: int,
- parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[InstructionTextToken]:
+ parent_type: Optional[types.Type], escaping: TokenEscapingType) -> List[InstructionTextToken]:
return [
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0),
+ InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0),
]
def get_type_string(self, type: types.Type, platform: Optional[Platform], name: types.QualifiedName,
- escaping: TokenEscapingType) -> str:
+ escaping: TokenEscapingType) -> str:
return f"the type is: {name} bottom text"
def get_type_string_before_name(self, type: types.Type, platform: Optional[Platform],
- escaping: TokenEscapingType) -> str:
+ escaping: TokenEscapingType) -> str:
return f"the type is: "
def get_type_string_after_name(self, type: types.Type, platform: Optional[Platform],
- escaping: TokenEscapingType) -> str:
+ escaping: TokenEscapingType) -> str:
return f" bottom text"
def get_type_lines(self, type: types.Type, data: binaryview.BinaryView, name: types.QualifiedName, line_width,
- collapsed, escaping: TokenEscapingType) -> List[types.TypeDefinitionLine]:
+ collapsed, escaping: TokenEscapingType) -> List[types.TypeDefinitionLine]:
return [
- TypeDefinitionLine(TypeDefinitionLineType.TypedefLineType, [
- InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
- InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
- InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
- ], type, type, '', 0, 1)
+ TypeDefinitionLine(TypeDefinitionLineType.TypedefLineType, [
+ InstructionTextToken(InstructionTextTokenType.TextToken, "the type is: ", 0),
+ InstructionTextToken(InstructionTextTokenType.TypeNameToken, str(name), 0),
+ InstructionTextToken(InstructionTextTokenType.TextToken, " bottom text", 0)
+ ], type, type, '', 0, 1)
]
MyTypePrinter().register()
@@ -2782,7 +2784,7 @@ class TestBinaryView(TestWithBinaryView):
def test_bv_comments(self):
self.bv.set_comment_at(self.bv.start, "This is a comment")
assert self.bv.get_comment_at(self.bv.start) == "This is a comment"
- assert self.bv.address_comments == {self.bv.start :"This is a comment"}
+ assert self.bv.address_comments == {self.bv.start : "This is a comment"}
def test_bv_sections(self):
assert self.bv.get_unique_section_names(['foo', 'foo']) == ["foo", "foo#1"]
@@ -3314,8 +3316,8 @@ class LowLevelILTests(TestWithBinaryView):
func.finalize()
self.assertEqual(func.basic_blocks[0].disassembly_text[target_expr_index].il_instruction.__class__, llil_instruction_type,
- f"LowLevelILFunction.{target_function.__name__} didn't append expected "
- f"{llil_instruction_type.__name__} instruction")
+ f"LowLevelILFunction.{target_function.__name__} didn't append expected "
+ f"{llil_instruction_type.__name__} instruction")
return func.basic_blocks[0].disassembly_text[target_expr_index].il_instruction
diff --git a/ui/settingsview.h b/ui/settingsview.h
index 5a785784..5507f182 100644
--- a/ui/settingsview.h
+++ b/ui/settingsview.h
@@ -186,6 +186,7 @@ class BINARYNINJAUIAPI SettingsEditor : public QWidget
void selectUiFont();
void selectInterpreter();
void selectVirtualEnv();
+ void selectExternalDebugInfo();
public Q_SLOTS:
void updateScope(BinaryViewRef, BNSettingsScope);