Path: blob/main/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/OutputSections.cpp
35291 views
//=== OutputSections.cpp --------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "OutputSections.h"9#include "DWARFLinkerCompileUnit.h"10#include "DWARFLinkerTypeUnit.h"11#include "llvm/ADT/StringSwitch.h"1213using namespace llvm;14using namespace dwarf_linker;15using namespace dwarf_linker::parallel;1617DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,18CompileUnit *RefCU, uint32_t RefIdx)19: SectionPatch({PatchOffset}),20RefCU(RefCU, (SrcCU != nullptr) &&21(SrcCU->getUniqueID() == RefCU->getUniqueID())),22RefDieIdxOrClonedOffset(RefIdx) {}2324DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,25CompileUnit *SrcCU,26CompileUnit *RefCU,27uint32_t RefIdx)28: SectionPatch({PatchOffset}),29RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),30RefDieIdxOrClonedOffset(RefIdx) {}3132DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,33TypeEntry *RefTypeName)34: SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}3536DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,37DIE *Die,38TypeEntry *TypeName,39TypeEntry *RefTypeName)40: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),41RefTypeName(RefTypeName) {}4243DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,44TypeEntry *TypeName, StringEntry *String)45: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),46String(String) {}4748DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,49TypeEntry *TypeName,50StringEntry *String)51: SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),52String(String) {}5354DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,55StringEntry *Directory,56StringEntry *FilePath)57: Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}5859void SectionDescriptor::clearAllSectionData() {60StartOffset = 0;61clearSectionContent();62ListDebugStrPatch.erase();63ListDebugLineStrPatch.erase();64ListDebugRangePatch.erase();65ListDebugLocPatch.erase();66ListDebugDieRefPatch.erase();67ListDebugULEB128DieRefPatch.erase();68ListDebugOffsetPatch.erase();69ListDebugType2TypeDieRefPatch.erase();70ListDebugTypeDeclFilePatch.erase();71ListDebugTypeLineStrPatch.erase();72ListDebugTypeStrPatch.erase();73}7475void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }7677void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {78if (Contents.empty())79return;8081MemoryBufferRef Mem(Contents, "obj");82Expected<std::unique_ptr<object::ObjectFile>> Obj =83object::ObjectFile::createObjectFile(Mem);84if (!Obj) {85consumeError(Obj.takeError());86Contents.clear();87return;88}8990for (const object::SectionRef &Sect : (*Obj).get()->sections()) {91Expected<StringRef> SectNameOrErr = Sect.getName();92if (!SectNameOrErr) {93consumeError(SectNameOrErr.takeError());94continue;95}96if (std::optional<DebugSectionKind> SectKind =97parseDebugTableName(*SectNameOrErr)) {98if (*SectKind == SectionKind) {99Expected<StringRef> Data = Sect.getContents();100if (!Data) {101consumeError(SectNameOrErr.takeError());102Contents.clear();103return;104}105106SectionOffsetInsideAsmPrinterOutputStart =107Data->data() - Contents.data();108SectionOffsetInsideAsmPrinterOutputEnd =109SectionOffsetInsideAsmPrinterOutputStart + Data->size();110}111}112}113}114115void SectionDescriptor::emitString(dwarf::Form StringForm,116const char *StringVal) {117assert(StringVal != nullptr);118119switch (StringForm) {120case dwarf::DW_FORM_string: {121emitInplaceString(StringVal);122} break;123case dwarf::DW_FORM_strp: {124notePatch(DebugStrPatch{125{OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});126emitStringPlaceholder();127} break;128case dwarf::DW_FORM_line_strp: {129notePatch(DebugLineStrPatch{130{OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});131emitStringPlaceholder();132} break;133default:134llvm_unreachable("Unsupported string form");135break;136};137}138139void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {140switch (Size) {141case 1: {142OS.write(static_cast<uint8_t>(Val));143} break;144case 2: {145uint16_t ShortVal = static_cast<uint16_t>(Val);146if (Endianess != llvm::endianness::native)147sys::swapByteOrder(ShortVal);148OS.write(reinterpret_cast<const char *>(&ShortVal), Size);149} break;150case 4: {151uint32_t ShortVal = static_cast<uint32_t>(Val);152if (Endianess != llvm::endianness::native)153sys::swapByteOrder(ShortVal);154OS.write(reinterpret_cast<const char *>(&ShortVal), Size);155} break;156case 8: {157if (Endianess != llvm::endianness::native)158sys::swapByteOrder(Val);159OS.write(reinterpret_cast<const char *>(&Val), Size);160} break;161default:162llvm_unreachable("Unsupported integer type size");163}164}165166void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {167OS.write(Data.data(), Data.size());168}169170void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,171uint64_t Val) {172switch (AttrForm) {173case dwarf::DW_FORM_strp:174case dwarf::DW_FORM_line_strp: {175applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());176} break;177178case dwarf::DW_FORM_ref_addr: {179applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());180} break;181case dwarf::DW_FORM_ref1: {182applyIntVal(PatchOffset, Val, 1);183} break;184case dwarf::DW_FORM_ref2: {185applyIntVal(PatchOffset, Val, 2);186} break;187case dwarf::DW_FORM_ref4: {188applyIntVal(PatchOffset, Val, 4);189} break;190case dwarf::DW_FORM_ref8: {191applyIntVal(PatchOffset, Val, 8);192} break;193194case dwarf::DW_FORM_data1: {195applyIntVal(PatchOffset, Val, 1);196} break;197case dwarf::DW_FORM_data2: {198applyIntVal(PatchOffset, Val, 2);199} break;200case dwarf::DW_FORM_data4: {201applyIntVal(PatchOffset, Val, 4);202} break;203case dwarf::DW_FORM_data8: {204applyIntVal(PatchOffset, Val, 8);205} break;206case dwarf::DW_FORM_udata: {207applyULEB128(PatchOffset, Val);208} break;209case dwarf::DW_FORM_sdata: {210applySLEB128(PatchOffset, Val);211} break;212case dwarf::DW_FORM_sec_offset: {213applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());214} break;215case dwarf::DW_FORM_flag: {216applyIntVal(PatchOffset, Val, 1);217} break;218219default:220llvm_unreachable("Unsupported attribute form");221break;222}223}224225uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {226assert(PatchOffset < getContents().size());227switch (Size) {228case 1: {229return *reinterpret_cast<const uint8_t *>(230(getContents().data() + PatchOffset));231}232case 2: {233return support::endian::read16(getContents().data() + PatchOffset,234Endianess);235}236case 4: {237return support::endian::read32(getContents().data() + PatchOffset,238Endianess);239}240case 8: {241return support::endian::read64(getContents().data() + PatchOffset,242Endianess);243}244}245llvm_unreachable("Unsupported integer type size");246return 0;247}248249void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,250unsigned Size) {251assert(PatchOffset < getContents().size());252253switch (Size) {254case 1: {255support::endian::write(256const_cast<char *>(getContents().data() + PatchOffset),257static_cast<uint8_t>(Val), Endianess);258} break;259case 2: {260support::endian::write(261const_cast<char *>(getContents().data() + PatchOffset),262static_cast<uint16_t>(Val), Endianess);263} break;264case 4: {265support::endian::write(266const_cast<char *>(getContents().data() + PatchOffset),267static_cast<uint32_t>(Val), Endianess);268} break;269case 8: {270support::endian::write(271const_cast<char *>(getContents().data() + PatchOffset),272static_cast<uint64_t>(Val), Endianess);273} break;274default:275llvm_unreachable("Unsupported integer type size");276}277}278279void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {280assert(PatchOffset < getContents().size());281282uint8_t ULEB[16];283uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;284uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);285286memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,287RealSize);288}289290/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.291void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {292assert(PatchOffset < getContents().size());293294uint8_t SLEB[16];295uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;296uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);297298memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,299RealSize);300}301302void OutputSections::applyPatches(303SectionDescriptor &Section,304StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,305StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,306TypeUnit *TypeUnitPtr) {307Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {308DwarfStringPoolEntryWithExtString *Entry =309DebugStrStrings.getExistingEntry(Patch.String);310assert(Entry != nullptr);311312Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);313});314Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {315assert(TypeUnitPtr != nullptr);316TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();317assert(TypeEntry &&318formatv("No data for type {0}", Patch.TypeName->getKey())319.str()320.c_str());321322if (&TypeEntry->getFinalDie() != Patch.Die)323return;324325DwarfStringPoolEntryWithExtString *Entry =326DebugStrStrings.getExistingEntry(Patch.String);327assert(Entry != nullptr);328329Patch.PatchOffset +=330Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());331332Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);333});334335Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {336DwarfStringPoolEntryWithExtString *Entry =337DebugLineStrStrings.getExistingEntry(Patch.String);338assert(Entry != nullptr);339340Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);341});342Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {343assert(TypeUnitPtr != nullptr);344TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();345assert(TypeEntry &&346formatv("No data for type {0}", Patch.TypeName->getKey())347.str()348.c_str());349350if (&TypeEntry->getFinalDie() != Patch.Die)351return;352353DwarfStringPoolEntryWithExtString *Entry =354DebugLineStrStrings.getExistingEntry(Patch.String);355assert(Entry != nullptr);356357Patch.PatchOffset +=358Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());359360Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);361});362363std::optional<SectionDescriptor *> RangeSection;364if (Format.Version >= 5)365RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);366else367RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);368369if (RangeSection) {370Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {371uint64_t FinalValue =372Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());373FinalValue += (*RangeSection)->StartOffset;374375Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);376});377}378379std::optional<SectionDescriptor *> LocationSection;380if (Format.Version >= 5)381LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);382else383LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);384385if (LocationSection) {386Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {387uint64_t FinalValue =388Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());389FinalValue += (*LocationSection)->StartOffset;390391Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);392});393}394395Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {396uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;397dwarf::Form FinalForm = dwarf::DW_FORM_ref4;398399// Check whether it is local or inter-CU reference.400if (!Patch.RefCU.getInt()) {401SectionDescriptor &ReferencedSectionDescriptor =402Patch.RefCU.getPointer()->getSectionDescriptor(403DebugSectionKind::DebugInfo);404405FinalForm = dwarf::DW_FORM_ref_addr;406FinalOffset += ReferencedSectionDescriptor.StartOffset;407}408409Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);410});411412Section.ListDebugULEB128DieRefPatch.forEach(413[&](DebugULEB128DieRefPatch &Patch) {414assert(Patch.RefCU.getInt());415Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,416Patch.RefDieIdxOrClonedOffset);417});418419Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {420assert(TypeUnitPtr != nullptr);421assert(Patch.RefTypeName != nullptr);422423TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();424assert(TypeEntry &&425formatv("No data for type {0}", Patch.RefTypeName->getKey())426.str()427.c_str());428429Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,430TypeEntry->getFinalDie().getOffset());431});432433Section.ListDebugType2TypeDieRefPatch.forEach(434[&](DebugType2TypeDieRefPatch &Patch) {435assert(TypeUnitPtr != nullptr);436TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();437assert(TypeEntry &&438formatv("No data for type {0}", Patch.TypeName->getKey())439.str()440.c_str());441442if (&TypeEntry->getFinalDie() != Patch.Die)443return;444445Patch.PatchOffset += Patch.Die->getOffset() +446getULEB128Size(Patch.Die->getAbbrevNumber());447448assert(Patch.RefTypeName != nullptr);449TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();450assert(TypeEntry &&451formatv("No data for type {0}", Patch.RefTypeName->getKey())452.str()453.c_str());454455Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,456RefTypeEntry->getFinalDie().getOffset());457});458459Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {460uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;461462// Check whether we need to read value from the original location.463if (Patch.SectionPtr.getInt())464FinalValue +=465Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());466467Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);468});469}470471472