1 //===- OutputSections.h -----------------------------------------*- C++ -*-===// 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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H 10 #define LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H 11 12 #include "ArrayList.h" 13 #include "StringEntryToDwarfStringPoolEntryMap.h" 14 #include "llvm/ADT/SmallString.h" 15 #include "llvm/ADT/StringRef.h" 16 #include "llvm/BinaryFormat/Dwarf.h" 17 #include "llvm/CodeGen/DwarfStringPoolEntry.h" 18 #include "llvm/DWARFLinker/StringPool.h" 19 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 20 #include "llvm/DebugInfo/DWARF/DWARFObject.h" 21 #include "llvm/Object/ObjectFile.h" 22 #include "llvm/Support/Endian.h" 23 #include "llvm/Support/Error.h" 24 #include "llvm/Support/FormatVariadic.h" 25 #include "llvm/Support/LEB128.h" 26 #include "llvm/Support/MemoryBufferRef.h" 27 #include "llvm/Support/raw_ostream.h" 28 #include <array> 29 #include <cstdint> 30 31 namespace llvm { 32 namespace dwarf_linker { 33 namespace parallel { 34 35 class TypeUnit; 36 37 /// There are fields(sizes, offsets) which should be updated after 38 /// sections are generated. To remember offsets and related data 39 /// the descendants of SectionPatch structure should be used. 40 41 struct SectionPatch { 42 uint64_t PatchOffset = 0; 43 }; 44 45 /// This structure is used to update strings offsets into .debug_str. 46 struct DebugStrPatch : SectionPatch { 47 const StringEntry *String = nullptr; 48 }; 49 50 /// This structure is used to update strings offsets into .debug_line_str. 51 struct DebugLineStrPatch : SectionPatch { 52 const StringEntry *String = nullptr; 53 }; 54 55 /// This structure is used to update range list offset into 56 /// .debug_ranges/.debug_rnglists. 57 struct DebugRangePatch : SectionPatch { 58 /// Indicates patch which points to immediate compile unit's attribute. 59 bool IsCompileUnitRanges = false; 60 }; 61 62 /// This structure is used to update location list offset into 63 /// .debug_loc/.debug_loclists. 64 struct DebugLocPatch : SectionPatch { 65 int64_t AddrAdjustmentValue = 0; 66 }; 67 68 /// This structure is used to update offset with start of another section. 69 struct SectionDescriptor; 70 struct DebugOffsetPatch : SectionPatch { 71 DebugOffsetPatch(uint64_t PatchOffset, SectionDescriptor *SectionPtr, 72 bool AddLocalValue = false) 73 : SectionPatch({PatchOffset}), SectionPtr(SectionPtr, AddLocalValue) {} 74 75 PointerIntPair<SectionDescriptor *, 1> SectionPtr; 76 }; 77 78 /// This structure is used to update reference to the DIE. 79 struct DebugDieRefPatch : SectionPatch { 80 DebugDieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, CompileUnit *RefCU, 81 uint32_t RefIdx); 82 83 PointerIntPair<CompileUnit *, 1> RefCU; 84 uint64_t RefDieIdxOrClonedOffset = 0; 85 }; 86 87 /// This structure is used to update reference to the DIE of ULEB128 form. 88 struct DebugULEB128DieRefPatch : SectionPatch { 89 DebugULEB128DieRefPatch(uint64_t PatchOffset, CompileUnit *SrcCU, 90 CompileUnit *RefCU, uint32_t RefIdx); 91 92 PointerIntPair<CompileUnit *, 1> RefCU; 93 uint64_t RefDieIdxOrClonedOffset = 0; 94 }; 95 96 /// This structure is used to update reference to the type DIE. 97 struct DebugDieTypeRefPatch : SectionPatch { 98 DebugDieTypeRefPatch(uint64_t PatchOffset, TypeEntry *RefTypeName); 99 100 TypeEntry *RefTypeName = nullptr; 101 }; 102 103 /// This structure is used to update reference to the type DIE. 104 struct DebugType2TypeDieRefPatch : SectionPatch { 105 DebugType2TypeDieRefPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, 106 TypeEntry *RefTypeName); 107 108 DIE *Die = nullptr; 109 TypeEntry *TypeName = nullptr; 110 TypeEntry *RefTypeName = nullptr; 111 }; 112 113 struct DebugTypeStrPatch : SectionPatch { 114 DebugTypeStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, 115 StringEntry *String); 116 117 DIE *Die = nullptr; 118 TypeEntry *TypeName = nullptr; 119 StringEntry *String = nullptr; 120 }; 121 122 struct DebugTypeLineStrPatch : SectionPatch { 123 DebugTypeLineStrPatch(uint64_t PatchOffset, DIE *Die, TypeEntry *TypeName, 124 StringEntry *String); 125 126 DIE *Die = nullptr; 127 TypeEntry *TypeName = nullptr; 128 StringEntry *String = nullptr; 129 }; 130 131 struct DebugTypeDeclFilePatch { 132 DebugTypeDeclFilePatch(DIE *Die, TypeEntry *TypeName, StringEntry *Directory, 133 StringEntry *FilePath); 134 135 DIE *Die = nullptr; 136 TypeEntry *TypeName = nullptr; 137 StringEntry *Directory = nullptr; 138 StringEntry *FilePath = nullptr; 139 uint32_t FileID = 0; 140 }; 141 142 /// Type for section data. 143 using OutSectionDataTy = SmallString<0>; 144 145 /// Type for list of pointers to patches offsets. 146 using OffsetsPtrVector = SmallVector<uint64_t *>; 147 148 class OutputSections; 149 150 /// This structure is used to keep data of the concrete section. 151 /// Like data bits, list of patches, format. 152 struct SectionDescriptor : SectionDescriptorBase { 153 friend OutputSections; 154 SectionDescriptorSectionDescriptor155 SectionDescriptor(DebugSectionKind SectionKind, LinkingGlobalData &GlobalData, 156 dwarf::FormParams Format, llvm::endianness Endianess) 157 : SectionDescriptorBase(SectionKind, Format, Endianess), OS(Contents), 158 ListDebugStrPatch(&GlobalData.getAllocator()), 159 ListDebugLineStrPatch(&GlobalData.getAllocator()), 160 ListDebugRangePatch(&GlobalData.getAllocator()), 161 ListDebugLocPatch(&GlobalData.getAllocator()), 162 ListDebugDieRefPatch(&GlobalData.getAllocator()), 163 ListDebugULEB128DieRefPatch(&GlobalData.getAllocator()), 164 ListDebugOffsetPatch(&GlobalData.getAllocator()), 165 ListDebugDieTypeRefPatch(&GlobalData.getAllocator()), 166 ListDebugType2TypeDieRefPatch(&GlobalData.getAllocator()), 167 ListDebugTypeStrPatch(&GlobalData.getAllocator()), 168 ListDebugTypeLineStrPatch(&GlobalData.getAllocator()), 169 ListDebugTypeDeclFilePatch(&GlobalData.getAllocator()), 170 GlobalData(GlobalData) {} 171 172 /// Erase whole section content(data bits, list of patches). 173 void clearAllSectionData(); 174 175 /// Erase only section output data bits. 176 void clearSectionContent(); 177 178 /// When objects(f.e. compile units) are glued into the single file, 179 /// the debug sections corresponding to the concrete object are assigned 180 /// with offsets inside the whole file. This field keeps offset 181 /// to the debug section, corresponding to this object. 182 uint64_t StartOffset = 0; 183 184 /// Stream which stores data to the Contents. 185 raw_svector_ostream OS; 186 187 /// Section patches. 188 #define ADD_PATCHES_LIST(T) \ 189 T ¬ePatch(const T &Patch) { return List##T.add(Patch); } \ 190 ArrayList<T> List##T; 191 192 ADD_PATCHES_LIST(DebugStrPatch) ADD_PATCHES_LISTSectionDescriptor193 ADD_PATCHES_LIST(DebugLineStrPatch) 194 ADD_PATCHES_LIST(DebugRangePatch) 195 ADD_PATCHES_LIST(DebugLocPatch) 196 ADD_PATCHES_LIST(DebugDieRefPatch) 197 ADD_PATCHES_LIST(DebugULEB128DieRefPatch) 198 ADD_PATCHES_LIST(DebugOffsetPatch) 199 ADD_PATCHES_LIST(DebugDieTypeRefPatch) 200 ADD_PATCHES_LIST(DebugType2TypeDieRefPatch) 201 ADD_PATCHES_LIST(DebugTypeStrPatch) 202 ADD_PATCHES_LIST(DebugTypeLineStrPatch) 203 ADD_PATCHES_LIST(DebugTypeDeclFilePatch) 204 205 /// While creating patches, offsets to attributes may be partially 206 /// unknown(because size of abbreviation number is unknown). In such case we 207 /// remember patch itself and pointer to patch application offset to add size 208 /// of abbreviation number later. 209 template <typename T> 210 void notePatchWithOffsetUpdate(const T &Patch, 211 OffsetsPtrVector &PatchesOffsetsList) { 212 PatchesOffsetsList.emplace_back(¬ePatch(Patch).PatchOffset); 213 } 214 215 /// Some sections are emitted using AsmPrinter. In that case "Contents" 216 /// member of SectionDescriptor contains elf file. This method searches 217 /// for section data inside elf file and remember offset to it. 218 void setSizesForSectionCreatedByAsmPrinter(); 219 220 /// Returns section content. getContentsSectionDescriptor221 StringRef getContents() override { 222 if (SectionOffsetInsideAsmPrinterOutputStart == 0) 223 return Contents; 224 225 return Contents.slice(SectionOffsetInsideAsmPrinterOutputStart, 226 SectionOffsetInsideAsmPrinterOutputEnd); 227 } 228 229 /// Emit unit length into the current section contents. emitUnitLengthSectionDescriptor230 void emitUnitLength(uint64_t Length) { 231 maybeEmitDwarf64Mark(); 232 emitIntVal(Length, getFormParams().getDwarfOffsetByteSize()); 233 } 234 235 /// Emit DWARF64 mark into the current section contents. maybeEmitDwarf64MarkSectionDescriptor236 void maybeEmitDwarf64Mark() { 237 if (getFormParams().Format != dwarf::DWARF64) 238 return; 239 emitIntVal(dwarf::DW_LENGTH_DWARF64, 4); 240 } 241 242 /// Emit specified offset value into the current section contents. emitOffsetSectionDescriptor243 void emitOffset(uint64_t Val) { 244 emitIntVal(Val, getFormParams().getDwarfOffsetByteSize()); 245 } 246 247 /// Emit specified integer value into the current section contents. 248 void emitIntVal(uint64_t Val, unsigned Size); 249 250 void emitString(dwarf::Form StringForm, const char *StringVal); 251 252 void emitBinaryData(llvm::StringRef Data); 253 254 /// Emit specified inplace string value into the current section contents. emitInplaceStringSectionDescriptor255 void emitInplaceString(StringRef String) { 256 OS << String; 257 emitIntVal(0, 1); 258 } 259 260 /// Emit string placeholder into the current section contents. emitStringPlaceholderSectionDescriptor261 void emitStringPlaceholder() { 262 // emit bad offset which should be updated later. 263 emitOffset(0xBADDEF); 264 } 265 266 /// Write specified \p Value of \p AttrForm to the \p PatchOffset. 267 void apply(uint64_t PatchOffset, dwarf::Form AttrForm, uint64_t Val); 268 269 /// Returns integer value of \p Size located by specified \p PatchOffset. 270 uint64_t getIntVal(uint64_t PatchOffset, unsigned Size); 271 272 protected: 273 /// Writes integer value \p Val of \p Size by specified \p PatchOffset. 274 void applyIntVal(uint64_t PatchOffset, uint64_t Val, unsigned Size); 275 276 /// Writes integer value \p Val of ULEB128 format by specified \p PatchOffset. 277 void applyULEB128(uint64_t PatchOffset, uint64_t Val); 278 279 /// Writes integer value \p Val of SLEB128 format by specified \p PatchOffset. 280 void applySLEB128(uint64_t PatchOffset, uint64_t Val); 281 282 /// Sets output format. setOutputFormatSectionDescriptor283 void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianess) { 284 this->Format = Format; 285 this->Endianess = Endianess; 286 } 287 288 LinkingGlobalData &GlobalData; 289 290 /// Section data bits. 291 OutSectionDataTy Contents; 292 293 /// Some sections are generated using AsmPrinter. The real section data 294 /// located inside elf file in that case. Following fields points to the 295 /// real section content inside elf file. 296 size_t SectionOffsetInsideAsmPrinterOutputStart = 0; 297 size_t SectionOffsetInsideAsmPrinterOutputEnd = 0; 298 }; 299 300 /// This class keeps contents and offsets to the debug sections. Any objects 301 /// which is supposed to be emitted into the debug sections should use this 302 /// class to track debug sections offsets and keep sections data. 303 class OutputSections { 304 public: OutputSections(LinkingGlobalData & GlobalData)305 OutputSections(LinkingGlobalData &GlobalData) : GlobalData(GlobalData) {} 306 307 /// Sets output format for all keeping sections. setOutputFormat(dwarf::FormParams Format,llvm::endianness Endianness)308 void setOutputFormat(dwarf::FormParams Format, llvm::endianness Endianness) { 309 this->Format = Format; 310 this->Endianness = Endianness; 311 } 312 313 /// Returns descriptor for the specified section of \p SectionKind. 314 /// The descriptor should already be created. The llvm_unreachable 315 /// would be raised if it is not. 316 const SectionDescriptor & getSectionDescriptor(DebugSectionKind SectionKind)317 getSectionDescriptor(DebugSectionKind SectionKind) const { 318 SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind); 319 320 if (It == SectionDescriptors.end()) 321 llvm_unreachable( 322 formatv("Section {0} does not exist", getSectionName(SectionKind)) 323 .str() 324 .c_str()); 325 326 return *It->second; 327 } 328 329 /// Returns descriptor for the specified section of \p SectionKind. 330 /// The descriptor should already be created. The llvm_unreachable 331 /// would be raised if it is not. getSectionDescriptor(DebugSectionKind SectionKind)332 SectionDescriptor &getSectionDescriptor(DebugSectionKind SectionKind) { 333 SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind); 334 335 if (It == SectionDescriptors.end()) 336 llvm_unreachable( 337 formatv("Section {0} does not exist", getSectionName(SectionKind)) 338 .str() 339 .c_str()); 340 341 assert(It->second.get() != nullptr); 342 343 return *It->second; 344 } 345 346 /// Returns descriptor for the specified section of \p SectionKind. 347 /// Returns std::nullopt if section descriptor is not created yet. 348 std::optional<const SectionDescriptor *> tryGetSectionDescriptor(DebugSectionKind SectionKind)349 tryGetSectionDescriptor(DebugSectionKind SectionKind) const { 350 SectionsSetTy::const_iterator It = SectionDescriptors.find(SectionKind); 351 352 if (It == SectionDescriptors.end()) 353 return std::nullopt; 354 355 return It->second.get(); 356 } 357 358 /// Returns descriptor for the specified section of \p SectionKind. 359 /// Returns std::nullopt if section descriptor is not created yet. 360 std::optional<SectionDescriptor *> tryGetSectionDescriptor(DebugSectionKind SectionKind)361 tryGetSectionDescriptor(DebugSectionKind SectionKind) { 362 SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind); 363 364 if (It == SectionDescriptors.end()) 365 return std::nullopt; 366 367 return It->second.get(); 368 } 369 370 /// Returns descriptor for the specified section of \p SectionKind. 371 /// If descriptor does not exist then creates it. 372 SectionDescriptor & getOrCreateSectionDescriptor(DebugSectionKind SectionKind)373 getOrCreateSectionDescriptor(DebugSectionKind SectionKind) { 374 SectionsSetTy::iterator It = SectionDescriptors.find(SectionKind); 375 376 if (It == SectionDescriptors.end()) { 377 SectionDescriptor *Section = 378 new SectionDescriptor(SectionKind, GlobalData, Format, Endianness); 379 auto Result = SectionDescriptors.try_emplace(SectionKind, Section); 380 assert(Result.second); 381 382 It = Result.first; 383 } 384 385 return *It->second; 386 } 387 388 /// Erases data of all sections. eraseSections()389 void eraseSections() { 390 for (auto &Section : SectionDescriptors) 391 Section.second->clearAllSectionData(); 392 } 393 394 /// Enumerate all sections and call \p Handler for each. forEach(function_ref<void (SectionDescriptor &)> Handler)395 void forEach(function_ref<void(SectionDescriptor &)> Handler) { 396 for (auto &Section : SectionDescriptors) { 397 assert(Section.second.get() != nullptr); 398 Handler(*(Section.second)); 399 } 400 } 401 402 /// Enumerate all sections and call \p Handler for each. forEach(function_ref<void (std::shared_ptr<SectionDescriptor> Section)> Handler)403 void forEach( 404 function_ref<void(std::shared_ptr<SectionDescriptor> Section)> Handler) { 405 for (auto &Section : SectionDescriptors) 406 Handler(Section.second); 407 } 408 409 /// Enumerate all sections, for each section set current offset 410 /// (kept by \p SectionSizesAccumulator), update current offset with section 411 /// length. assignSectionsOffsetAndAccumulateSize(std::array<uint64_t,SectionKindsNum> & SectionSizesAccumulator)412 void assignSectionsOffsetAndAccumulateSize( 413 std::array<uint64_t, SectionKindsNum> &SectionSizesAccumulator) { 414 for (auto &Section : SectionDescriptors) { 415 Section.second->StartOffset = 416 SectionSizesAccumulator[static_cast<uint8_t>( 417 Section.second->getKind())]; 418 SectionSizesAccumulator[static_cast<uint8_t>( 419 Section.second->getKind())] += Section.second->getContents().size(); 420 } 421 } 422 423 /// Enumerate all sections, for each section apply all section patches. 424 void applyPatches(SectionDescriptor &Section, 425 StringEntryToDwarfStringPoolEntryMap &DebugStrStrings, 426 StringEntryToDwarfStringPoolEntryMap &DebugLineStrStrings, 427 TypeUnit *TypeUnitPtr); 428 429 /// Endiannes for the sections. getEndianness()430 llvm::endianness getEndianness() const { return Endianness; } 431 432 /// Return DWARF version. getVersion()433 uint16_t getVersion() const { return Format.Version; } 434 435 /// Return size of header of debug_info table. getDebugInfoHeaderSize()436 uint16_t getDebugInfoHeaderSize() const { 437 return Format.Version >= 5 ? 12 : 11; 438 } 439 440 /// Return size of header of debug_ table. getDebugAddrHeaderSize()441 uint16_t getDebugAddrHeaderSize() const { 442 assert(Format.Version >= 5); 443 return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16; 444 } 445 446 /// Return size of header of debug_str_offsets table. getDebugStrOffsetsHeaderSize()447 uint16_t getDebugStrOffsetsHeaderSize() const { 448 assert(Format.Version >= 5); 449 return Format.Format == dwarf::DwarfFormat::DWARF32 ? 8 : 16; 450 } 451 452 /// Return size of address. getFormParams()453 const dwarf::FormParams &getFormParams() const { return Format; } 454 455 protected: 456 LinkingGlobalData &GlobalData; 457 458 /// Format for sections. 459 dwarf::FormParams Format = {4, 4, dwarf::DWARF32}; 460 461 /// Endiannes for sections. 462 llvm::endianness Endianness = llvm::endianness::native; 463 464 /// All keeping sections. 465 using SectionsSetTy = 466 std::map<DebugSectionKind, std::shared_ptr<SectionDescriptor>>; 467 SectionsSetTy SectionDescriptors; 468 }; 469 470 } // end of namespace parallel 471 } // end of namespace dwarf_linker 472 } // end of namespace llvm 473 474 #endif // LLVM_LIB_DWARFLINKER_PARALLEL_OUTPUTSECTIONS_H 475