This document describes how to extend the Component Inspection File Format
A total of 256 types are possible in the Inspect Format. This section describes how to add a new type and update all library implementations.
This section describes how to break down your change into multiple Gerrit changes:
View the type table in the Inspect file format, and choose an unused type number.
Update the documentation for your new type, and then submit this change for review.
The examples in this section create a new type called “MyFoo.”
Every change from this section goes into a single Gerrit change:
fx set ... --with //zircon/system/ulib/inspect:tests
fx test -od inspect-unittest-package
This section describes how to define the bitfields for your new type.
Update /zircon/system/ulib/inspect/include/lib/inspect/cpp/vmo/block.h.
Change BlockType
to include your new type. For example: kMyFoo = #
;
If your type needs a new header (typically if it is not a VALUE):
Define the header bitfields for your type with a struct. For example: struct MyFooBlockFields final : public BlockFields
.
If your type needs a new payload (it requires using the second 8 bytes of the block):
Define the payload bitfields for your type with a struct. For example: struct MyFooBlockPayload final
.
If your type contains enums (such as format
):
Define a new enum at the top of block.h. For example: enum class MyFooBlockFormat : uint8_t
.
This section describes how to declare a C++ RAII-style wrapper for your new type.
Type wrappers contain indices of blocks that are owned by the type. You are responsible for implementing operations on those blocks, including creation and deletion, in State action updates.
Update /zircon/system/ulib/inspect/include/lib/inspect/cpp/vmo/types.h.
Determine:
Add
, Subtract
, and Set
: using MyFoo = internal::NumericProperty<T>
, where T is the argument type to those operations.Set
: using MyFoo = internal::Property<T>
, where T is the argument type to Set
.using MyFood = internal::ArrayProperty<T>
, where T
is the argument type for slots in the array.using MyFoo = internal::{Linear,Expnential}Histogram<T>
, where T
is the argument to Insert
.class MyFoo final
.class Link
for a copyable starting point.The State
class is the actual implementation for all operations on all types. This section describes how to implement the operations you will need to complete your wrapper implementation.
Update /zircon/system/ulib/inspect/include/lib/inspect/cpp/vmo/state.h:
Create
and Free methods
. For example: MyFoo CreateMyFoo(<args>); void FreeMyFoo(MyFoo* property);
where args typically includes name, parent, and some initial value.Set
, void SetMyFoo(MyFoo* property, T)
, where T
is the same type from your update to types.h
.MyFoo CreateMyFoo(Args...)
is responsible for allocating a number of blocks, setting their values, and returning them wrapped in a MyFoo. You may use a private constructor to create MyFoo from the BlockIndex objects it wraps. Various internal helpers exist to simplify this operation. See CreateIntProperty
for an example.void FreeMyFoo(MyFoo* property)
is responsible for freeing all blocks wrapped by the MyFoo. There are sometimes particular ordering requirements or updates necessary for freeing blocks. See InnerFreeValue
for an example of how values are freed.void SetMyFoo(MyFoo* property, T value)
change the value of blocks allocated to MyFoo to implement the operation. See SetIntProperty
for an example.std::lock_guard<std::mutex> lock(mutex_);
AutoGenerationIncrement gen(header_, heap_.get());
This section describes how to implement the wrapper methods declared previously.
T
. For example, if you typed using MyFoo = internal::Property<T>
, you will write:template<> void internal::Property::OPERATION(...) { ... } ```
state_->CreateMyFoo(...);
state_->FreeMyFoo(...);
State
.state_
is not null before calling.This section describes how to make your new type readable.
PropertyFormat
enum with a new number for your type. This must be sequential in this specific enum and does not need to match the format type ordinal you chose.using MyFooValue = internal::Value\<T, static_cast<size_t>(PropertyFormat::kMyFoo)>;
PropertyValue
variant with the new value. Note: The index in fit::internal::variant
must match the value of PropertyFormat
.InnerScanBlocks
to dispatch your type. If you are creating a new Property, you may only have to add your BlockType
.InnerParseMyFoo
, which takes a parent (if needed) and the pointer to the scanned block.TODO(fxbug.dev/43131)
TODO(fxbug.dev/43131)
TODO(fxbug.dev/43131)