diff options
| author | Peter LaFosse <peter@vector35.com> | 2022-01-26 16:56:45 -0500 |
|---|---|---|
| committer | Peter LaFosse <peter@vector35.com> | 2022-01-26 16:56:45 -0500 |
| commit | f24bb9d747eebdd9487620c396ff94ff873e9c02 (patch) | |
| tree | 1f918c3420c7ee6099e07581ebf208d3cce3d308 /PythonAPIDocumentation.md | |
| parent | 1c6a98ab93a7daf5946a1bf05420b9dbb0717519 (diff) | |
Update documentation on creating and applying types
Diffstat (limited to 'PythonAPIDocumentation.md')
| -rw-r--r-- | PythonAPIDocumentation.md | 241 |
1 files changed, 0 insertions, 241 deletions
diff --git a/PythonAPIDocumentation.md b/PythonAPIDocumentation.md index dfecb8ac..95e5e9dd 100644 --- a/PythonAPIDocumentation.md +++ b/PythonAPIDocumentation.md @@ -1,244 +1,3 @@ -_NOTE: This is a work in progress the structure is bad and a lot of improvements need to be made but the information contained is probably helpful_ - -# Working with Types in Binary Ninja - -Binary Ninja provides a flexible API for creating and defining types. Binary Ninja `Type` objects are immutable, we provide two different methods for creating them. For simple types there are one-shot APIs that allow you to define the type with a single function call. Some situations are more complex and incremental construction is preferred, so we provide an additional 'builder' interface. - -## Simple Type Creation - -There are a number of different type objects available for creation: -* Integer Types -* Characters Types (technically an integer) -* Wide Characters Types (also technically an integer) -* Boolean (guess what? also technically an integer) -* Float Types (definitely not an integer) -* Pointers -* Void (like an integer but if its size was zero) -* Functions -* Arrays -* Enumeration (kind of an integer) -* Structures (probably has integers in it) -* Type Definitions - -### Creating Types Using the Type Parser - -Binary Ninja's built-in type parser provides a very convenient way of creating types when you can't remember the exact API to call. The `parse_type_string` API returns a tuple of `Type` and `string` name for the string passed. - -```python ->>> bv.parse_type_string("uint64_t") -(<type: uint64_t>, '') -``` - -Though convenient it is many orders of magnitude slower than simply calling the APIs directly. For applications where performance is at all desired the following APIs should be used. - -### Integer Types - -```python -Type.int(4) # Creates a 4 byte signed integer -Type.int(8, False) # Creates an 8 bytes unsigned integer -Type.int(2, altName="short") # Creates a 2 byte signed integer named 'short' -# Similarly through their classes directly -IntegerType.create(4) -IntegerType.create(8, False) -IntegerType.create(2, altName="short") -``` - -### Character Types - -```python -Type.char() # This is just a 1 byte signed integer and can be used as such -Type.wideChar(2, altName="wchar_t") # Creates a wide character with the name 'wchar_t' -# Similarly through their classes directly -CharType.create() -WideCharType.create(2) -``` - -### Boolean - -```python -Type.bool() -# Similarly through its class directly -BoolType.create() -``` - -### Floating-point Types - -_All floating point numbers are assumed to be signed_ - -```python -Type.float(4) # Creates a 4 byte ieee754 'float' -Type.float(8) # Creates a 8 byte ieee754 'double' -Type.float(10) # Creates a 10 byte ieee754 'long double' -Type.float(16) # Creates a 16 byte ieee754 'float128' -# Similarly through their classes directly -FloatType.create(4) -FloatType.create(8) -FloatType.create(10) -FloatType.create(16) -``` - -### Void - -```python -Type.void() # Create a void type which has zero size -# Similarly through its class directly -VoidType.create() -``` - -### Pointers - -```python -Type.pointer(bv.arch, Type.int(4)) # Create a pointer to a signed 4 byte integer -Type.pointer(type=Type.int(4), width=bv.arch.address_size) # Equivalent to the above but doesn't require an Architecture object be passed around -Type.pointer(bv.arch, Type.void(), const=True, volatile=False) # Creates a constant non volatile void pointer. -# Similarly through their classes directly -PointerType.create(bv.arch, Type.int(4)) -PointerType.create(type=Type.int(4), width=bv.arch.address_size) -PointerType.create(bv.arch, Type.void(), const=True, volatile=False) -``` - -### Arrays - -```python -Type.array(Type.int(4), 2) # Create an array of 2 - 4 byte integers -# Similarly through their classes directly -ArrayType.create(Type.int(4), 2) -``` - -### Function Types - -```python -Type.function() # Creates a function with which takes no parameters and returns void -Type.function(Type.void(), [(Type.int(4), 'arg1')]) # Create a function type which takes an integer as parameter and returns void -Type.function(params=[(Type.int(4), 'arg1')]) # Same as the above -# Similarly through their classes directly -FunctionType.create() -FunctionType.create(Type.void(), [(Type.int(4), 'arg1')]) -FunctionType.create(params=[(Type.int(4), 'arg1')]) -``` - -### Create Anonymous Structures/Class/Unions - -In Binary Ninja's type system supports anonymous and named structures. Anonymous structures are the simplest -to understand, and what most people would expect. - -```python -Type.structure(members=[(Type.int(4), 'field_0')], type=StructureVariant.UnionStructureType) # Create a union with one integer members -Type.structure(members=[(Type.int(4), 'field_0'), (Type.int(4), 'field_4')], packed=True) # Created a packed structure containing two integer members -Type.structure(members=[(Type.int(4), 'field_0')], type=StructureVariant.ClassStructureType) # Create a class with one integer members -# Similarly through their classes directly -StructureType.create(members=[(Type.int(4), 'field_0')], type=StructureVariant.UnionStructureType) -StructureType.create(members=[(Type.int(4), 'field_0'), (Type.int(4), 'field_4')], packed=True) -StructureType.create(members=[(Type.int(4), 'field_0')], type=StructureVariant.ClassStructureType) -``` - -### Create Anonymous Enumerations - -```python -Type.enumeration(members=[('ENUM_2', 2), ('ENUM_4', 4), ('ENUM_8', 8)]) -Type.enumeration(members=['ENUM_0', 'ENUM_1', 'ENUM_2']) -``` - -## Named Types - -In Binary Ninja the name of a class/struct/union or enumeration is separate from its type definition. This -is much like how it's done in C. The mapping between a structure's definition and its name is kept in the Binary View. -Thus if we want to associate a name with our type we need an extra step. - -```python -bv.define_user_type('Foo', Type.structure(members=[(Type.int(4), 'field_0')])) -``` - -To reference a named type a `NamedTypeReference` object must be used. Say we want to add the struct `Foo` to our a new -structure `Bar`. - -```python -t = Type.structure(members=[(Type.int(4), 'inner')]) -n = 'Foo' -bv.define_user_type(n, t) -ntr = Type.named_type_reference(n, t) -bv.define_user_type('Bar', Type.structure(members=[(ntr, 'outer')])) -``` - -The above is equivalent to the following C - -```C -struct Foo { - int32_t inner; -}; - -struct Bar { - struct Foo outer; -}; -``` - -It is also possible to add the type referenced by `Foo` directly as an anonymous structure and thus there would be no need for a `NamedTypeReference` - -```python -t = Type.structure(members=[(Type.int(4), 'inner')]) -bv.define_user_type('Bas', Type.structure(members=[(t, 'outer')])) -``` - -Yielding the following C equivalent: - -```C -struct Bas -{ - struct { int32_t inner; } outer; -} -``` - - -## Mutable Types - -As `Type` objects are immutable, the Binary Ninja API provides a pure python implementation of types to provide mutability, these all inherit from `MutableType` and keep the same names as their immutable counterparts minus the `Type` part. Thus `Structure` is the mutable version of `StructureType` and `Enumeration` is the mutable version of `MutableType`. `Type` objects can be converted to `MutableType` objects using the `Type.mutable_copy` API and, `MutableType` objects can be converted to `Type` objects through the `MutableType.immutable_copy` API. Generally speaking you shouldn't need the mutable type variants for anything except creation of structures and enumerations, mutable type variants are provided for convenience and consistency. Building and defining a new structure can be done in a few ways. The first way would be the two step process of creating the structure then defining it. - -```python -s = StructureBuilder.create(members=[(IntegerType.create(4), 'field_0')]) -bv.define_user_type('Foo', s) -``` - -A second option for more complicated situations you can opt for incremental initialization of the type: - -```python -s = StructureBuilder.create() -s.packed = True -s.append(IntegerType.create(2)) -s.append(IntegerType.create(4)) -bv.define_user_type('Foo', s) -``` - -Finally you can use the built-in context manager which automatically registers the created type with the provided `BinaryView` (`bv`) and name(`Foo`). Additionally when creating TypeLibraries a `Type` can be passed instead of a `BinaryView` - -```python -with StructureBuilder.builder(bv, 'Foo') as s: - s.packed = True - s.append(Type.int(2)) - s.append(Type.int(4)) -``` - -## Type Modification - -Sometimes it's desired to modify a type which has already been registered with a Binary View. The hard way would be as follows: - -1. Look up the type you want to modify -2. Get a mutable version of that type -3. Modify the type how you wish -4. Register that type with the Binary View again - -```python -s = bv.types['Foo'].mutable_copy() -s.append(Type.int(2)) -bv.define_user_type('Foo', s) -``` - -This is a bit easier by using the builder context manager as follows: - -```python -with Type.builder(bv, 'Foo') as s: - s.append(Type.int(2)) -``` - # 3.0 Python API Changes |
