llvm::Error DWARFDebugNames::Header::extract(const DWARFDataExtractor &AS,
                                             uint32_t *Offset) {
  // Check that we can read the fixed-size part.
  if (!AS.isValidOffset(*Offset + sizeof(HeaderPOD) - 1))
    return make_error<StringError>("Section too small: cannot read header.",
                                   inconvertibleErrorCode());

  UnitLength = AS.getU32(Offset);
  Version = AS.getU16(Offset);
  Padding = AS.getU16(Offset);
  CompUnitCount = AS.getU32(Offset);
  LocalTypeUnitCount = AS.getU32(Offset);
  ForeignTypeUnitCount = AS.getU32(Offset);
  BucketCount = AS.getU32(Offset);
  NameCount = AS.getU32(Offset);
  AbbrevTableSize = AS.getU32(Offset);
  AugmentationStringSize = AS.getU32(Offset);

  if (!AS.isValidOffsetForDataOfSize(*Offset, AugmentationStringSize))
    return make_error<StringError>(
        "Section too small: cannot read header augmentation.",
        inconvertibleErrorCode());
  AugmentationString.resize(AugmentationStringSize);
  AS.getU8(Offset, reinterpret_cast<uint8_t *>(AugmentationString.data()),
           AugmentationStringSize);
  *Offset = alignTo(*Offset, 4);
  return Error::success();
}
示例#2
0
bool DWARFTypeUnit::extractImpl(const DWARFDataExtractor &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;
}
示例#3
0
文件: DWARFUnit.cpp 项目: MatzeB/llvm
// Look for a DWARF32-formatted contribution to the string offsets table
// starting at a given offset and record it in a descriptor.
static Optional<StrOffsetsContributionDescriptor>
parseDWARF32StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
  if (!DA.isValidOffsetForDataOfSize(Offset, 8))
    return None;
  uint32_t ContributionSize = DA.getU32(&Offset);
  if (ContributionSize >= 0xfffffff0)
    return None;
  uint8_t Version = DA.getU16(&Offset);
  (void)DA.getU16(&Offset); // padding
  // The encoded length includes the 2-byte version field and the 2-byte
  // padding, so we need to subtract them out when we populate the descriptor.
  return {{Offset, ContributionSize - 4, Version, DWARF32}};
}
示例#4
0
// Look for a DWARF64-formatted contribution to the string offsets table
// starting at a given offset and record it in a descriptor.
static Optional<StrOffsetsContributionDescriptor>
parseDWARF64StringOffsetsTableHeader(DWARFDataExtractor &DA, uint32_t Offset) {
  if (!DA.isValidOffsetForDataOfSize(Offset, 16))
    return Optional<StrOffsetsContributionDescriptor>();

  if (DA.getU32(&Offset) != 0xffffffff)
    return Optional<StrOffsetsContributionDescriptor>();

  uint64_t Size = DA.getU64(&Offset);
  uint8_t Version = DA.getU16(&Offset);
  (void)DA.getU16(&Offset); // padding
  // The encoded length includes the 2-byte version field and the 2-byte
  // padding, so we need to subtract them out when we populate the descriptor.
  return StrOffsetsContributionDescriptor(Offset, Size - 4, Version, DWARF64);
  //return Optional<StrOffsetsContributionDescriptor>(Descriptor);
}
示例#5
0
bool DWARFVerifier::verifyUnitHeader(const DWARFDataExtractor DebugInfoData,
                                     uint32_t *Offset, unsigned UnitIndex,
                                     uint8_t &UnitType, bool &isUnitDWARF64) {
  uint32_t AbbrOffset, Length;
  uint8_t AddrSize = 0;
  uint16_t Version;
  bool Success = true;

  bool ValidLength = false;
  bool ValidVersion = false;
  bool ValidAddrSize = false;
  bool ValidType = true;
  bool ValidAbbrevOffset = true;

  uint32_t OffsetStart = *Offset;
  Length = DebugInfoData.getU32(Offset);
  if (Length == UINT32_MAX) {
    isUnitDWARF64 = true;
    OS << format(
        "Unit[%d] is in 64-bit DWARF format; cannot verify from this point.\n",
        UnitIndex);
    return false;
  }
  Version = DebugInfoData.getU16(Offset);

  if (Version >= 5) {
    UnitType = DebugInfoData.getU8(Offset);
    AddrSize = DebugInfoData.getU8(Offset);
    AbbrOffset = DebugInfoData.getU32(Offset);
    ValidType = dwarf::isUnitType(UnitType);
  } else {
    UnitType = 0;
    AbbrOffset = DebugInfoData.getU32(Offset);
    AddrSize = DebugInfoData.getU8(Offset);
  }

  if (!DCtx.getDebugAbbrev()->getAbbreviationDeclarationSet(AbbrOffset))
    ValidAbbrevOffset = false;

  ValidLength = DebugInfoData.isValidOffset(OffsetStart + Length + 3);
  ValidVersion = DWARFContext::isSupportedVersion(Version);
  ValidAddrSize = AddrSize == 4 || AddrSize == 8;
  if (!ValidLength || !ValidVersion || !ValidAddrSize || !ValidAbbrevOffset ||
      !ValidType) {
    Success = false;
    error() << format("Units[%d] - start offset: 0x%08x \n", UnitIndex,
                      OffsetStart);
    if (!ValidLength)
      note() << "The length for this unit is too "
            "large for the .debug_info provided.\n";
    if (!ValidVersion)
      note() << "The 16 bit unit header version is not valid.\n";
    if (!ValidType)
      note() << "The unit type encoding is not valid.\n";
    if (!ValidAbbrevOffset)
      note() << "The offset into the .debug_abbrev section is "
            "not valid.\n";
    if (!ValidAddrSize)
      note() << "The address size is unsupported.\n";
  }
  *Offset = OffsetStart + Length + 4;
  return Success;
}
示例#6
0
bool DWARFFormValue::extractValue(const DWARFDataExtractor &Data,
                                  uint32_t *OffsetPtr, DWARFFormParams FP,
                                  const DWARFUnit *CU) {
  U = CU;
  bool Indirect = false;
  bool IsBlock = 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 Size =
          (Form == DW_FORM_addr) ? FP.AddrSize : FP.getRefAddrByteSize();
      Value.uval = Data.getRelocatedValue(Size, OffsetPtr, &Value.SectionIndex);
      break;
    }
    case DW_FORM_exprloc:
    case DW_FORM_block:
      Value.uval = Data.getULEB128(OffsetPtr);
      IsBlock = true;
      break;
    case DW_FORM_block1:
      Value.uval = Data.getU8(OffsetPtr);
      IsBlock = true;
      break;
    case DW_FORM_block2:
      Value.uval = Data.getU16(OffsetPtr);
      IsBlock = true;
      break;
    case DW_FORM_block4:
      Value.uval = Data.getU32(OffsetPtr);
      IsBlock = true;
      break;
    case DW_FORM_data1:
    case DW_FORM_ref1:
    case DW_FORM_flag:
    case DW_FORM_strx1:
    case DW_FORM_addrx1:
      Value.uval = Data.getU8(OffsetPtr);
      break;
    case DW_FORM_data2:
    case DW_FORM_ref2:
    case DW_FORM_strx2:
    case DW_FORM_addrx2:
      Value.uval = Data.getU16(OffsetPtr);
      break;
    case DW_FORM_strx3:
      Value.uval = Data.getU24(OffsetPtr);
      break;
    case DW_FORM_data4:
    case DW_FORM_ref4:
    case DW_FORM_ref_sup4:
    case DW_FORM_strx4:
    case DW_FORM_addrx4:
      Value.uval = Data.getRelocatedValue(4, OffsetPtr);
      break;
    case DW_FORM_data8:
    case DW_FORM_ref8:
    case DW_FORM_ref_sup8:
      Value.uval = Data.getU64(OffsetPtr);
      break;
    case DW_FORM_data16:
      // Treat this like a 16-byte block.
      Value.uval = 16;
      IsBlock = true;
      break;
    case DW_FORM_sdata:
      Value.sval = Data.getSLEB128(OffsetPtr);
      break;
    case DW_FORM_udata:
    case DW_FORM_ref_udata:
      Value.uval = Data.getULEB128(OffsetPtr);
      break;
    case DW_FORM_string:
      Value.cstr = Data.getCStr(OffsetPtr);
      break;
    case DW_FORM_indirect:
      Form = static_cast<dwarf::Form>(Data.getULEB128(OffsetPtr));
      Indirect = true;
      break;
    case DW_FORM_strp:
    case DW_FORM_sec_offset:
    case DW_FORM_GNU_ref_alt:
    case DW_FORM_GNU_strp_alt:
    case DW_FORM_line_strp:
    case DW_FORM_strp_sup: {
      Value.uval =
          Data.getRelocatedValue(FP.getDwarfOffsetByteSize(), OffsetPtr);
      break;
    }
    case DW_FORM_flag_present:
      Value.uval = 1;
      break;
    case DW_FORM_ref_sig8:
      Value.uval = Data.getU64(OffsetPtr);
      break;
    case DW_FORM_GNU_addr_index:
    case DW_FORM_GNU_str_index:
    case DW_FORM_strx:
      Value.uval = Data.getULEB128(OffsetPtr);
      break;
    default:
      // DWARFFormValue::skipValue() will have caught this and caused all
      // DWARF DIEs to fail to be parsed, so this code is not be reachable.
      llvm_unreachable("unsupported form");
    }
  } while (Indirect);

  if (IsBlock) {
    StringRef Str = Data.getData().substr(*OffsetPtr, Value.uval);
    Value.data = nullptr;
    if (!Str.empty()) {
      Value.data = reinterpret_cast<const uint8_t *>(Str.data());
      *OffsetPtr += Value.uval;
    }
  }

  return true;
}
示例#7
0
bool DWARFUnitHeader::extract(DWARFContext &Context,
                              const DWARFDataExtractor &debug_info,
                              uint32_t *offset_ptr,
                              DWARFSectionKind SectionKind,
                              const DWARFUnitIndex *Index) {
  Offset = *offset_ptr;
  IndexEntry = Index ? Index->getFromOffset(*offset_ptr) : nullptr;
  Length = debug_info.getU32(offset_ptr);
  // FIXME: Support DWARF64.
  unsigned SizeOfLength = 4;
  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.getRelocatedValue(4, offset_ptr);
    FormParams.AddrSize = debug_info.getU8(offset_ptr);
    // Fake a unit type based on the section type.  This isn't perfect,
    // but distinguishing compile and type units is generally enough.
    if (SectionKind == DW_SECT_TYPES)
      UnitType = DW_UT_type;
    else
      UnitType = DW_UT_compile;
  }
  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;
  }
  if (isTypeUnit()) {
    TypeHash = debug_info.getU64(offset_ptr);
    TypeOffset = debug_info.getU32(offset_ptr);
  } else if (UnitType == DW_UT_split_compile || UnitType == DW_UT_skeleton)
    DWOId = debug_info.getU64(offset_ptr);

  // Header fields all parsed, capture the size of this unit header.
  assert(*offset_ptr - Offset <= 255 && "unexpected header size");
  Size = uint8_t(*offset_ptr - Offset);

  // Type offset is unit-relative; should be after the header and before
  // the end of the current unit.
  bool TypeOffsetOK =
      !isTypeUnit()
          ? true
          : TypeOffset >= Size && TypeOffset < getLength() + SizeOfLength;
  bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1);
  bool VersionOK = DWARFContext::isSupportedVersion(getVersion());
  bool AddrSizeOK = getAddressByteSize() == 4 || getAddressByteSize() == 8;

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

  // Keep track of the highest DWARF version we encounter across all units.
  Context.setMaxVersionIfGreater(getVersion());
  return true;
}
示例#8
0
bool DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
                                     uint32_t *OffsetPtr, const DWARFUnit *U) {
  const uint64_t PrologueOffset = *OffsetPtr;

  clear();
  TotalLength = DebugLineData.getU32(OffsetPtr);
  if (TotalLength == UINT32_MAX) {
    FormParams.Format = dwarf::DWARF64;
    TotalLength = DebugLineData.getU64(OffsetPtr);
  } else if (TotalLength >= 0xffffff00) {
    return false;
  }
  FormParams.Version = DebugLineData.getU16(OffsetPtr);
  if (getVersion() < 2)
    return false;

  if (getVersion() >= 5) {
    FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
    assert((DebugLineData.getAddressSize() == 0 ||
            DebugLineData.getAddressSize() == getAddressSize()) &&
           "Line table header and data extractor disagree");
    SegSelectorSize = DebugLineData.getU8(OffsetPtr);
  }

  PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
  const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
  MinInstLength = DebugLineData.getU8(OffsetPtr);
  if (getVersion() >= 4)
    MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
  DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
  LineBase = DebugLineData.getU8(OffsetPtr);
  LineRange = DebugLineData.getU8(OffsetPtr);
  OpcodeBase = DebugLineData.getU8(OffsetPtr);

  StandardOpcodeLengths.reserve(OpcodeBase - 1);
  for (uint32_t I = 1; I < OpcodeBase; ++I) {
    uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
    StandardOpcodeLengths.push_back(OpLen);
  }

  if (getVersion() >= 5) {
    if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
                              FormParams, U, HasMD5, IncludeDirectories,
                              FileNames)) {
      fprintf(stderr,
              "warning: parsing line table prologue at 0x%8.8" PRIx64
              " found an invalid directory or file table description at"
              " 0x%8.8" PRIx64 "\n", PrologueOffset, (uint64_t)*OffsetPtr);
      return false;
    }
  } else
    parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
                         IncludeDirectories, FileNames);

  if (*OffsetPtr != EndPrologueOffset) {
    fprintf(stderr,
            "warning: parsing line table prologue at 0x%8.8" PRIx64
            " should have ended at 0x%8.8" PRIx64
            " but it ended at 0x%8.8" PRIx64 "\n",
            PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
    return false;
  }
  return true;
}
示例#9
0
Error DWARFDebugLine::Prologue::parse(const DWARFDataExtractor &DebugLineData,
                                      uint32_t *OffsetPtr,
                                      const DWARFContext &Ctx,
                                      const DWARFUnit *U) {
  const uint64_t PrologueOffset = *OffsetPtr;

  clear();
  TotalLength = DebugLineData.getU32(OffsetPtr);
  if (TotalLength == UINT32_MAX) {
    FormParams.Format = dwarf::DWARF64;
    TotalLength = DebugLineData.getU64(OffsetPtr);
  } else if (TotalLength >= 0xffffff00) {
    return createStringError(errc::invalid_argument,
        "parsing line table prologue at offset 0x%8.8" PRIx64
        " unsupported reserved unit length found of value 0x%8.8" PRIx64,
        PrologueOffset, TotalLength);
  }
  FormParams.Version = DebugLineData.getU16(OffsetPtr);
  if (getVersion() < 2)
    return createStringError(errc::not_supported,
                       "parsing line table prologue at offset 0x%8.8" PRIx64
                       " found unsupported version 0x%2.2" PRIx16,
                       PrologueOffset, getVersion());

  if (getVersion() >= 5) {
    FormParams.AddrSize = DebugLineData.getU8(OffsetPtr);
    assert((DebugLineData.getAddressSize() == 0 ||
            DebugLineData.getAddressSize() == getAddressSize()) &&
           "Line table header and data extractor disagree");
    SegSelectorSize = DebugLineData.getU8(OffsetPtr);
  }

  PrologueLength = DebugLineData.getUnsigned(OffsetPtr, sizeofPrologueLength());
  const uint64_t EndPrologueOffset = PrologueLength + *OffsetPtr;
  MinInstLength = DebugLineData.getU8(OffsetPtr);
  if (getVersion() >= 4)
    MaxOpsPerInst = DebugLineData.getU8(OffsetPtr);
  DefaultIsStmt = DebugLineData.getU8(OffsetPtr);
  LineBase = DebugLineData.getU8(OffsetPtr);
  LineRange = DebugLineData.getU8(OffsetPtr);
  OpcodeBase = DebugLineData.getU8(OffsetPtr);

  StandardOpcodeLengths.reserve(OpcodeBase - 1);
  for (uint32_t I = 1; I < OpcodeBase; ++I) {
    uint8_t OpLen = DebugLineData.getU8(OffsetPtr);
    StandardOpcodeLengths.push_back(OpLen);
  }

  if (getVersion() >= 5) {
    if (!parseV5DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
                              FormParams, Ctx, U, ContentTypes,
                              IncludeDirectories, FileNames)) {
      return createStringError(errc::invalid_argument,
          "parsing line table prologue at 0x%8.8" PRIx64
          " found an invalid directory or file table description at"
          " 0x%8.8" PRIx64,
          PrologueOffset, (uint64_t)*OffsetPtr);
    }
  } else
    parseV2DirFileTables(DebugLineData, OffsetPtr, EndPrologueOffset,
                         ContentTypes, IncludeDirectories, FileNames);

  if (*OffsetPtr != EndPrologueOffset)
    return createStringError(errc::invalid_argument,
                       "parsing line table prologue at 0x%8.8" PRIx64
                       " should have ended at 0x%8.8" PRIx64
                       " but it ended at 0x%8.8" PRIx64,
                       PrologueOffset, EndPrologueOffset, (uint64_t)*OffsetPtr);
  return Error::success();
}