470 lines · cpp
1//=== OutputSections.cpp --------------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "OutputSections.h"10#include "DWARFLinkerCompileUnit.h"11#include "DWARFLinkerTypeUnit.h"12 13using namespace llvm;14using namespace dwarf_linker;15using namespace dwarf_linker::parallel;16 17DebugDieRefPatch::DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU,18 CompileUnit *RefCU, uint32_t RefIdx)19 : SectionPatch({PatchOffset}),20 RefCU(RefCU, (SrcCU != nullptr) &&21 (SrcCU->getUniqueID() == RefCU->getUniqueID())),22 RefDieIdxOrClonedOffset(RefIdx) {}23 24DebugULEB128DieRefPatch::DebugULEB128DieRefPatch(uint64_t PatchOffset,25 CompileUnit *SrcCU,26 CompileUnit *RefCU,27 uint32_t RefIdx)28 : SectionPatch({PatchOffset}),29 RefCU(RefCU, SrcCU->getUniqueID() == RefCU->getUniqueID()),30 RefDieIdxOrClonedOffset(RefIdx) {}31 32DebugDieTypeRefPatch::DebugDieTypeRefPatch(uint64_t PatchOffset,33 TypeEntry *RefTypeName)34 : SectionPatch({PatchOffset}), RefTypeName(RefTypeName) {}35 36DebugType2TypeDieRefPatch::DebugType2TypeDieRefPatch(uint64_t PatchOffset,37 DIE *Die,38 TypeEntry *TypeName,39 TypeEntry *RefTypeName)40 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),41 RefTypeName(RefTypeName) {}42 43DebugTypeStrPatch::DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die,44 TypeEntry *TypeName, StringEntry *String)45 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),46 String(String) {}47 48DebugTypeLineStrPatch::DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die,49 TypeEntry *TypeName,50 StringEntry *String)51 : SectionPatch({PatchOffset}), Die(Die), TypeName(TypeName),52 String(String) {}53 54DebugTypeDeclFilePatch::DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName,55 StringEntry *Directory,56 StringEntry *FilePath)57 : Die(Die), TypeName(TypeName), Directory(Directory), FilePath(FilePath) {}58 59void SectionDescriptor::clearAllSectionData() {60 StartOffset = 0;61 clearSectionContent();62 ListDebugStrPatch.erase();63 ListDebugLineStrPatch.erase();64 ListDebugRangePatch.erase();65 ListDebugLocPatch.erase();66 ListDebugDieRefPatch.erase();67 ListDebugULEB128DieRefPatch.erase();68 ListDebugOffsetPatch.erase();69 ListDebugType2TypeDieRefPatch.erase();70 ListDebugTypeDeclFilePatch.erase();71 ListDebugTypeLineStrPatch.erase();72 ListDebugTypeStrPatch.erase();73}74 75void SectionDescriptor::clearSectionContent() { Contents = OutSectionDataTy(); }76 77void SectionDescriptor::setSizesForSectionCreatedByAsmPrinter() {78 if (Contents.empty())79 return;80 81 MemoryBufferRef Mem(Contents, "obj");82 Expected<std::unique_ptr<object::ObjectFile>> Obj =83 object::ObjectFile::createObjectFile(Mem);84 if (!Obj) {85 consumeError(Obj.takeError());86 Contents.clear();87 return;88 }89 90 for (const object::SectionRef &Sect : (*Obj).get()->sections()) {91 Expected<StringRef> SectNameOrErr = Sect.getName();92 if (!SectNameOrErr) {93 consumeError(SectNameOrErr.takeError());94 continue;95 }96 if (std::optional<DebugSectionKind> SectKind =97 parseDebugTableName(*SectNameOrErr)) {98 if (*SectKind == SectionKind) {99 Expected<StringRef> Data = Sect.getContents();100 if (!Data) {101 consumeError(SectNameOrErr.takeError());102 Contents.clear();103 return;104 }105 106 SectionOffsetInsideAsmPrinterOutputStart =107 Data->data() - Contents.data();108 SectionOffsetInsideAsmPrinterOutputEnd =109 SectionOffsetInsideAsmPrinterOutputStart + Data->size();110 }111 }112 }113}114 115void SectionDescriptor::emitString(dwarf::Form StringForm,116 const char *StringVal) {117 assert(StringVal != nullptr);118 119 switch (StringForm) {120 case dwarf::DW_FORM_string: {121 emitInplaceString(StringVal);122 } break;123 case dwarf::DW_FORM_strp: {124 notePatch(DebugStrPatch{125 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});126 emitStringPlaceholder();127 } break;128 case dwarf::DW_FORM_line_strp: {129 notePatch(DebugLineStrPatch{130 {OS.tell()}, GlobalData.getStringPool().insert(StringVal).first});131 emitStringPlaceholder();132 } break;133 default:134 llvm_unreachable("Unsupported string form");135 break;136 };137}138 139void SectionDescriptor::emitIntVal(uint64_t Val, unsigned Size) {140 switch (Size) {141 case 1: {142 OS.write(static_cast<uint8_t>(Val));143 } break;144 case 2: {145 uint16_t ShortVal = static_cast<uint16_t>(Val);146 if (Endianess != llvm::endianness::native)147 sys::swapByteOrder(ShortVal);148 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);149 } break;150 case 4: {151 uint32_t ShortVal = static_cast<uint32_t>(Val);152 if (Endianess != llvm::endianness::native)153 sys::swapByteOrder(ShortVal);154 OS.write(reinterpret_cast<const char *>(&ShortVal), Size);155 } break;156 case 8: {157 if (Endianess != llvm::endianness::native)158 sys::swapByteOrder(Val);159 OS.write(reinterpret_cast<const char *>(&Val), Size);160 } break;161 default:162 llvm_unreachable("Unsupported integer type size");163 }164}165 166void SectionDescriptor::emitBinaryData(llvm::StringRef Data) {167 OS.write(Data.data(), Data.size());168}169 170void SectionDescriptor::apply(uint64_t PatchOffset, dwarf::Form AttrForm,171 uint64_t Val) {172 switch (AttrForm) {173 case dwarf::DW_FORM_strp:174 case dwarf::DW_FORM_line_strp: {175 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());176 } break;177 178 case dwarf::DW_FORM_ref_addr: {179 applyIntVal(PatchOffset, Val, Format.getRefAddrByteSize());180 } break;181 case dwarf::DW_FORM_ref1: {182 applyIntVal(PatchOffset, Val, 1);183 } break;184 case dwarf::DW_FORM_ref2: {185 applyIntVal(PatchOffset, Val, 2);186 } break;187 case dwarf::DW_FORM_ref4: {188 applyIntVal(PatchOffset, Val, 4);189 } break;190 case dwarf::DW_FORM_ref8: {191 applyIntVal(PatchOffset, Val, 8);192 } break;193 194 case dwarf::DW_FORM_data1: {195 applyIntVal(PatchOffset, Val, 1);196 } break;197 case dwarf::DW_FORM_data2: {198 applyIntVal(PatchOffset, Val, 2);199 } break;200 case dwarf::DW_FORM_data4: {201 applyIntVal(PatchOffset, Val, 4);202 } break;203 case dwarf::DW_FORM_data8: {204 applyIntVal(PatchOffset, Val, 8);205 } break;206 case dwarf::DW_FORM_udata: {207 applyULEB128(PatchOffset, Val);208 } break;209 case dwarf::DW_FORM_sdata: {210 applySLEB128(PatchOffset, Val);211 } break;212 case dwarf::DW_FORM_sec_offset: {213 applyIntVal(PatchOffset, Val, Format.getDwarfOffsetByteSize());214 } break;215 case dwarf::DW_FORM_flag: {216 applyIntVal(PatchOffset, Val, 1);217 } break;218 219 default:220 llvm_unreachable("Unsupported attribute form");221 break;222 }223}224 225uint64_t SectionDescriptor::getIntVal(uint64_t PatchOffset, unsigned Size) {226 assert(PatchOffset < getContents().size());227 switch (Size) {228 case 1: {229 return *reinterpret_cast<const uint8_t *>(230 (getContents().data() + PatchOffset));231 }232 case 2: {233 return support::endian::read16(getContents().data() + PatchOffset,234 Endianess);235 }236 case 4: {237 return support::endian::read32(getContents().data() + PatchOffset,238 Endianess);239 }240 case 8: {241 return support::endian::read64(getContents().data() + PatchOffset,242 Endianess);243 }244 }245 llvm_unreachable("Unsupported integer type size");246 return 0;247}248 249void SectionDescriptor::applyIntVal(uint64_t PatchOffset, uint64_t Val,250 unsigned Size) {251 assert(PatchOffset < getContents().size());252 253 switch (Size) {254 case 1: {255 support::endian::write(256 const_cast<char *>(getContents().data() + PatchOffset),257 static_cast<uint8_t>(Val), Endianess);258 } break;259 case 2: {260 support::endian::write(261 const_cast<char *>(getContents().data() + PatchOffset),262 static_cast<uint16_t>(Val), Endianess);263 } break;264 case 4: {265 support::endian::write(266 const_cast<char *>(getContents().data() + PatchOffset),267 static_cast<uint32_t>(Val), Endianess);268 } break;269 case 8: {270 support::endian::write(271 const_cast<char *>(getContents().data() + PatchOffset),272 static_cast<uint64_t>(Val), Endianess);273 } break;274 default:275 llvm_unreachable("Unsupported integer type size");276 }277}278 279void SectionDescriptor::applyULEB128(uint64_t PatchOffset, uint64_t Val) {280 assert(PatchOffset < getContents().size());281 282 uint8_t ULEB[16];283 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;284 uint8_t RealSize = encodeULEB128(Val, ULEB, DestSize);285 286 memcpy(const_cast<char *>(getContents().data() + PatchOffset), ULEB,287 RealSize);288}289 290/// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset.291void SectionDescriptor::applySLEB128(uint64_t PatchOffset, uint64_t Val) {292 assert(PatchOffset < getContents().size());293 294 uint8_t SLEB[16];295 uint8_t DestSize = Format.getDwarfOffsetByteSize() + 1;296 uint8_t RealSize = encodeSLEB128(Val, SLEB, DestSize);297 298 memcpy(const_cast<char *>(getContents().data() + PatchOffset), SLEB,299 RealSize);300}301 302void OutputSections::applyPatches(303 SectionDescriptor &Section,304 StringEntryToDwarfStringPoolEntryMap &DebugStrStrings,305 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings,306 TypeUnit *TypeUnitPtr) {307 Section.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {308 DwarfStringPoolEntryWithExtString *Entry =309 DebugStrStrings.getExistingEntry(Patch.String);310 assert(Entry != nullptr);311 312 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);313 });314 Section.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {315 assert(TypeUnitPtr != nullptr);316 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();317 assert(TypeEntry &&318 formatv("No data for type {0}", Patch.TypeName->getKey())319 .str()320 .c_str());321 322 if (&TypeEntry->getFinalDie() != Patch.Die)323 return;324 325 DwarfStringPoolEntryWithExtString *Entry =326 DebugStrStrings.getExistingEntry(Patch.String);327 assert(Entry != nullptr);328 329 Patch.PatchOffset +=330 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());331 332 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_strp, Entry->Offset);333 });334 335 Section.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {336 DwarfStringPoolEntryWithExtString *Entry =337 DebugLineStrStrings.getExistingEntry(Patch.String);338 assert(Entry != nullptr);339 340 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);341 });342 Section.ListDebugTypeLineStrPatch.forEach([&](DebugTypeLineStrPatch &Patch) {343 assert(TypeUnitPtr != nullptr);344 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();345 assert(TypeEntry &&346 formatv("No data for type {0}", Patch.TypeName->getKey())347 .str()348 .c_str());349 350 if (&TypeEntry->getFinalDie() != Patch.Die)351 return;352 353 DwarfStringPoolEntryWithExtString *Entry =354 DebugLineStrStrings.getExistingEntry(Patch.String);355 assert(Entry != nullptr);356 357 Patch.PatchOffset +=358 Patch.Die->getOffset() + getULEB128Size(Patch.Die->getAbbrevNumber());359 360 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_line_strp, Entry->Offset);361 });362 363 std::optional<SectionDescriptor *> RangeSection;364 if (Format.Version >= 5)365 RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRngLists);366 else367 RangeSection = tryGetSectionDescriptor(DebugSectionKind::DebugRange);368 369 if (RangeSection) {370 Section.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {371 uint64_t FinalValue =372 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());373 FinalValue += (*RangeSection)->StartOffset;374 375 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);376 });377 }378 379 std::optional<SectionDescriptor *> LocationSection;380 if (Format.Version >= 5)381 LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLocLists);382 else383 LocationSection = tryGetSectionDescriptor(DebugSectionKind::DebugLoc);384 385 if (LocationSection) {386 Section.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {387 uint64_t FinalValue =388 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());389 FinalValue += (*LocationSection)->StartOffset;390 391 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);392 });393 }394 395 Section.ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {396 uint64_t FinalOffset = Patch.RefDieIdxOrClonedOffset;397 dwarf::Form FinalForm = dwarf::DW_FORM_ref4;398 399 // Check whether it is local or inter-CU reference.400 if (!Patch.RefCU.getInt()) {401 SectionDescriptor &ReferencedSectionDescriptor =402 Patch.RefCU.getPointer()->getSectionDescriptor(403 DebugSectionKind::DebugInfo);404 405 FinalForm = dwarf::DW_FORM_ref_addr;406 FinalOffset += ReferencedSectionDescriptor.StartOffset;407 }408 409 Section.apply(Patch.PatchOffset, FinalForm, FinalOffset);410 });411 412 Section.ListDebugULEB128DieRefPatch.forEach(413 [&](DebugULEB128DieRefPatch &Patch) {414 assert(Patch.RefCU.getInt());415 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_udata,416 Patch.RefDieIdxOrClonedOffset);417 });418 419 Section.ListDebugDieTypeRefPatch.forEach([&](DebugDieTypeRefPatch &Patch) {420 assert(TypeUnitPtr != nullptr);421 assert(Patch.RefTypeName != nullptr);422 423 TypeEntryBody *TypeEntry = Patch.RefTypeName->getValue().load();424 assert(TypeEntry &&425 formatv("No data for type {0}", Patch.RefTypeName->getKey())426 .str()427 .c_str());428 429 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref_addr,430 TypeEntry->getFinalDie().getOffset());431 });432 433 Section.ListDebugType2TypeDieRefPatch.forEach(434 [&](DebugType2TypeDieRefPatch &Patch) {435 assert(TypeUnitPtr != nullptr);436 TypeEntryBody *TypeEntry = Patch.TypeName->getValue().load();437 assert(TypeEntry &&438 formatv("No data for type {0}", Patch.TypeName->getKey())439 .str()440 .c_str());441 442 if (&TypeEntry->getFinalDie() != Patch.Die)443 return;444 445 Patch.PatchOffset += Patch.Die->getOffset() +446 getULEB128Size(Patch.Die->getAbbrevNumber());447 448 assert(Patch.RefTypeName != nullptr);449 TypeEntryBody *RefTypeEntry = Patch.RefTypeName->getValue().load();450 assert(TypeEntry &&451 formatv("No data for type {0}", Patch.RefTypeName->getKey())452 .str()453 .c_str());454 455 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_ref4,456 RefTypeEntry->getFinalDie().getOffset());457 });458 459 Section.ListDebugOffsetPatch.forEach([&](DebugOffsetPatch &Patch) {460 uint64_t FinalValue = Patch.SectionPtr.getPointer()->StartOffset;461 462 // Check whether we need to read value from the original location.463 if (Patch.SectionPtr.getInt())464 FinalValue +=465 Section.getIntVal(Patch.PatchOffset, Format.getDwarfOffsetByteSize());466 467 Section.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset, FinalValue);468 });469}470