BNMF Reference
Binary Ninja Modification Format (BNMF) is the declarative JSON protocol Sidekick uses to write changes back to the Binary Ninja database. Instead of issuing imperative commands, you describe the desired state of an object. The processor reads the current state, computes the delta, and applies the minimum changes needed.
BNMF is used internally by Sidekick's AI agents whenever they rename functions, define types, annotate code, or perform any other database modification. You can also submit BNMF directly via the Sidekick API.
For a conceptual overview of how modifications fit into the analysis workflow, see Editing Binaries with Suggestions.
Request Structure
A BNMF request is a JSON object with a human-readable description and a list of per-view change sets.
{
"description": "Human-readable summary for Binary Ninja undo history",
"binary_view_changes": [
{
"modifications": [
{"uri": "bv:function/0x401000", "state": {"name": "process_input"}}
]
}
]
}
binary_view_id inside a change set is optional when only one binary is open.
ModificationBatch fields
| Field |
Type |
Default |
Description |
modifications |
Array[Modification] |
Required |
Modifications to apply |
summary |
String |
None |
Description for the undo history entry |
mode |
"atomic" | "best_effort" |
"atomic" |
Processing mode (see Processing Modes) |
Modification fields
| Field |
Type |
Default |
Description |
uri |
String |
Required |
Target object identifier |
state |
Object | null |
Required |
Desired state; null deletes the object |
id |
String |
None |
Client-assigned ID for dependency references |
depends_on |
Array[String] |
None |
IDs of modifications that must succeed first |
expect |
Object |
None |
Preconditions to validate before applying |
Processing Modes
Atomic (default)
All modifications succeed or none are applied. If any modification fails, the entire batch is rolled back using Binary Ninja's undo system.
Best effort
Processing continues after individual failures. Failed modifications are recorded in the result but do not stop the batch. All changes that did succeed are committed.
Dependency Ordering
Use id and depends_on to enforce ordering when one modification must precede another — for example, defining a type before using it.
{
"modifications": [
{
"id": "def_type",
"uri": "bv:type/Buffer",
"state": {"definition": "struct Buffer { char* data; size_t len; }"}
},
{
"uri": "bv:function/0x401000/variable/arg1",
"state": {"type": "struct Buffer*"},
"depends_on": ["def_type"]
}
]
}
Rules:
- Modifications are sorted topologically by depends_on before execution.
- If a modification fails, all modifications that depend on it (directly or transitively) are skipped.
- Duplicate id values, unknown dependency IDs, and circular dependencies all raise an error and fail the entire batch.
Preconditions (expect)
The expect field validates the current state before applying a modification. If validation fails, the modification fails with an ExpectationError.
$exists operator
{"expect": {"$exists": true}} // Entity must already exist
{"expect": {"$exists": false}} // Entity must NOT exist
An empty expect object ({}) requires the entity to exist without constraining any property values.
Property matching
{"expect": {"name": "sub_401000"}} // name property must equal "sub_401000"
Multiple properties can be checked simultaneously. All must match.
Collection Operators
For array-valued properties, use $add and $remove to make targeted changes without replacing the entire list.
{
"state": {
"parameters": {
"$add": [{"name": "len", "type": "size_t"}],
"$remove": [{"name": "arg3", "type": "int32_t"}]
}
}
}
Processing order: $remove is applied first, then $add. $add deduplicates — adding an item that already exists is a no-op.
URI Reference
All URIs use the bv: scheme. Addresses are always in hexadecimal with a 0x prefix.
Summary table
| URI Pattern |
Description |
bv:comment/{address} |
Address-level comment |
bv:type/{name} |
Named type definition |
bv:type/{type_name}/member/{member_id} |
Struct or union member |
bv:datavar/{address} |
Data variable |
bv:function/{address} |
Function |
bv:function/{address}/instruction/{instr_addr} |
Instruction within a function |
bv:function/{address}/instruction/{instr_addr}/integer/{value}/{operand} |
Integer operand display type |
bv:function/{address}/variable/{var_name} |
Local variable within a function |
bv:function/{address}/block/{block_addr} |
Basic block highlight |
bv:dataref/{from_addr}/{to_addr} |
User-defined data cross-reference |
bv:pointer |
Global pointer value |
bv:memory/{address} |
Raw bytes at an address |
bv:symbol/{address}/{symbol_type} |
Named symbol |
bv:section/{name} |
Memory section |
bv:segment/{address} |
Memory segment |
bv:tag/{address}/{type_name} |
Tag at an address |
bv:tagtype/{name} |
Tag type definition |
bv:library/{name} |
External library |
bv:external/{library}/{source_address} |
External symbol location |
bv:import/{address} |
Imported function signature (IAT slot / GOT entry) |
bv:component/{component_id} |
Component (function/data grouping) |
bv:stack/{function_address}/variable/{offset} |
Stack variable |
bv:stack/{function_address}/call_adjustment/{instruction_address} |
Per-call stack adjustment |
bv:stack/{function_address}/return_adjustment |
Function return stack adjustment |
Handler Reference
| Property |
Type |
Read |
Write |
Notes |
text |
String |
Yes |
Yes |
Empty string is the default (no comment) |
- Comments always "exist" — there is no absent state, only an empty string.
state: null clears the comment (equivalent to {"text": ""}).
{"uri": "bv:comment/0x401200", "state": {"text": "AES key schedule loop"}}
Type — bv:type/{name}
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Rename by setting name to a new value |
definition |
String |
Yes |
Yes |
Full C-syntax type definition |
state: null undefines the type (undefine_user_type).
- Namespace qualifiers (
::) in type strings are automatically wrapped in backticks if needed.
{"uri": "bv:type/Config", "state": {"definition": "struct Config { int version; char name[32]; }"}}
Structured Type Member — bv:type/{type_name}/member/{member_id}
member_id formats:
- Hex offset: 0x8, 0x10
- Decimal offset: 8, 16
- Member name: fieldName
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Member name |
type |
String |
Yes |
Yes |
Member type string |
offset |
Integer |
Yes |
Yes |
Byte offset in the structure |
- Only works on
struct and union types.
- Changing
offset removes the member and re-inserts it at the new position.
state: null removes the member from the structure.
- Union limitation: For unions all members share offset 0, so address-based lookup returns the first match. Use member name as the
member_id to target a specific union member.
{"uri": "bv:type/Header/member/field_name", "state": {"name": "magic", "type": "uint32_t"}}
Data Variable — bv:datavar/{address}
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Symbol name; empty string means unnamed |
type |
String |
Yes |
Yes |
Type string; required when creating |
confidence |
Integer |
Yes |
Yes |
Binary Ninja type confidence (0–255) attached to type; omit on write for the default (maximum) |
comment |
String |
Yes |
Yes |
Comment at this address |
state: null undefines the variable (undefine_user_data_var). Only user-defined variables can be deleted — analysis-generated variables (such as jump tables) cannot be removed and will raise an error.
- Creating a data variable requires
type to be specified.
confidence only takes effect on write when type is also provided in the same modification. It is attached to the parsed type via Type.with_confidence(...) before assignment. Use a lower value (e.g. 128) to mark an AI-suggested type as "soft" so subsequent analysis can still refine it; omit the field (or use 255) to pin a user-confident type that analysis will not override.
{"uri": "bv:datavar/0x804a020", "state": {"name": "g_config", "type": "struct Config*"}}
{
"uri": "bv:datavar/0x804a020",
"state": {"type": "struct Config*", "confidence": 128}
}
Function — bv:function/{address}
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Function name |
type |
String |
Yes |
Yes |
Full function type signature |
comment |
String |
Yes |
Yes |
Function-level comment |
return_type |
String |
Yes |
Yes |
Return type only |
calling_convention |
String |
Yes |
Yes |
e.g. "cdecl", "stdcall" (case-insensitive) |
inline |
Boolean |
Yes |
Yes |
Mark function as inline during analysis |
analysis_skipped |
Boolean |
Yes |
Yes |
Skip analysis for this function |
can_return |
Boolean |
Yes |
Yes |
Whether the function can return |
clobbered_regs |
Array[String] |
Yes |
Yes |
Register names clobbered by the function; null reverts to auto-detected |
parameters |
Array[Object] |
Yes |
Yes |
[{"name": "buf", "type": "char*"}, ...] |
state: null removes the user-defined function (remove_user_function).
state: {} creates a function at the address (create_user_function).
- Invalid register names in
clobbered_regs raise an error with examples of valid names.
- The function signature itself has no
confidence field: Binary Ninja's BNSetFunctionUserType stores user function types at maximum confidence and provides no confidence parameter, so any confidence on the parsed type would be silently dropped. If you need a soft type, apply it to individual arguments via bv:function/{address}/variable/{var_name} with confidence, or set the data variable at a global's address via bv:datavar/{address}.
{"uri": "bv:function/0x406ec0", "state": {"name": "command_interpreter", "return_type": "void"}}
Function Instruction — bv:function/{address}/instruction/{instr_addr}
| Property |
Type |
Read |
Write |
Notes |
comment |
String |
Yes |
Yes |
Instruction-level comment |
highlight |
String |
Yes |
Yes |
Color name: blue, red, green, cyan, magenta, yellow, orange, white |
goto_label |
String |
No |
Yes |
Label name for jump target (requires HLIL) |
call_type |
String |
No |
Yes |
Call type override; must be a function type such as int64_t(void*, int16_t*), not a pointer-to-function type |
stack_adjustment |
Integer |
No |
Yes |
Stack adjustment value at this call site |
reg_stack_adjustment |
Integer |
No |
Yes |
Register stack adjustment value |
indirect_branches |
Array |
No |
Yes |
Target addresses for indirect branches (integers or hex strings) |
code_refs |
Array |
No |
Yes |
Addresses to add as user code cross-references |
state: null clears the comment and highlight.
indirect_branches takes raw addresses: ["0x100000e58", "0x100000eb8"]. Do not use symbol names or (arch, address) tuples.
{
"uri": "bv:function/0x401200/instruction/0x401210",
"state": {"highlight": "yellow", "comment": "Round key XOR"}
}
Function Instruction Integer — bv:function/{address}/instruction/{instr_addr}/integer/{value}/{operand}
| Property |
Type |
Read |
Write |
Notes |
display_type |
String |
No |
Yes |
Hex, Decimal, Pointer, etc. |
operand is a zero-based index that disambiguates when the same integer value appears multiple times in an instruction.
{
"uri": "bv:function/0x401000/instruction/0x401005/integer/0x100/0",
"state": {"display_type": "Decimal"}
}
Function Variable — bv:function/{address}/variable/{var_name}
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Variable name |
type |
String |
Yes |
Yes |
Variable type |
confidence |
Integer |
Yes |
Yes |
Binary Ninja type confidence (0–255) attached to type; omit on write for the default (maximum) |
value |
Integer |
No |
Yes |
Constant value to assign to the variable at def_address via func.set_user_var_value. Write-only. Must be used together with def_address. |
def_address |
Integer or hex String |
No |
Yes |
Address of the definition site for the value write. Write-only. Defaults to 0 if omitted when value is present. |
dead_store_elimination |
Boolean |
Yes |
Yes |
Enable or disable dead store elimination |
merge_from |
Array[String] |
No |
Yes |
Variable names to merge into this one |
- Variables cannot be deleted in Binary Ninja — delete operations are no-ops.
- The variable must already exist.
confidence only takes effect on write when type is also provided in the same modification. It is attached to the parsed type via Type.with_confidence(...) before the underlying create_user_var call. Use a lower value to mark an AI-suggested type as "soft" so subsequent analysis can still refine it; omit the field (or use 255) to pin a user-confident type.
merge_from combines the listed source variables into the target using func.merge_vars. Source names that do not exist are silently skipped.
{"uri": "bv:function/0x406ec0/variable/var_8", "state": {"name": "buffer", "type": "char*"}}
{
"uri": "bv:function/0x406ec0/variable/arg1",
"state": {"type": "struct Connection*", "confidence": 128}
}
Function Block — bv:function/{address}/block/{block_addr}
| Property |
Type |
Read |
Write |
Notes |
color |
String |
Yes |
Yes |
Block highlight color (HighlightStandardColor value) |
Block lookup is scoped to the specific function, so the same address in multiple functions is unambiguous.
Data Reference — bv:dataref/{from_addr}/{to_addr}
No properties — this is an existence-only resource.
state: {} creates the reference (add_user_data_ref).
state: null removes the reference (remove_user_data_ref).
{"uri": "bv:dataref/0x401050/0x804a000", "state": {}}
Pointer — bv:pointer
| Property |
Type |
Read |
Write |
Notes |
value |
Integer |
Yes |
Yes |
Global pointer address (binary-wide) |
user_set |
Boolean |
Yes |
No |
Whether the user has set the value (read-only) |
state: null clears the user-set global pointer value.
state: {"value": null} forces the pointer to Undetermined.
Memory — bv:memory/{address}
| Property |
Type |
Read |
Write |
Notes |
bytes |
Hex String |
No |
Yes |
Raw bytes to write, e.g. "90909090" |
expect |
Hex String |
No |
Yes |
Expected current bytes (compare-and-swap) |
state: null raises an error — memory cannot be deleted.
- When
expect is provided, the write only proceeds if the current bytes at the address match. Use this to avoid overwriting bytes that have already changed.
{"uri": "bv:memory/0x401000", "state": {"bytes": "9090", "expect": "7401"}}
Symbol — bv:symbol/{address}/{symbol_type}
symbol_type values: FunctionSymbol, DataSymbol, ImportedFunctionSymbol, ImportedDataSymbol, ExternalSymbol, LibraryFunctionSymbol
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Short name (required for create or update) |
full_name |
String |
Yes |
Yes |
Full name including namespace (defaults to name) |
raw_name |
String |
Yes |
Yes |
Raw or mangled name (defaults to full_name) |
binding |
String |
Yes |
Yes |
NoBinding, LocalBinding, GlobalBinding, WeakBinding |
namespace |
String |
Yes |
Yes |
Symbol namespace |
ordinal |
Integer |
Yes |
Yes |
Symbol ordinal (default 0) |
- Multiple symbols of different types can exist at the same address.
- When updating, the existing symbol of the matching type is undefined before the new one is created.
- Only user-defined symbols can be deleted. Loader-generated symbols (e.g.
ImportedFunctionSymbol from the file format) cannot be removed and will raise an error.
{"uri": "bv:symbol/0x401000/FunctionSymbol", "state": {"name": "main", "binding": "GlobalBinding"}}
Section — bv:section/{name}
| Property |
Type |
Read |
Write |
Notes |
start |
Integer |
Yes |
Yes |
Start address |
length |
Integer |
Yes |
Yes |
Size in bytes |
semantics |
String |
Yes |
Yes |
See semantics values below |
type |
String |
Yes |
Yes |
Section type string |
align |
Integer |
Yes |
Yes |
Alignment (default 1) |
entry_size |
Integer |
Yes |
Yes |
Entry size (default 1) |
linked_section |
String |
Yes |
Yes |
Linked section name |
info_section |
String |
Yes |
Yes |
Info section name |
info_data |
Integer |
Yes |
Yes |
Info data value |
auto_defined |
Boolean |
Yes |
No |
Whether the section is loader-defined (read-only) |
Semantics values: DefaultSectionSemantics, ReadOnlyCodeSectionSemantics, ReadOnlyDataSectionSemantics, ReadWriteDataSectionSemantics, ExternalSectionSemantics
- Creating a section requires
start and length.
state: null calls remove_user_section — only user-created sections can be deleted.
- Modifying a user section is implemented as delete-and-recreate with merged properties. Only the properties you specify change; the rest retain their existing values.
- Loader-defined sections (
auto_defined: true, such as .text or .rodata) cannot be modified and will raise an error.
Segment — bv:segment/{address}
| Property |
Type |
Read |
Write |
Notes |
length |
Integer |
Yes |
Yes |
Total size |
data_offset |
Integer |
Yes |
Yes |
File offset |
data_length |
Integer |
Yes |
Yes |
File size |
readable |
Boolean |
Yes |
Yes |
Read permission |
writable |
Boolean |
Yes |
Yes |
Write permission |
executable |
Boolean |
Yes |
Yes |
Execute permission |
contains_data |
Boolean |
No |
Yes |
Contains data flag |
contains_code |
Boolean |
No |
Yes |
Contains code flag |
- Creating a segment requires
length, data_offset, and data_length.
state: null calls remove_user_segment.
Tag — bv:tag/{address}/{type_name}
| Property |
Type |
Read |
Write |
Notes |
data |
String |
Yes |
Yes |
Tag content |
icon |
String |
No |
Yes |
Icon (used when auto-creating the tag type) |
- If the tag type does not exist, it is created automatically.
- An existing tag of the same type at the address is removed before the new one is added.
{"uri": "bv:tag/0x401000/Reviewed", "state": {"data": "confirmed benign"}}
Tag Type — bv:tagtype/{name}
| Property |
Type |
Read |
Write |
Notes |
icon |
String |
Yes |
Yes |
Icon character |
state: null calls remove_tag_type.
- Changing the icon on an existing tag type requires a delete-and-recreate, which may orphan existing tags of that type.
External Library — bv:library/{name}
| Property |
Type |
Read |
Write |
Notes |
backing_file |
String |
Yes |
Yes |
Path to the backing file |
state: null calls remove_external_library.
External Location — bv:external/{library}/{source_address}
source_address is the address of the import reference in the binary (the source symbol address), which uniquely identifies the location even when multiple symbols share a name.
| Property |
Type |
Read |
Write |
Notes |
source_symbol |
String |
Yes |
No |
Name of the source symbol (read-only) |
target_symbol |
String |
Yes |
Yes |
Symbol name in the target library |
target_address |
Integer |
Yes |
Yes |
Address in the target library |
- The external library must exist before creating an external location.
Imported Function — bv:import/{address}
Apply a recovered signature to an imported symbol and have it propagate to every caller automatically. This is the right URI for the import-type-recovery workflow — it hides the platform-specific plumbing behind a single address and a function type.
address is the IAT slot (PE) or GOT entry (ELF) — the address Binary Ninja flags with ImportAddressSymbol, same value the enumerator returns as iat_or_got.
| Property |
Type |
Read |
Write |
Notes |
symbol |
String |
Yes |
No |
Short name of the imported symbol (read-only) |
type |
String |
Yes |
Yes |
Function type — e.g. "int32_t(const char* fmt, ...)", not pointer-to-function |
confidence |
Integer |
Yes |
Yes |
0–255. Advisory — Binary Ninja drops per-function-type confidence on write (see Function notes) |
library |
String |
Yes |
No |
Attributed library when the format states one (PE); null on ELF |
plt_address |
String |
Yes |
Yes |
ELF PLT stub address. Read-side: the resolved stub. Write-side: optional hint that short-circuits code-ref lookup |
- ELF: the handler locates the small PLT stub that jumps through the GOT entry (the first code-ref whose function has ≤3 basic blocks, matching the standard x86-64 / ARM64 / MIPS PLT shape) and calls
Function.set_user_type on it. Analysis propagates the stub's signature to every caller's HLIL automatically. If you already know the PLT stub's address, pass plt_address in the state to skip the lookup.
- PE: there is no PLT stub — the handler wraps the function type in a pointer and assigns it to the IAT data variable. Callers see the type through the normal indirect-call pointer propagation path.
- The
type attribute must be a function type. Pointer-to-function forms are rejected with a clear error — pointer wrapping on PE is handled internally so callers use one form on both platforms.
state: null is a no-op: Binary Ninja has no "un-apply" API for imported types, and we don't want to strip types we didn't author.
- Why not
bv:datavar/{got_addr}? On ELF, typing the GOT data variable does not propagate to callers. The GOT slot is not what analysis consults when resolving calls through the PLT — the stub's own function signature is. bv:import targets the stub, which is the only thing post-load analysis honors.
{
"uri": "bv:import/0x5cac0",
"state": {"type": "int32_t(const char* ident, int32_t option, int32_t facility)"}
}
{
"uri": "bv:import/0x5cac0",
"state": {
"type": "int32_t(const char* ident, int32_t option, int32_t facility)",
"plt_address": "0xc060"
}
}
Component — bv:component/{component_id}
component_id can be a GUID or a component name. The lookup searches recursively through all nested components.
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Component display name |
functions |
Array[String] |
Yes |
Yes |
Function addresses (hex strings); setting this replaces the entire list |
datavars |
Array[String] |
Yes |
Yes |
Data variable addresses (hex strings); setting this replaces the entire list |
state: null calls remove_component.
- Use
$add/$remove collection operators to add or remove individual entries without replacing the full list.
Stack Variable — bv:stack/{function_address}/variable/{offset}
offset formats: -0x10, 0x10, -16, 16
| Property |
Type |
Read |
Write |
Notes |
name |
String |
Yes |
Yes |
Variable name |
type |
String |
Yes |
Yes |
Variable type |
offset |
Integer |
Yes |
No |
Stack offset (from URI; read-only in state) |
state: null calls delete_user_stack_var(offset).
- Creating or updating uses
create_user_stack_var(offset, type, name).
{"uri": "bv:stack/0x401000/variable/-0x28", "state": {"name": "local_buf", "type": "char[40]"}}
Stack Call Adjustment — bv:stack/{function_address}/call_adjustment/{instruction_address}
| Property |
Type |
Read |
Write |
Notes |
value |
Integer |
Yes |
Yes |
Stack adjustment value at this call site |
state: null resets the adjustment to 0.
Stack Return Adjustment — bv:stack/{function_address}/return_adjustment
| Property |
Type |
Read |
Write |
Notes |
value |
Integer |
Yes |
Yes |
Return stack adjustment for the function |
state: null resets the adjustment to OffsetWithConfidence(0).
Result Structure
BatchResult
| Field |
Type |
Description |
results |
Array[ModificationResult] |
Individual result for each modification |
succeeded_ids |
Array[String] |
IDs of modifications that succeeded |
failed_ids |
Array[String] |
IDs of modifications that failed |
skipped_ids |
Array[String] |
IDs skipped due to a dependency failure |
undo_id |
String |
Binary Ninja undo action ID |
committed |
Boolean |
true if changes were committed; false if rolled back |
all_succeeded |
Boolean |
true if there were no failures |
ModificationResult
| Field |
Type |
Description |
uri |
String |
The modification's target URI |
id |
String | null |
The modification ID, if one was provided |
status |
"success" | "failed" | "skipped" |
Outcome |
error |
String | null |
Error message when status is "failed" |
reason |
String | null |
Skip reason when status is "skipped" |
Error Reference
| Error type |
When it occurs |
ExpectationError |
expect precondition check failed |
ValueError |
Duplicate modification id; circular dependency; unknown dependency id; invalid URI format; missing required properties; invalid register name in clobbered_regs; attempt to delete a non-user-defined object |
NotImplementedError |
No handler is registered for the URI's scheme prefix |
Examples
Rename a function and its variables
{
"description": "Recover session handling function",
"binary_view_changes": [{
"modifications": [
{"uri": "bv:function/0x406ec0", "state": {"name": "command_interpreter"}},
{"uri": "bv:function/0x406ec0/variable/arg1", "state": {"name": "db", "type": "int64_t*"}},
{"uri": "bv:function/0x406ec0/variable/arg2", "state": {"name": "input", "type": "FILE*"}},
{"uri": "bv:function/0x406ec0/variable/var_28", "state": {"name": "current_user"}},
{"uri": "bv:function/0x406ec0/variable/var_30_1", "state": {"name": "input_buffer"}}
]
}]
}
Define a struct and apply it to a variable
{
"description": "Define connection struct",
"binary_view_changes": [{
"modifications": [
{
"id": "def_conn",
"uri": "bv:type/Connection",
"state": {"definition": "struct Connection { int fd; char* hostname; uint16_t port; }"}
},
{
"uri": "bv:function/0x401000/variable/arg1",
"state": {"type": "struct Connection*"},
"depends_on": ["def_conn"]
}
]
}]
}
Annotate a crypto loop
{
"description": "Mark AES key schedule",
"binary_view_changes": [{
"modifications": [
{"uri": "bv:comment/0x401200", "state": {"text": "AES key schedule loop"}},
{"uri": "bv:function/0x401200/instruction/0x401210", "state": {"highlight": "yellow", "comment": "Round key XOR"}},
{"uri": "bv:function/0x401200/instruction/0x401230", "state": {"highlight": "yellow", "comment": "S-box substitution"}}
]
}]
}
Guard a rename with a precondition
{
"description": "Rename only if still auto-named",
"binary_view_changes": [{
"modifications": [
{
"uri": "bv:function/0x401000",
"expect": {"name": "sub_401000"},
"state": {"name": "init_config"}
}
]
}]
}
Add and remove component members without full replacement
{
"description": "Update network component membership",
"binary_view_changes": [{
"modifications": [
{
"uri": "bv:component/NetworkSubsystem",
"state": {
"functions": {
"$add": ["0x401500", "0x401600"],
"$remove": ["0x401100"]
}
}
}
]
}]
}