Example #1
0
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
  Length = debug_info.getU32(offset_ptr);
  Version = debug_info.getU16(offset_ptr);
  uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
  if (IndexEntry) {
    if (AbbrOffset)
      return false;
    auto *UnitContrib = IndexEntry->getOffset();
    if (!UnitContrib || UnitContrib->Length != (Length + 4))
      return false;
    auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
    if (!AbbrEntry)
      return false;
    AbbrOffset = AbbrEntry->Offset;
  }
  AddrSize = debug_info.getU8(offset_ptr);

  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
  bool VersionOK = DWARFContext::isSupportedVersion(Version);
  bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;

  if (!LengthOK || !VersionOK || !AddrSizeOK)
    return false;

  Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
  return Abbrevs != nullptr;
}
bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) {
  clear();

  Offset = *offset_ptr;

  if (debug_info.isValidOffset(*offset_ptr)) {
    uint64_t abbrOffset;
    Length = debug_info.getU32(offset_ptr);
    Version = debug_info.getU16(offset_ptr);
    abbrOffset = debug_info.getU32(offset_ptr);
    AddrSize = debug_info.getU8(offset_ptr);

    bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1);
    bool versionOK = DWARFContext::isSupportedVersion(Version);
    bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
    bool addrSizeOK = AddrSize == 4 || AddrSize == 8;

    if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && Abbrev != NULL) {
      Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
      return true;
    }

    // reset the offset to where we tried to parse from if anything went wrong
    *offset_ptr = Offset;
  }

  return false;
}
Example #3
0
bool DWARFUnitIndex::parseImpl(DataExtractor IndexData) {
  uint32_t Offset = 0;
  if (!Header.parse(IndexData, &Offset))
    return false;

  if (!IndexData.isValidOffsetForDataOfSize(
          Offset, Header.NumBuckets * (8 + 4) +
                      (2 * Header.NumUnits + 1) * 4 * Header.NumColumns))
    return false;

  Rows = llvm::make_unique<Entry[]>(Header.NumBuckets);
  auto Contribs =
      llvm::make_unique<Entry::SectionContribution *[]>(Header.NumUnits);
  ColumnKinds = llvm::make_unique<DWARFSectionKind[]>(Header.NumColumns);

  // Read Hash Table of Signatures
  for (unsigned i = 0; i != Header.NumBuckets; ++i)
    Rows[i].Signature = IndexData.getU64(&Offset);

  // Read Parallel Table of Indexes
  for (unsigned i = 0; i != Header.NumBuckets; ++i) {
    auto Index = IndexData.getU32(&Offset);
    if (!Index)
      continue;
    Rows[i].Index = this;
    Rows[i].Contributions =
        llvm::make_unique<Entry::SectionContribution[]>(Header.NumColumns);
    Contribs[Index - 1] = Rows[i].Contributions.get();
  }

  // Read the Column Headers
  for (unsigned i = 0; i != Header.NumColumns; ++i) {
    ColumnKinds[i] = static_cast<DWARFSectionKind>(IndexData.getU32(&Offset));
    if (ColumnKinds[i] == InfoColumnKind) {
      if (InfoColumn != -1)
        return false;
      InfoColumn = i;
    }
  }

  if (InfoColumn == -1)
    return false;

  // Read Table of Section Offsets
  for (unsigned i = 0; i != Header.NumUnits; ++i) {
    auto *Contrib = Contribs[i];
    for (unsigned i = 0; i != Header.NumColumns; ++i)
      Contrib[i].Offset = IndexData.getU32(&Offset);
  }

  // Read Table of Section Sizes
  for (unsigned i = 0; i != Header.NumUnits; ++i) {
    auto *Contrib = Contribs[i];
    for (unsigned i = 0; i != Header.NumColumns; ++i)
      Contrib[i].Length = IndexData.getU32(&Offset);
  }

  return true;
}
Example #4
0
bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data,
                                     uint32_t *offset_ptr) {
  const uint32_t prologue_offset = *offset_ptr;

  clear();
  TotalLength = debug_line_data.getU32(offset_ptr);
  Version = debug_line_data.getU16(offset_ptr);
  if (Version < 2)
    return false;

  PrologueLength = debug_line_data.getU32(offset_ptr);
  const uint32_t end_prologue_offset = PrologueLength + *offset_ptr;
  MinInstLength = debug_line_data.getU8(offset_ptr);
  if (Version >= 4)
    MaxOpsPerInst = debug_line_data.getU8(offset_ptr);
  DefaultIsStmt = debug_line_data.getU8(offset_ptr);
  LineBase = debug_line_data.getU8(offset_ptr);
  LineRange = debug_line_data.getU8(offset_ptr);
  OpcodeBase = debug_line_data.getU8(offset_ptr);

  StandardOpcodeLengths.reserve(OpcodeBase - 1);
  for (uint32_t i = 1; i < OpcodeBase; ++i) {
    uint8_t op_len = debug_line_data.getU8(offset_ptr);
    StandardOpcodeLengths.push_back(op_len);
  }

  while (*offset_ptr < end_prologue_offset) {
    const char *s = debug_line_data.getCStr(offset_ptr);
    if (s && s[0])
      IncludeDirectories.push_back(s);
    else
      break;
  }

  while (*offset_ptr < end_prologue_offset) {
    const char *name = debug_line_data.getCStr(offset_ptr);
    if (name && name[0]) {
      FileNameEntry fileEntry;
      fileEntry.Name = name;
      fileEntry.DirIdx = debug_line_data.getULEB128(offset_ptr);
      fileEntry.ModTime = debug_line_data.getULEB128(offset_ptr);
      fileEntry.Length = debug_line_data.getULEB128(offset_ptr);
      FileNames.push_back(fileEntry);
    } else {
      break;
    }
  }

  if (*offset_ptr != end_prologue_offset) {
    fprintf(stderr, "warning: parsing line table prologue at 0x%8.8x should"
                    " have ended at 0x%8.8x but it ended at 0x%8.8x\n",
            prologue_offset, end_prologue_offset, *offset_ptr);
    return false;
  }
  return true;
}
Example #5
0
bool DWARFUnitIndex::Header::parse(DataExtractor IndexData,
                                   uint32_t *OffsetPtr) {
  if (!IndexData.isValidOffsetForDataOfSize(*OffsetPtr, 16))
    return false;
  Version = IndexData.getU32(OffsetPtr);
  NumColumns = IndexData.getU32(OffsetPtr);
  NumUnits = IndexData.getU32(OffsetPtr);
  NumBuckets = IndexData.getU32(OffsetPtr);
  return Version <= 2;
}
Example #6
0
Optional<DWARFDebugLocDWO::LocationList>
DWARFDebugLocDWO::parseOneLocationList(DataExtractor Data, unsigned *Offset) {
  LocationList LL;
  LL.Offset = *Offset;

  // dwarf::DW_LLE_end_of_list_entry is 0 and indicates the end of the list.
  while (auto Kind =
             static_cast<dwarf::LocationListEntry>(Data.getU8(Offset))) {
    if (Kind != dwarf::DW_LLE_startx_length) {
      llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
                   << " not implemented\n";
      return None;
    }

    Entry E;
    E.Start = Data.getULEB128(Offset);
    E.Length = Data.getU32(Offset);

    unsigned Bytes = Data.getU16(Offset);
    // A single location description describing the location of the object...
    StringRef str = Data.getData().substr(*Offset, Bytes);
    *Offset += Bytes;
    E.Loc.resize(str.size());
    std::copy(str.begin(), str.end(), E.Loc.begin());

    LL.Entries.push_back(std::move(E));
  }
  return LL;
}
Example #7
0
void DWARFDebugLocDWO::parse(DataExtractor data) {
  uint32_t Offset = 0;
  while (data.isValidOffset(Offset)) {
    Locations.resize(Locations.size() + 1);
    LocationList &Loc = Locations.back();
    Loc.Offset = Offset;
    dwarf::LocationListEntry Kind;
    while ((Kind = static_cast<dwarf::LocationListEntry>(
                data.getU8(&Offset))) != dwarf::DW_LLE_end_of_list) {

      if (Kind != dwarf::DW_LLE_startx_length) {
        llvm::errs() << "error: dumping support for LLE of kind " << (int)Kind
                     << " not implemented\n";
        return;
      }

      Entry E;

      E.Start = data.getULEB128(&Offset);
      E.Length = data.getU32(&Offset);

      unsigned Bytes = data.getU16(&Offset);
      // A single location description describing the location of the object...
      StringRef str = data.getData().substr(Offset, Bytes);
      Offset += Bytes;
      E.Loc.resize(str.size());
      std::copy(str.begin(), str.end(), E.Loc.begin());

      Loc.Entries.push_back(std::move(E));
    }
  }
}
Example #8
0
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
  Length = debug_info.getU32(offset_ptr);
  Version = debug_info.getU16(offset_ptr);
  uint64_t abbrOffset = debug_info.getU32(offset_ptr);
  AddrSize = debug_info.getU8(offset_ptr);

  bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
  bool versionOK = DWARFContext::isSupportedVersion(Version);
  bool abbrOffsetOK = AbbrevSection.size() > abbrOffset;
  bool addrSizeOK = AddrSize == 4 || AddrSize == 8;

  if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK)
    return false;

  Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset);
  return true;
}
Example #9
0
bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
                                uint32_t *offset_ptr) {
  if (!DWARFUnit::extractImpl(debug_info, offset_ptr))
    return false;
  TypeHash = debug_info.getU64(offset_ptr);
  TypeOffset = debug_info.getU32(offset_ptr);
  return TypeOffset < getLength();
}
Example #10
0
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
  Length = debug_info.getU32(offset_ptr);
  Version = debug_info.getU16(offset_ptr);
  uint64_t AbbrOffset = debug_info.getU32(offset_ptr);
  AddrSize = debug_info.getU8(offset_ptr);

  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
  bool VersionOK = DWARFContext::isSupportedVersion(Version);
  bool AddrSizeOK = AddrSize == 4 || AddrSize == 8;

  if (!LengthOK || !VersionOK || !AddrSizeOK)
    return false;

  Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset);
  if (Abbrevs == nullptr)
    return false;

  return true;
}
Example #11
0
bool DWARFTypeUnit::extractImpl(DataExtractor debug_info,
                                uint32_t *offset_ptr) {
  if (!DWARFUnit::extractImpl(debug_info, offset_ptr))
    return false;
  TypeHash = debug_info.getU64(offset_ptr);
  TypeOffset = debug_info.getU32(offset_ptr);
  // TypeOffset is relative to the beginning of the header,
  // so we have to account for the leading length field.
  // FIXME: The size of the length field is 12 in DWARF64.
  unsigned SizeOfLength = 4;
  return TypeOffset < getLength() + SizeOfLength;
}
Example #12
0
static uint64_t readPointer(const DataExtractor &Data, uint32_t &Offset,
                            unsigned Encoding) {
  switch (getSizeForEncoding(Data, Encoding)) {
    case 2:
      return Data.getU16(&Offset);
    case 4:
      return Data.getU32(&Offset);
    case 8:
      return Data.getU64(&Offset);
    default:
      llvm_unreachable("Illegal data size");
  }
}
uint32_t
DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data,
                          const DWARFAbbreviationDeclarationSet *abbrevs) {
  clear();

  Offset = offset;

  if (debug_info_data.isValidOffset(offset)) {
    Length = debug_info_data.getU32(&offset);
    Version = debug_info_data.getU16(&offset);
    bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset();
    Abbrevs = abbrevs;
    AddrSize = debug_info_data.getU8(&offset);

    bool versionOK = DWARFContext::isSupportedVersion(Version);
    bool addrSizeOK = AddrSize == 4 || AddrSize == 8;

    if (versionOK && addrSizeOK && abbrevsOK &&
        debug_info_data.isValidOffset(offset))
      return offset;
  }
  return 0;
}
Example #14
0
bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) {
  Length = debug_info.getU32(offset_ptr);
  // FIXME: Support DWARF64.
  FormParams.Format = DWARF32;
  FormParams.Version = debug_info.getU16(offset_ptr);
  if (FormParams.Version >= 5) {
    UnitType = debug_info.getU8(offset_ptr);
    FormParams.AddrSize = debug_info.getU8(offset_ptr);
    AbbrOffset = debug_info.getU32(offset_ptr);
  } else {
    AbbrOffset = debug_info.getU32(offset_ptr);
    FormParams.AddrSize = debug_info.getU8(offset_ptr);
  }
  if (IndexEntry) {
    if (AbbrOffset)
      return false;
    auto *UnitContrib = IndexEntry->getOffset();
    if (!UnitContrib || UnitContrib->Length != (Length + 4))
      return false;
    auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV);
    if (!AbbrEntry)
      return false;
    AbbrOffset = AbbrEntry->Offset;
  }

  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
  bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
  bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;

  if (!LengthOK || !VersionOK || !AddrSizeOK)
    return false;

  // Keep track of the highest DWARF version we encounter across all units.
  Context.setMaxVersionIfGreater(getVersion());
  return true;
}
Example #15
0
/// State transition when a CustomEventMarker is encountered.
Error processCustomEventMarker(FDRState &State, uint8_t RecordFirstByte,
                               DataExtractor &RecordExtractor,
                               size_t &RecordSize) {
  // We can encounter a CustomEventMarker anywhere in the log, so we can handle
  // it regardless of the expectation. However, we do se the expectation to read
  // a set number of fixed bytes, as described in the metadata.
  uint32_t OffsetPtr = 1; // Read after the first byte.
  uint32_t DataSize = RecordExtractor.getU32(&OffsetPtr);
  uint64_t TSC = RecordExtractor.getU64(&OffsetPtr);

  // FIXME: Actually represent the record through the API. For now we only skip
  // through the data.
  (void)TSC;
  RecordSize = 16 + DataSize;
  return Error::success();
}
Example #16
0
void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
                                   uint32_t EndOffset) {
  while (*Offset < EndOffset) {
    uint8_t Opcode = Data.getU8(Offset);
    // Some instructions have a primary opcode encoded in the top bits.
    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;

    if (Primary) {
      // If it's a primary opcode, the first operand is encoded in the bottom
      // bits of the opcode itself.
      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
      switch (Primary) {
        default: llvm_unreachable("Impossible primary CFI opcode");
        case DW_CFA_advance_loc:
        case DW_CFA_restore:
          addInstruction(Primary, Op1);
          break;
        case DW_CFA_offset:
          addInstruction(Primary, Op1, Data.getULEB128(Offset));
          break;
      }
    } else {
      // Extended opcode - its value is Opcode itself.
      switch (Opcode) {
        default: llvm_unreachable("Invalid extended CFI opcode");
        case DW_CFA_nop:
        case DW_CFA_remember_state:
        case DW_CFA_restore_state:
        case DW_CFA_GNU_window_save:
          // No operands
          addInstruction(Opcode);
          break;
        case DW_CFA_set_loc:
          // Operands: Address
          addInstruction(Opcode, Data.getAddress(Offset));
          break;
        case DW_CFA_advance_loc1:
          // Operands: 1-byte delta
          addInstruction(Opcode, Data.getU8(Offset));
          break;
        case DW_CFA_advance_loc2:
          // Operands: 2-byte delta
          addInstruction(Opcode, Data.getU16(Offset));
          break;
        case DW_CFA_advance_loc4:
          // Operands: 4-byte delta
          addInstruction(Opcode, Data.getU32(Offset));
          break;
        case DW_CFA_restore_extended:
        case DW_CFA_undefined:
        case DW_CFA_same_value:
        case DW_CFA_def_cfa_register:
        case DW_CFA_def_cfa_offset:
          // Operands: ULEB128
          addInstruction(Opcode, Data.getULEB128(Offset));
          break;
        case DW_CFA_def_cfa_offset_sf:
          // Operands: SLEB128
          addInstruction(Opcode, Data.getSLEB128(Offset));
          break;
        case DW_CFA_offset_extended:
        case DW_CFA_register:
        case DW_CFA_def_cfa:
        case DW_CFA_val_offset:
          // Operands: ULEB128, ULEB128
          addInstruction(Opcode, Data.getULEB128(Offset),
                                 Data.getULEB128(Offset));
          break;
        case DW_CFA_offset_extended_sf:
        case DW_CFA_def_cfa_sf:
        case DW_CFA_val_offset_sf:
          // Operands: ULEB128, SLEB128
          addInstruction(Opcode, Data.getULEB128(Offset),
                                 Data.getSLEB128(Offset));
          break;
        case DW_CFA_def_cfa_expression:
        case DW_CFA_expression:
        case DW_CFA_val_expression:
          // TODO: implement this
          report_fatal_error("Values with expressions not implemented yet!");
      }
    }
  }
}
Example #17
0
void DWARFDebugFrame::parse(DataExtractor Data) {
  uint32_t Offset = 0;
  DenseMap<uint32_t, CIE *> CIEs;

  while (Data.isValidOffset(Offset)) {
    uint32_t StartOffset = Offset;

    bool IsDWARF64 = false;
    uint64_t Length = Data.getU32(&Offset);
    uint64_t Id;

    if (Length == UINT32_MAX) {
      // DWARF-64 is distinguished by the first 32 bits of the initial length
      // field being 0xffffffff. Then, the next 64 bits are the actual entry
      // length.
      IsDWARF64 = true;
      Length = Data.getU64(&Offset);
    }

    // At this point, Offset points to the next field after Length.
    // Length is the structure size excluding itself. Compute an offset one
    // past the end of the structure (needed to know how many instructions to
    // read).
    // TODO: For honest DWARF64 support, DataExtractor will have to treat
    //       offset_ptr as uint64_t*
    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);

    // The Id field's size depends on the DWARF format
    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);

    if (IsCIE) {
      uint8_t Version = Data.getU8(&Offset);
      const char *Augmentation = Data.getCStr(&Offset);
      uint8_t AddressSize = Version < 4 ? Data.getAddressSize() : Data.getU8(&Offset);
      Data.setAddressSize(AddressSize);
      uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);

      auto Cie = make_unique<CIE>(StartOffset, Length, Version,
                                  StringRef(Augmentation), AddressSize,
                                  SegmentDescriptorSize, CodeAlignmentFactor,
                                  DataAlignmentFactor, ReturnAddressRegister);
      CIEs[StartOffset] = Cie.get();
      Entries.emplace_back(std::move(Cie));
    } else {
      // FDE
      uint64_t CIEPointer = Id;
      uint64_t InitialLocation = Data.getAddress(&Offset);
      uint64_t AddressRange = Data.getAddress(&Offset);

      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
                                   InitialLocation, AddressRange,
                                   CIEs[CIEPointer]));
    }

    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);

    if (Offset != EndStructureOffset) {
      std::string Str;
      raw_string_ostream OS(Str);
      OS << format("Parsing entry instructions at %lx failed", StartOffset);
      report_fatal_error(Str);
    }
  }
}
Example #18
0
bool
DWARFFormValue::skipValue(uint16_t form, DataExtractor debug_info_data,
                          uint32_t *offset_ptr, const DWARFUnit *cu) {
  bool indirect = false;
  do {
    switch (form) {
    // Blocks if inlined data that have a length field and the data bytes
    // inlined in the .debug_info
    case DW_FORM_exprloc:
    case DW_FORM_block: {
      uint64_t size = debug_info_data.getULEB128(offset_ptr);
      *offset_ptr += size;
      return true;
    }
    case DW_FORM_block1: {
      uint8_t size = debug_info_data.getU8(offset_ptr);
      *offset_ptr += size;
      return true;
    }
    case DW_FORM_block2: {
      uint16_t size = debug_info_data.getU16(offset_ptr);
      *offset_ptr += size;
      return true;
    }
    case DW_FORM_block4: {
      uint32_t size = debug_info_data.getU32(offset_ptr);
      *offset_ptr += size;
      return true;
    }

    // Inlined NULL terminated C-strings
    case DW_FORM_string:
      debug_info_data.getCStr(offset_ptr);
      return true;

    // Compile unit address sized values
    case DW_FORM_addr:
      *offset_ptr += cu->getAddressByteSize();
      return true;
    case DW_FORM_ref_addr:
      *offset_ptr += getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
      return true;

    // 0 byte values - implied from the form.
    case DW_FORM_flag_present:
      return true;

    // 1 byte values
    case DW_FORM_data1:
    case DW_FORM_flag:
    case DW_FORM_ref1:
      *offset_ptr += 1;
      return true;

    // 2 byte values
    case DW_FORM_data2:
    case DW_FORM_ref2:
      *offset_ptr += 2;
      return true;

    // 4 byte values
    case DW_FORM_strp:
    case DW_FORM_data4:
    case DW_FORM_ref4:
      *offset_ptr += 4;
      return true;

    // 8 byte values
    case DW_FORM_data8:
    case DW_FORM_ref8:
    case DW_FORM_ref_sig8:
      *offset_ptr += 8;
      return true;

    // signed or unsigned LEB 128 values
    //  case DW_FORM_APPLE_db_str:
    case DW_FORM_sdata:
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
    case DW_FORM_GNU_str_index:
    case DW_FORM_GNU_addr_index:
      debug_info_data.getULEB128(offset_ptr);
      return true;

    case DW_FORM_indirect:
      indirect = true;
      form = debug_info_data.getULEB128(offset_ptr);
      break;

    // FIXME: 4 for DWARF32, 8 for DWARF64.
    case DW_FORM_sec_offset:
      *offset_ptr += 4;
      return true;

    default:
      return false;
    }
  } while (indirect);
  return true;
}
Example #19
0
bool DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
                                  const DWARFUnit *cu) {
  bool indirect = false;
  bool is_block = false;
  Value.data = nullptr;
  // Read the value for the form into value and follow and DW_FORM_indirect
  // instances we run into
  do {
    indirect = false;
    switch (Form) {
    case DW_FORM_addr:
    case DW_FORM_ref_addr: {
      uint16_t AddrSize =
          (Form == DW_FORM_addr)
              ? cu->getAddressByteSize()
              : getRefAddrSize(cu->getAddressByteSize(), cu->getVersion());
      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
      if (AI != cu->getRelocMap()->end()) {
        const std::pair<uint8_t, int64_t> &R = AI->second;
        Value.uval = data.getUnsigned(offset_ptr, AddrSize) + R.second;
      } else
        Value.uval = data.getUnsigned(offset_ptr, AddrSize);
      break;
    }
    case DW_FORM_exprloc:
    case DW_FORM_block:
      Value.uval = data.getULEB128(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block1:
      Value.uval = data.getU8(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block2:
      Value.uval = data.getU16(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block4:
      Value.uval = data.getU32(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_data1:
    case DW_FORM_ref1:
    case DW_FORM_flag:
      Value.uval = data.getU8(offset_ptr);
      break;
    case DW_FORM_data2:
    case DW_FORM_ref2:
      Value.uval = data.getU16(offset_ptr);
      break;
    case DW_FORM_data4:
    case DW_FORM_ref4: {
      RelocAddrMap::const_iterator AI = cu->getRelocMap()->find(*offset_ptr);
      Value.uval = data.getU32(offset_ptr);
      if (AI != cu->getRelocMap()->end())
        Value.uval += AI->second.second;
      break;
    }
    case DW_FORM_data8:
    case DW_FORM_ref8:
      Value.uval = data.getU64(offset_ptr);
      break;
    case DW_FORM_sdata:
      Value.sval = data.getSLEB128(offset_ptr);
      break;
    case DW_FORM_strp: {
      RelocAddrMap::const_iterator AI
        = cu->getRelocMap()->find(*offset_ptr);
      if (AI != cu->getRelocMap()->end()) {
        const std::pair<uint8_t, int64_t> &R = AI->second;
        Value.uval = data.getU32(offset_ptr) + R.second;
      } else
        Value.uval = data.getU32(offset_ptr);
      break;
    }
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    case DW_FORM_string:
      Value.cstr = data.getCStr(offset_ptr);
      break;
    case DW_FORM_indirect:
      Form = data.getULEB128(offset_ptr);
      indirect = true;
      break;
    case DW_FORM_sec_offset: {
      // FIXME: This is 64-bit for DWARF64.
      RelocAddrMap::const_iterator AI
        = cu->getRelocMap()->find(*offset_ptr);
      if (AI != cu->getRelocMap()->end()) {
        const std::pair<uint8_t, int64_t> &R = AI->second;
        Value.uval = data.getU32(offset_ptr) + R.second;
      } else
        Value.uval = data.getU32(offset_ptr);
      break;
    }
    case DW_FORM_flag_present:
      Value.uval = 1;
      break;
    case DW_FORM_ref_sig8:
      Value.uval = data.getU64(offset_ptr);
      break;
    case DW_FORM_GNU_addr_index:
    case DW_FORM_GNU_str_index:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    default:
      return false;
    }
  } while (indirect);

  if (is_block) {
    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
    Value.data = nullptr;
    if (!str.empty()) {
      Value.data = reinterpret_cast<const uint8_t *>(str.data());
      *offset_ptr += Value.uval;
    }
  }

  return true;
}
Example #20
0
void DWARFDebugFrame::parse(DataExtractor Data) {
  uint32_t Offset = 0;
  DenseMap<uint32_t, CIE *> CIEs;

  while (Data.isValidOffset(Offset)) {
    uint32_t StartOffset = Offset;

    auto ReportError = [StartOffset](const char *ErrorMsg) {
      std::string Str;
      raw_string_ostream OS(Str);
      OS << format(ErrorMsg, StartOffset);
      OS.flush();
      report_fatal_error(Str);
    };

    bool IsDWARF64 = false;
    uint64_t Length = Data.getU32(&Offset);
    uint64_t Id;

    if (Length == UINT32_MAX) {
      // DWARF-64 is distinguished by the first 32 bits of the initial length
      // field being 0xffffffff. Then, the next 64 bits are the actual entry
      // length.
      IsDWARF64 = true;
      Length = Data.getU64(&Offset);
    }

    // At this point, Offset points to the next field after Length.
    // Length is the structure size excluding itself. Compute an offset one
    // past the end of the structure (needed to know how many instructions to
    // read).
    // TODO: For honest DWARF64 support, DataExtractor will have to treat
    //       offset_ptr as uint64_t*
    uint32_t StartStructureOffset = Offset;
    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);

    // The Id field's size depends on the DWARF format
    Id = Data.getUnsigned(&Offset, (IsDWARF64 && !IsEH) ? 8 : 4);
    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) ||
                  Id == DW_CIE_ID ||
                  (IsEH && !Id));

    if (IsCIE) {
      uint8_t Version = Data.getU8(&Offset);
      const char *Augmentation = Data.getCStr(&Offset);
      StringRef AugmentationString(Augmentation ? Augmentation : "");
      uint8_t AddressSize = Version < 4 ? Data.getAddressSize() :
                                          Data.getU8(&Offset);
      Data.setAddressSize(AddressSize);
      uint8_t SegmentDescriptorSize = Version < 4 ? 0 : Data.getU8(&Offset);
      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);

      // Parse the augmentation data for EH CIEs
      StringRef AugmentationData("");
      uint32_t FDEPointerEncoding = DW_EH_PE_omit;
      uint32_t LSDAPointerEncoding = DW_EH_PE_omit;
      if (IsEH) {
        Optional<uint32_t> PersonalityEncoding;
        Optional<uint64_t> Personality;

        Optional<uint64_t> AugmentationLength;
        uint32_t StartAugmentationOffset;
        uint32_t EndAugmentationOffset;

        // Walk the augmentation string to get all the augmentation data.
        for (unsigned i = 0, e = AugmentationString.size(); i != e; ++i) {
          switch (AugmentationString[i]) {
            default:
              ReportError("Unknown augmentation character in entry at %lx");
            case 'L':
              LSDAPointerEncoding = Data.getU8(&Offset);
              break;
            case 'P': {
              if (Personality)
                ReportError("Duplicate personality in entry at %lx");
              PersonalityEncoding = Data.getU8(&Offset);
              Personality = readPointer(Data, Offset, *PersonalityEncoding);
              break;
            }
            case 'R':
              FDEPointerEncoding = Data.getU8(&Offset);
              break;
            case 'z':
              if (i)
                ReportError("'z' must be the first character at %lx");
              // Parse the augmentation length first.  We only parse it if
              // the string contains a 'z'.
              AugmentationLength = Data.getULEB128(&Offset);
              StartAugmentationOffset = Offset;
              EndAugmentationOffset = Offset +
                static_cast<uint32_t>(*AugmentationLength);
          }
        }

        if (AugmentationLength.hasValue()) {
          if (Offset != EndAugmentationOffset)
            ReportError("Parsing augmentation data at %lx failed");

          AugmentationData = Data.getData().slice(StartAugmentationOffset,
                                                  EndAugmentationOffset);
        }
      }

      auto Cie = make_unique<CIE>(StartOffset, Length, Version,
                                  AugmentationString, AddressSize,
                                  SegmentDescriptorSize, CodeAlignmentFactor,
                                  DataAlignmentFactor, ReturnAddressRegister,
                                  AugmentationData, FDEPointerEncoding,
                                  LSDAPointerEncoding);
      CIEs[StartOffset] = Cie.get();
      Entries.emplace_back(std::move(Cie));
    } else {
      // FDE
      uint64_t CIEPointer = Id;
      uint64_t InitialLocation = 0;
      uint64_t AddressRange = 0;
      CIE *Cie = CIEs[IsEH ? (StartStructureOffset - CIEPointer) : CIEPointer];

      if (IsEH) {
        // The address size is encoded in the CIE we reference.
        if (!Cie)
          ReportError("Parsing FDE data at %lx failed due to missing CIE");

        InitialLocation = readPointer(Data, Offset,
                                      Cie->getFDEPointerEncoding());
        AddressRange = readPointer(Data, Offset,
                                   Cie->getFDEPointerEncoding());

        StringRef AugmentationString = Cie->getAugmentationString();
        if (!AugmentationString.empty()) {
          // Parse the augmentation length and data for this FDE.
          uint64_t AugmentationLength = Data.getULEB128(&Offset);

          uint32_t EndAugmentationOffset =
            Offset + static_cast<uint32_t>(AugmentationLength);

          // Decode the LSDA if the CIE augmentation string said we should.
          if (Cie->getLSDAPointerEncoding() != DW_EH_PE_omit)
            readPointer(Data, Offset, Cie->getLSDAPointerEncoding());

          if (Offset != EndAugmentationOffset)
            ReportError("Parsing augmentation data at %lx failed");
        }
      } else {
        InitialLocation = Data.getAddress(&Offset);
        AddressRange = Data.getAddress(&Offset);
      }

      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
                                   InitialLocation, AddressRange,
                                   Cie));
    }

    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);

    if (Offset != EndStructureOffset)
      ReportError("Parsing entry instructions at %lx failed");
  }
}
Example #21
0
void FrameEntry::parseInstructions(DataExtractor Data, uint32_t *Offset,
                                   uint32_t EndOffset) {
  while (*Offset < EndOffset) {
    uint8_t Opcode = Data.getU8(Offset);
    // Some instructions have a primary opcode encoded in the top bits.
    uint8_t Primary = Opcode & DWARF_CFI_PRIMARY_OPCODE_MASK;

    if (Primary) {
      // If it's a primary opcode, the first operand is encoded in the bottom
      // bits of the opcode itself.
      uint64_t Op1 = Opcode & DWARF_CFI_PRIMARY_OPERAND_MASK;
      switch (Primary) {
        default: llvm_unreachable("Impossible primary CFI opcode");
        case DW_CFA_advance_loc:
        case DW_CFA_restore:
          addInstruction(Primary, Op1);
          break;
        case DW_CFA_offset:
          addInstruction(Primary, Op1, Data.getULEB128(Offset));
          break;
      }
    } else {
      // Extended opcode - its value is Opcode itself.
      switch (Opcode) {
        default: llvm_unreachable("Invalid extended CFI opcode");
        case DW_CFA_nop:
        case DW_CFA_remember_state:
        case DW_CFA_restore_state:
        case DW_CFA_GNU_window_save:
          // No operands
          addInstruction(Opcode);
          break;
        case DW_CFA_set_loc:
          // Operands: Address
          addInstruction(Opcode, Data.getAddress(Offset));
          break;
        case DW_CFA_advance_loc1:
          // Operands: 1-byte delta
          addInstruction(Opcode, Data.getU8(Offset));
          break;
        case DW_CFA_advance_loc2:
          // Operands: 2-byte delta
          addInstruction(Opcode, Data.getU16(Offset));
          break;
        case DW_CFA_advance_loc4:
          // Operands: 4-byte delta
          addInstruction(Opcode, Data.getU32(Offset));
          break;
        case DW_CFA_restore_extended:
        case DW_CFA_undefined:
        case DW_CFA_same_value:
        case DW_CFA_def_cfa_register:
        case DW_CFA_def_cfa_offset:
        case DW_CFA_GNU_args_size:
          // Operands: ULEB128
          addInstruction(Opcode, Data.getULEB128(Offset));
          break;
        case DW_CFA_def_cfa_offset_sf:
          // Operands: SLEB128
          addInstruction(Opcode, Data.getSLEB128(Offset));
          break;
        case DW_CFA_offset_extended:
        case DW_CFA_register:
        case DW_CFA_def_cfa:
        case DW_CFA_val_offset: {
          // Operands: ULEB128, ULEB128
          // Note: We can not embed getULEB128 directly into function
          // argument list. getULEB128 changes Offset and order of evaluation
          // for arguments is unspecified.
          auto op1 = Data.getULEB128(Offset);
          auto op2 = Data.getULEB128(Offset);
          addInstruction(Opcode, op1, op2);
          break;
        }
        case DW_CFA_offset_extended_sf:
        case DW_CFA_def_cfa_sf:
        case DW_CFA_val_offset_sf: {
          // Operands: ULEB128, SLEB128
          // Note: see comment for the previous case
          auto op1 = Data.getULEB128(Offset);
          auto op2 = (uint64_t)Data.getSLEB128(Offset);
          addInstruction(Opcode, op1, op2);
          break;
        }
        case DW_CFA_def_cfa_expression:
          // FIXME: Parse the actual instruction.
          *Offset += Data.getULEB128(Offset);
          break;
        case DW_CFA_expression:
        case DW_CFA_val_expression: {
          // FIXME: Parse the actual instruction.
          Data.getULEB128(Offset);
          *Offset += Data.getULEB128(Offset);
          break;
        }
      }
    }
  }
}
bool
DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
                             const DWARFCompileUnit *cu) {
  bool indirect = false;
  bool is_block = false;
  Value.data = NULL;
  // Read the value for the form into value and follow and DW_FORM_indirect
  // instances we run into
  do {
    indirect = false;
    switch (Form) {
    case DW_FORM_addr:
    case DW_FORM_ref_addr:
      Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
      break;
    case DW_FORM_block:
      Value.uval = data.getULEB128(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block1:
      Value.uval = data.getU8(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block2:
      Value.uval = data.getU16(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block4:
      Value.uval = data.getU32(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_data1:
    case DW_FORM_ref1:
    case DW_FORM_flag:
      Value.uval = data.getU8(offset_ptr);
      break;
    case DW_FORM_data2:
    case DW_FORM_ref2:
      Value.uval = data.getU16(offset_ptr);
      break;
    case DW_FORM_data4:
    case DW_FORM_ref4:
      Value.uval = data.getU32(offset_ptr);
      break;
    case DW_FORM_data8:
    case DW_FORM_ref8:
      Value.uval = data.getU64(offset_ptr);
      break;
    case DW_FORM_sdata:
      Value.sval = data.getSLEB128(offset_ptr);
      break;
    case DW_FORM_strp:
      Value.uval = data.getU32(offset_ptr);
      break;
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    case DW_FORM_string:
      Value.cstr = data.getCStr(offset_ptr);
      // Set the string value to also be the data for inlined cstr form
      // values only so we can tell the differnence between DW_FORM_string
      // and DW_FORM_strp form values
      Value.data = (uint8_t*)Value.cstr;
      break;
    case DW_FORM_indirect:
      Form = data.getULEB128(offset_ptr);
      indirect = true;
      break;
    default:
      return false;
    }
  } while (indirect);

  if (is_block) {
    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
    Value.data = NULL;
    if (!str.empty()) {
      Value.data = reinterpret_cast<const uint8_t *>(str.data());
      *offset_ptr += Value.uval;
    }
  }

  return true;
}
void DWARFDebugFrame::parse(DataExtractor Data) {
  uint32_t Offset = 0;

  while (Data.isValidOffset(Offset)) {
    uint32_t StartOffset = Offset;

    bool IsDWARF64 = false;
    uint64_t Length = Data.getU32(&Offset);
    uint64_t Id;

    if (Length == UINT32_MAX) {
      // DWARF-64 is distinguished by the first 32 bits of the initial length
      // field being 0xffffffff. Then, the next 64 bits are the actual entry
      // length.
      IsDWARF64 = true;
      Length = Data.getU64(&Offset);
    }

    // At this point, Offset points to the next field after Length.
    // Length is the structure size excluding itself. Compute an offset one
    // past the end of the structure (needed to know how many instructions to
    // read).
    // TODO: For honest DWARF64 support, DataExtractor will have to treat
    //       offset_ptr as uint64_t*
    uint32_t EndStructureOffset = Offset + static_cast<uint32_t>(Length);

    // The Id field's size depends on the DWARF format
    Id = Data.getUnsigned(&Offset, IsDWARF64 ? 8 : 4);
    bool IsCIE = ((IsDWARF64 && Id == DW64_CIE_ID) || Id == DW_CIE_ID);

    if (IsCIE) {
      // Note: this is specifically DWARFv3 CIE header structure. It was
      // changed in DWARFv4. We currently don't support reading DWARFv4
      // here because LLVM itself does not emit it (and LLDB doesn't
      // support it either).
      uint8_t Version = Data.getU8(&Offset);
      const char *Augmentation = Data.getCStr(&Offset);
      uint64_t CodeAlignmentFactor = Data.getULEB128(&Offset);
      int64_t DataAlignmentFactor = Data.getSLEB128(&Offset);
      uint64_t ReturnAddressRegister = Data.getULEB128(&Offset);

      Entries.emplace_back(new CIE(StartOffset, Length, Version,
                                   StringRef(Augmentation), CodeAlignmentFactor,
                                   DataAlignmentFactor, ReturnAddressRegister));
    } else {
      // FDE
      uint64_t CIEPointer = Id;
      uint64_t InitialLocation = Data.getAddress(&Offset);
      uint64_t AddressRange = Data.getAddress(&Offset);

      Entries.emplace_back(new FDE(StartOffset, Length, CIEPointer,
                                   InitialLocation, AddressRange));
    }

    Entries.back()->parseInstructions(Data, &Offset, EndStructureOffset);

    if (Offset != EndStructureOffset) {
      string_ostream Str;
      Str << format("Parsing entry instructions at %lx failed", StartOffset);
      report_fatal_error(Str.str());
    }
  }
}
Example #24
0
bool
DWARFFormValue::extractValue(DataExtractor data, uint32_t *offset_ptr,
                             const DWARFCompileUnit *cu) {
  bool indirect = false;
  bool is_block = false;
  Value.data = NULL;
  // Read the value for the form into value and follow and DW_FORM_indirect
  // instances we run into
  do {
    indirect = false;
    switch (Form) {
    case DW_FORM_addr:
    case DW_FORM_ref_addr: {
      RelocAddrMap::const_iterator AI
        = cu->getRelocMap()->find(*offset_ptr);
      if (AI != cu->getRelocMap()->end()) {
        const std::pair<uint8_t, int64_t> &R = AI->second;
        Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize()) +
                     R.second;
      } else
        Value.uval = data.getUnsigned(offset_ptr, cu->getAddressByteSize());
      break;
    }
    case DW_FORM_exprloc:
    case DW_FORM_block:
      Value.uval = data.getULEB128(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block1:
      Value.uval = data.getU8(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block2:
      Value.uval = data.getU16(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_block4:
      Value.uval = data.getU32(offset_ptr);
      is_block = true;
      break;
    case DW_FORM_data1:
    case DW_FORM_ref1:
    case DW_FORM_flag:
      Value.uval = data.getU8(offset_ptr);
      break;
    case DW_FORM_data2:
    case DW_FORM_ref2:
      Value.uval = data.getU16(offset_ptr);
      break;
    case DW_FORM_data4:
    case DW_FORM_ref4:
      Value.uval = data.getU32(offset_ptr);
      break;
    case DW_FORM_data8:
    case DW_FORM_ref8:
      Value.uval = data.getU64(offset_ptr);
      break;
    case DW_FORM_sdata:
      Value.sval = data.getSLEB128(offset_ptr);
      break;
    case DW_FORM_strp: {
      RelocAddrMap::const_iterator AI
        = cu->getRelocMap()->find(*offset_ptr);
      if (AI != cu->getRelocMap()->end()) {
        const std::pair<uint8_t, int64_t> &R = AI->second;
        Value.uval = data.getU32(offset_ptr) + R.second;
      } else
        Value.uval = data.getU32(offset_ptr);
      break;
    }
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    case DW_FORM_string:
      Value.cstr = data.getCStr(offset_ptr);
      // Set the string value to also be the data for inlined cstr form
      // values only so we can tell the differnence between DW_FORM_string
      // and DW_FORM_strp form values
      Value.data = (const uint8_t*)Value.cstr;
      break;
    case DW_FORM_indirect:
      Form = data.getULEB128(offset_ptr);
      indirect = true;
      break;
    case DW_FORM_sec_offset:
      // FIXME: This is 64-bit for DWARF64.
      Value.uval = data.getU32(offset_ptr);
      break;
    case DW_FORM_flag_present:
      Value.uval = 1;
      break;
    case DW_FORM_ref_sig8:
      Value.uval = data.getU64(offset_ptr);
      break;
    case DW_FORM_GNU_addr_index:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    case DW_FORM_GNU_str_index:
      Value.uval = data.getULEB128(offset_ptr);
      break;
    default:
      return false;
    }
  } while (indirect);

  if (is_block) {
    StringRef str = data.getData().substr(*offset_ptr, Value.uval);
    Value.data = NULL;
    if (!str.empty()) {
      Value.data = reinterpret_cast<const uint8_t *>(str.data());
      *offset_ptr += Value.uval;
    }
  }

  return true;
}
Example #25
0
bool DWARFFormValue::skipValue(dwarf::Form Form, DataExtractor DebugInfoData,
                               uint32_t *OffsetPtr,
                               const DWARFFormParams Params) {
  bool Indirect = false;
  do {
    switch (Form) {
    // Blocks of inlined data that have a length field and the data bytes
    // inlined in the .debug_info.
    case DW_FORM_exprloc:
    case DW_FORM_block: {
      uint64_t size = DebugInfoData.getULEB128(OffsetPtr);
      *OffsetPtr += size;
      return true;
    }
    case DW_FORM_block1: {
      uint8_t size = DebugInfoData.getU8(OffsetPtr);
      *OffsetPtr += size;
      return true;
    }
    case DW_FORM_block2: {
      uint16_t size = DebugInfoData.getU16(OffsetPtr);
      *OffsetPtr += size;
      return true;
    }
    case DW_FORM_block4: {
      uint32_t size = DebugInfoData.getU32(OffsetPtr);
      *OffsetPtr += size;
      return true;
    }

    // Inlined NULL terminated C-strings.
    case DW_FORM_string:
      DebugInfoData.getCStr(OffsetPtr);
      return true;

    case DW_FORM_addr:
    case DW_FORM_ref_addr:
    case DW_FORM_flag_present:
    case DW_FORM_data1:
    case DW_FORM_data2:
    case DW_FORM_data4:
    case DW_FORM_data8:
    case DW_FORM_data16:
    case DW_FORM_flag:
    case DW_FORM_ref1:
    case DW_FORM_ref2:
    case DW_FORM_ref4:
    case DW_FORM_ref8:
    case DW_FORM_ref_sig8:
    case DW_FORM_ref_sup4:
    case DW_FORM_ref_sup8:
    case DW_FORM_strx1:
    case DW_FORM_strx2:
    case DW_FORM_strx4:
    case DW_FORM_addrx1:
    case DW_FORM_addrx2:
    case DW_FORM_addrx4:
    case DW_FORM_sec_offset:
    case DW_FORM_strp:
    case DW_FORM_strp_sup:
    case DW_FORM_line_strp:
    case DW_FORM_GNU_ref_alt:
    case DW_FORM_GNU_strp_alt:
      if (Optional<uint8_t> FixedSize =
              DWARFFormValue::getFixedByteSize(Form, Params)) {
        *OffsetPtr += *FixedSize;
        return true;
      }
      return false;

    // signed or unsigned LEB 128 values.
    case DW_FORM_sdata:
      DebugInfoData.getSLEB128(OffsetPtr);
      return true;

    case DW_FORM_udata:
    case DW_FORM_ref_udata:
    case DW_FORM_strx:
    case DW_FORM_addrx:
    case DW_FORM_loclistx:
    case DW_FORM_rnglistx:
    case DW_FORM_GNU_addr_index:
    case DW_FORM_GNU_str_index:
      DebugInfoData.getULEB128(OffsetPtr);
      return true;

    case DW_FORM_indirect:
      Indirect = true;
      Form = static_cast<dwarf::Form>(DebugInfoData.getULEB128(OffsetPtr));
      break;

    default:
      return false;
    }
  } while (Indirect);
  return true;
}