1*890232f2SAndroid Build Coastguard Worker /*
2*890232f2SAndroid Build Coastguard Worker * Copyright 2021 Google Inc. All rights reserved.
3*890232f2SAndroid Build Coastguard Worker *
4*890232f2SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*890232f2SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*890232f2SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*890232f2SAndroid Build Coastguard Worker *
8*890232f2SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*890232f2SAndroid Build Coastguard Worker *
10*890232f2SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*890232f2SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*890232f2SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*890232f2SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*890232f2SAndroid Build Coastguard Worker * limitations under the License.
15*890232f2SAndroid Build Coastguard Worker */
16*890232f2SAndroid Build Coastguard Worker
17*890232f2SAndroid Build Coastguard Worker #ifndef FLATBUFFERS_BINARY_ANNOTATOR_H_
18*890232f2SAndroid Build Coastguard Worker #define FLATBUFFERS_BINARY_ANNOTATOR_H_
19*890232f2SAndroid Build Coastguard Worker
20*890232f2SAndroid Build Coastguard Worker #include <map>
21*890232f2SAndroid Build Coastguard Worker #include <string>
22*890232f2SAndroid Build Coastguard Worker #include <vector>
23*890232f2SAndroid Build Coastguard Worker
24*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/base.h"
25*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/reflection.h"
26*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/stl_emulation.h"
27*890232f2SAndroid Build Coastguard Worker #include "flatbuffers/util.h"
28*890232f2SAndroid Build Coastguard Worker
29*890232f2SAndroid Build Coastguard Worker namespace flatbuffers {
30*890232f2SAndroid Build Coastguard Worker
31*890232f2SAndroid Build Coastguard Worker enum class BinaryRegionType {
32*890232f2SAndroid Build Coastguard Worker Unknown = 0,
33*890232f2SAndroid Build Coastguard Worker UOffset = 1,
34*890232f2SAndroid Build Coastguard Worker SOffset = 2,
35*890232f2SAndroid Build Coastguard Worker VOffset = 3,
36*890232f2SAndroid Build Coastguard Worker Bool = 4,
37*890232f2SAndroid Build Coastguard Worker Byte = 5,
38*890232f2SAndroid Build Coastguard Worker Char = 6,
39*890232f2SAndroid Build Coastguard Worker Uint8 = 7,
40*890232f2SAndroid Build Coastguard Worker Int8 = 8,
41*890232f2SAndroid Build Coastguard Worker Uint16 = 9,
42*890232f2SAndroid Build Coastguard Worker Int16 = 10,
43*890232f2SAndroid Build Coastguard Worker Uint32 = 11,
44*890232f2SAndroid Build Coastguard Worker Int32 = 12,
45*890232f2SAndroid Build Coastguard Worker Uint64 = 13,
46*890232f2SAndroid Build Coastguard Worker Int64 = 14,
47*890232f2SAndroid Build Coastguard Worker Float = 15,
48*890232f2SAndroid Build Coastguard Worker Double = 16,
49*890232f2SAndroid Build Coastguard Worker UType = 17,
50*890232f2SAndroid Build Coastguard Worker };
51*890232f2SAndroid Build Coastguard Worker
52*890232f2SAndroid Build Coastguard Worker template<typename T>
53*890232f2SAndroid Build Coastguard Worker static inline std::string ToHex(T i, size_t width = sizeof(T)) {
54*890232f2SAndroid Build Coastguard Worker std::stringstream stream;
55*890232f2SAndroid Build Coastguard Worker stream << std::hex << std::uppercase << std::setfill('0') << std::setw(width)
56*890232f2SAndroid Build Coastguard Worker << i;
57*890232f2SAndroid Build Coastguard Worker return stream.str();
58*890232f2SAndroid Build Coastguard Worker }
59*890232f2SAndroid Build Coastguard Worker
60*890232f2SAndroid Build Coastguard Worker // Specialized version for uint8_t that don't work well with std::hex.
ToHex(uint8_t i)61*890232f2SAndroid Build Coastguard Worker static inline std::string ToHex(uint8_t i) {
62*890232f2SAndroid Build Coastguard Worker return ToHex(static_cast<int>(i), 2);
63*890232f2SAndroid Build Coastguard Worker }
64*890232f2SAndroid Build Coastguard Worker
65*890232f2SAndroid Build Coastguard Worker enum class BinaryRegionStatus {
66*890232f2SAndroid Build Coastguard Worker OK = 0,
67*890232f2SAndroid Build Coastguard Worker WARN = 100,
68*890232f2SAndroid Build Coastguard Worker WARN_NO_REFERENCES,
69*890232f2SAndroid Build Coastguard Worker WARN_CORRUPTED_PADDING,
70*890232f2SAndroid Build Coastguard Worker WARN_PADDING_LENGTH,
71*890232f2SAndroid Build Coastguard Worker ERROR = 200,
72*890232f2SAndroid Build Coastguard Worker // An offset is pointing outside the binary bounds.
73*890232f2SAndroid Build Coastguard Worker ERROR_OFFSET_OUT_OF_BINARY,
74*890232f2SAndroid Build Coastguard Worker // Expecting to read N bytes but not enough remain in the binary.
75*890232f2SAndroid Build Coastguard Worker ERROR_INCOMPLETE_BINARY,
76*890232f2SAndroid Build Coastguard Worker // When a length of a vtable/vector is longer than possible.
77*890232f2SAndroid Build Coastguard Worker ERROR_LENGTH_TOO_LONG,
78*890232f2SAndroid Build Coastguard Worker // When a length of a vtable/vector is shorter than possible.
79*890232f2SAndroid Build Coastguard Worker ERROR_LENGTH_TOO_SHORT,
80*890232f2SAndroid Build Coastguard Worker // A field mark required is not present in the vtable.
81*890232f2SAndroid Build Coastguard Worker ERROR_REQUIRED_FIELD_NOT_PRESENT,
82*890232f2SAndroid Build Coastguard Worker // A realized union type is not within the enum bounds.
83*890232f2SAndroid Build Coastguard Worker ERROR_INVALID_UNION_TYPE,
84*890232f2SAndroid Build Coastguard Worker // Occurs when there is a cycle in offsets.
85*890232f2SAndroid Build Coastguard Worker ERROR_CYCLE_DETECTED,
86*890232f2SAndroid Build Coastguard Worker };
87*890232f2SAndroid Build Coastguard Worker
88*890232f2SAndroid Build Coastguard Worker enum class BinaryRegionCommentType {
89*890232f2SAndroid Build Coastguard Worker Unknown = 0,
90*890232f2SAndroid Build Coastguard Worker SizePrefix,
91*890232f2SAndroid Build Coastguard Worker // The offset to the root table.
92*890232f2SAndroid Build Coastguard Worker RootTableOffset,
93*890232f2SAndroid Build Coastguard Worker // The optional 4-char file identifier.
94*890232f2SAndroid Build Coastguard Worker FileIdentifier,
95*890232f2SAndroid Build Coastguard Worker // Generic 0-filled padding
96*890232f2SAndroid Build Coastguard Worker Padding,
97*890232f2SAndroid Build Coastguard Worker // The size of the vtable.
98*890232f2SAndroid Build Coastguard Worker VTableSize,
99*890232f2SAndroid Build Coastguard Worker // The size of the referring table.
100*890232f2SAndroid Build Coastguard Worker VTableRefferingTableLength,
101*890232f2SAndroid Build Coastguard Worker // Offsets to vtable fields.
102*890232f2SAndroid Build Coastguard Worker VTableFieldOffset,
103*890232f2SAndroid Build Coastguard Worker // Offsets to unknown vtable fields.
104*890232f2SAndroid Build Coastguard Worker VTableUnknownFieldOffset,
105*890232f2SAndroid Build Coastguard Worker // The vtable offset of a table.
106*890232f2SAndroid Build Coastguard Worker TableVTableOffset,
107*890232f2SAndroid Build Coastguard Worker // A "inline" table field value.
108*890232f2SAndroid Build Coastguard Worker TableField,
109*890232f2SAndroid Build Coastguard Worker // A table field that is unknown.
110*890232f2SAndroid Build Coastguard Worker TableUnknownField,
111*890232f2SAndroid Build Coastguard Worker // A table field value that points to another section.
112*890232f2SAndroid Build Coastguard Worker TableOffsetField,
113*890232f2SAndroid Build Coastguard Worker // A struct field value.
114*890232f2SAndroid Build Coastguard Worker StructField,
115*890232f2SAndroid Build Coastguard Worker // A array field value.
116*890232f2SAndroid Build Coastguard Worker ArrayField,
117*890232f2SAndroid Build Coastguard Worker // The length of the string.
118*890232f2SAndroid Build Coastguard Worker StringLength,
119*890232f2SAndroid Build Coastguard Worker // The string contents.
120*890232f2SAndroid Build Coastguard Worker StringValue,
121*890232f2SAndroid Build Coastguard Worker // The explicit string terminator.
122*890232f2SAndroid Build Coastguard Worker StringTerminator,
123*890232f2SAndroid Build Coastguard Worker // The length of the vector (# of items).
124*890232f2SAndroid Build Coastguard Worker VectorLength,
125*890232f2SAndroid Build Coastguard Worker // A "inline" value of a vector.
126*890232f2SAndroid Build Coastguard Worker VectorValue,
127*890232f2SAndroid Build Coastguard Worker // A vector value that points to another section.
128*890232f2SAndroid Build Coastguard Worker VectorTableValue,
129*890232f2SAndroid Build Coastguard Worker VectorStringValue,
130*890232f2SAndroid Build Coastguard Worker VectorUnionValue,
131*890232f2SAndroid Build Coastguard Worker };
132*890232f2SAndroid Build Coastguard Worker
133*890232f2SAndroid Build Coastguard Worker struct BinaryRegionComment {
134*890232f2SAndroid Build Coastguard Worker BinaryRegionStatus status = BinaryRegionStatus::OK;
135*890232f2SAndroid Build Coastguard Worker
136*890232f2SAndroid Build Coastguard Worker // If status is non OK, this may be filled in with additional details.
137*890232f2SAndroid Build Coastguard Worker std::string status_message;
138*890232f2SAndroid Build Coastguard Worker
139*890232f2SAndroid Build Coastguard Worker BinaryRegionCommentType type = BinaryRegionCommentType::Unknown;
140*890232f2SAndroid Build Coastguard Worker
141*890232f2SAndroid Build Coastguard Worker std::string name;
142*890232f2SAndroid Build Coastguard Worker
143*890232f2SAndroid Build Coastguard Worker std::string default_value;
144*890232f2SAndroid Build Coastguard Worker
145*890232f2SAndroid Build Coastguard Worker size_t index = 0;
146*890232f2SAndroid Build Coastguard Worker };
147*890232f2SAndroid Build Coastguard Worker
148*890232f2SAndroid Build Coastguard Worker struct BinaryRegion {
149*890232f2SAndroid Build Coastguard Worker // Offset into the binary where this region begins.
150*890232f2SAndroid Build Coastguard Worker uint64_t offset = 0;
151*890232f2SAndroid Build Coastguard Worker
152*890232f2SAndroid Build Coastguard Worker // The length of this region in bytes.
153*890232f2SAndroid Build Coastguard Worker uint64_t length = 0;
154*890232f2SAndroid Build Coastguard Worker
155*890232f2SAndroid Build Coastguard Worker // The underlying datatype of this region
156*890232f2SAndroid Build Coastguard Worker BinaryRegionType type = BinaryRegionType::Unknown;
157*890232f2SAndroid Build Coastguard Worker
158*890232f2SAndroid Build Coastguard Worker // If `type` is an array/vector, this is the number of those types this region
159*890232f2SAndroid Build Coastguard Worker // encompasses.
160*890232f2SAndroid Build Coastguard Worker uint64_t array_length = 0;
161*890232f2SAndroid Build Coastguard Worker
162*890232f2SAndroid Build Coastguard Worker // If the is an offset to some other region, this is what it points to. The
163*890232f2SAndroid Build Coastguard Worker // offset is relative to overall binary, not to this region.
164*890232f2SAndroid Build Coastguard Worker uint64_t points_to_offset = 0;
165*890232f2SAndroid Build Coastguard Worker
166*890232f2SAndroid Build Coastguard Worker // The comment on the region.
167*890232f2SAndroid Build Coastguard Worker BinaryRegionComment comment;
168*890232f2SAndroid Build Coastguard Worker };
169*890232f2SAndroid Build Coastguard Worker
170*890232f2SAndroid Build Coastguard Worker enum class BinarySectionType {
171*890232f2SAndroid Build Coastguard Worker Unknown = 0,
172*890232f2SAndroid Build Coastguard Worker Header = 1,
173*890232f2SAndroid Build Coastguard Worker Table = 2,
174*890232f2SAndroid Build Coastguard Worker RootTable = 3,
175*890232f2SAndroid Build Coastguard Worker VTable = 4,
176*890232f2SAndroid Build Coastguard Worker Struct = 5,
177*890232f2SAndroid Build Coastguard Worker String = 6,
178*890232f2SAndroid Build Coastguard Worker Vector = 7,
179*890232f2SAndroid Build Coastguard Worker Union = 8,
180*890232f2SAndroid Build Coastguard Worker Padding = 9,
181*890232f2SAndroid Build Coastguard Worker };
182*890232f2SAndroid Build Coastguard Worker
183*890232f2SAndroid Build Coastguard Worker // A section of the binary that is grouped together in some logical manner, and
184*890232f2SAndroid Build Coastguard Worker // often is pointed too by some other offset BinaryRegion. Sections include
185*890232f2SAndroid Build Coastguard Worker // `tables`, `vtables`, `strings`, `vectors`, etc..
186*890232f2SAndroid Build Coastguard Worker struct BinarySection {
187*890232f2SAndroid Build Coastguard Worker // User-specified name of the section, if applicable.
188*890232f2SAndroid Build Coastguard Worker std::string name;
189*890232f2SAndroid Build Coastguard Worker
190*890232f2SAndroid Build Coastguard Worker // The type of this section.
191*890232f2SAndroid Build Coastguard Worker BinarySectionType type = BinarySectionType::Unknown;
192*890232f2SAndroid Build Coastguard Worker
193*890232f2SAndroid Build Coastguard Worker // The binary regions that make up this section, in order of their offsets.
194*890232f2SAndroid Build Coastguard Worker std::vector<BinaryRegion> regions;
195*890232f2SAndroid Build Coastguard Worker };
196*890232f2SAndroid Build Coastguard Worker
GetRegionType(reflection::BaseType base_type)197*890232f2SAndroid Build Coastguard Worker inline static BinaryRegionType GetRegionType(reflection::BaseType base_type) {
198*890232f2SAndroid Build Coastguard Worker switch (base_type) {
199*890232f2SAndroid Build Coastguard Worker case reflection::UType: return BinaryRegionType::UType;
200*890232f2SAndroid Build Coastguard Worker case reflection::Bool: return BinaryRegionType::Uint8;
201*890232f2SAndroid Build Coastguard Worker case reflection::Byte: return BinaryRegionType::Uint8;
202*890232f2SAndroid Build Coastguard Worker case reflection::UByte: return BinaryRegionType::Uint8;
203*890232f2SAndroid Build Coastguard Worker case reflection::Short: return BinaryRegionType::Int16;
204*890232f2SAndroid Build Coastguard Worker case reflection::UShort: return BinaryRegionType::Uint16;
205*890232f2SAndroid Build Coastguard Worker case reflection::Int: return BinaryRegionType::Uint32;
206*890232f2SAndroid Build Coastguard Worker case reflection::UInt: return BinaryRegionType::Uint32;
207*890232f2SAndroid Build Coastguard Worker case reflection::Long: return BinaryRegionType::Int64;
208*890232f2SAndroid Build Coastguard Worker case reflection::ULong: return BinaryRegionType::Uint64;
209*890232f2SAndroid Build Coastguard Worker case reflection::Float: return BinaryRegionType::Float;
210*890232f2SAndroid Build Coastguard Worker case reflection::Double: return BinaryRegionType::Double;
211*890232f2SAndroid Build Coastguard Worker default: return BinaryRegionType::Unknown;
212*890232f2SAndroid Build Coastguard Worker }
213*890232f2SAndroid Build Coastguard Worker }
214*890232f2SAndroid Build Coastguard Worker
ToString(const BinaryRegionType type)215*890232f2SAndroid Build Coastguard Worker inline static std::string ToString(const BinaryRegionType type) {
216*890232f2SAndroid Build Coastguard Worker switch (type) {
217*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::UOffset: return "UOffset32";
218*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::SOffset: return "SOffset32";
219*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::VOffset: return "VOffset16";
220*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Bool: return "bool";
221*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Char: return "char";
222*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Byte: return "int8_t";
223*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Uint8: return "uint8_t";
224*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Uint16: return "uint16_t";
225*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Uint32: return "uint32_t";
226*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Uint64: return "uint64_t"; ;
227*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Int8: return "int8_t";
228*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Int16: return "int16_t";
229*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Int32: return "int32_t";
230*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Int64: return "int64_t";
231*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Double: return "double";
232*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Float: return "float";
233*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::UType: return "UType8";
234*890232f2SAndroid Build Coastguard Worker case BinaryRegionType::Unknown: return "?uint8_t";
235*890232f2SAndroid Build Coastguard Worker default: return "todo";
236*890232f2SAndroid Build Coastguard Worker }
237*890232f2SAndroid Build Coastguard Worker }
238*890232f2SAndroid Build Coastguard Worker
239*890232f2SAndroid Build Coastguard Worker class BinaryAnnotator {
240*890232f2SAndroid Build Coastguard Worker public:
BinaryAnnotator(const uint8_t * const bfbs,const uint64_t bfbs_length,const uint8_t * const binary,const uint64_t binary_length)241*890232f2SAndroid Build Coastguard Worker explicit BinaryAnnotator(const uint8_t *const bfbs,
242*890232f2SAndroid Build Coastguard Worker const uint64_t bfbs_length,
243*890232f2SAndroid Build Coastguard Worker const uint8_t *const binary,
244*890232f2SAndroid Build Coastguard Worker const uint64_t binary_length)
245*890232f2SAndroid Build Coastguard Worker : bfbs_(bfbs),
246*890232f2SAndroid Build Coastguard Worker bfbs_length_(bfbs_length),
247*890232f2SAndroid Build Coastguard Worker schema_(reflection::GetSchema(bfbs)),
248*890232f2SAndroid Build Coastguard Worker binary_(binary),
249*890232f2SAndroid Build Coastguard Worker binary_length_(binary_length) {}
250*890232f2SAndroid Build Coastguard Worker
251*890232f2SAndroid Build Coastguard Worker std::map<uint64_t, BinarySection> Annotate();
252*890232f2SAndroid Build Coastguard Worker
253*890232f2SAndroid Build Coastguard Worker private:
254*890232f2SAndroid Build Coastguard Worker struct VTable {
255*890232f2SAndroid Build Coastguard Worker struct Entry {
256*890232f2SAndroid Build Coastguard Worker const reflection::Field *field = nullptr;
257*890232f2SAndroid Build Coastguard Worker uint16_t offset_from_table = 0;
258*890232f2SAndroid Build Coastguard Worker };
259*890232f2SAndroid Build Coastguard Worker
260*890232f2SAndroid Build Coastguard Worker // Field ID -> {field def, offset from table}
261*890232f2SAndroid Build Coastguard Worker std::map<uint16_t, Entry> fields;
262*890232f2SAndroid Build Coastguard Worker
263*890232f2SAndroid Build Coastguard Worker uint16_t vtable_size = 0;
264*890232f2SAndroid Build Coastguard Worker uint16_t table_size = 0;
265*890232f2SAndroid Build Coastguard Worker };
266*890232f2SAndroid Build Coastguard Worker
267*890232f2SAndroid Build Coastguard Worker uint64_t BuildHeader(uint64_t offset);
268*890232f2SAndroid Build Coastguard Worker
269*890232f2SAndroid Build Coastguard Worker void BuildVTable(uint64_t offset, const reflection::Object *table,
270*890232f2SAndroid Build Coastguard Worker uint64_t offset_of_referring_table);
271*890232f2SAndroid Build Coastguard Worker
272*890232f2SAndroid Build Coastguard Worker void BuildTable(uint64_t offset, const BinarySectionType type,
273*890232f2SAndroid Build Coastguard Worker const reflection::Object *table);
274*890232f2SAndroid Build Coastguard Worker
275*890232f2SAndroid Build Coastguard Worker uint64_t BuildStruct(uint64_t offset, std::vector<BinaryRegion> ®ions,
276*890232f2SAndroid Build Coastguard Worker const reflection::Object *structure);
277*890232f2SAndroid Build Coastguard Worker
278*890232f2SAndroid Build Coastguard Worker void BuildString(uint64_t offset, const reflection::Object *table,
279*890232f2SAndroid Build Coastguard Worker const reflection::Field *field);
280*890232f2SAndroid Build Coastguard Worker
281*890232f2SAndroid Build Coastguard Worker void BuildVector(uint64_t offset, const reflection::Object *table,
282*890232f2SAndroid Build Coastguard Worker const reflection::Field *field, uint64_t parent_table_offset,
283*890232f2SAndroid Build Coastguard Worker const VTable &vtable);
284*890232f2SAndroid Build Coastguard Worker
285*890232f2SAndroid Build Coastguard Worker std::string BuildUnion(uint64_t offset, uint8_t realized_type,
286*890232f2SAndroid Build Coastguard Worker const reflection::Field *field);
287*890232f2SAndroid Build Coastguard Worker
288*890232f2SAndroid Build Coastguard Worker void FixMissingRegions();
289*890232f2SAndroid Build Coastguard Worker void FixMissingSections();
290*890232f2SAndroid Build Coastguard Worker
IsValidOffset(const uint64_t offset)291*890232f2SAndroid Build Coastguard Worker inline bool IsValidOffset(const uint64_t offset) const {
292*890232f2SAndroid Build Coastguard Worker return offset < binary_length_;
293*890232f2SAndroid Build Coastguard Worker }
294*890232f2SAndroid Build Coastguard Worker
295*890232f2SAndroid Build Coastguard Worker // Determines if performing a GetScalar request for `T` at `offset` would read
296*890232f2SAndroid Build Coastguard Worker // passed the end of the binary.
IsValidRead(const uint64_t offset)297*890232f2SAndroid Build Coastguard Worker template<typename T> inline bool IsValidRead(const uint64_t offset) const {
298*890232f2SAndroid Build Coastguard Worker return IsValidRead(offset, sizeof(T));
299*890232f2SAndroid Build Coastguard Worker }
300*890232f2SAndroid Build Coastguard Worker
IsValidRead(const uint64_t offset,const uint64_t length)301*890232f2SAndroid Build Coastguard Worker inline bool IsValidRead(const uint64_t offset, const uint64_t length) const {
302*890232f2SAndroid Build Coastguard Worker return length < binary_length_ && IsValidOffset(offset + length - 1);
303*890232f2SAndroid Build Coastguard Worker }
304*890232f2SAndroid Build Coastguard Worker
305*890232f2SAndroid Build Coastguard Worker // Calculate the number of bytes remaining from the given offset. If offset is
306*890232f2SAndroid Build Coastguard Worker // > binary_length, 0 is returned.
RemainingBytes(const uint64_t offset)307*890232f2SAndroid Build Coastguard Worker uint64_t RemainingBytes(const uint64_t offset) const {
308*890232f2SAndroid Build Coastguard Worker return IsValidOffset(offset) ? binary_length_ - offset : 0;
309*890232f2SAndroid Build Coastguard Worker }
310*890232f2SAndroid Build Coastguard Worker
311*890232f2SAndroid Build Coastguard Worker template<typename T>
ReadScalar(const uint64_t offset)312*890232f2SAndroid Build Coastguard Worker flatbuffers::Optional<T> ReadScalar(const uint64_t offset) const {
313*890232f2SAndroid Build Coastguard Worker if (!IsValidRead<T>(offset)) { return flatbuffers::nullopt; }
314*890232f2SAndroid Build Coastguard Worker
315*890232f2SAndroid Build Coastguard Worker return flatbuffers::ReadScalar<T>(binary_ + offset);
316*890232f2SAndroid Build Coastguard Worker }
317*890232f2SAndroid Build Coastguard Worker
318*890232f2SAndroid Build Coastguard Worker // Adds the provided `section` keyed by the `offset` it occurs at. If a
319*890232f2SAndroid Build Coastguard Worker // section is already added at that offset, it doesn't replace the exisiting
320*890232f2SAndroid Build Coastguard Worker // one.
AddSection(const uint64_t offset,const BinarySection & section)321*890232f2SAndroid Build Coastguard Worker void AddSection(const uint64_t offset, const BinarySection §ion) {
322*890232f2SAndroid Build Coastguard Worker sections_.insert(std::make_pair(offset, section));
323*890232f2SAndroid Build Coastguard Worker }
324*890232f2SAndroid Build Coastguard Worker
IsInlineField(const reflection::Field * const field)325*890232f2SAndroid Build Coastguard Worker bool IsInlineField(const reflection::Field *const field) {
326*890232f2SAndroid Build Coastguard Worker if (field->type()->base_type() == reflection::BaseType::Obj) {
327*890232f2SAndroid Build Coastguard Worker return schema_->objects()->Get(field->type()->index())->is_struct();
328*890232f2SAndroid Build Coastguard Worker }
329*890232f2SAndroid Build Coastguard Worker return IsScalar(field->type()->base_type());
330*890232f2SAndroid Build Coastguard Worker }
331*890232f2SAndroid Build Coastguard Worker
IsUnionType(const reflection::BaseType type)332*890232f2SAndroid Build Coastguard Worker bool IsUnionType(const reflection::BaseType type) {
333*890232f2SAndroid Build Coastguard Worker return (type == reflection::BaseType::UType ||
334*890232f2SAndroid Build Coastguard Worker type == reflection::BaseType::Union);
335*890232f2SAndroid Build Coastguard Worker }
336*890232f2SAndroid Build Coastguard Worker
IsUnionType(const reflection::Field * const field)337*890232f2SAndroid Build Coastguard Worker bool IsUnionType(const reflection::Field *const field) {
338*890232f2SAndroid Build Coastguard Worker return IsUnionType(field->type()->base_type()) &&
339*890232f2SAndroid Build Coastguard Worker field->type()->index() >= 0;
340*890232f2SAndroid Build Coastguard Worker }
341*890232f2SAndroid Build Coastguard Worker
IsValidUnionValue(const reflection::Field * const field,const uint8_t value)342*890232f2SAndroid Build Coastguard Worker bool IsValidUnionValue(const reflection::Field *const field,
343*890232f2SAndroid Build Coastguard Worker const uint8_t value) {
344*890232f2SAndroid Build Coastguard Worker return IsUnionType(field) &&
345*890232f2SAndroid Build Coastguard Worker IsValidUnionValue(field->type()->index(), value);
346*890232f2SAndroid Build Coastguard Worker }
347*890232f2SAndroid Build Coastguard Worker
IsValidUnionValue(const uint32_t enum_id,const uint8_t value)348*890232f2SAndroid Build Coastguard Worker bool IsValidUnionValue(const uint32_t enum_id, const uint8_t value) {
349*890232f2SAndroid Build Coastguard Worker if (enum_id >= schema_->enums()->size()) { return false; }
350*890232f2SAndroid Build Coastguard Worker
351*890232f2SAndroid Build Coastguard Worker const reflection::Enum *enum_def = schema_->enums()->Get(enum_id);
352*890232f2SAndroid Build Coastguard Worker
353*890232f2SAndroid Build Coastguard Worker if (enum_def == nullptr) { return false; }
354*890232f2SAndroid Build Coastguard Worker
355*890232f2SAndroid Build Coastguard Worker return value < enum_def->values()->size();
356*890232f2SAndroid Build Coastguard Worker }
357*890232f2SAndroid Build Coastguard Worker
GetElementSize(const reflection::Field * const field)358*890232f2SAndroid Build Coastguard Worker uint64_t GetElementSize(const reflection::Field *const field) {
359*890232f2SAndroid Build Coastguard Worker if (IsScalar(field->type()->element())) {
360*890232f2SAndroid Build Coastguard Worker return GetTypeSize(field->type()->element());
361*890232f2SAndroid Build Coastguard Worker }
362*890232f2SAndroid Build Coastguard Worker
363*890232f2SAndroid Build Coastguard Worker switch (field->type()->element()) {
364*890232f2SAndroid Build Coastguard Worker case reflection::BaseType::Obj: {
365*890232f2SAndroid Build Coastguard Worker auto obj = schema_->objects()->Get(field->type()->index());
366*890232f2SAndroid Build Coastguard Worker return obj->is_struct() ? obj->bytesize() : sizeof(uint32_t);
367*890232f2SAndroid Build Coastguard Worker }
368*890232f2SAndroid Build Coastguard Worker default: return sizeof(uint32_t);
369*890232f2SAndroid Build Coastguard Worker }
370*890232f2SAndroid Build Coastguard Worker }
371*890232f2SAndroid Build Coastguard Worker
372*890232f2SAndroid Build Coastguard Worker bool ContainsSection(const uint64_t offset);
373*890232f2SAndroid Build Coastguard Worker
374*890232f2SAndroid Build Coastguard Worker // The schema for the binary file
375*890232f2SAndroid Build Coastguard Worker const uint8_t *bfbs_;
376*890232f2SAndroid Build Coastguard Worker const uint64_t bfbs_length_;
377*890232f2SAndroid Build Coastguard Worker const reflection::Schema *schema_;
378*890232f2SAndroid Build Coastguard Worker
379*890232f2SAndroid Build Coastguard Worker // The binary data itself.
380*890232f2SAndroid Build Coastguard Worker const uint8_t *binary_;
381*890232f2SAndroid Build Coastguard Worker const uint64_t binary_length_;
382*890232f2SAndroid Build Coastguard Worker
383*890232f2SAndroid Build Coastguard Worker // Map of binary offset to vtables, to dedupe vtables.
384*890232f2SAndroid Build Coastguard Worker std::map<uint64_t, VTable> vtables_;
385*890232f2SAndroid Build Coastguard Worker
386*890232f2SAndroid Build Coastguard Worker // The annotated binary sections, index by their absolute offset.
387*890232f2SAndroid Build Coastguard Worker std::map<uint64_t, BinarySection> sections_;
388*890232f2SAndroid Build Coastguard Worker };
389*890232f2SAndroid Build Coastguard Worker
390*890232f2SAndroid Build Coastguard Worker } // namespace flatbuffers
391*890232f2SAndroid Build Coastguard Worker
392*890232f2SAndroid Build Coastguard Worker #endif // FLATBUFFERS_BINARY_ANNOTATOR_H_