summaryrefslogtreecommitdiff
path: root/docs/guide/types
diff options
context:
space:
mode:
authorJordan Wiens <jordan@psifertex.com>2024-02-19 15:04:00 -0500
committerJordan Wiens <jordan@psifertex.com>2024-02-23 11:14:06 -0500
commit448f40be71dffa86a6581c3696627ccc1bdf74f2 (patch)
treecd79923c85986c0135b41eb7432e54218f1a56e5 /docs/guide/types
parent748c2295e31c03afa1d4b1b776a59f9fa9a48d34 (diff)
4.0 documentation
- Refactored Type Documentation - Added Projects - Added Type Archives - Added New Sidebar Documentation - Added String Concepts - Added Light/Dark Mode - Added New Tab Documentation - Added BNIL Guide: HLIL docs - Added new cookbook examples - Added migration guide - Added script for building docsets - Added documentation for themes - Updated all images to Ninja Edit - API Docs : Documents BasicBlockEdge and BasicBlock - API Docs : Documents CoreVariable, Variable, and VariableNameAndType - API Docs : Corrects note on `BinaryView.update_analysis` and `BinaryView.update_analysis_and_wait` to represent that analysis is run by default for you now. - Many, many other changes
Diffstat (limited to 'docs/guide/types')
-rw-r--r--docs/guide/types/basictypes.md173
-rw-r--r--docs/guide/types/cpp.md618
-rw-r--r--docs/guide/types/debuginfo.md37
-rw-r--r--docs/guide/types/index.md18
-rw-r--r--docs/guide/types/platformtypes.md42
-rw-r--r--docs/guide/types/type.md88
-rw-r--r--docs/guide/types/typearchives.md47
-rw-r--r--docs/guide/types/typeimportexport.md184
-rw-r--r--docs/guide/types/typelibraries.md37
9 files changed, 1244 insertions, 0 deletions
diff --git a/docs/guide/types/basictypes.md b/docs/guide/types/basictypes.md
new file mode 100644
index 00000000..b9530ddb
--- /dev/null
+++ b/docs/guide/types/basictypes.md
@@ -0,0 +1,173 @@
+# Basic Type Editing
+
+The biggest culprit of bad decompilation is often missing type information. Therefore, some of the most important actions you can take while reverse engineering is renaming symbols/variables, applying types, and creating new types to apply.
+
+## Renaming Symbols and Variables
+
+![Rename a function](../../img/rename.png "Renaming a function")
+
+Some binaries helpfully have symbol information in them which makes reverse engineering easier. Of course, even if the binary doesn't come with symbol information, you can always add your own. From the UI, just select the function, variable, member, or register you want to change and press `n`.
+
+## Applying / Changing Structures and Types
+
+Simply select an appropriate token (function, parameter, variable or memory address), and press `y` to bring up the change type dialog. Types can be applied on both disassembly and all levels of IL. Any variables that are shared between the ILs will be updated as types are applied.
+
+![Changing a type](../../img/change-type.png "Changing a type")
+
+## Types View
+
+![Types View](../../img/types-view.png "Types View")
+
+The Types View is the main view for organizing and modifying types in Binary Ninja.
+You can access it in a number of different ways:
+
+- Open it in the sidebar with the {T} icon
+- Open it in the sidebar in the Command Palette under "Focus Types"
+- Switch the current view pane to it by selecting "Types" under the view type menu
+- Switch the current view pane in the Command Palette under "Types"
+
+The Types View comprises two main views: the [Type List](#the-type-list) and the [Type Editor](#the-type-editor).
+There is also a search box that filters the Type List, and a menu button that shows the context menu
+for the active view.
+
+### The Type List
+
+![Types View](../../img/types-list.png "Types View")
+
+The Type List shows you both the types available in your analysis session and types from
+the [various other places](#type-containers) related to your analysis that can be imported.
+Types you select in the Type List will be shown in the Type Editor view, and you can view
+multiple types at once by clicking with Shift or Ctrl (Cmd on macOS). Selected types will
+show cross-references in the [cross-references sidebar pane](../index.md#cross-references).
+You can edit selected types in the Type Editor, or if you double-click a type
+(or use Change Type in the context menu), you can edit them as C source.
+
+Types in the list have their class indicated by icons:
+
+* **S**: Structure types
+* **C**: Class types (a variant of structure types)
+* **U**: Union types (a variant of structure types)
+* **E**: Enumeration types
+* **T**: All other types
+
+#### Type List Actions
+
+* Type Creation
+ * **Create Types from C Source** - Open a text box where you can enter C source type and structure definitions
+ * **Create New Structure** - Create a new blank structure type
+ * **Create New Enumeration** - Create a new blank enumeration type
+ * **Create New Union** - Create a new blank union type
+* Type Editing
+ * **Rename Type** - Rename the currently selected type
+ * **Change Type** - Edit the currently selected type in a text box with C source
+* Type Archives
+ * **Create Type Archive** - Create a [Type Archive](typearchives.md) and attach it to your analysis
+ * **Attach Type Archive** - Attach an existing [Type Archive](typearchives.md) to your analysis
+ * **Detach Type Archive** - Detach an attached [Type Archive](typearchives.md) and disassociate all types from it
+ * **Push Types to Archive** - Push the selected types to a [Type Archive](typearchives.md)
+ * **Pull Types from Archive** - Pull the selected types from a [Type Archive](typearchives.md)
+ * **Disassociate Types from Archive** - Disassociate, or break connections between, the selected types and their associated [Type Archive](typearchives.md)
+* Type Libraries
+ * **Import Type** - Import a type from a [Type Library](../../dev/annotation.md#type-libraries) into your analysis
+ * **Import Type by GUID** - (Windows binary analyses only) Import a COM type by its GUID
+ * **Add Type Library** - Add an existing [Type Library](../../dev/annotation.md#type-libraries) to your analysis
+* Settings
+ * **Search** - Change how the search box filters types
+ * **Type Names** - Search only filters by names of types (default)
+ * **Type and Member Names** - Search filters by both names of types and names of members in structure types
+ * **Full Definition Text** - Search filters by matching the full text representation of types (can be slow for large numbers of types)
+
+#### Type Containers
+
+All of the type containers described in the [type introduction](index.md) are available in the Types View along with `User Types` in a section of its own.
+
+* **User Types**: In your analysis: Types created by you, either manually or through actions/plugins
+* **System Types**: In your analysis: Types created by analysis or imported during analysis, such as from Libraries or Debug Info
+* **Archive**: Types in an attached [Type Archive](typearchives.md). You can edit and delete them, without affecting the types in your analysis, and you can push/pull them into your analysis.
+* **Library**: Types in a [Type Library](../../dev/annotation.md#type-libraries). You cannot edit them, but you can import them into your analysis.
+* **Debug Info**: Types found in [Debug Info](debuginfo.md). You cannot edit them here, but they are copied into the System Types where you can edit them.
+* **Platform**: Types from the analyzed binary's [Platform](platformtypes.md). You cannot edit them here, but they are copied into the System Types where you can edit them.
+
+![Types Containers](../../img/types-containers.png "Type Containers")
+
+### The Type Editor
+
+The Type Editor is the primary interface for editing types used in your analysis. It shows
+whichever types you select in the Type List above, and allows you to edit them in many ways.
+Types are shown in C syntax with various [annotations](#type-annotations). Structure members
+have their offsets indicated on the left, and empty space between structure members is shown
+with `??` marks indicating individual bytes. Selecting members in a structure will show
+[cross-references](../index.md#cross-references) to those members, and double-clicking
+the name of a type will take you to its definition.
+
+#### Type Editor Actions
+
+* Modifying Types
+ * **Change Type** - Edit an entire type, or structure member, as C source
+ * **Rename** - Rename a type or structure member
+ * **Undefine** - Delete a type from your analysis, or delete a structure member
+ * **Set Structure Size** - Manually specify a structure's size, alignment, and packing
+* Creating Structure Members
+ * **Type > Make 8-bit Integer** - Create `uint8_t` members in selection
+ * **Type > Make 16-bit Integer** - Create `uint16_t` members in selection
+ * **Type > Make 32-bit Integer** - Create `uint32_t` members in selection
+ * **Type > Make 64-bit Integer** - Create `uint64_t` members in selection
+ * **Type > Invert Integer Sign** - Toggle integer signedness, e.g. between `uint8_t` and `int8_t`
+ * **Type > Cycle Integer Size** - Change integer member size in order: `uint8_t`, `uint16_t`, `uint32_t`, `uint64_t`
+ * **Type > Make 32-bit Float** - Create `float` members in selection
+ * **Type > Make 64-bit Float** - Create `double` members in selection
+ * **Type > Cycle Float Size** - Change float member size in order: `float`, `double`
+ * **Type > Make Pointer** - Create `void*` members in selection
+ * **Type > Make C String** - Create `char*` members in selection
+ * **Type > Make UTF-16 String** - Create `wchar16*` members in selection
+ * **Type > Make UTF-32 String** - Create `wchar32*` members in selection
+* Utility
+ * **Add Cross Reference from** - Manually add a cross-reference to a type (or member) from an address in the analysis
+* Settings
+ * **Show Inherited Members** - When working with [structures with inheritance](cpp.md#derived-classes), show members from base classes in child classes
+ * **Wrap Lines** - Soft-wrap long text lines
+
+### Type Annotations
+
+The Types view now annotates code references to structure offsets. It uses the same convention as in the graph/linear view. For example, the `__offset(0x8).q` token means the code references the offset 0x8 bytes into this structure, and the size of the access is a qword. This will make it easier to see which offsets of a structure are being used, and aid in the process of creating structure members.
+
+## Attributes
+
+Structs support the attribute `__packed` to indicate that there is no padding. Additionally, function prototypes support the following keywords to indicate their calling convention or other features:
+
+``` text
+__cdecl
+__stdcall
+__fastcall
+__convention
+__noreturn
+```
+
+To use the `__convention` keyword, pass in the convention name as a parameter argument:
+
+```
+__convention("customconvention")
+```
+
+
+## Examples
+
+``` C
+enum _flags
+{
+ F_X = 0x1,
+ F_W = 0x2,
+ F_R = 0x4
+};
+```
+
+``` C
+struct Header __packed
+{
+ char *name;
+ uint32_t version;
+ void (* callback)();
+ uint16_t size;
+ enum _flags flags;
+};
+```
diff --git a/docs/guide/types/cpp.md b/docs/guide/types/cpp.md
new file mode 100644
index 00000000..455e59fd
--- /dev/null
+++ b/docs/guide/types/cpp.md
@@ -0,0 +1,618 @@
+# Working with C++ Types and Virtual Function Tables
+
+## Derived Classes
+
+Structures in Binary Ninja can be derived from other structures, allowing C++ class hierarchies
+to be represented without having to redefine base class members. Defining the class hierarchy
+in Binary Ninja will also allow the cross references to reflect the hierarchy, such that
+base class members are cross referenced in all derived classes automatically.
+
+In-memory layout of C++ classes is not defined by the standard and varies by compiler, so Binary
+Ninja provides a low-level representation for describing the class layout.
+
+### Defining a Derived Class or Structure
+
+A derived class can be defined using the Create Structure dialog. From the Types sidebar this
+dialog can be opened with a default hotkey of `s` or by using the add menu on the right of
+the sidebar.
+
+![Create Structure menu](../../img/create-struct-menu.png "Create Structure menu")
+
+First, enter the offset and name of the base structure below the "Base structures" list. The
+offset should be where in the derived structure to place the base structure's members, which
+will usually be zero for single inheritance.
+
+![Adding a base structure](../../img/create-derived-struct-1.png "Adding a base structure")
+
+Click the add button to add the base structure to the new structure.
+
+![Base structure added](../../img/create-derived-struct-2.png "Base structure added")
+
+The offset will automatically update to be just after the added structure in case you need to
+add additional base structures. Click the Create button to create the new structure.
+
+The new structure will appear in the types sidebar with special syntax to show the base
+structures and the inherited members:
+
+``` C
+struct __base(Foo, 0) Bar __packed
+{
+ __inherited int32_t Foo::field_0;
+ __inherited int32_t Foo::field_4;
+ __inherited int32_t Foo::field_8;
+};
+```
+
+This syntax can also be used in the Create Types interface to create derived structures
+from C source. When creating types from the Create Types interface, `__inherited` members
+need only match the structure's size and can be more easily defined like this:
+
+``` C
+struct __base(Foo, 0) Bar
+{
+ __inherited Foo foo;
+};
+```
+
+Derived structures can also be defined using the API. Use the `base_structures` property of
+the structure builder to do this. It takes a list of `BaseStructure` objects, which are defined
+using a `Type` and an offset.
+
+``` python
+s = TypeBuilder.structure()
+s.base_structures = [BaseStructure(bv.types['Foo'], 0)]
+```
+
+## Virtual Function Tables
+
+Virtual functions are implemented by compilers using a virtual function table structure that is
+pointed to by instances of the class. The layout of these structures is compiler dependent, so
+when reverse engineering a C++ binary these structures must be created to match the in-memory
+layout used by the binary.
+
+One of the most common tasks when reversing a C++ binary is discovering which functions a virtual
+function call can resolve to. Binary Ninja provides a "propagate data variable references"
+option in the Create Structure dialog to help with this. When this is enabled, pointers
+found in the data section that are part of any instance of the structure will be considered
+as cross references of the structure field itself. This allows you to click on the name of a
+virtual function and see which functions it can potentially call in the cross references view.
+
+### Defining a virtual function table
+
+To create a virtual function table, select the "propagate data variable references" option when
+creating the structure in the Create Structure dialog. Alternatively, use the `__data_var_refs`
+or `__vtable` attributes (these are aliases of each other) when creating the structure from
+C source. Here is an example virtual function table structure:
+
+``` C
+struct __data_var_refs vtable_for_Foo
+{
+ void (* fizz)(struct Foo* this);
+ void (* buzz)(struct Foo* this);
+};
+```
+
+Now, apply the new virtual function table structure to each instance of the table in the data
+section. You can usually find pointers to them in the constructors.
+
+### Derived virtual function tables
+
+Virtual functions are typically used in conjunction with derived classes. In order to get the
+best results from Binary Ninja, each class should have its own virtual function table structure,
+and the virtual function table structures should use the base structures feature described
+earlier to mirror the class hierarchy. For example, if the class `Foo` mentioned in the virtual
+function table above has a derived class of `Bar`, you would define a second virtual function
+table structure `vtable_for_Bar` that derives from `vtable_for_Foo`:
+
+``` C
+struct __base(vtable_for_Foo, 0) __data_var_refs vtable_for_Bar
+{
+ __inherited void (* vtable_for_Foo::fizz)(struct Foo* this);
+ __inherited void (* vtable_for_Foo::buzz)(struct Foo* this);
+ void (* beep)(struct Bar* this);
+};
+```
+
+You should always define these derived virtual function table structures, even if they have the
+same members. This allows Binary Ninja to get more accurate results.
+
+The last step is to ensure that the virtual function tables are pointed to correctly in the
+class itself. This is often the first member of the structure. Make sure that each class points
+to its own virtual function table structure. Derived structure members can be overridden simply
+by changing their type.
+
+The example `Foo` and `Bar` classes would look like this:
+
+``` C
+struct Foo
+{
+ struct vtable_for_Foo* vtable;
+ // Foo members
+};
+
+struct __base(Foo, 0) Bar
+{
+ struct vtable_for_Bar* vtable; // Overridden Foo::vtable
+ // __inherited Foo members
+ // Additional Bar members
+};
+```
+
+???+ Warning "Tip"
+ Do not leave the `vtable` members deriving from the base class. You should always make a
+ derived virtual function table structure for each new class, and override the `vtable`
+ member to point at the corresponding structure. This will significantly improve Binary
+ Ninja's cross references for virtual function calls.
+
+## Template Simplifier
+
+The [`analysis.types.templateSimplifier`](../settings.md#analysis.types.templateSimplifier) setting can be helpful when working with C++ symbols.
+
+<div class="juxtapose">
+ <img src="../../img/before-template-simplification.png" data-label="Before Simplification"/>
+ <img src="../../img/after-template-simplification.png" data-label="After Simplification"/>
+</div>
+
+## Example
+
+Consider the following C++ program:
+
+``` C++
+class Animal
+{
+public:
+ const char* name;
+
+ virtual void make_sound() = 0;
+
+ virtual void approach()
+ {
+ make_sound();
+ }
+
+ void greet()
+ {
+ printf("You:\n");
+ printf("Hello %s!\n", name);
+ printf("%s:\n", name);
+ make_sound();
+ }
+};
+
+class Flying
+{
+public:
+ int max_airspeed;
+
+ virtual void fly()
+ {
+ puts("Up, up, and away!");
+ }
+};
+
+class Dog: public Animal
+{
+public:
+ int bark_count;
+
+ virtual void make_sound() override
+ {
+ puts("Woof!");
+ bark_count++;
+ }
+};
+
+class Cat: public Animal
+{
+public:
+ int nap_count;
+
+ virtual void make_sound() override
+ {
+ puts("Meow!");
+ }
+
+ virtual void approach() override
+ {
+ if (nap_count)
+ puts("Zzzz...");
+ else
+ make_sound();
+ }
+
+ virtual void nap()
+ {
+ nap_count++;
+ }
+};
+
+class Lion: public Cat
+{
+public:
+ virtual void make_sound() override
+ {
+ puts("Roar!");
+ }
+};
+
+class Bird: public Animal, public Flying
+{
+public:
+ int song_length;
+
+ virtual void make_sound() override
+ {
+ for (int i = 0; i < song_length; i++)
+ puts("Tweet!");
+ }
+
+ virtual void approach() override
+ {
+ fly();
+ }
+};
+```
+
+### Defining the base classes
+
+First, we define the base classes `Animal` and `Flying`. We leave the `vtable` member as a `void*`
+for now, since we will need these structures defined first:
+
+``` C
+struct Animal
+{
+ void* vtable;
+ char* name;
+};
+
+struct Flying
+{
+ void* vtable;
+ int32_t max_airspeed;
+};
+```
+
+We can use these structures in the member functions to see better results in the decompiler:
+
+``` C
+int64_t Animal::greet(struct Animal* this)
+{
+ _printf("You:\n");
+ _printf("Hello %s!\n", this->name);
+ _printf("%s:\n", this->name);
+ return *(int64_t*)this->vtable();
+}
+```
+
+???+ Warning "Tip"
+ `this` is a keyword in the type parser, so if you try to define the function prototype with
+ `this` as the name of a parameter, you will get an error. You can enclose the parameter name
+ with backticks to work around this. Here, the parameter declaration would need to be
+ ``Animal* `this` `` to pass the type parser.
+
+### Defining the derived classes
+
+The `Dog`, `Cat`, and `Lion` classes can be defined by using the [derived structure feature](#defining-a-derived-class-or-structure), with the base class at offset zero. These classes
+will look like this at this point:
+
+``` C
+struct __base(Animal, 0) Dog
+{
+ __inherited void* Animal::vtable;
+ __inherited char* Animal::name;
+ int32_t bark_count;
+};
+
+struct __base(Animal, 0) Cat
+{
+ __inherited void* Animal::vtable;
+ __inherited char* Animal::name;
+ int32_t nap_count;
+};
+
+struct __base(Cat, 0) Lion
+{
+ __inherited void* Animal::vtable;
+ __inherited char* Animal::name;
+ __inherited int32_t Cat::nap_count;
+};
+```
+
+Applying these structures to the parameter types will improve decompilation of these classes:
+
+``` C
+void Dog::make_sound(struct Dog* this)
+{
+ _puts("Woof!");
+ this->bark_count = (this->bark_count + 1);
+}
+
+void Cat::nap(struct Cat* this)
+{
+ this->nap_count = (this->nap_count + 1);
+}
+```
+
+### Multiple inheritance
+
+The `Bird` class derives from both `Animal` and `Flying`. The typical in-memory layout of this
+class is to place `Animal` at offset zero, `Flying` just after `Animal`, and any members from
+the derived class after both. We set up this structure in the Create Structure dialog by first
+adding `Animal` as a base structure and then adding `Flying`. The Create Structure dialog will
+automatically adjust the offset as you add structures. The dialog should look like this after
+the base structures are added:
+
+![Multiple base structures](../../img/create-multi-derived-struct.png "Multiple base structures")
+
+After defining and adding the additional member, the `Bird` structure looks like this:
+
+``` C
+struct __base(Animal, 0) __base(Flying, 0x10) Bird
+{
+ __inherited void* Animal::vtable;
+ __inherited char* Animal::name;
+ __inherited void* Flying::vtable;
+ __inherited int32_t Flying::max_airspeed;
+ int32_t song_length;
+};
+```
+
+### Base class virtual function tables
+
+Now it is time to start adding the virtual function tables, starting with the base classes.
+Add the virtual function table structures for `Animal` and `Flying`. Ensure to check the
+"propagate data variable references" option when creating any virtual function table. The
+virtual function table structures will look like this:
+
+``` C
+struct __data_var_refs vtable_for_Animal
+{
+ void (* make_sound)(struct Animal* this);
+ void (* approach)(struct Animal* this);
+};
+
+struct __data_var_refs vtable_for_Flying
+{
+ void (* fly)(struct Flying* this);
+};
+```
+
+Change the `vtable` members in the base classes to point to the virtual function table
+structures:
+
+``` C
+struct Animal
+{
+ struct vtable_for_Animal* vtable;
+ char* name;
+};
+
+struct Flying
+{
+ struct vtable_for_Flying* vtable;
+ int32_t max_airspeed;
+};
+```
+
+Now, go to the data section and apply the virtual function table structures to the
+virtual function tables themselves:
+
+``` C
+00004020 struct vtable_for_Animal _vtable_for_Animal =
+00004020 {
+00004020 void (* make_sound)(struct Animal* this) = nullptr
+00004028 void (* approach)(struct Animal* this) = Animal::approach()
+00004030 }
+
+00004050 struct vtable_for_Flying _vtable_for_Flying =
+00004050 {
+00004050 void (* fly)(struct Flying* this) = Flying::fly
+00004058 }
+```
+
+### Derived class virtual function tables
+
+The virtual function tables for the derived classes should be derived from the virtual
+function tables for the base classes using the
+[derived structure feature](#defining-a-derived-class-or-structure). Define the
+`Dog` and `Cat` virtual function tables with a base of `vtable_for_Animal`:
+
+``` C
+struct __base(vtable_for_Animal, 0) __data_var_refs vtable_for_Dog
+{
+ __inherited void (* vtable_for_Animal::make_sound)(struct Animal* this);
+ __inherited void (* vtable_for_Animal::approach)(struct Animal* this);
+};
+
+struct __base(vtable_for_Animal, 0) __data_var_refs vtable_for_Cat
+{
+ __inherited void (* vtable_for_Animal::make_sound)(struct Animal* this);
+ __inherited void (* vtable_for_Animal::approach)(struct Animal* this);
+ void (* nap)(struct Cat* this);
+};
+```
+
+Define the `Lion` virtual function table with a base of `vtable_for_Cat`:
+
+``` C
+struct __base(vtable_for_Cat, 0) __data_var_refs vtable_for_Lion
+{
+ __inherited void (* vtable_for_Animal::make_sound)(struct Animal* this);
+ __inherited void (* vtable_for_Animal::approach)(struct Animal* this);
+ __inherited void (* vtable_for_Cat::nap)(struct Cat* this);
+};
+```
+
+Change the `vtable` inherited members in the derived classes to point to the correct
+virtual function table structure for that class:
+
+``` C
+struct __base(Animal, 0) Dog
+{
+ struct vtable_for_Dog* vtable;
+ __inherited char* Animal::name;
+ int32_t bark_count;
+};
+
+struct __base(Animal, 0) Cat
+{
+ struct vtable_for_Cat* vtable;
+ __inherited char* Animal::name;
+ int32_t nap_count;
+};
+
+struct __base(Cat, 0) Lion
+{
+ struct vtable_for_Lion* vtable;
+ __inherited char* Animal::name;
+ __inherited int32_t Cat::nap_count;
+};
+```
+
+Apply the new virtual function table structures to the virtual function tables in
+the data section:
+
+``` C
+00004078 struct vtable_for_Dog _vtable_for_Dog =
+00004078 {
+00004078 void (* make_sound)(struct Animal* this) = Dog::make_sound()
+00004080 void (* approach)(struct Animal* this) = Animal::approach()
+00004088 }
+
+000040b0 struct vtable_for_Cat _vtable_for_Cat =
+000040b0 {
+000040b0 void (* make_sound)(struct Animal* this) = Cat::make_sound
+000040b8 void (* approach)(struct Animal* this) = Cat::approach()
+000040c0 void (* nap)(struct Cat* this) = Cat::nap()
+000040c8 }
+
+000040f0 struct vtable_for_Lion _vtable_for_Lion =
+000040f0 {
+000040f0 void (* make_sound)(struct Animal* this) = Lion::make_sound
+000040f8 void (* approach)(struct Animal* this) = Cat::approach()
+00004100 void (* nap)(struct Cat* this) = Cat::nap()
+00004108 }
+```
+
+At this point virtual method calls in the decompilation should start looking more correct:
+
+``` C
+void Animal::greet(struct Animal* this)
+{
+ _printf("You:\n");
+ _printf("Hello %s!\n", this->name);
+ _printf("%s:\n", this->name);
+ this->vtable->make_sound(this);
+}
+```
+
+### Virtual function tables with multiple inheritance
+
+The `Bird` class is derived from both `Animal` and `Flying`, so it has two different virtual function
+tables, one for each base class. Define both virtual function table structures, each deriving from
+the base class that it came from:
+
+``` C
+struct __base(vtable_for_Animal, 0) __data_var_refs vtable_for_Bird_as_Animal
+{
+ __inherited void (* vtable_for_Animal::make_sound)(struct Animal* this);
+ __inherited void (* vtable_for_Animal::approach)(struct Animal* this);
+};
+
+struct __base(vtable_for_Flying, 0) __data_var_refs vtable_for_Bird_as_Flying
+{
+ __inherited void (* vtable_for_Flying::fly)(struct Flying* this);
+};
+```
+
+There were two inherited `vtable` members in the `Bird` structure. Replace the types of these with
+the new derived virtual function table types:
+
+``` C
+struct __base(Animal, 0) __base(Flying, 0x10) Bird
+{
+ struct vtable_for_Bird_as_Animal* animal_vtable;
+ __inherited char* Animal::name;
+ struct vtable_for_Bird_as_Flying* flying_vtable;
+ __inherited int32_t Flying::max_airspeed;
+ int32_t song_length;
+};
+```
+
+Apply the virtual function table structures to the corresponding virtual function tables in the
+data section:
+
+``` C
+00004130 struct vtable_for_Bird_as_Animal _vtable_for_Bird_as_Animal =
+00004130 {
+00004130 void (* make_sound)(struct Animal* this) = Bird::make_sound()
+00004138 void (* approach)(struct Animal* this) = Bird::approach()
+00004140 }
+
+00004150 struct vtable_for_Bird_as_Flying _vtable_for_Bird_as_Flying =
+00004150 {
+00004150 void (* fly)(struct Flying* this) = Flying::fly
+00004158 }
+```
+
+Now the decompiler is able to determine the destination of a virtual function call in `Bird`:
+
+``` C
+void Bird::approach(struct Bird* this)
+{
+ this->flying_vtable->fly(&this->flying_vtable);
+}
+```
+
+The transformation on the `this` parameter is the compiler obtaining a pointer to `Flying` from
+the `Bird` instance so that it can be used by the `Flying` class.
+
+### Cross references
+
+Now that the data structures have been set up, Binary Ninja can provide helpful cross references
+when navigating the C++ program. For example, clicking on the `make_sound` member in the `Animal`
+structure will populate the cross references view with the list of functions that implement the
+method:
+
+![Virtual function table references](../../img/vtable-cross-refs.png "Virtual function table references")
+
+These cross references are aware of context when viewed from code. For example, in the following
+function:
+
+``` C
+void Cat::approach(struct Cat* this)
+{
+ if (this->nap_count == 0)
+ {
+ this->vtable->make_sound();
+ }
+ else
+ {
+ _puts("Zzzz...");
+ }
+}
+```
+
+Clicking on `make_sound` will populate the cross references with *only* the functions that are
+in `Cat` or derived classes of `Cat`:
+
+![Virtual function table references with context](../../img/vtable-cross-refs-context.png "Virtual function table references with context")
+
+## Offset Pointers
+
+When implementing multiple inheritance, sometimes compilers will define a pointer to a class as
+pointing into the middle of the memory layout of that class. If this is the case, you can use
+the `__ptr_offset` attribute on a structure to tell Binary Ninja that pointers to the structure
+are actually pointing at the given offset into the structure. For example, consider the following
+definition:
+
+``` C
+struct __ptr_offset(4) Foo
+{
+ int fizz;
+ int buzz;
+};
+```
+
+When dereferencing `Foo*`, Binary Ninja will treat `buzz` as the member being pointed to, with
+`fizz` being at offset `-4`.
diff --git a/docs/guide/types/debuginfo.md b/docs/guide/types/debuginfo.md
new file mode 100644
index 00000000..c994843c
--- /dev/null
+++ b/docs/guide/types/debuginfo.md
@@ -0,0 +1,37 @@
+# Debug Info
+
+Debug Info is a mechanism for importing types, function signatures, and data variables from either the original binary (eg. an ELF compiled with DWARF) or a supplemental file (eg. a PDB).
+
+Currently debug info plugins are limited to types, function signatures, and data variables, but in the future will include line number information, comments, local variables, and possibly more.
+
+## Supported DEBUG Info
+
+Out of the box, Binary Ninja supports PDBs and DWARF.
+
+For PDBs, Binary Ninja will automatically try to source from specified local folders and Microsoft's symbol server ([see the PDB settings for more information](../settings.md#all-settings)).
+
+For DWARF, this includes DWARF information compiled in to ELF binaries, DWARF information in external ELF files (`.dwo`, `.debug`, etc), DWARF information compiled in to Mach-O's, and DWARF information in external `.dSYM` files as well. Support for DWARF information in PEs is [planned](https://github.com/Vector35/binaryninja-api/issues/1555).
+
+## Applying debug info
+
+### PDB Notes
+
+PDBs will make a best effort to find relevant debug info and apply it when you open a binary. Some PDBs can be very large and take a significant amount of time to parse. When you open a large PDB, you'll see a progress indicator in the status bar at the bottom of the application.
+
+### DWARF Notes
+
+DWARF information will be imported by default if the file contains DWARF sections. Currently, Binary Ninja will not search local or remote locations to attempt to find the associated DWARF information for you. If you have separate DWARF info, you'll need to import that from an external file.
+
+### Importing from External Files
+
+Whether the Binary Ninja chooses the wrong PDB to import debug information from, or you have an external DWARF file you with to import the debug information from, you'll need to explicitly import debug info from that external file. You can either do this on-load by populating the "External Debug Info File" setting field (`analysis.debugInfo.external`), or by using the toolbar menu `Analysis` -> `Import Debug Info from External File`.
+
+#### Special Note for `.dSYM` Files
+
+`.dSYM` packages are often provided as application bundles. Binary Ninja currently does not support extracting the actual `.dSYM` file out of the package for parsing, so you may need to provide a full path for Binary Ninja to correctly parse.
+
+For example, you could have the file `hello.macho` that you would like to import debug info for. Thankfully, you also have `hello.dSYM`. So you open `hello.macho` with options, find the "External Debug Info File" and provide the `hello.dSYM` file. When the file opens, you notice that no information was imported and the log reads "No available/valid parsers for file." This is because `hello.dSYM` is a bundle. The actual path you needed to provide for the "External Debug Info File" setting would look something like `hello.dSYM/Contents/Resources/DWARF/hello`.
+
+## Not applying debug info
+
+If you wish not to import debug information for a file, you'll need to change the setting "Import Debug Information" (or `analysis.debugInfo.internal`). If you want to import debug information later, you can use the toolbar menu `Analysis` -> `Import Debug Info`, this will parse the current file and try to apply the recovered debug information.
diff --git a/docs/guide/types/index.md b/docs/guide/types/index.md
new file mode 100644
index 00000000..acf1046c
--- /dev/null
+++ b/docs/guide/types/index.md
@@ -0,0 +1,18 @@
+# Working with Types, Structures, and Symbols
+
+There's so many things to learn about working with Types in Binary Ninja that we've organized it into several sections!
+
+- [Basic Type Editing](basictypes.md): Brief overview of the basics
+- [Working with Types](type.md): Interacting with types in disassembly and decompilation
+- [Importing/Exporting Types](typeimportexport.md): How to import or export types from header files, archives, or other BNDBs
+
+Additionally, several types of containers for type information are documented here:
+
+- [Debug Info](debuginfo.md): Debug Info can provide additional type information (examples include DWARF and PDB files)
+- [Type Libraries](typelibraries.md): Type Libraries contain types from commonly-used dynamic libraries
+- [Platform Types](platformtypes.md): Types that automatically apply to a platform
+- [Type Archives](typearchives.md): How you can use type archives to share types between analysis databases
+- [Signature Libraries](../../dev/annotation.md#signature-library): Signature libraries are used to match names of functions with signatures for code that is statically compiled
+- [Platform Types](platformtypes.md): Platform types are base types that apply to all binaries on a particular platform
+
+Additionally, make sure to see the [applying annotations](../../dev/annotation.md) section of the developer guide for information about using the API with types and covering the creation of many of the items described below. \ No newline at end of file
diff --git a/docs/guide/types/platformtypes.md b/docs/guide/types/platformtypes.md
new file mode 100644
index 00000000..286615e6
--- /dev/null
+++ b/docs/guide/types/platformtypes.md
@@ -0,0 +1,42 @@
+# Platform Types
+
+Binary Ninja pulls type information from a variety of sources. The highest-level source are the platform types loaded for the given platform (which includes operating system and architecture). There are two sources of platform types. The first are shipped with the product in a [binary path](../index.md#directories). The second location is in your [user folder](../index.md#user-folder) and is intended for you to put custom platform types.
+
+???+ Danger "Warning"
+ Do NOT make changes to platform types in the binary path as they will be overwritten any time Binary Ninja updates.
+
+Platform types are used to define types that should be available to all programs available on that particular platform. They are only for global common types. Consider, for example, that you might want to add the following on windows:
+
+```
+typedef uint8_t u8;
+```
+
+You could write this type into:
+
+```
+/home/user/.binaryninja/types/platform/windows-x86.c
+```
+
+And any time you opened a 32bit windows binary, that type would be available to use. However, please note that these are not substitutes for [Type Libraries](../../dev/annotation.md#type-libraries). Type Libraries are used to provide a collection of types for a given library such as a libc, or common DLL.
+
+???+ Warning "Tip"
+ If you don't know the specific platform (and thus filename) you need to create for a given file, just enter `bv.platform` in the scripting console.
+
+## Common Types
+
+You may wish to provide types that are common across multiple architectures or platforms. The easiest way to do this is to use a `#include "filename.c"` line in the specific platform so that any common types will be loaded.
+
+The base path for these files is in your [user folder](../index.md#user-folder) inside of a "types/platform" subfolder.
+
+For example, something like:
+
+```
+$ pwd
+/home/user/.binaryninja/types/platform
+$ cat windows-x86.c
+#include "windows.c"
+$ cat windows-x86_64.c
+#include "windows.c"
+$ cat windows.c
+typedef uint8_t u8;
+```
diff --git a/docs/guide/types/type.md b/docs/guide/types/type.md
new file mode 100644
index 00000000..5526efa1
--- /dev/null
+++ b/docs/guide/types/type.md
@@ -0,0 +1,88 @@
+# Working with Types, Structures, and Symbols in Decompilation
+
+There are two main ways to interact with types in decompilation or disassembly. The first is to use the [types view](basictypes.md#types-view), and the second is to take advantage of the [smart structures workflow](#smart-structures-workflow) or otherwise annotate types directly in a disassembly or IL view.
+
+## Direct UI manipulation
+
+The simplest way to directly manipulate types in disassembly is by viewing an existing variable or sequence of bytes in linear view and using the following hotkeys:
+
+ - `1`, `2`, `4`, `8`: The number hotkeys will create a data variable at the current location if none exists, and then change the size of the variable to an integer in the size of bytes specified in the hotkey.
+ - `d`: If you want to cycle through the different integer sizes, repeatedly pressing `d` has the same effect as pressing the numbers in order.
+ - `-`: To quickly toggle integers between signed and unsigned integers, you can use the `-` hotkey.
+ - `a`: This hotkey sets or creates the current variable to a character array up until and including the next null byte.
+ - `o`: `o` will set or create the current variable to be a pointer reference.
+ - `*`: If you have a selection of identical variables, `*` will convert them into an array of elements. If you have no selection, the "Create Array" dialog will be shown allowing you to create an array of specific type and count at the current location.
+![Create Array Dialog](../../img/create-array.png "Create Array Dialog")
+ - `s`: `s` is a magic hotkey described in the next section in greater detail
+ - `m`: Used to apply an enumeration display at an integer (more details [below](#enumeration-selector))
+
+ Note that you can apply these types to a region of memory as well, not just a single variable. So selecting a large block of bytes and pressing `2` `*` for example will create an array of `int16_t` sized elements.
+
+## Enumeration Selector
+
+![Select Enum Dialog](../../img/select-enum-member.png "Select Enum Dialog")
+
+The Enum Dialog, with a default hotkey of `m` can be used to both change the type for data variables, arguments, and local variables to an enum type and also to change the Display Type of constant integers to any matching enumeration members.
+
+When used on an integer, all matching enumeration members will be shown.
+
+1. Filter box to search large lists of matching enums
+1. "New Enum" button to allow creation of a new enum
+1. Enum preview (can also be used to edit an existing enum by double clicking a given line)
+1. Currently selected enum/member (when the enum is selected, the preview will update, and you can also right-click here to change the type)
+1. Name of currently selected enum
+1. Checkbox (set by default) that hides enums with no matching members for the current integer.
+
+However in instances where the hotkey is used on other variables, the display will only be used to apply the enum type to the selection and does not allow editing.
+
+## Smart Structures Workflow
+
+![Auto Create Members](../../img/auto-create-members.png "Automatically Creating Struct Members")
+
+"Smart Structures" feature enables automatic creation of a structure and its members directly from the disassembly/IL view using the `s` hotkey.
+It simplifies the traditional workflow in which the user first creates a type in the types view and then applies it to disassembly.
+It works in the following ways:
+
+| View | Selection | Current Type | Behavior |
+|--------------------|--------------------------------------------------------------|----------------------|-----------------------------------------------------------------------------------|
+| Linear/Graph | A variable | Not a struct/struct\* | Create structure dialog |
+| Linear/Graph | A variable that is the result an allocation routine | Not a struct/struct\* | Create structure with allocation size |
+| Linear/Graph/Types | A variable, data variable, or a type name | struct/struct\* | Create all members for structure |
+| Linear/Graph/Types | A StructOffsetToken token, e.g., `__offset(0x18)` | N/A | Create current member for structure |
+
+Below are detailed explanation of it:
+
+1. In linear/graph view, if the selection is a variable that is not a structure, a dialog pops up and asks you to create a structure. You can specify the structure's name and size. There is also a checkbox that asks you whether the variable's type should be the structure itself or a pointer to the structure.
+2. In linear/graph view, if the selection is a variable that is not a structure, and it happens to be the result of a memory allocation routine, e.g., `malloc`, a new structure will be created and its size is automatically determined (if possible). The variable's type will be a pointer to the structure.
+3. In linear/graph/types view, If you select a variable whose type is a structure, or a pointer to a structure, BN will try to create all structure field at any offset that has been accessed in the code.
+4. In linear/graph/types view, If you select a StructOffsetToken, BN will try to create a structure member at the current offset.
+
+The automatic member creation mentioned in #3 and #4 takes into consideration both incoming and outgoing type information for the accessed offsets and selects the most confident one as the type for the offset.
+When no type information can be used to create the structure member, we fall back to creating an integer type based on the size of accesses. For example, if we see an access of size 4, we will create an `int32_t`. In case there are different sizes of accesses, we do not create the member. You will need to examine the conflicting size information and decide how to create a member.
+
+
+
+Consider the following example (created using [taped](../../files/taped) from the 2011 Ghost in the Shellcode CTF if you'd like to play along at home):
+
+| Step | Preview |
+|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
+| Go to address `0x8048e20` and switch to HLIL. | <img src="../../img/taped/1.png" alt="Structure Workflow 1"/> |
+| Select variable `var_18` and press `s`. <br/>Since `calloc` is a known allocation routine and the allocation size can be determined to be 0x30, a new structure, `struct_1` is created with size 0x30. | <img src="../../img/taped/2.png" alt="Structure Workflow 2"/> |
+| Select an offset, e.g., `__offset(0x4).d` and press `s`. A member will be automatically created. | <img src="../../img/taped/3.png" alt="Structure Workflow 3"/> |
+| Alternatively, select the `var_18` or the type name `struct_1` and press `s`. All members in the `struct_1` will be automatically created. | <img src="../../img/taped/4.png" alt="Structure Workflow 4"/> |
+| Viewing the automatically created structure members. | <img src="../../img/taped/5.png" alt="Structure Workflow 5"/> |
+
+
+The `s` hotkey also works when working with structures in the linear view. Its behavior differs based on the current selection:
+
+
+| Selection | Behavior |
+|--------------------------------------------------------------|-----------------------------------------------------------------------------------|
+| A single byte | Create structure dialog |
+| A range of bytes | Create structure with selection size |
+| A range of bytes covering existing data variables | Create structure with selection size and add existing data vars as struct members |
+
+
+In linear view, if the selection is a single byte outside any function, it will pop up the create structure dialog. If the selection is a range of bytes, a structure of the selection size is created and the start of the selection. If the selection covers any existing data variables, these data variables will become members within the newly created structure.
+
+This also works within data variables with structure type. For example, if the selection is a range of bytes within a structure, a new structure will be created within the existing structure.
diff --git a/docs/guide/types/typearchives.md b/docs/guide/types/typearchives.md
new file mode 100644
index 00000000..ce605c0d
--- /dev/null
+++ b/docs/guide/types/typearchives.md
@@ -0,0 +1,47 @@
+# Type Archives
+
+Type Archives are files you can use to share types between analysis databases. You can create them and manage their contents in [Types View](./basictypes.md#the-type-list).
+
+![Type Archives](../../img/type-archives.png "Type Archives"){ width="400" }
+
+## Creating and Attaching
+
+Using the context menu in the [Type List](basictypes.md#the-type-list) in Types View, you can create Type Archives using **Create Type Archive**. Simply pick a file location, and one will be created and attached to your analysis. Once you have done this, you can attach that Type Archive to other analyses in the same menu, by instead using **Attach Type Archive**. If you don't want to use a specific Type Archive in your analysis, you can right-click it in the Type List and use **Detach Type Archive**, which will remove any associations made to types it contains, but will not remove any types in your analysis.
+
+???+ Tip "Tip"
+ Type Archives have an associated Platform (e.g. windows-x86_64), which will determine
+ various Platform-specific type details, like pointer width. You may attach a
+ Type Archive to files with a different Platform, but note that these details may
+ cause issues with any types pulled from the Type Archive.
+
+Attached Type Archives are remembered in saved analysis databases, and will be attached on reopen, provided the file still exists. If the Type Archive file is moved (or deleted), then the Type List will report the Type Archive as Disconnected (but still attached). You can reconnect the Type Archive by using **Connect Type Archive** and pointing Binary Ninja at the new location of the Type Archive file.
+
+Enterprise users can create Type Archives in Remote Projects in the same manner, and all changes made to Type Archives in Remote Projects will be automatically synced with the Collaboration Server. Updates made by you are sent immediately, whereas updates made by other users on your server are fetched periodically in the background every 30 seconds (configurable by the `collaboration.autoPollInterval` setting). Once changes have been fetched, you can pull them into your analysis in the same way as described below. You may also attach Type Archives created outside your Remote Project, but note they will not be synced to the Collaboration Server.
+
+## Managing Types
+
+Once you have one or more Type Archives created and attached, you can start using them to store and share types between your analyses:
+
+1. In one analysis, create some types and use **Push Types to Archive** to add them to a Type Archive
+2. In another analysis, you can use **Pull Types from Archive** to import those types from the Type Archive
+3. Now, in either analysis, you can [make changes to those types](basictypes.md#the-type-editor) and once again use **Push Types to Archive** to send the changes to the Type Archive
+4. And after doing so, you can open the other analysis and use **Pull Types from Archive** to receive those changes from the Type Archive
+5. If you push changes to a Type Archive and, before pulling them in the other analysis, change them there as well, you will have to choose which version of the individual types you want to use. Either push or pull the specific types and, when prompted, confirm your choice to use that version.
+
+If you want to rename a type in the Type Archive, you can use **Rename Type** in the context menu in the Type List. You can either rename it in your analysis, and then push the type, or rename it directly in the Type Archive, and then pull the type. Note that renaming a type will cause updates for other types that reference it, which may also need to be pushed or pulled afterward.
+
+If you want to delete a type in the Type Archive, you can select it in the Type List under the Type Archive, and use **Undefine Type**. This will not delete it from your analysis, and indeed if you had instead deleted it from your analysis, it would not have been deleted in the Type Archive. If you delete the type in either place, the association will no longer apply and changes made to the type will not be shown as needing to be pushed or pulled.
+
+If you want to manually disassociate a type in your analysis from a Type Archive, you can use **Disassociate Types from Archive**, and then no changes made to that type, either in the analysis, or in the Type Archive, will be shown as needing to be pushed or pulled.
+
+![Type Archives >](../../img/type-archives-status.png "Type Archives Status"){ width="500" }
+
+When you have pushed or pulled types from a Type Archive, you will see their status reflected in the Type List:
+
+1. Normal type, not associated with a Type Archive
+2. Type associated with a Type Archive with no changes
+3. Type associated with a Type Archive with changes made in the analysis that can be pushed to the Type Archive
+4. Type associated with a Type Archive with changes made in the Type Archive that can be pulled into the analysis
+5. Type associated with a Type Archive with changes made both in the analysis and the Type Archive, that will need you to choose which version to keep
+6. Type associated with a Type Archive that is missing
+
diff --git a/docs/guide/types/typeimportexport.md b/docs/guide/types/typeimportexport.md
new file mode 100644
index 00000000..43fbfa90
--- /dev/null
+++ b/docs/guide/types/typeimportexport.md
@@ -0,0 +1,184 @@
+# Importing Type Information
+
+Type information can be imported from a variety of sources. If you have header files, you can [import a header](#import-header-file). If your types exist in an existing BNDB, you can use [import from a bndb](#import-bndb-file). With the introduction of [type archives](typearchives.md) we recommend migrating away from importing via BNDB to type archives as they allow types to remain synced between different databases.
+
+## Import BNDB File
+
+The Import BNDB File feature imports types from a previous BNDB into your currently open file. In addition, it will apply types for matching symbols in functions and variables. Import BNDB *will not* port symbols from a BNDB with symbols to one without -- the names must already match. Matching functions and porting symbols is beyond the scope of this feature.
+
+![Importing a BNDB](../../img/import-bndb.png "Importing a BNDB")
+
+### Usage
+
+To use this feature select `Import From BNDB` from the `Analysis` menu, use the [command palette](../index.md#command-palette), or [bind a hotkey](../index.md#custom-hotkeys) and select the BNDB you'd like to import. Wait for the BNDB to load then you'll be presented with a list of things to import.
+
+* Types - Various types to be imported from the source BNDB
+* Functions - Attempt to find target functions whose symbol already matches the symbol of the source BNDB and apply their type
+* Function to Imports - Attempt to find target Imports whose symbol matches the Functions symbols in the source BNDB and apply their type
+* Data Variables - Attempt to find target DataVariables with symbols that match DataVariables in the source BNDB and apply their type
+
+This feature enables a number of workflows:
+
+### Porting Analysis Between Target Versions
+
+If you're working with version 1 of a file which has symbols and you now want to port your work over to version 2 (as long as they both have symbols). This isn't going to be perfect as this feature isn't interactive and doesn't take into account changes in parameter counts or ordering, so *use this with caution*.
+
+### Quickly Defining Externs
+
+If you have a binary with externs which don't have TypeLibraries this can allow you to quickly import them (and their types) from another source, this is especially effective when you have debug information for the dependent libraries
+
+## Import Header File
+
+If you already have a collection of headers containing types you want to use, you can import them directly. You can specify the compiler flags that would be used if a compiler were compiling a source file that uses this header. Specifically this means you can/should specify:
+
+- `-isystem<path>` for various system header paths
+- `-I<path>` for various user header paths
+- `-D<macro>=<value>` for macro definitions
+- `-x c -std=c99` to specify C99 mode
+- Other Clang-compatible command-line flags are accepted (eg `-fms-extensions`, `-fms-compatibility`, etc)
+
+You can specify that types from system headers, accessed via `#include <header.h>`, will be in the results. Otherwise, only files from user headers, accessed via `#include "header.h"` will be used.
+
+You can also specify Define Binary Ninja Macros, which makes the type parser include the various parser extensions that Binary Ninja allows in the Type View editors, eg `__packed`, `__padding`, `__syscall`, etc. You probably only want to use this option when importing a header file exported using [Export Header File](#export-header-file).
+
+After specifying the file(s) and flag(s), pressing Preview will give a list of all the types and functions defined in the file(s). You may check or uncheck the box next to any of the types/functions to control whether they will be imported to your analysis.
+
+If there were any parse errors, those will be shown instead of a list of types. Generally speaking, what this means is you're missing either header search paths or compile definitions. See the section below on [finding system headers](#finding-system-headers).
+
+After pressing Import, all the checked types/functions will be added to your analysis. Imported types will override any existing types you had defined so they are disabled by default as indicated via the `Exists Already` column. Imported functions will replace signatures of any functions in your analysis whose name matches signatures found in the header.
+
+![Importing a header file](../../img/import-header.png "Importing a header file")
+
+### Finding System Headers
+
+Since you need to specify the include paths for system headers, you will need to deduce them for the target platform of your analysis. Here are a few tricks that may help:
+
+#### Systems with GCC/Clang (macOS, Linux, etc)
+
+On these systems, you can run a command to print the default search path for compilation:
+
+ gcc -Wp,-v -E -
+ clang -Wp,-v -E -
+
+For the directories printed by this command, you should include them with `-isystem<path>` in the order specified.
+
+For example on macOS, with Xcode 13:
+
+ $ clang -Wp,-v -E -
+ clang -cc1 version 13.0.0 (clang-1300.0.29.3) default target arm64-apple-darwin21.6.0
+ ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
+ ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
+ #include "..." search starts here:
+ #include <...> search starts here:
+ /usr/local/include
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include
+ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
+ /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
+ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
+ End of search list.
+
+From this example, the flags would be: (note: not including the framework directory line)
+
+ -isystem/usr/local/include
+ -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/13.0.0/include
+ -isystem/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
+ -isystem/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
+
+Another example on Arch Linux:
+
+ $ gcc -Wp,-v -E -
+ ignoring nonexistent directory "/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/../../../../../../../../x86_64-pc-linux-gnu/include"
+ #include "..." search starts here:
+ #include <...> search starts here:
+ /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/include
+ /usr/local/include
+ /usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/include-fixed
+ /usr/include
+ End of search list.
+
+From this example, the flags would be:
+
+ -isystem/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/include
+ -isystem/usr/local/include
+ -isystem/usr/lib/gcc/x86_64-pc-linux-gnu/12.2.0/include-fixed
+ -isystem/usr/include
+
+##### For Windows
+
+For windows, there's no easy command to list all the include paths so you have to piece them together from the `Include Directory` property in a Visual Studio project. You also want to include `-x c -std=c99` since Windows headers include lots of C++ types that the type importer currently does not support.
+
+You will end up with something like the following for user mode:
+
+ -x c -std=c99
+ -isystem"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29333\include"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um"
+
+Or, for kernel mode:
+
+ -x c -std=c99
+ -isystem"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29333\include"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\km"
+
+Note that some header files might require manually including a specific `windows.h` header which necessitates specifying a target platform to get the appropriate includes:
+
+ --target=x86_64-pc-windows-msvc
+ -x c -std=c99
+ -include"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um\windows.h"
+ -isystem"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\VC\Tools\MSVC\14.28.29333\include"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\ucrt"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\shared"
+ -isystem"C:\Program Files (x86)\Windows Kits\10\Include\10.0.19041.0\um"
+
+
+##### Cross-Platform Targets
+
+If you are analyzing a target that is for a different operating system, you need to both find the header include paths for that system, and copy (or mount) them to a location accessible by the computer running Binary Ninja.
+
+### Export Header File
+
+If you want to compile code using the structures you defined during your analysis, you can export all the types to a C-compatible header file that can be used via `#include` by a C compiler. You can also import this header in another analysis session via [Import Header File](#import-header-file), just be sure to enable `Define Binary Ninja Macros` when doing so.
+
+## Platform Types
+
+Binary Ninja pulls type information from a variety of sources. The highest-level source are the platform types loaded for the given platform (which includes operating system and architecture). There are two sources of platform types. The first are shipped with the product in a [binary path](../index.md#directories). The second location is in your [user folder](../index.md#user-folder) and is intended for you to put custom platform types.
+
+???+ Danger "Warning"
+ Do NOT make changes to platform types in the binary path as they will be overwritten any time Binary Ninja updates.
+
+Platform types are used to define types that should be available to all programs available on that particular platform. They are only for global common types. Consider, for example, that you might want to add the following on windows:
+
+```
+typedef uint8_t u8;
+```
+
+You could write this type into:
+
+```
+/home/user/.binaryninja/types/platform/windows-x86.c
+```
+
+And any time you opened a 32bit windows binary, that type would be available to use. However, please note that these are not substitutes for [Type Libraries](../../dev/annotation.md#type-libraries). Type Libraries are used to provide a collection of types for a given library such as a libc, or common DLL.
+
+???+ Warning "Tip"
+ If you don't know the specific platform (and thus filename) you need to create for a given file, just enter `bv.platform` in the scripting console.
+
+### Common Types
+
+You may wish to provide types that are common across multiple architectures or platforms. The easiest way to do this is to use a `#include "filename.c"` line in the specific platform so that any common types will be loaded.
+
+For example, something like:
+
+```
+$ pwd
+/home/user/.binaryninja/types/platform
+$ cat windows-x86.c
+#include "windows.c"
+$ cat windows-x86_64.c
+#include "windows.c"
+$ cat windows.c
+typedef uint8_t u8;
+```
diff --git a/docs/guide/types/typelibraries.md b/docs/guide/types/typelibraries.md
new file mode 100644
index 00000000..28e0b4fb
--- /dev/null
+++ b/docs/guide/types/typelibraries.md
@@ -0,0 +1,37 @@
+# Type Libraries
+
+Type Libraries are collections of type information (structs, enums, function types, etc.), corresponding to specific dynamic libraries that are imported into your analysis. You can browse and import them in the [Types View](./basictypes.md#the-type-list).
+
+__image of Type List showing a couple imported type libraries, with one expanded showing its types__
+
+## Usage
+
+Most of your usage of Type Libraries will be performed automatically by Binary Ninja when you analyze a binary. They are automatically imported based on the libraries that your binary uses. Any library functions or global variables your binary references will have their type signature imported, and any structures those functions and variables reference are imported as well.
+
+__image of linear view showing a bunch of imported functions from a type library__
+
+Compared to [Platform Types](./platformtypes.md), only Type Libraries needed by your binary will be imported into your analysis. If you want to manually import additional Type Libraries (e.g. if your binary dynamically loads a library), you can use the **Import Type Library** action in [Types View](./basictypes.md#the-type-list). Just pick a Type Library from the list shown, and it will be added to the list where you can import types from it.
+
+If you want to use types from a Type Library that have not yet been imported, you can select them in the [Types View](./basictypes.md#the-type-list) and use the **Import Types** action. They will be copied into your analysis's System Types and you can use them in your own structure and function annotations.
+
+## Design and Purpose
+
+Type Libraries contain details about a specific library that is imported by binaries. They contain information about the types used in the library:
+* Types
+ * Structures, Classes, Unions
+ * Enumerations
+ * Typedefs
+* Objects
+ * Function Signatures
+ * Global Variables
+
+Type Libraries are named after the source library they are providing types for. When a binary is opened, Binary Ninja finds all of its linked library dependencies, and looks up Type Libraries for them. Those with a File Name or Alternative Name matching the exact text of a library used by the binary will be imported into the analysis. You can see this process in the Log:
+
+ elf: searching for 'libc.so.6' in type libraries
+ Type library 'libc.so.6' imported
+
+The [Developer Guide](../../dev/typelibraries.md) contains more details about the implementation details of the Type Library format.
+
+## Creating and Modifying
+
+Type Libraries are read-only by design, so while you cannot modify the ones built into Binary Ninja, you can create your own and use them as replacements. While there is no User Interface for doing this, there are plenty of APIs available. Check the [Developer Guide](../../dev/typelibraries.md) for details on how to create a Type Library.