void DWARFDebugLoc::parse(DataExtractor data, unsigned AddressSize) { uint32_t Offset = 0; while (data.isValidOffset(Offset+AddressSize-1)) { Locations.resize(Locations.size() + 1); LocationList &Loc = Locations.back(); Loc.Offset = Offset; // 2.6.2 Location Lists // A location list entry consists of: while (true) { Entry E; RelocAddrMap::const_iterator AI = RelocMap.find(Offset); // 1. A beginning address offset. ... E.Begin = data.getUnsigned(&Offset, AddressSize); if (AI != RelocMap.end()) E.Begin += AI->second.second; AI = RelocMap.find(Offset); // 2. An ending address offset. ... E.End = data.getUnsigned(&Offset, AddressSize); if (AI != RelocMap.end()) E.End += AI->second.second; // The end of any given location list is marked by an end of list entry, // which consists of a 0 for the beginning address offset and a 0 for the // ending address offset. if (E.Begin == 0 && E.End == 0) break; 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.reserve(str.size()); std::copy(str.begin(), str.end(), std::back_inserter(E.Loc)); Loc.Entries.push_back(llvm_move(E)); } } if (data.isValidOffset(Offset)) llvm::errs() << "error: failed to consume entire .debug_loc section\n"; }
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); } } }
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; }
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()); } } }
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; 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"); } }
bool DWARFDebugLine::Prologue::parse(DataExtractor debug_line_data, uint32_t *offset_ptr) { const uint64_t prologue_offset = *offset_ptr; clear(); TotalLength = debug_line_data.getU32(offset_ptr); if (TotalLength == UINT32_MAX) { IsDWARF64 = true; TotalLength = debug_line_data.getU64(offset_ptr); } else if (TotalLength > 0xffffff00) { return false; } Version = debug_line_data.getU16(offset_ptr); if (Version < 2) return false; PrologueLength = debug_line_data.getUnsigned(offset_ptr, sizeofPrologueLength()); const uint64_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.8" PRIx64 " should have ended at 0x%8.8" PRIx64 " but it ended at 0x%8.8" PRIx64 "\n", prologue_offset, end_prologue_offset, (uint64_t)*offset_ptr); return false; } return true; }
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; }