diff --git a/src/binary_annotator.cpp b/src/binary_annotator.cpp
new file mode 100644
index 0000000..dd0b454
--- /dev/null
+++ b/src/binary_annotator.cpp
@@ -0,0 +1,1419 @@
+#include "binary_annotator.h"
+
+#include <limits>
+#include <string>
+#include <vector>
+
+#include "flatbuffers/reflection.h"
+#include "flatbuffers/verifier.h"
+
+namespace flatbuffers {
+namespace {
+
+static bool BinaryRegionSort(const BinaryRegion &a, const BinaryRegion &b) {
+  return a.offset < b.offset;
+}
+
+static void SetError(BinaryRegionComment &comment, BinaryRegionStatus status,
+                     std::string message = "") {
+  comment.status = status;
+  comment.status_message = message;
+}
+
+static BinaryRegion MakeBinaryRegion(
+    const uint64_t offset = 0, const uint64_t length = 0,
+    const BinaryRegionType type = BinaryRegionType::Unknown,
+    const uint64_t array_length = 0, const uint64_t points_to_offset = 0,
+    const BinaryRegionComment comment = {}) {
+  BinaryRegion region;
+  region.offset = offset;
+  region.length = length;
+  region.type = type;
+  region.array_length = array_length;
+  region.points_to_offset = points_to_offset;
+  region.comment = std::move(comment);
+  return region;
+}
+
+static BinarySection MakeBinarySection(
+    const std::string &name, const BinarySectionType type,
+    const std::vector<BinaryRegion> regions) {
+  BinarySection section;
+  section.name = name;
+  section.type = type;
+  section.regions = std::move(regions);
+  return section;
+}
+
+static BinarySection MakeSingleRegionBinarySection(const std::string &name,
+                                                   const BinarySectionType type,
+                                                   const BinaryRegion &region) {
+  std::vector<BinaryRegion> regions;
+  regions.push_back(region);
+  return MakeBinarySection(name, type, std::move(regions));
+}
+
+static bool IsNonZeroRegion(const uint64_t offset, const uint64_t length,
+                            const uint8_t *const binary) {
+  for (uint64_t i = offset; i < offset + length; ++i) {
+    if (binary[i] != 0) { return true; }
+  }
+  return false;
+}
+
+static bool IsPrintableRegion(const uint64_t offset, const uint64_t length,
+                              const uint8_t *const binary) {
+  for (uint64_t i = offset; i < offset + length; ++i) {
+    if (!isprint(binary[i])) { return false; }
+  }
+  return true;
+}
+
+static BinarySection GenerateMissingSection(const uint64_t offset,
+                                            const uint64_t length,
+                                            const uint8_t *const binary) {
+  std::vector<BinaryRegion> regions;
+
+  // Check if the region is all zeros or not, as that can tell us if it is
+  // padding or not.
+  if (IsNonZeroRegion(offset, length, binary)) {
+    // Some of the padding bytes are non-zero, so this might be an unknown
+    // section of the binary.
+    // TODO(dbaileychess): We could be a bit smarter with different sized
+    // alignments. For now, the 8 byte check encompasses all the smaller
+    // alignments.
+    BinaryRegionComment comment;
+    comment.type = BinaryRegionCommentType::Unknown;
+    if (length >= 8) {
+      SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+    } else {
+      SetError(comment, BinaryRegionStatus::WARN_CORRUPTED_PADDING);
+    }
+
+    regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+                                       BinaryRegionType::Unknown, length, 0,
+                                       comment));
+
+    return MakeBinarySection("no known references", BinarySectionType::Unknown,
+                             std::move(regions));
+  }
+
+  BinaryRegionComment comment;
+  comment.type = BinaryRegionCommentType::Padding;
+  if (length >= 8) {
+    SetError(comment, BinaryRegionStatus::WARN_PADDING_LENGTH);
+  }
+
+  // This region is most likely padding.
+  regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
+                                     BinaryRegionType::Uint8, length, 0,
+                                     comment));
+
+  return MakeBinarySection("", BinarySectionType::Padding, std::move(regions));
+}
+
+}  // namespace
+
+std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
+  flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
+  if (!reflection::VerifySchemaBuffer(verifier)) { return {}; }
+
+  // The binary is too short to read as a flatbuffers.
+  // TODO(dbaileychess): We could spit out the annotated buffer sections, but
+  // I'm not sure if it is worth it.
+  if (binary_length_ < 4) { return {}; }
+
+  // Make sure we start with a clean slate.
+  vtables_.clear();
+  sections_.clear();
+
+  // First parse the header region which always start at offset 0.
+  // The returned offset will point to the root_table location.
+  const uint64_t root_table_offset = BuildHeader(0);
+
+  if (IsValidOffset(root_table_offset)) {
+    // Build the root table, and all else will be referenced from it.
+    BuildTable(root_table_offset, BinarySectionType::RootTable,
+               schema_->root_table());
+  }
+
+  // Now that all the sections are built, make sure the binary sections are
+  // contiguous.
+  FixMissingRegions();
+
+  // Then scan the area between BinarySections insert padding sections that are
+  // implied.
+  FixMissingSections();
+
+  return sections_;
+}
+
+uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
+  const auto root_table_offset = ReadScalar<uint32_t>(header_offset);
+
+  if (!root_table_offset.has_value()) {
+    // This shouldn't occur, since we validate the min size of the buffer
+    // before. But for completion sake, we shouldn't read passed the binary end.
+    return std::numeric_limits<uint64_t>::max();
+  }
+
+  std::vector<BinaryRegion> regions;
+  uint64_t offset = header_offset;
+  // TODO(dbaileychess): sized prefixed value
+
+  BinaryRegionComment root_offset_comment;
+  root_offset_comment.type = BinaryRegionCommentType::RootTableOffset;
+  root_offset_comment.name = schema_->root_table()->name()->str();
+
+  if (!IsValidOffset(root_table_offset.value())) {
+    SetError(root_offset_comment,
+             BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+  }
+
+  regions.push_back(
+      MakeBinaryRegion(offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+                       root_table_offset.value(), root_offset_comment));
+  offset += sizeof(uint32_t);
+
+  if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
+      IsPrintableRegion(offset, flatbuffers::kFileIdentifierLength, binary_)) {
+    BinaryRegionComment comment;
+    comment.type = BinaryRegionCommentType::FileIdentifier;
+    // Check if the file identifier region has non-zero data, and assume its
+    // the file identifier. Otherwise, it will get filled in with padding
+    // later.
+    regions.push_back(MakeBinaryRegion(
+        offset, flatbuffers::kFileIdentifierLength * sizeof(uint8_t),
+        BinaryRegionType::Char, flatbuffers::kFileIdentifierLength, 0,
+        comment));
+  }
+
+  AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
+                                              std::move(regions)));
+
+  return root_table_offset.value();
+}
+
+void BinaryAnnotator::BuildVTable(const uint64_t vtable_offset,
+                                  const reflection::Object *const table,
+                                  const uint64_t offset_of_referring_table) {
+  // First see if we have used this vtable before, if so skip building it again.
+  auto it = vtables_.find(vtable_offset);
+  if (it != vtables_.end()) { return; }
+
+  if (ContainsSection(vtable_offset)) { return; }
+
+  BinaryRegionComment vtable_size_comment;
+  vtable_size_comment.type = BinaryRegionCommentType::VTableSize;
+
+  const auto vtable_length = ReadScalar<uint16_t>(vtable_offset);
+  if (!vtable_length.has_value()) {
+    const uint64_t remaining = RemainingBytes(vtable_offset);
+
+    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+             "2");
+
+    AddSection(vtable_offset,
+               MakeSingleRegionBinarySection(
+                   table->name()->str(), BinarySectionType::VTable,
+                   MakeBinaryRegion(vtable_offset, remaining,
+                                    BinaryRegionType::Unknown, remaining, 0,
+                                    vtable_size_comment)));
+    return;
+  }
+
+  // Vtables start with the size of the vtable
+  const uint16_t vtable_size = vtable_length.value();
+
+  if (!IsValidOffset(vtable_offset + vtable_size - 1)) {
+    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+    // The vtable_size points to off the end of the binary.
+    AddSection(vtable_offset,
+               MakeSingleRegionBinarySection(
+                   table->name()->str(), BinarySectionType::VTable,
+                   MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+                                    BinaryRegionType::Uint16, 0, 0,
+                                    vtable_size_comment)));
+
+    return;
+  } else if (vtable_size < 2 * sizeof(uint16_t)) {
+    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+             "4");
+    // The size includes itself and the table size which are both uint16_t.
+    AddSection(vtable_offset,
+               MakeSingleRegionBinarySection(
+                   table->name()->str(), BinarySectionType::VTable,
+                   MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+                                    BinaryRegionType::Uint16, 0, 0,
+                                    vtable_size_comment)));
+    return;
+  }
+
+  std::vector<BinaryRegion> regions;
+
+  regions.push_back(MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
+                                     BinaryRegionType::Uint16, 0, 0,
+                                     vtable_size_comment));
+  uint64_t offset = vtable_offset + sizeof(uint16_t);
+
+  BinaryRegionComment ref_table_len_comment;
+  ref_table_len_comment.type =
+      BinaryRegionCommentType::VTableRefferingTableLength;
+
+  // Ensure we can read the next uint16_t field, which is the size of the
+  // referring table.
+  const auto table_length = ReadScalar<uint16_t>(offset);
+
+  if (!table_length.has_value()) {
+    const uint64_t remaining = RemainingBytes(offset);
+    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+             "2");
+
+    AddSection(offset, MakeSingleRegionBinarySection(
+                           table->name()->str(), BinarySectionType::VTable,
+                           MakeBinaryRegion(
+                               offset, remaining, BinaryRegionType::Unknown,
+                               remaining, 0, ref_table_len_comment)));
+    return;
+  }
+
+  // Then they have the size of the table they reference.
+  const uint16_t table_size = table_length.value();
+
+  if (!IsValidOffset(offset_of_referring_table + table_size - 1)) {
+    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+  } else if (table_size < 4) {
+    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
+             "4");
+  }
+
+  regions.push_back(MakeBinaryRegion(offset, sizeof(uint16_t),
+                                     BinaryRegionType::Uint16, 0, 0,
+                                     ref_table_len_comment));
+  offset += sizeof(uint16_t);
+
+  const uint64_t offset_start = offset;
+
+  // A mapping between field (and its id) to the relative offset (uin16_t) from
+  // the start of the table.
+  std::map<uint16_t, VTable::Entry> fields;
+
+  // Counter for determining if the binary has more vtable entries than the
+  // schema provided. This can occur if the binary was created at a newer schema
+  // version and is being processed with an older one.
+  uint16_t fields_processed = 0;
+
+  // Loop over all the fields.
+  ForAllFields(table, /*reverse=*/false, [&](const reflection::Field *field) {
+    const uint64_t field_offset = offset_start + field->id() * sizeof(uint16_t);
+
+    if (field_offset >= vtable_offset + vtable_size) {
+      // This field_offset is too large for this vtable, so it must come from a
+      // newer schema than the binary was create with or the binary writer did
+      // not write it. For either case, it is safe to ignore.
+
+      // TODO(dbaileychess): We could show which fields are not set an their
+      // default values if we want. We just need a way to make it obvious that
+      // it isn't part of the buffer.
+      return;
+    }
+
+    BinaryRegionComment field_comment;
+    field_comment.type = BinaryRegionCommentType::VTableFieldOffset;
+    field_comment.name = std::string(field->name()->c_str()) +
+                         "` (id: " + std::to_string(field->id()) + ")";
+
+    const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+    if (!offset_from_table.has_value()) {
+      const uint64_t remaining = RemainingBytes(field_offset);
+
+      SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+      regions.push_back(MakeBinaryRegion(field_offset, remaining,
+                                         BinaryRegionType::Unknown, remaining,
+                                         0, field_comment));
+
+      return;
+    }
+
+    if (!IsValidOffset(offset_of_referring_table + offset_from_table.value() -
+                       1)) {
+      SetError(field_comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+      regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+                                         BinaryRegionType::VOffset, 0, 0,
+                                         field_comment));
+      return;
+    }
+
+    VTable::Entry entry;
+    entry.field = field;
+    entry.offset_from_table = offset_from_table.value();
+    fields.insert(std::make_pair(field->id(), entry));
+
+    std::string default_label;
+    if (offset_from_table.value() == 0) {
+      // Not present, so could be default or be optional.
+      if (field->required()) {
+        SetError(field_comment,
+                 BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT);
+        // If this is a required field, make it known this is an error.
+        regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+                                           BinaryRegionType::VOffset, 0, 0,
+                                           field_comment));
+        return;
+      } else {
+        // Its an optional field, so get the default value and interpret and
+        // provided an annotation for it.
+        if (IsScalar(field->type()->base_type())) {
+          default_label += "<defaults to ";
+          default_label += IsFloat(field->type()->base_type())
+                               ? std::to_string(field->default_real())
+                               : std::to_string(field->default_integer());
+          default_label += "> (";
+        } else {
+          default_label += "<null> (";
+        }
+        default_label +=
+            reflection::EnumNameBaseType(field->type()->base_type());
+        default_label += ")";
+      }
+    }
+    field_comment.default_value = default_label;
+
+    regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+                                       BinaryRegionType::VOffset, 0, 0,
+                                       field_comment));
+
+    fields_processed++;
+  });
+
+  // Check if we covered all the expectant fields. If not, we need to add them
+  // as unknown fields.
+  uint16_t expectant_vtable_fields =
+      (vtable_size - sizeof(uint16_t) - sizeof(uint16_t)) / sizeof(uint16_t);
+
+  // Prevent a bad binary from declaring a really large vtable_size, that we can
+  // not indpendently verify.
+  expectant_vtable_fields = std::min(
+      static_cast<uint16_t>(fields_processed * 3), expectant_vtable_fields);
+
+  for (uint16_t id = fields_processed; id < expectant_vtable_fields; ++id) {
+    const uint64_t field_offset = offset_start + id * sizeof(uint16_t);
+
+    const auto offset_from_table = ReadScalar<uint16_t>(field_offset);
+
+    BinaryRegionComment field_comment;
+    field_comment.type = BinaryRegionCommentType::VTableUnknownFieldOffset;
+    field_comment.index = id;
+
+    if (!offset_from_table.has_value()) {
+      const uint64_t remaining = RemainingBytes(field_offset);
+      SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+      regions.push_back(MakeBinaryRegion(field_offset, remaining,
+                                         BinaryRegionType::Unknown, remaining,
+                                         0, field_comment));
+      continue;
+    }
+
+    VTable::Entry entry;
+    entry.field = nullptr;  // No field to reference.
+    entry.offset_from_table = offset_from_table.value();
+    fields.insert(std::make_pair(id, entry));
+
+    regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
+                                       BinaryRegionType::VOffset, 0, 0,
+                                       field_comment));
+  }
+
+  sections_[vtable_offset] = MakeBinarySection(
+      table->name()->str(), BinarySectionType::VTable, std::move(regions));
+
+  VTable vtable;
+  vtable.fields = std::move(fields);
+  vtable.table_size = table_size;
+  vtable.vtable_size = vtable_size;
+
+  vtables_[vtable_offset] = vtable;
+}
+
+void BinaryAnnotator::BuildTable(const uint64_t table_offset,
+                                 const BinarySectionType type,
+                                 const reflection::Object *const table) {
+  if (ContainsSection(table_offset)) { return; }
+
+  BinaryRegionComment vtable_offset_comment;
+  vtable_offset_comment.type = BinaryRegionCommentType::TableVTableOffset;
+
+  const auto vtable_soffset = ReadScalar<int32_t>(table_offset);
+
+  if (!vtable_soffset.has_value()) {
+    const uint64_t remaining = RemainingBytes(table_offset);
+    SetError(vtable_offset_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+             "4");
+
+    AddSection(
+        table_offset,
+        MakeSingleRegionBinarySection(
+            table->name()->str(), type,
+            MakeBinaryRegion(table_offset, remaining, BinaryRegionType::Unknown,
+                             remaining, 0, vtable_offset_comment)));
+
+    // If there aren't enough bytes left to read the vtable offset, there is
+    // nothing we can do.
+    return;
+  }
+
+  // Tables start with the vtable
+  const uint64_t vtable_offset = table_offset - vtable_soffset.value();
+
+  if (!IsValidOffset(vtable_offset)) {
+    SetError(vtable_offset_comment,
+             BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+    AddSection(table_offset,
+               MakeSingleRegionBinarySection(
+                   table->name()->str(), type,
+                   MakeBinaryRegion(table_offset, sizeof(int32_t),
+                                    BinaryRegionType::SOffset, 0, vtable_offset,
+                                    vtable_offset_comment)));
+
+    // There isn't much to do with an invalid vtable offset, as we won't be able
+    // to intepret the rest of the table fields.
+    return;
+  }
+
+  std::vector<BinaryRegion> regions;
+  regions.push_back(MakeBinaryRegion(table_offset, sizeof(int32_t),
+                                     BinaryRegionType::SOffset, 0,
+                                     vtable_offset, vtable_offset_comment));
+
+  // Parse the vtable first so we know what the rest of the fields in the table
+  // are.
+  BuildVTable(vtable_offset, table, table_offset);
+
+  auto vtable_entry = vtables_.find(vtable_offset);
+  if (vtable_entry == vtables_.end()) {
+    // There is no valid vtable for this table, so we cannot process the rest of
+    // the table entries.
+    return;
+  }
+
+  const VTable &vtable = vtable_entry->second;
+
+  // This is the size and length of this table.
+  const uint16_t table_size = vtable.table_size;
+  uint64_t table_end_offset = table_offset + table_size;
+
+  if (!IsValidOffset(table_end_offset - 1)) {
+    // We already validated the table size in BuildVTable, but we have to make
+    // sure we don't use a bad value here.
+    table_end_offset = binary_length_;
+  }
+
+  // We need to iterate over the vtable fields by their offset in the binary,
+  // not by their IDs. So copy them over to another vector that we can sort on
+  // the offset_from_table property.
+  std::vector<VTable::Entry> fields;
+  for (const auto &vtable_field : vtable.fields) {
+    fields.push_back(vtable_field.second);
+  }
+
+  std::stable_sort(fields.begin(), fields.end(),
+                   [](const VTable::Entry &a, const VTable::Entry &b) {
+                     return a.offset_from_table < b.offset_from_table;
+                   });
+
+  // Iterate over all the fields by order of their offset.
+  for (size_t i = 0; i < fields.size(); ++i) {
+    const reflection::Field *field = fields[i].field;
+    const uint16_t offset_from_table = fields[i].offset_from_table;
+
+    if (offset_from_table == 0) {
+      // Skip non-present fields.
+      continue;
+    }
+
+    // The field offsets are relative to the start of the table.
+    const uint64_t field_offset = table_offset + offset_from_table;
+
+    if (!IsValidOffset(field_offset)) {
+      // The field offset is larger than the binary, nothing we can do.
+      continue;
+    }
+
+    // We have a vtable entry for a non-existant field, that means its a binary
+    // generated by a newer schema than we are currently processing.
+    if (field == nullptr) {
+      // Calculate the length of this unknown field.
+      const uint64_t unknown_field_length =
+          // Check if there is another unknown field after this one.
+          ((i + 1 < fields.size())
+               ? table_offset + fields[i + 1].offset_from_table
+               // Otherwise use the known end of the table.
+               : table_end_offset) -
+          field_offset;
+
+      if (unknown_field_length == 0) { continue; }
+
+      std::string hint;
+
+      if (unknown_field_length == 4) {
+        const auto relative_offset = ReadScalar<uint32_t>(field_offset);
+        if (relative_offset.has_value()) {
+          // The field is 4 in length, so it could be an offset? Provide a hint.
+          hint += "<possibly an offset? Check Loc: +0x";
+          hint += ToHex(field_offset + relative_offset.value());
+          hint += ">";
+        }
+      }
+
+      BinaryRegionComment unknown_field_comment;
+      unknown_field_comment.type = BinaryRegionCommentType::TableUnknownField;
+
+      if (!IsValidRead(field_offset, unknown_field_length)) {
+        const uint64_t remaining = RemainingBytes(field_offset);
+
+        SetError(unknown_field_comment,
+                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+                 std::to_string(unknown_field_length));
+
+        regions.push_back(MakeBinaryRegion(field_offset, remaining,
+                                           BinaryRegionType::Unknown, remaining,
+                                           0, unknown_field_comment));
+        continue;
+      }
+
+      unknown_field_comment.default_value = hint;
+
+      regions.push_back(MakeBinaryRegion(
+          field_offset, unknown_field_length, BinaryRegionType::Unknown,
+          unknown_field_length, 0, unknown_field_comment));
+      continue;
+    }
+
+    if (IsScalar(field->type()->base_type())) {
+      // These are the raw values store in the table.
+      const uint64_t type_size = GetTypeSize(field->type()->base_type());
+      const BinaryRegionType region_type =
+          GetRegionType(field->type()->base_type());
+
+      BinaryRegionComment scalar_field_comment;
+      scalar_field_comment.type = BinaryRegionCommentType::TableField;
+      scalar_field_comment.name =
+          std::string(field->name()->c_str()) + "` (" +
+          reflection::EnumNameBaseType(field->type()->base_type()) + ")";
+
+      if (!IsValidRead(field_offset, type_size)) {
+        const uint64_t remaining = RemainingBytes(field_offset);
+        SetError(scalar_field_comment,
+                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+                 std::to_string(type_size));
+
+        regions.push_back(MakeBinaryRegion(field_offset, remaining,
+                                           BinaryRegionType::Unknown, remaining,
+                                           0, scalar_field_comment));
+        continue;
+      }
+
+      if (IsUnionType(field)) {
+        // This is a type for a union. Validate the value
+        const auto enum_value = ReadScalar<uint8_t>(field_offset);
+
+        // This should always have a value, due to the IsValidRead check above.
+        if (!IsValidUnionValue(field, enum_value.value())) {
+          SetError(scalar_field_comment,
+                   BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+
+          regions.push_back(MakeBinaryRegion(field_offset, type_size,
+                                             region_type, 0, 0,
+                                             scalar_field_comment));
+          continue;
+        }
+      }
+
+      regions.push_back(MakeBinaryRegion(field_offset, type_size, region_type,
+                                         0, 0, scalar_field_comment));
+      continue;
+    }
+
+    // Read the offset
+    const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
+    uint64_t offset_of_next_item = 0;
+    BinaryRegionComment offset_field_comment;
+    offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
+    offset_field_comment.name = field->name()->c_str();
+    const std::string offset_prefix =
+        "offset to field `" + std::string(field->name()->c_str()) + "`";
+
+    // Validate any field that isn't inline (i.e., non-structs).
+    if (!IsInlineField(field)) {
+      if (!offset_from_field.has_value()) {
+        const uint64_t remaining = RemainingBytes(field_offset);
+
+        SetError(offset_field_comment,
+                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+        regions.push_back(MakeBinaryRegion(field_offset, remaining,
+                                           BinaryRegionType::Unknown, remaining,
+                                           0, offset_field_comment));
+        continue;
+      }
+
+      offset_of_next_item = field_offset + offset_from_field.value();
+
+      if (!IsValidOffset(offset_of_next_item)) {
+        SetError(offset_field_comment,
+                 BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+        regions.push_back(MakeBinaryRegion(
+            field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+            offset_of_next_item, offset_field_comment));
+        continue;
+      }
+    }
+
+    switch (field->type()->base_type()) {
+      case reflection::BaseType::Obj: {
+        const reflection::Object *next_object =
+            schema_->objects()->Get(field->type()->index());
+
+        if (next_object->is_struct()) {
+          // Structs are stored inline.
+          BuildStruct(field_offset, regions, next_object);
+        } else {
+          offset_field_comment.default_value = "(table)";
+
+          regions.push_back(MakeBinaryRegion(
+              field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+              offset_of_next_item, offset_field_comment));
+
+          BuildTable(offset_of_next_item, BinarySectionType::Table,
+                     next_object);
+        }
+      } break;
+
+      case reflection::BaseType::String: {
+        offset_field_comment.default_value = "(string)";
+        regions.push_back(MakeBinaryRegion(
+            field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+            offset_of_next_item, offset_field_comment));
+        BuildString(offset_of_next_item, table, field);
+      } break;
+
+      case reflection::BaseType::Vector: {
+        offset_field_comment.default_value = "(vector)";
+        regions.push_back(MakeBinaryRegion(
+            field_offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+            offset_of_next_item, offset_field_comment));
+        BuildVector(offset_of_next_item, table, field, table_offset, vtable);
+      } break;
+
+      case reflection::BaseType::Union: {
+        const uint64_t union_offset = offset_of_next_item;
+
+        // The union type field is always one less than the union itself.
+        const uint16_t union_type_id = field->id() - 1;
+
+        auto vtable_field = vtable.fields.find(union_type_id);
+        if (vtable_field == vtable.fields.end()) {
+          // TODO(dbaileychess): need to capture this error condition.
+          break;
+        }
+        offset_field_comment.default_value = "(union)";
+
+        const uint64_t type_offset =
+            table_offset + vtable_field->second.offset_from_table;
+
+        const auto realized_type = ReadScalar<uint8_t>(type_offset);
+        if (!realized_type.has_value()) {
+          const uint64_t remaining = RemainingBytes(type_offset);
+          SetError(offset_field_comment,
+                   BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+          regions.push_back(MakeBinaryRegion(
+              type_offset, remaining, BinaryRegionType::Unknown, remaining, 0,
+              offset_field_comment));
+          continue;
+        }
+
+        if (!IsValidUnionValue(field, realized_type.value())) {
+          // We already export an error in the union type field, so just skip
+          // building the union itself and it will default to an unreference
+          // Binary section.
+          continue;
+        }
+
+        const std::string enum_type =
+            BuildUnion(union_offset, realized_type.value(), field);
+
+        offset_field_comment.default_value =
+            "(union of type `" + enum_type + "`)";
+
+        regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint32_t),
+                                           BinaryRegionType::UOffset, 0,
+                                           union_offset, offset_field_comment));
+
+      } break;
+
+      default: break;
+    }
+  }
+
+  // Handle the case where there is padding after the last known binary
+  // region. Calculate where we left off towards the expected end of the
+  // table.
+  const uint64_t i = regions.back().offset + regions.back().length + 1;
+
+  if (i < table_end_offset) {
+    const uint64_t pad_bytes = table_end_offset - i + 1;
+
+    BinaryRegionComment padding_comment;
+    padding_comment.type = BinaryRegionCommentType::Padding;
+
+    regions.push_back(MakeBinaryRegion(i - 1, pad_bytes * sizeof(uint8_t),
+                                       BinaryRegionType::Uint8, pad_bytes, 0,
+                                       padding_comment));
+  }
+
+  AddSection(table_offset,
+             MakeBinarySection(table->name()->str(), type, std::move(regions)));
+}
+
+uint64_t BinaryAnnotator::BuildStruct(const uint64_t struct_offset,
+                                      std::vector<BinaryRegion> &regions,
+                                      const reflection::Object *const object) {
+  if (!object->is_struct()) { return struct_offset; }
+  uint64_t offset = struct_offset;
+
+  // Loop over all the fields in increasing order
+  ForAllFields(object, /*reverse=*/false, [&](const reflection::Field *field) {
+    if (IsScalar(field->type()->base_type())) {
+      // Structure Field value
+      const uint64_t type_size = GetTypeSize(field->type()->base_type());
+      const BinaryRegionType region_type =
+          GetRegionType(field->type()->base_type());
+
+      BinaryRegionComment comment;
+      comment.type = BinaryRegionCommentType::StructField;
+      comment.name =
+          std::string(object->name()->c_str()) + "." + field->name()->c_str();
+      comment.default_value = "(" +
+                              std::string(reflection::EnumNameBaseType(
+                                  field->type()->base_type())) +
+                              ")";
+
+      if (!IsValidRead(offset, type_size)) {
+        const uint64_t remaining = RemainingBytes(offset);
+        SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+                 std::to_string(type_size));
+        regions.push_back(MakeBinaryRegion(offset, remaining,
+                                           BinaryRegionType::Unknown, remaining,
+                                           0, comment));
+
+        // TODO(dbaileychess): Should I bail out here? This sets offset to the
+        // end of the binary. So all other reads in the loop should fail.
+        offset += remaining;
+        return;
+      }
+
+      regions.push_back(
+          MakeBinaryRegion(offset, type_size, region_type, 0, 0, comment));
+      offset += type_size;
+    } else if (field->type()->base_type() == reflection::BaseType::Obj) {
+      // Structs are stored inline, even when nested.
+      offset = BuildStruct(offset, regions,
+                           schema_->objects()->Get(field->type()->index()));
+    } else if (field->type()->base_type() == reflection::BaseType::Array) {
+      const bool is_scalar = IsScalar(field->type()->element());
+      const uint64_t type_size = GetTypeSize(field->type()->element());
+      const BinaryRegionType region_type =
+          GetRegionType(field->type()->element());
+
+      // Arrays are just repeated structures.
+      for (uint16_t i = 0; i < field->type()->fixed_length(); ++i) {
+        if (is_scalar) {
+          BinaryRegionComment array_comment;
+          array_comment.type = BinaryRegionCommentType::ArrayField;
+          array_comment.name = std::string(object->name()->c_str()) + "." +
+                               field->name()->c_str();
+          array_comment.index = i;
+          array_comment.default_value =
+              "(" +
+              std::string(
+                  reflection::EnumNameBaseType(field->type()->element())) +
+              ")";
+
+          if (!IsValidRead(offset, type_size)) {
+            const uint64_t remaining = RemainingBytes(offset);
+
+            SetError(array_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+                     std::to_string(type_size));
+
+            regions.push_back(MakeBinaryRegion(offset, remaining,
+                                               BinaryRegionType::Unknown,
+                                               remaining, 0, array_comment));
+
+            // TODO(dbaileychess): Should I bail out here? This sets offset to
+            // the end of the binary. So all other reads in the loop should
+            // fail.
+            offset += remaining;
+            break;
+          }
+
+          regions.push_back(MakeBinaryRegion(offset, type_size, region_type, 0,
+                                             0, array_comment));
+
+          offset += type_size;
+        } else {
+          // Array of Structs.
+          //
+          // TODO(dbaileychess): This works, but the comments on the fields lose
+          // some context. Need to figure a way how to plumb the nested arrays
+          // comments together that isn't too confusing.
+          offset = BuildStruct(offset, regions,
+                               schema_->objects()->Get(field->type()->index()));
+        }
+      }
+    }
+
+    // Insert any padding after this field.
+    const uint16_t padding = field->padding();
+    if (padding > 0 && IsValidOffset(offset + padding)) {
+      BinaryRegionComment padding_comment;
+      padding_comment.type = BinaryRegionCommentType::Padding;
+
+      regions.push_back(MakeBinaryRegion(offset, padding,
+                                         BinaryRegionType::Uint8, padding, 0,
+                                         padding_comment));
+      offset += padding;
+    }
+  });
+
+  return offset;
+}
+
+void BinaryAnnotator::BuildString(const uint64_t string_offset,
+                                  const reflection::Object *const table,
+                                  const reflection::Field *const field) {
+  // Check if we have already generated this string section, and this is a
+  // shared string instance.
+  if (ContainsSection(string_offset)) { return; }
+
+  std::vector<BinaryRegion> regions;
+  const auto string_length = ReadScalar<uint32_t>(string_offset);
+
+  BinaryRegionComment string_length_comment;
+  string_length_comment.type = BinaryRegionCommentType::StringLength;
+
+  if (!string_length.has_value()) {
+    const uint64_t remaining = RemainingBytes(string_offset);
+
+    SetError(string_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+             "4");
+
+    regions.push_back(MakeBinaryRegion(string_offset, remaining,
+                                       BinaryRegionType::Unknown, remaining, 0,
+                                       string_length_comment));
+
+  } else {
+    const uint32_t string_size = string_length.value();
+    const uint64_t string_end =
+        string_offset + sizeof(uint32_t) + string_size + sizeof(char);
+
+    if (!IsValidOffset(string_end - 1)) {
+      SetError(string_length_comment,
+               BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+
+      regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+                                         BinaryRegionType::Uint32, 0, 0,
+                                         string_length_comment));
+    } else {
+      regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
+                                         BinaryRegionType::Uint32, 0, 0,
+                                         string_length_comment));
+
+      BinaryRegionComment string_comment;
+      string_comment.type = BinaryRegionCommentType::StringValue;
+
+      regions.push_back(MakeBinaryRegion(string_offset + sizeof(uint32_t),
+                                         string_size, BinaryRegionType::Char,
+                                         string_size, 0, string_comment));
+
+      BinaryRegionComment string_terminator_comment;
+      string_terminator_comment.type =
+          BinaryRegionCommentType::StringTerminator;
+
+      regions.push_back(MakeBinaryRegion(
+          string_offset + sizeof(uint32_t) + string_size, sizeof(char),
+          BinaryRegionType::Char, 0, 0, string_terminator_comment));
+    }
+  }
+
+  AddSection(string_offset,
+             MakeBinarySection(std::string(table->name()->c_str()) + "." +
+                                   field->name()->c_str(),
+                               BinarySectionType::String, std::move(regions)));
+}
+
+void BinaryAnnotator::BuildVector(const uint64_t vector_offset,
+                                  const reflection::Object *const table,
+                                  const reflection::Field *const field,
+                                  const uint64_t parent_table_offset,
+                                  const VTable &vtable) {
+  if (ContainsSection(vector_offset)) { return; }
+
+  BinaryRegionComment vector_length_comment;
+  vector_length_comment.type = BinaryRegionCommentType::VectorLength;
+
+  const auto vector_length = ReadScalar<uint32_t>(vector_offset);
+  if (!vector_length.has_value()) {
+    const uint64_t remaining = RemainingBytes(vector_offset);
+    SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+             "4");
+
+    AddSection(
+        vector_offset,
+        MakeSingleRegionBinarySection(
+            std::string(table->name()->c_str()) + "." + field->name()->c_str(),
+            BinarySectionType::Vector,
+            MakeBinaryRegion(vector_offset, remaining,
+                             BinaryRegionType::Unknown, remaining, 0,
+                             vector_length_comment)));
+    return;
+  }
+
+  // Validate there are enough bytes left in the binary to process all the
+  // items.
+  const uint64_t last_item_offset =
+      vector_offset + sizeof(uint32_t) +
+      vector_length.value() * GetElementSize(field);
+
+  if (!IsValidOffset(last_item_offset - 1)) {
+    SetError(vector_length_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
+    AddSection(
+        vector_offset,
+        MakeSingleRegionBinarySection(
+            std::string(table->name()->c_str()) + "." + field->name()->c_str(),
+            BinarySectionType::Vector,
+            MakeBinaryRegion(vector_offset, sizeof(uint32_t),
+                             BinaryRegionType::Uint32, 0, 0,
+                             vector_length_comment)));
+
+    return;
+  }
+
+  std::vector<BinaryRegion> regions;
+
+  regions.push_back(MakeBinaryRegion(vector_offset, sizeof(uint32_t),
+                                     BinaryRegionType::Uint32, 0, 0,
+                                     vector_length_comment));
+
+  uint64_t offset = vector_offset + sizeof(uint32_t);
+
+  switch (field->type()->element()) {
+    case reflection::BaseType::Obj: {
+      const reflection::Object *object =
+          schema_->objects()->Get(field->type()->index());
+
+      if (object->is_struct()) {
+        // Vector of structs
+        for (size_t i = 0; i < vector_length.value(); ++i) {
+          // Structs are inline to the vector.
+          const uint64_t next_offset = BuildStruct(offset, regions, object);
+          if (next_offset == offset) { break; }
+          offset = next_offset;
+        }
+      } else {
+        // Vector of objects
+        for (size_t i = 0; i < vector_length.value(); ++i) {
+          BinaryRegionComment vector_object_comment;
+          vector_object_comment.type =
+              BinaryRegionCommentType::VectorTableValue;
+          vector_object_comment.index = i;
+
+          const auto table_relative_offset = ReadScalar<uint32_t>(offset);
+          if (!table_relative_offset.has_value()) {
+            const uint64_t remaining = RemainingBytes(offset);
+            SetError(vector_object_comment,
+                     BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+            regions.push_back(
+                MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+                                 remaining, 0, vector_object_comment));
+            break;
+          }
+
+          // The table offset is relative from the offset location itself.
+          const uint64_t table_offset = offset + table_relative_offset.value();
+
+          if (!IsValidOffset(table_offset)) {
+            SetError(vector_object_comment,
+                     BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+            regions.push_back(MakeBinaryRegion(
+                offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+                table_offset, vector_object_comment));
+
+            offset += sizeof(uint32_t);
+            continue;
+          }
+
+          if (table_offset == parent_table_offset) {
+            SetError(vector_object_comment,
+                     BinaryRegionStatus::ERROR_CYCLE_DETECTED);
+            // A cycle detected where a table vector field is pointing to
+            // itself. This should only happen in corrupted files.
+            regions.push_back(MakeBinaryRegion(
+                offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+                table_offset, vector_object_comment));
+
+            offset += sizeof(uint32_t);
+            continue;
+          }
+
+          regions.push_back(MakeBinaryRegion(
+              offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+              table_offset, vector_object_comment));
+
+          offset += sizeof(uint32_t);
+
+          BuildTable(table_offset, BinarySectionType::Table, object);
+        }
+      }
+    } break;
+    case reflection::BaseType::String: {
+      // Vector of strings
+      for (size_t i = 0; i < vector_length.value(); ++i) {
+        BinaryRegionComment vector_object_comment;
+        vector_object_comment.type = BinaryRegionCommentType::VectorStringValue;
+        vector_object_comment.index = i;
+
+        const auto string_relative_offset = ReadScalar<uint32_t>(offset);
+        if (!string_relative_offset.has_value()) {
+          const uint64_t remaining = RemainingBytes(offset);
+
+          SetError(vector_object_comment,
+                   BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+          regions.push_back(
+              MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+                               remaining, 0, vector_object_comment));
+          break;
+        }
+
+        // The string offset is relative from the offset location itself.
+        const uint64_t string_offset = offset + string_relative_offset.value();
+
+        if (!IsValidOffset(string_offset)) {
+          SetError(vector_object_comment,
+                   BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+          regions.push_back(MakeBinaryRegion(
+              offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+              string_offset, vector_object_comment));
+
+          offset += sizeof(uint32_t);
+          continue;
+        }
+
+        regions.push_back(MakeBinaryRegion(
+            offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
+            string_offset, vector_object_comment));
+
+        BuildString(string_offset, table, field);
+
+        offset += sizeof(uint32_t);
+      }
+    } break;
+    case reflection::BaseType::Union: {
+      // Vector of unions
+      // Unions have both their realized type (uint8_t for now) that are
+      // stored separately. These are stored in the field->index() - 1
+      // location.
+      const uint16_t union_type_vector_id = field->id() - 1;
+
+      auto vtable_entry = vtable.fields.find(union_type_vector_id);
+      if (vtable_entry == vtable.fields.end()) {
+        // TODO(dbaileychess): need to capture this error condition.
+        break;
+      }
+
+      const uint64_t union_type_vector_field_offset =
+          parent_table_offset + vtable_entry->second.offset_from_table;
+
+      const auto union_type_vector_field_relative_offset =
+          ReadScalar<uint16_t>(union_type_vector_field_offset);
+
+      if (!union_type_vector_field_relative_offset.has_value()) {
+        const uint64_t remaining = RemainingBytes(offset);
+        BinaryRegionComment vector_union_comment;
+        vector_union_comment.type = BinaryRegionCommentType::VectorUnionValue;
+        SetError(vector_union_comment,
+                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
+
+        regions.push_back(MakeBinaryRegion(offset, remaining,
+                                           BinaryRegionType::Unknown, remaining,
+                                           0, vector_union_comment));
+
+        break;
+      }
+
+      // Get the offset to the first type (the + sizeof(uint32_t) is to skip
+      // over the vector length which we already know). Validation happens
+      // within the loop below.
+      const uint64_t union_type_vector_data_offset =
+          union_type_vector_field_offset +
+          union_type_vector_field_relative_offset.value() + sizeof(uint32_t);
+
+      for (size_t i = 0; i < vector_length.value(); ++i) {
+        BinaryRegionComment comment;
+        comment.type = BinaryRegionCommentType::VectorUnionValue;
+        comment.index = i;
+
+        const auto union_relative_offset = ReadScalar<uint32_t>(offset);
+        if (!union_relative_offset.has_value()) {
+          const uint64_t remaining = RemainingBytes(offset);
+
+          SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");
+
+          regions.push_back(MakeBinaryRegion(offset, remaining,
+                                             BinaryRegionType::Unknown,
+                                             remaining, 0, comment));
+
+          break;
+        }
+
+        // The union offset is relative from the offset location itself.
+        const uint64_t union_offset = offset + union_relative_offset.value();
+
+        if (!IsValidOffset(union_offset)) {
+          SetError(comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
+
+          regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+                                             BinaryRegionType::UOffset, 0,
+                                             union_offset, comment));
+          continue;
+        }
+
+        const auto realized_type =
+            ReadScalar<uint8_t>(union_type_vector_data_offset + i);
+
+        if (!realized_type.has_value()) {
+          SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
+          regions.push_back(MakeBinaryRegion(
+              offset, 0, BinaryRegionType::Unknown, 0, 0, comment));
+          continue;
+        }
+
+        if (!IsValidUnionValue(vtable_entry->second.field->type()->index(),
+                               realized_type.value())) {
+          // We already export an error in the union type field, so just skip
+          // building the union itself and it will default to an unreference
+          // Binary section.
+          offset += sizeof(uint32_t);
+          continue;
+        }
+
+        const std::string enum_type =
+            BuildUnion(union_offset, realized_type.value(), field);
+
+        comment.default_value = "(`" + enum_type + "`)";
+        regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
+                                           BinaryRegionType::UOffset, 0,
+                                           union_offset, comment));
+
+        offset += sizeof(uint32_t);
+      }
+    } break;
+    default: {
+      if (IsScalar(field->type()->element())) {
+        const BinaryRegionType binary_region_type =
+            GetRegionType(field->type()->element());
+
+        const uint64_t type_size = GetTypeSize(field->type()->element());
+
+        // TODO(dbaileychess): It might be nicer to user the
+        // BinaryRegion.array_length field to indicate this.
+        for (size_t i = 0; i < vector_length.value(); ++i) {
+          BinaryRegionComment vector_scalar_comment;
+          vector_scalar_comment.type = BinaryRegionCommentType::VectorValue;
+          vector_scalar_comment.index = i;
+
+          if (!IsValidRead(offset, type_size)) {
+            const uint64_t remaining = RemainingBytes(offset);
+
+            SetError(vector_scalar_comment,
+                     BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
+                     std::to_string(type_size));
+
+            regions.push_back(
+                MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
+                                 remaining, 0, vector_scalar_comment));
+            break;
+          }
+
+          if (IsUnionType(field->type()->element())) {
+            // This is a type for a union. Validate the value
+            const auto enum_value = ReadScalar<uint8_t>(offset);
+
+            // This should always have a value, due to the IsValidRead check
+            // above.
+            if (!IsValidUnionValue(field->type()->index(),
+                                   enum_value.value())) {
+              SetError(vector_scalar_comment,
+                       BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
+              regions.push_back(MakeBinaryRegion(offset, type_size,
+                                                 binary_region_type, 0, 0,
+                                                 vector_scalar_comment));
+              offset += type_size;
+              continue;
+            }
+          }
+
+          regions.push_back(MakeBinaryRegion(offset, type_size,
+                                             binary_region_type, 0, 0,
+                                             vector_scalar_comment));
+          offset += type_size;
+        }
+      }
+    } break;
+  }
+  AddSection(vector_offset,
+             MakeBinarySection(std::string(table->name()->c_str()) + "." +
+                                   field->name()->c_str(),
+                               BinarySectionType::Vector, std::move(regions)));
+}
+
+std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,
+                                        const uint8_t realized_type,
+                                        const reflection::Field *const field) {
+  const reflection::Enum *next_enum =
+      schema_->enums()->Get(field->type()->index());
+
+  const reflection::EnumVal *enum_val = next_enum->values()->Get(realized_type);
+
+  if (ContainsSection(union_offset)) { return enum_val->name()->c_str(); }
+
+  const reflection::Type *union_type = enum_val->union_type();
+
+  if (union_type->base_type() == reflection::BaseType::Obj) {
+    const reflection::Object *object =
+        schema_->objects()->Get(union_type->index());
+
+    if (object->is_struct()) {
+      // Union of vectors point to a new Binary section
+      std::vector<BinaryRegion> regions;
+
+      BuildStruct(union_offset, regions, object);
+
+      AddSection(
+          union_offset,
+          MakeBinarySection(std::string(object->name()->c_str()) + "." +
+                                field->name()->c_str(),
+                            BinarySectionType::Union, std::move(regions)));
+    } else {
+      BuildTable(union_offset, BinarySectionType::Table, object);
+    }
+  }
+  // TODO(dbaileychess): handle the other union types.
+
+  return enum_val->name()->c_str();
+}
+
+void BinaryAnnotator::FixMissingRegions() {
+  std::vector<BinaryRegion> regions_to_insert;
+  for (auto &current_section : sections_) {
+    BinarySection &section = current_section.second;
+    if (section.regions.empty()) {
+      // TODO(dbaileychess): is this possible?
+      continue;
+    }
+
+    uint64_t offset = section.regions[0].offset + section.regions[0].length;
+    for (size_t i = 1; i < section.regions.size(); ++i) {
+      BinaryRegion &region = section.regions[i];
+
+      const uint64_t next_offset = region.offset;
+      if (!IsValidOffset(next_offset)) {
+        // TODO(dbaileychess): figure out how we get into this situation.
+        continue;
+      }
+
+      if (offset < next_offset) {
+        const uint64_t padding_bytes = next_offset - offset;
+
+        BinaryRegionComment comment;
+        comment.type = BinaryRegionCommentType::Padding;
+
+        if (IsNonZeroRegion(offset, padding_bytes, binary_)) {
+          SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
+          regions_to_insert.push_back(
+              MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Unknown,
+                               padding_bytes, 0, comment));
+        } else {
+          regions_to_insert.push_back(
+              MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Uint8,
+                               padding_bytes, 0, comment));
+        }
+      }
+      offset = next_offset + region.length;
+    }
+
+    if (!regions_to_insert.empty()) {
+      section.regions.insert(section.regions.end(), regions_to_insert.begin(),
+                             regions_to_insert.end());
+      std::stable_sort(section.regions.begin(), section.regions.end(),
+                       BinaryRegionSort);
+      regions_to_insert.clear();
+    }
+  }
+}
+
+void BinaryAnnotator::FixMissingSections() {
+  uint64_t offset = 0;
+
+  std::vector<BinarySection> sections_to_insert;
+
+  for (auto &current_section : sections_) {
+    BinarySection &section = current_section.second;
+    const uint64_t section_start_offset = current_section.first;
+    const uint64_t section_end_offset =
+        section.regions.back().offset + section.regions.back().length;
+
+    if (offset < section_start_offset) {
+      // We are at an offset that is less then the current section.
+      const uint64_t pad_bytes = section_start_offset - offset + 1;
+
+      sections_to_insert.push_back(
+          GenerateMissingSection(offset - 1, pad_bytes, binary_));
+    }
+    offset = section_end_offset + 1;
+  }
+
+  // Handle the case where there are still bytes left in the binary that are
+  // unaccounted for.
+  if (offset < binary_length_) {
+    const uint64_t pad_bytes = binary_length_ - offset + 1;
+    sections_to_insert.push_back(
+        GenerateMissingSection(offset - 1, pad_bytes, binary_));
+  }
+
+  for (const BinarySection &section_to_insert : sections_to_insert) {
+    AddSection(section_to_insert.regions[0].offset, section_to_insert);
+  }
+}
+
+bool BinaryAnnotator::ContainsSection(const uint64_t offset) {
+  auto it = sections_.lower_bound(offset);
+  // If the section is found, check that it is exactly equal its offset.
+  if (it != sections_.end() && it->first == offset) { return true; }
+
+  // If this was the first section, there are no other previous sections to
+  // check.
+  if (it == sections_.begin()) { return false; }
+
+  // Go back one section.
+  --it;
+
+  // And check that if the offset is covered by the section.
+  return offset >= it->first && offset < it->second.regions.back().offset +
+                                             it->second.regions.back().length;
+}
+
+}  // namespace flatbuffers
\ No newline at end of file
