10b57cec5SDimitry Andric //===- DWARFAbbreviationDeclaration.cpp -----------------------------------===// 20b57cec5SDimitry Andric // 30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 60b57cec5SDimitry Andric // 70b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 80b57cec5SDimitry Andric 90b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFAbbreviationDeclaration.h" 100b57cec5SDimitry Andric 110b57cec5SDimitry Andric #include "llvm/ADT/None.h" 120b57cec5SDimitry Andric #include "llvm/ADT/Optional.h" 130b57cec5SDimitry Andric #include "llvm/BinaryFormat/Dwarf.h" 140b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 150b57cec5SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFUnit.h" 160b57cec5SDimitry Andric #include "llvm/Support/DataExtractor.h" 170b57cec5SDimitry Andric #include "llvm/Support/Format.h" 180b57cec5SDimitry Andric #include "llvm/Support/FormatVariadic.h" 190b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h" 200b57cec5SDimitry Andric #include <cstddef> 210b57cec5SDimitry Andric #include <cstdint> 220b57cec5SDimitry Andric 230b57cec5SDimitry Andric using namespace llvm; 240b57cec5SDimitry Andric using namespace dwarf; 250b57cec5SDimitry Andric 260b57cec5SDimitry Andric void DWARFAbbreviationDeclaration::clear() { 270b57cec5SDimitry Andric Code = 0; 280b57cec5SDimitry Andric Tag = DW_TAG_null; 290b57cec5SDimitry Andric CodeByteSize = 0; 300b57cec5SDimitry Andric HasChildren = false; 310b57cec5SDimitry Andric AttributeSpecs.clear(); 320b57cec5SDimitry Andric FixedAttributeSize.reset(); 330b57cec5SDimitry Andric } 340b57cec5SDimitry Andric 350b57cec5SDimitry Andric DWARFAbbreviationDeclaration::DWARFAbbreviationDeclaration() { 360b57cec5SDimitry Andric clear(); 370b57cec5SDimitry Andric } 380b57cec5SDimitry Andric 390b57cec5SDimitry Andric bool 400b57cec5SDimitry Andric DWARFAbbreviationDeclaration::extract(DataExtractor Data, 418bcb0991SDimitry Andric uint64_t* OffsetPtr) { 420b57cec5SDimitry Andric clear(); 438bcb0991SDimitry Andric const uint64_t Offset = *OffsetPtr; 440b57cec5SDimitry Andric Code = Data.getULEB128(OffsetPtr); 450b57cec5SDimitry Andric if (Code == 0) { 460b57cec5SDimitry Andric return false; 470b57cec5SDimitry Andric } 480b57cec5SDimitry Andric CodeByteSize = *OffsetPtr - Offset; 490b57cec5SDimitry Andric Tag = static_cast<llvm::dwarf::Tag>(Data.getULEB128(OffsetPtr)); 500b57cec5SDimitry Andric if (Tag == DW_TAG_null) { 510b57cec5SDimitry Andric clear(); 520b57cec5SDimitry Andric return false; 530b57cec5SDimitry Andric } 540b57cec5SDimitry Andric uint8_t ChildrenByte = Data.getU8(OffsetPtr); 550b57cec5SDimitry Andric HasChildren = (ChildrenByte == DW_CHILDREN_yes); 560b57cec5SDimitry Andric // Assign a value to our optional FixedAttributeSize member variable. If 570b57cec5SDimitry Andric // this member variable still has a value after the while loop below, then 580b57cec5SDimitry Andric // all attribute data in this abbreviation declaration has a fixed byte size. 590b57cec5SDimitry Andric FixedAttributeSize = FixedSizeInfo(); 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric // Read all of the abbreviation attributes and forms. 620b57cec5SDimitry Andric while (true) { 630b57cec5SDimitry Andric auto A = static_cast<Attribute>(Data.getULEB128(OffsetPtr)); 640b57cec5SDimitry Andric auto F = static_cast<Form>(Data.getULEB128(OffsetPtr)); 650b57cec5SDimitry Andric if (A && F) { 660b57cec5SDimitry Andric bool IsImplicitConst = (F == DW_FORM_implicit_const); 670b57cec5SDimitry Andric if (IsImplicitConst) { 680b57cec5SDimitry Andric int64_t V = Data.getSLEB128(OffsetPtr); 690b57cec5SDimitry Andric AttributeSpecs.push_back(AttributeSpec(A, F, V)); 700b57cec5SDimitry Andric continue; 710b57cec5SDimitry Andric } 720b57cec5SDimitry Andric Optional<uint8_t> ByteSize; 730b57cec5SDimitry Andric // If this abbrevation still has a fixed byte size, then update the 740b57cec5SDimitry Andric // FixedAttributeSize as needed. 750b57cec5SDimitry Andric switch (F) { 760b57cec5SDimitry Andric case DW_FORM_addr: 770b57cec5SDimitry Andric if (FixedAttributeSize) 780b57cec5SDimitry Andric ++FixedAttributeSize->NumAddrs; 790b57cec5SDimitry Andric break; 800b57cec5SDimitry Andric 810b57cec5SDimitry Andric case DW_FORM_ref_addr: 820b57cec5SDimitry Andric if (FixedAttributeSize) 830b57cec5SDimitry Andric ++FixedAttributeSize->NumRefAddrs; 840b57cec5SDimitry Andric break; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric case DW_FORM_strp: 870b57cec5SDimitry Andric case DW_FORM_GNU_ref_alt: 880b57cec5SDimitry Andric case DW_FORM_GNU_strp_alt: 890b57cec5SDimitry Andric case DW_FORM_line_strp: 900b57cec5SDimitry Andric case DW_FORM_sec_offset: 910b57cec5SDimitry Andric case DW_FORM_strp_sup: 920b57cec5SDimitry Andric if (FixedAttributeSize) 930b57cec5SDimitry Andric ++FixedAttributeSize->NumDwarfOffsets; 940b57cec5SDimitry Andric break; 950b57cec5SDimitry Andric 960b57cec5SDimitry Andric default: 970b57cec5SDimitry Andric // The form has a byte size that doesn't depend on Params. 980b57cec5SDimitry Andric // If it's a fixed size, keep track of it. 990b57cec5SDimitry Andric if ((ByteSize = dwarf::getFixedFormByteSize(F, dwarf::FormParams()))) { 1000b57cec5SDimitry Andric if (FixedAttributeSize) 1010b57cec5SDimitry Andric FixedAttributeSize->NumBytes += *ByteSize; 1020b57cec5SDimitry Andric break; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric // Indicate we no longer have a fixed byte size for this 1050b57cec5SDimitry Andric // abbreviation by clearing the FixedAttributeSize optional value 1060b57cec5SDimitry Andric // so it doesn't have a value. 1070b57cec5SDimitry Andric FixedAttributeSize.reset(); 1080b57cec5SDimitry Andric break; 1090b57cec5SDimitry Andric } 1100b57cec5SDimitry Andric // Record this attribute and its fixed size if it has one. 1110b57cec5SDimitry Andric AttributeSpecs.push_back(AttributeSpec(A, F, ByteSize)); 1120b57cec5SDimitry Andric } else if (A == 0 && F == 0) { 1130b57cec5SDimitry Andric // We successfully reached the end of this abbreviation declaration 1140b57cec5SDimitry Andric // since both attribute and form are zero. 1150b57cec5SDimitry Andric break; 1160b57cec5SDimitry Andric } else { 1170b57cec5SDimitry Andric // Attribute and form pairs must either both be non-zero, in which case 1180b57cec5SDimitry Andric // they are added to the abbreviation declaration, or both be zero to 1190b57cec5SDimitry Andric // terminate the abbrevation declaration. In this case only one was 1200b57cec5SDimitry Andric // zero which is an error. 1210b57cec5SDimitry Andric clear(); 1220b57cec5SDimitry Andric return false; 1230b57cec5SDimitry Andric } 1240b57cec5SDimitry Andric } 1250b57cec5SDimitry Andric return true; 1260b57cec5SDimitry Andric } 1270b57cec5SDimitry Andric 1280b57cec5SDimitry Andric void DWARFAbbreviationDeclaration::dump(raw_ostream &OS) const { 1290b57cec5SDimitry Andric OS << '[' << getCode() << "] "; 1300b57cec5SDimitry Andric OS << formatv("{0}", getTag()); 1310b57cec5SDimitry Andric OS << "\tDW_CHILDREN_" << (hasChildren() ? "yes" : "no") << '\n'; 1320b57cec5SDimitry Andric for (const AttributeSpec &Spec : AttributeSpecs) { 1330b57cec5SDimitry Andric OS << formatv("\t{0}\t{1}", Spec.Attr, Spec.Form); 1340b57cec5SDimitry Andric if (Spec.isImplicitConst()) 1350b57cec5SDimitry Andric OS << '\t' << Spec.getImplicitConstValue(); 1360b57cec5SDimitry Andric OS << '\n'; 1370b57cec5SDimitry Andric } 1380b57cec5SDimitry Andric OS << '\n'; 1390b57cec5SDimitry Andric } 1400b57cec5SDimitry Andric 1410b57cec5SDimitry Andric Optional<uint32_t> 1420b57cec5SDimitry Andric DWARFAbbreviationDeclaration::findAttributeIndex(dwarf::Attribute Attr) const { 1430b57cec5SDimitry Andric for (uint32_t i = 0, e = AttributeSpecs.size(); i != e; ++i) { 1440b57cec5SDimitry Andric if (AttributeSpecs[i].Attr == Attr) 1450b57cec5SDimitry Andric return i; 1460b57cec5SDimitry Andric } 1470b57cec5SDimitry Andric return None; 1480b57cec5SDimitry Andric } 1490b57cec5SDimitry Andric 150*349cc55cSDimitry Andric uint64_t DWARFAbbreviationDeclaration::getAttributeOffsetFromIndex( 151*349cc55cSDimitry Andric uint32_t AttrIndex, uint64_t DIEOffset, const DWARFUnit &U) const { 152*349cc55cSDimitry Andric DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 153*349cc55cSDimitry Andric 154*349cc55cSDimitry Andric // Add the byte size of ULEB that for the abbrev Code so we can start 155*349cc55cSDimitry Andric // skipping the attribute data. 156*349cc55cSDimitry Andric uint64_t Offset = DIEOffset + CodeByteSize; 157*349cc55cSDimitry Andric for (uint32_t CurAttrIdx = 0; CurAttrIdx != AttrIndex; ++CurAttrIdx) 158*349cc55cSDimitry Andric // Match Offset along until we get to the attribute we want. 159*349cc55cSDimitry Andric if (auto FixedSize = AttributeSpecs[CurAttrIdx].getByteSize(U)) 160*349cc55cSDimitry Andric Offset += *FixedSize; 161*349cc55cSDimitry Andric else 162*349cc55cSDimitry Andric DWARFFormValue::skipValue(AttributeSpecs[CurAttrIdx].Form, DebugInfoData, 163*349cc55cSDimitry Andric &Offset, U.getFormParams()); 164*349cc55cSDimitry Andric return Offset; 165*349cc55cSDimitry Andric } 166*349cc55cSDimitry Andric 167*349cc55cSDimitry Andric Optional<DWARFFormValue> 168*349cc55cSDimitry Andric DWARFAbbreviationDeclaration::getAttributeValueFromOffset( 169*349cc55cSDimitry Andric uint32_t AttrIndex, uint64_t Offset, const DWARFUnit &U) const { 170*349cc55cSDimitry Andric assert(AttributeSpecs.size() > AttrIndex && 171*349cc55cSDimitry Andric "Attribute Index is out of bounds."); 172*349cc55cSDimitry Andric 173*349cc55cSDimitry Andric // We have arrived at the attribute to extract, extract if from Offset. 174*349cc55cSDimitry Andric const AttributeSpec &Spec = AttributeSpecs[AttrIndex]; 175*349cc55cSDimitry Andric if (Spec.isImplicitConst()) 176*349cc55cSDimitry Andric return DWARFFormValue::createFromSValue(Spec.Form, 177*349cc55cSDimitry Andric Spec.getImplicitConstValue()); 178*349cc55cSDimitry Andric 179*349cc55cSDimitry Andric DWARFFormValue FormValue(Spec.Form); 180*349cc55cSDimitry Andric DWARFDataExtractor DebugInfoData = U.getDebugInfoExtractor(); 181*349cc55cSDimitry Andric if (FormValue.extractValue(DebugInfoData, &Offset, U.getFormParams(), &U)) 182*349cc55cSDimitry Andric return FormValue; 183*349cc55cSDimitry Andric return None; 184*349cc55cSDimitry Andric } 185*349cc55cSDimitry Andric 186*349cc55cSDimitry Andric Optional<DWARFFormValue> 187*349cc55cSDimitry Andric DWARFAbbreviationDeclaration::getAttributeValue(const uint64_t DIEOffset, 188*349cc55cSDimitry Andric const dwarf::Attribute Attr, 1890b57cec5SDimitry Andric const DWARFUnit &U) const { 1905ffd83dbSDimitry Andric // Check if this abbreviation has this attribute without needing to skip 1915ffd83dbSDimitry Andric // any data so we can return quickly if it doesn't. 1920b57cec5SDimitry Andric Optional<uint32_t> MatchAttrIndex = findAttributeIndex(Attr); 1930b57cec5SDimitry Andric if (!MatchAttrIndex) 1940b57cec5SDimitry Andric return None; 1950b57cec5SDimitry Andric 196*349cc55cSDimitry Andric uint64_t Offset = getAttributeOffsetFromIndex(*MatchAttrIndex, DIEOffset, U); 1970b57cec5SDimitry Andric 198*349cc55cSDimitry Andric return getAttributeValueFromOffset(*MatchAttrIndex, Offset, U); 1990b57cec5SDimitry Andric } 2000b57cec5SDimitry Andric 2010b57cec5SDimitry Andric size_t DWARFAbbreviationDeclaration::FixedSizeInfo::getByteSize( 2020b57cec5SDimitry Andric const DWARFUnit &U) const { 2030b57cec5SDimitry Andric size_t ByteSize = NumBytes; 2040b57cec5SDimitry Andric if (NumAddrs) 2050b57cec5SDimitry Andric ByteSize += NumAddrs * U.getAddressByteSize(); 2060b57cec5SDimitry Andric if (NumRefAddrs) 2070b57cec5SDimitry Andric ByteSize += NumRefAddrs * U.getRefAddrByteSize(); 2080b57cec5SDimitry Andric if (NumDwarfOffsets) 2090b57cec5SDimitry Andric ByteSize += NumDwarfOffsets * U.getDwarfOffsetByteSize(); 2100b57cec5SDimitry Andric return ByteSize; 2110b57cec5SDimitry Andric } 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric Optional<int64_t> DWARFAbbreviationDeclaration::AttributeSpec::getByteSize( 2140b57cec5SDimitry Andric const DWARFUnit &U) const { 2150b57cec5SDimitry Andric if (isImplicitConst()) 2160b57cec5SDimitry Andric return 0; 2170b57cec5SDimitry Andric if (ByteSize.HasByteSize) 2180b57cec5SDimitry Andric return ByteSize.ByteSize; 2190b57cec5SDimitry Andric Optional<int64_t> S; 2200b57cec5SDimitry Andric auto FixedByteSize = dwarf::getFixedFormByteSize(Form, U.getFormParams()); 2210b57cec5SDimitry Andric if (FixedByteSize) 2220b57cec5SDimitry Andric S = *FixedByteSize; 2230b57cec5SDimitry Andric return S; 2240b57cec5SDimitry Andric } 2250b57cec5SDimitry Andric 2260b57cec5SDimitry Andric Optional<size_t> DWARFAbbreviationDeclaration::getFixedAttributesByteSize( 2270b57cec5SDimitry Andric const DWARFUnit &U) const { 2280b57cec5SDimitry Andric if (FixedAttributeSize) 2290b57cec5SDimitry Andric return FixedAttributeSize->getByteSize(U); 2300b57cec5SDimitry Andric return None; 2310b57cec5SDimitry Andric } 232