| 1 | //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===// |
| 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 | // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF |
| 10 | // package files). |
| 11 | // |
| 12 | //===----------------------------------------------------------------------===// |
| 13 | #include "llvm/DWP/DWP.h" |
| 14 | #include "llvm/ADT/Twine.h" |
| 15 | #include "llvm/DWP/DWPError.h" |
| 16 | #include "llvm/MC/MCContext.h" |
| 17 | #include "llvm/MC/MCObjectFileInfo.h" |
| 18 | #include "llvm/MC/MCTargetOptionsCommandFlags.h" |
| 19 | #include "llvm/Object/Decompressor.h" |
| 20 | #include "llvm/Object/ELFObjectFile.h" |
| 21 | #include <limits> |
| 22 | |
| 23 | using namespace llvm; |
| 24 | using namespace llvm::object; |
| 25 | |
| 26 | static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags; |
| 27 | |
| 28 | // Returns the size of debug_str_offsets section headers in bytes. |
| 29 | static uint64_t (DataExtractor StrOffsetsData, |
| 30 | uint16_t DwarfVersion) { |
| 31 | if (DwarfVersion <= 4) |
| 32 | return 0; // There is no header before dwarf 5. |
| 33 | uint64_t Offset = 0; |
| 34 | uint64_t Length = StrOffsetsData.getU32(offset_ptr: &Offset); |
| 35 | if (Length == llvm::dwarf::DW_LENGTH_DWARF64) |
| 36 | return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes. |
| 37 | return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes. |
| 38 | } |
| 39 | |
| 40 | static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) { |
| 41 | uint64_t Offset = 0; |
| 42 | DataExtractor AbbrevData(Abbrev, true, 0); |
| 43 | while (AbbrevData.getULEB128(offset_ptr: &Offset) != AbbrCode) { |
| 44 | // Tag |
| 45 | AbbrevData.getULEB128(offset_ptr: &Offset); |
| 46 | // DW_CHILDREN |
| 47 | AbbrevData.getU8(offset_ptr: &Offset); |
| 48 | // Attributes |
| 49 | while (AbbrevData.getULEB128(offset_ptr: &Offset) | AbbrevData.getULEB128(offset_ptr: &Offset)) |
| 50 | ; |
| 51 | } |
| 52 | return Offset; |
| 53 | } |
| 54 | |
| 55 | static Expected<const char *> |
| 56 | (dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset, |
| 57 | StringRef StrOffsets, StringRef Str, uint16_t Version) { |
| 58 | if (Form == dwarf::DW_FORM_string) |
| 59 | return InfoData.getCStr(OffsetPtr: &InfoOffset); |
| 60 | uint64_t StrIndex; |
| 61 | switch (Form) { |
| 62 | case dwarf::DW_FORM_strx1: |
| 63 | StrIndex = InfoData.getU8(offset_ptr: &InfoOffset); |
| 64 | break; |
| 65 | case dwarf::DW_FORM_strx2: |
| 66 | StrIndex = InfoData.getU16(offset_ptr: &InfoOffset); |
| 67 | break; |
| 68 | case dwarf::DW_FORM_strx3: |
| 69 | StrIndex = InfoData.getU24(OffsetPtr: &InfoOffset); |
| 70 | break; |
| 71 | case dwarf::DW_FORM_strx4: |
| 72 | StrIndex = InfoData.getU32(offset_ptr: &InfoOffset); |
| 73 | break; |
| 74 | case dwarf::DW_FORM_strx: |
| 75 | case dwarf::DW_FORM_GNU_str_index: |
| 76 | StrIndex = InfoData.getULEB128(offset_ptr: &InfoOffset); |
| 77 | break; |
| 78 | default: |
| 79 | return make_error<DWPError>( |
| 80 | Args: "string field must be encoded with one of the following: " |
| 81 | "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, " |
| 82 | "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index." ); |
| 83 | } |
| 84 | DataExtractor StrOffsetsData(StrOffsets, true, 0); |
| 85 | uint64_t StrOffsetsOffset = 4 * StrIndex; |
| 86 | StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, DwarfVersion: Version); |
| 87 | |
| 88 | uint64_t StrOffset = StrOffsetsData.getU32(offset_ptr: &StrOffsetsOffset); |
| 89 | DataExtractor StrData(Str, true, 0); |
| 90 | return StrData.getCStr(OffsetPtr: &StrOffset); |
| 91 | } |
| 92 | |
| 93 | static Expected<CompileUnitIdentifiers> |
| 94 | (InfoSectionUnitHeader &, StringRef Abbrev, |
| 95 | StringRef Info, StringRef StrOffsets, StringRef Str) { |
| 96 | DataExtractor InfoData(Info, true, 0); |
| 97 | uint64_t Offset = Header.HeaderSize; |
| 98 | if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile) |
| 99 | return make_error<DWPError>( |
| 100 | Args: std::string("unit type DW_UT_split_compile type not found in " |
| 101 | "debug_info header. Unexpected unit type 0x" + |
| 102 | utostr(X: Header.UnitType) + " found" )); |
| 103 | |
| 104 | CompileUnitIdentifiers ID; |
| 105 | |
| 106 | uint32_t AbbrCode = InfoData.getULEB128(offset_ptr: &Offset); |
| 107 | DataExtractor AbbrevData(Abbrev, true, 0); |
| 108 | uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode); |
| 109 | auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(offset_ptr: &AbbrevOffset)); |
| 110 | if (Tag != dwarf::DW_TAG_compile_unit) |
| 111 | return make_error<DWPError>(Args: "top level DIE is not a compile unit" ); |
| 112 | // DW_CHILDREN |
| 113 | AbbrevData.getU8(offset_ptr: &AbbrevOffset); |
| 114 | uint32_t Name; |
| 115 | dwarf::Form Form; |
| 116 | while ((Name = AbbrevData.getULEB128(offset_ptr: &AbbrevOffset)) | |
| 117 | (Form = static_cast<dwarf::Form>( |
| 118 | AbbrevData.getULEB128(offset_ptr: &AbbrevOffset))) && |
| 119 | (Name != 0 || Form != 0)) { |
| 120 | switch (Name) { |
| 121 | case dwarf::DW_AT_name: { |
| 122 | Expected<const char *> EName = getIndexedString( |
| 123 | Form, InfoData, InfoOffset&: Offset, StrOffsets, Str, Version: Header.Version); |
| 124 | if (!EName) |
| 125 | return EName.takeError(); |
| 126 | ID.Name = *EName; |
| 127 | break; |
| 128 | } |
| 129 | case dwarf::DW_AT_GNU_dwo_name: |
| 130 | case dwarf::DW_AT_dwo_name: { |
| 131 | Expected<const char *> EName = getIndexedString( |
| 132 | Form, InfoData, InfoOffset&: Offset, StrOffsets, Str, Version: Header.Version); |
| 133 | if (!EName) |
| 134 | return EName.takeError(); |
| 135 | ID.DWOName = *EName; |
| 136 | break; |
| 137 | } |
| 138 | case dwarf::DW_AT_GNU_dwo_id: |
| 139 | Header.Signature = InfoData.getU64(offset_ptr: &Offset); |
| 140 | break; |
| 141 | default: |
| 142 | DWARFFormValue::skipValue( |
| 143 | Form, DebugInfoData: InfoData, OffsetPtr: &Offset, |
| 144 | FormParams: dwarf::FormParams({.Version: Header.Version, .AddrSize: Header.AddrSize, .Format: Header.Format})); |
| 145 | } |
| 146 | } |
| 147 | if (!Header.Signature) |
| 148 | return make_error<DWPError>(Args: "compile unit missing dwo_id" ); |
| 149 | ID.Signature = *Header.Signature; |
| 150 | return ID; |
| 151 | } |
| 152 | |
| 153 | static bool isSupportedSectionKind(DWARFSectionKind Kind) { |
| 154 | return Kind != DW_SECT_EXT_unknown; |
| 155 | } |
| 156 | |
| 157 | // Convert an internal section identifier into the index to use with |
| 158 | // UnitIndexEntry::Contributions. |
| 159 | static unsigned getContributionIndex(DWARFSectionKind Kind, |
| 160 | uint32_t IndexVersion) { |
| 161 | assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO); |
| 162 | return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO; |
| 163 | } |
| 164 | |
| 165 | // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk |
| 166 | // value of the section identifier. |
| 167 | static unsigned getOnDiskSectionId(unsigned Index) { |
| 168 | return Index + DW_SECT_INFO; |
| 169 | } |
| 170 | |
| 171 | static StringRef getSubsection(StringRef Section, |
| 172 | const DWARFUnitIndex::Entry &Entry, |
| 173 | DWARFSectionKind Kind) { |
| 174 | const auto *Off = Entry.getContribution(Sec: Kind); |
| 175 | if (!Off) |
| 176 | return StringRef(); |
| 177 | return Section.substr(Start: Off->getOffset(), N: Off->getLength()); |
| 178 | } |
| 179 | |
| 180 | static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset, |
| 181 | uint32_t OverflowedOffset, |
| 182 | StringRef SectionName, |
| 183 | OnCuIndexOverflow OverflowOptValue, |
| 184 | bool &AnySectionOverflow) { |
| 185 | std::string Msg = |
| 186 | (SectionName + |
| 187 | Twine(" Section Contribution Offset overflow 4G. Previous Offset " ) + |
| 188 | Twine(PrevOffset) + Twine(", After overflow offset " ) + |
| 189 | Twine(OverflowedOffset) + Twine("." )) |
| 190 | .str(); |
| 191 | if (OverflowOptValue == OnCuIndexOverflow::Continue) { |
| 192 | WithColor::defaultWarningHandler(Warning: make_error<DWPError>(Args&: Msg)); |
| 193 | return Error::success(); |
| 194 | } else if (OverflowOptValue == OnCuIndexOverflow::SoftStop) { |
| 195 | AnySectionOverflow = true; |
| 196 | WithColor::defaultWarningHandler(Warning: make_error<DWPError>(Args&: Msg)); |
| 197 | return Error::success(); |
| 198 | } |
| 199 | return make_error<DWPError>(Args&: Msg); |
| 200 | } |
| 201 | |
| 202 | static Error addAllTypesFromDWP( |
| 203 | MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, |
| 204 | const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types, |
| 205 | const UnitIndexEntry &TUEntry, uint32_t &TypesOffset, |
| 206 | unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue, |
| 207 | bool &AnySectionOverflow) { |
| 208 | Out.switchSection(Section: OutputTypes); |
| 209 | for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) { |
| 210 | auto *I = E.getContributions(); |
| 211 | if (!I) |
| 212 | continue; |
| 213 | auto P = TypeIndexEntries.insert(KV: std::make_pair(x: E.getSignature(), y: TUEntry)); |
| 214 | if (!P.second) |
| 215 | continue; |
| 216 | auto &Entry = P.first->second; |
| 217 | // Zero out the debug_info contribution |
| 218 | Entry.Contributions[0] = {}; |
| 219 | for (auto Kind : TUIndex.getColumnKinds()) { |
| 220 | if (!isSupportedSectionKind(Kind)) |
| 221 | continue; |
| 222 | auto &C = |
| 223 | Entry.Contributions[getContributionIndex(Kind, IndexVersion: TUIndex.getVersion())]; |
| 224 | C.setOffset(C.getOffset() + I->getOffset()); |
| 225 | C.setLength(I->getLength()); |
| 226 | ++I; |
| 227 | } |
| 228 | auto &C = Entry.Contributions[TypesContributionIndex]; |
| 229 | Out.emitBytes(Data: Types.substr( |
| 230 | Start: C.getOffset() - |
| 231 | TUEntry.Contributions[TypesContributionIndex].getOffset(), |
| 232 | N: C.getLength())); |
| 233 | C.setOffset(TypesOffset); |
| 234 | uint32_t OldOffset = TypesOffset; |
| 235 | static_assert(sizeof(OldOffset) == sizeof(TypesOffset)); |
| 236 | TypesOffset += C.getLength(); |
| 237 | if (OldOffset > TypesOffset) { |
| 238 | if (Error Err = sectionOverflowErrorOrWarning(PrevOffset: OldOffset, OverflowedOffset: TypesOffset, |
| 239 | SectionName: "Types" , OverflowOptValue, |
| 240 | AnySectionOverflow)) |
| 241 | return Err; |
| 242 | if (AnySectionOverflow) { |
| 243 | TypesOffset = OldOffset; |
| 244 | return Error::success(); |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | return Error::success(); |
| 249 | } |
| 250 | |
| 251 | static Error addAllTypesFromTypesSection( |
| 252 | MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries, |
| 253 | MCSection *OutputTypes, const std::vector<StringRef> &TypesSections, |
| 254 | const UnitIndexEntry &CUEntry, uint32_t &TypesOffset, |
| 255 | OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow) { |
| 256 | for (StringRef Types : TypesSections) { |
| 257 | Out.switchSection(Section: OutputTypes); |
| 258 | uint64_t Offset = 0; |
| 259 | DataExtractor Data(Types, true, 0); |
| 260 | while (Data.isValidOffset(offset: Offset)) { |
| 261 | UnitIndexEntry Entry = CUEntry; |
| 262 | // Zero out the debug_info contribution |
| 263 | Entry.Contributions[0] = {}; |
| 264 | auto &C = Entry.Contributions[getContributionIndex(Kind: DW_SECT_EXT_TYPES, IndexVersion: 2)]; |
| 265 | C.setOffset(TypesOffset); |
| 266 | auto PrevOffset = Offset; |
| 267 | // Length of the unit, including the 4 byte length field. |
| 268 | C.setLength(Data.getU32(offset_ptr: &Offset) + 4); |
| 269 | |
| 270 | Data.getU16(offset_ptr: &Offset); // Version |
| 271 | Data.getU32(offset_ptr: &Offset); // Abbrev offset |
| 272 | Data.getU8(offset_ptr: &Offset); // Address size |
| 273 | auto Signature = Data.getU64(offset_ptr: &Offset); |
| 274 | Offset = PrevOffset + C.getLength32(); |
| 275 | |
| 276 | auto P = TypeIndexEntries.insert(KV: std::make_pair(x&: Signature, y&: Entry)); |
| 277 | if (!P.second) |
| 278 | continue; |
| 279 | |
| 280 | Out.emitBytes(Data: Types.substr(Start: PrevOffset, N: C.getLength32())); |
| 281 | uint32_t OldOffset = TypesOffset; |
| 282 | TypesOffset += C.getLength32(); |
| 283 | if (OldOffset > TypesOffset) { |
| 284 | if (Error Err = sectionOverflowErrorOrWarning(PrevOffset: OldOffset, OverflowedOffset: TypesOffset, |
| 285 | SectionName: "Types" , OverflowOptValue, |
| 286 | AnySectionOverflow)) |
| 287 | return Err; |
| 288 | if (AnySectionOverflow) { |
| 289 | TypesOffset = OldOffset; |
| 290 | return Error::success(); |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | } |
| 295 | return Error::success(); |
| 296 | } |
| 297 | |
| 298 | static std::string buildDWODescription(StringRef Name, StringRef DWPName, |
| 299 | StringRef DWOName) { |
| 300 | std::string Text = "\'" ; |
| 301 | Text += Name; |
| 302 | Text += '\''; |
| 303 | bool HasDWO = !DWOName.empty(); |
| 304 | bool HasDWP = !DWPName.empty(); |
| 305 | if (HasDWO || HasDWP) { |
| 306 | Text += " (from " ; |
| 307 | if (HasDWO) { |
| 308 | Text += '\''; |
| 309 | Text += DWOName; |
| 310 | Text += '\''; |
| 311 | } |
| 312 | if (HasDWO && HasDWP) |
| 313 | Text += " in " ; |
| 314 | if (!DWPName.empty()) { |
| 315 | Text += '\''; |
| 316 | Text += DWPName; |
| 317 | Text += '\''; |
| 318 | } |
| 319 | Text += ")" ; |
| 320 | } |
| 321 | return Text; |
| 322 | } |
| 323 | |
| 324 | static Error createError(StringRef Name, Error E) { |
| 325 | return make_error<DWPError>( |
| 326 | Args: ("failure while decompressing compressed section: '" + Name + "', " + |
| 327 | llvm::toString(E: std::move(E))) |
| 328 | .str()); |
| 329 | } |
| 330 | |
| 331 | static Error |
| 332 | handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections, |
| 333 | SectionRef Sec, StringRef Name, StringRef &Contents) { |
| 334 | auto *Obj = dyn_cast<ELFObjectFileBase>(Val: Sec.getObject()); |
| 335 | if (!Obj || |
| 336 | !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED)) |
| 337 | return Error::success(); |
| 338 | bool IsLE = isa<object::ELF32LEObjectFile>(Val: Obj) || |
| 339 | isa<object::ELF64LEObjectFile>(Val: Obj); |
| 340 | bool Is64 = isa<object::ELF64LEObjectFile>(Val: Obj) || |
| 341 | isa<object::ELF64BEObjectFile>(Val: Obj); |
| 342 | Expected<Decompressor> Dec = Decompressor::create(Name, Data: Contents, IsLE, Is64Bit: Is64); |
| 343 | if (!Dec) |
| 344 | return createError(Name, E: Dec.takeError()); |
| 345 | |
| 346 | UncompressedSections.emplace_back(); |
| 347 | if (Error E = Dec->resizeAndDecompress(Out&: UncompressedSections.back())) |
| 348 | return createError(Name, E: std::move(E)); |
| 349 | |
| 350 | Contents = UncompressedSections.back(); |
| 351 | return Error::success(); |
| 352 | } |
| 353 | |
| 354 | namespace llvm { |
| 355 | // Parse and return the header of an info section compile/type unit. |
| 356 | Expected<InfoSectionUnitHeader> (StringRef Info) { |
| 357 | InfoSectionUnitHeader ; |
| 358 | Error Err = Error::success(); |
| 359 | uint64_t Offset = 0; |
| 360 | DWARFDataExtractor InfoData(Info, true, 0); |
| 361 | std::tie(args&: Header.Length, args&: Header.Format) = |
| 362 | InfoData.getInitialLength(Off: &Offset, Err: &Err); |
| 363 | if (Err) |
| 364 | return make_error<DWPError>(Args: "cannot parse compile unit length: " + |
| 365 | llvm::toString(E: std::move(Err))); |
| 366 | |
| 367 | if (!InfoData.isValidOffset(offset: Offset + (Header.Length - 1))) { |
| 368 | return make_error<DWPError>( |
| 369 | Args: "compile unit exceeds .debug_info section range: " + |
| 370 | utostr(X: Offset + Header.Length) + " >= " + utostr(X: InfoData.size())); |
| 371 | } |
| 372 | |
| 373 | Header.Version = InfoData.getU16(offset_ptr: &Offset, Err: &Err); |
| 374 | if (Err) |
| 375 | return make_error<DWPError>(Args: "cannot parse compile unit version: " + |
| 376 | llvm::toString(E: std::move(Err))); |
| 377 | |
| 378 | uint64_t ; |
| 379 | if (Header.Version >= 5) { |
| 380 | // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4), |
| 381 | // Signature (8) |
| 382 | MinHeaderLength = 16; |
| 383 | } else { |
| 384 | // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1) |
| 385 | MinHeaderLength = 7; |
| 386 | } |
| 387 | if (Header.Length < MinHeaderLength) { |
| 388 | return make_error<DWPError>(Args: "unit length is too small: expected at least " + |
| 389 | utostr(X: MinHeaderLength) + " got " + |
| 390 | utostr(X: Header.Length) + "." ); |
| 391 | } |
| 392 | if (Header.Version >= 5) { |
| 393 | Header.UnitType = InfoData.getU8(offset_ptr: &Offset); |
| 394 | Header.AddrSize = InfoData.getU8(offset_ptr: &Offset); |
| 395 | Header.DebugAbbrevOffset = InfoData.getU32(offset_ptr: &Offset); |
| 396 | Header.Signature = InfoData.getU64(offset_ptr: &Offset); |
| 397 | if (Header.UnitType == dwarf::DW_UT_split_type) { |
| 398 | // Type offset. |
| 399 | MinHeaderLength += 4; |
| 400 | if (Header.Length < MinHeaderLength) |
| 401 | return make_error<DWPError>(Args: "type unit is missing type offset" ); |
| 402 | InfoData.getU32(offset_ptr: &Offset); |
| 403 | } |
| 404 | } else { |
| 405 | // Note that, address_size and debug_abbrev_offset fields have switched |
| 406 | // places between dwarf version 4 and 5. |
| 407 | Header.DebugAbbrevOffset = InfoData.getU32(offset_ptr: &Offset); |
| 408 | Header.AddrSize = InfoData.getU8(offset_ptr: &Offset); |
| 409 | } |
| 410 | |
| 411 | Header.HeaderSize = Offset; |
| 412 | return Header; |
| 413 | } |
| 414 | |
| 415 | static void (MCStreamer &Out, DataExtractor &Data, |
| 416 | DenseMap<uint64_t, uint32_t> &OffsetRemapping, |
| 417 | uint64_t &Offset, uint64_t &Size) { |
| 418 | |
| 419 | while (Offset < Size) { |
| 420 | auto OldOffset = Data.getU32(offset_ptr: &Offset); |
| 421 | auto NewOffset = OffsetRemapping[OldOffset]; |
| 422 | Out.emitIntValue(Value: NewOffset, Size: 4); |
| 423 | } |
| 424 | } |
| 425 | |
| 426 | void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings, |
| 427 | MCSection *StrOffsetSection, |
| 428 | StringRef CurStrSection, |
| 429 | StringRef CurStrOffsetSection, uint16_t Version) { |
| 430 | // Could possibly produce an error or warning if one of these was non-null but |
| 431 | // the other was null. |
| 432 | if (CurStrSection.empty() || CurStrOffsetSection.empty()) |
| 433 | return; |
| 434 | |
| 435 | DenseMap<uint64_t, uint32_t> OffsetRemapping; |
| 436 | |
| 437 | DataExtractor Data(CurStrSection, true, 0); |
| 438 | uint64_t LocalOffset = 0; |
| 439 | uint64_t PrevOffset = 0; |
| 440 | while (const char *S = Data.getCStr(OffsetPtr: &LocalOffset)) { |
| 441 | OffsetRemapping[PrevOffset] = |
| 442 | Strings.getOffset(Str: S, Length: LocalOffset - PrevOffset); |
| 443 | PrevOffset = LocalOffset; |
| 444 | } |
| 445 | |
| 446 | Data = DataExtractor(CurStrOffsetSection, true, 0); |
| 447 | |
| 448 | Out.switchSection(Section: StrOffsetSection); |
| 449 | |
| 450 | uint64_t Offset = 0; |
| 451 | uint64_t Size = CurStrOffsetSection.size(); |
| 452 | if (Version > 4) { |
| 453 | while (Offset < Size) { |
| 454 | uint64_t = debugStrOffsetsHeaderSize(StrOffsetsData: Data, DwarfVersion: Version); |
| 455 | assert(HeaderSize <= Size - Offset && |
| 456 | "StrOffsetSection size is less than its header" ); |
| 457 | |
| 458 | uint64_t ContributionEnd = 0; |
| 459 | uint64_t ContributionSize = 0; |
| 460 | uint64_t = Offset; |
| 461 | if (HeaderSize == 8) { |
| 462 | ContributionSize = Data.getU32(offset_ptr: &HeaderLengthOffset); |
| 463 | } else if (HeaderSize == 16) { |
| 464 | HeaderLengthOffset += 4; // skip the dwarf64 marker |
| 465 | ContributionSize = Data.getU64(offset_ptr: &HeaderLengthOffset); |
| 466 | } |
| 467 | ContributionEnd = ContributionSize + HeaderLengthOffset; |
| 468 | Out.emitBytes(Data: Data.getBytes(OffsetPtr: &Offset, Length: HeaderSize)); |
| 469 | writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size&: ContributionEnd); |
| 470 | } |
| 471 | |
| 472 | } else { |
| 473 | writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size); |
| 474 | } |
| 475 | } |
| 476 | |
| 477 | enum AccessField { Offset, Length }; |
| 478 | void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets, |
| 479 | const MapVector<uint64_t, UnitIndexEntry> &IndexEntries, |
| 480 | const AccessField &Field) { |
| 481 | for (const auto &E : IndexEntries) |
| 482 | for (size_t I = 0; I != std::size(E.second.Contributions); ++I) |
| 483 | if (ContributionOffsets[I]) |
| 484 | Out.emitIntValue(Value: (Field == AccessField::Offset |
| 485 | ? E.second.Contributions[I].getOffset32() |
| 486 | : E.second.Contributions[I].getLength32()), |
| 487 | Size: 4); |
| 488 | } |
| 489 | |
| 490 | void writeIndex(MCStreamer &Out, MCSection *Section, |
| 491 | ArrayRef<unsigned> ContributionOffsets, |
| 492 | const MapVector<uint64_t, UnitIndexEntry> &IndexEntries, |
| 493 | uint32_t IndexVersion) { |
| 494 | if (IndexEntries.empty()) |
| 495 | return; |
| 496 | |
| 497 | unsigned Columns = 0; |
| 498 | for (auto &C : ContributionOffsets) |
| 499 | if (C) |
| 500 | ++Columns; |
| 501 | |
| 502 | std::vector<unsigned> Buckets(NextPowerOf2(A: 3 * IndexEntries.size() / 2)); |
| 503 | uint64_t Mask = Buckets.size() - 1; |
| 504 | size_t I = 0; |
| 505 | for (const auto &P : IndexEntries) { |
| 506 | auto S = P.first; |
| 507 | auto H = S & Mask; |
| 508 | auto HP = ((S >> 32) & Mask) | 1; |
| 509 | while (Buckets[H]) { |
| 510 | assert(S != IndexEntries.begin()[Buckets[H] - 1].first && |
| 511 | "Duplicate unit" ); |
| 512 | H = (H + HP) & Mask; |
| 513 | } |
| 514 | Buckets[H] = I + 1; |
| 515 | ++I; |
| 516 | } |
| 517 | |
| 518 | Out.switchSection(Section); |
| 519 | Out.emitIntValue(Value: IndexVersion, Size: 4); // Version |
| 520 | Out.emitIntValue(Value: Columns, Size: 4); // Columns |
| 521 | Out.emitIntValue(Value: IndexEntries.size(), Size: 4); // Num Units |
| 522 | Out.emitIntValue(Value: Buckets.size(), Size: 4); // Num Buckets |
| 523 | |
| 524 | // Write the signatures. |
| 525 | for (const auto &I : Buckets) |
| 526 | Out.emitIntValue(Value: I ? IndexEntries.begin()[I - 1].first : 0, Size: 8); |
| 527 | |
| 528 | // Write the indexes. |
| 529 | for (const auto &I : Buckets) |
| 530 | Out.emitIntValue(Value: I, Size: 4); |
| 531 | |
| 532 | // Write the column headers (which sections will appear in the table) |
| 533 | for (size_t I = 0; I != ContributionOffsets.size(); ++I) |
| 534 | if (ContributionOffsets[I]) |
| 535 | Out.emitIntValue(Value: getOnDiskSectionId(Index: I), Size: 4); |
| 536 | |
| 537 | // Write the offsets. |
| 538 | writeIndexTable(Out, ContributionOffsets, IndexEntries, Field: AccessField::Offset); |
| 539 | |
| 540 | // Write the lengths. |
| 541 | writeIndexTable(Out, ContributionOffsets, IndexEntries, Field: AccessField::Length); |
| 542 | } |
| 543 | |
| 544 | Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE, |
| 545 | const CompileUnitIdentifiers &ID, StringRef DWPName) { |
| 546 | return make_error<DWPError>( |
| 547 | Args: std::string("duplicate DWO ID (" ) + utohexstr(X: PrevE.first) + ") in " + |
| 548 | buildDWODescription(Name: PrevE.second.Name, DWPName: PrevE.second.DWPName, |
| 549 | DWOName: PrevE.second.DWOName) + |
| 550 | " and " + buildDWODescription(Name: ID.Name, DWPName, DWOName: ID.DWOName)); |
| 551 | } |
| 552 | |
| 553 | Error handleSection( |
| 554 | const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections, |
| 555 | const MCSection *StrSection, const MCSection *StrOffsetSection, |
| 556 | const MCSection *TypesSection, const MCSection *CUIndexSection, |
| 557 | const MCSection *TUIndexSection, const MCSection *InfoSection, |
| 558 | const SectionRef &Section, MCStreamer &Out, |
| 559 | std::deque<SmallString<32>> &UncompressedSections, |
| 560 | uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry, |
| 561 | StringRef &CurStrSection, StringRef &CurStrOffsetSection, |
| 562 | std::vector<StringRef> &CurTypesSection, |
| 563 | std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection, |
| 564 | StringRef &CurCUIndexSection, StringRef &CurTUIndexSection, |
| 565 | std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) { |
| 566 | if (Section.isBSS()) |
| 567 | return Error::success(); |
| 568 | |
| 569 | if (Section.isVirtual()) |
| 570 | return Error::success(); |
| 571 | |
| 572 | Expected<StringRef> NameOrErr = Section.getName(); |
| 573 | if (!NameOrErr) |
| 574 | return NameOrErr.takeError(); |
| 575 | StringRef Name = *NameOrErr; |
| 576 | |
| 577 | Expected<StringRef> ContentsOrErr = Section.getContents(); |
| 578 | if (!ContentsOrErr) |
| 579 | return ContentsOrErr.takeError(); |
| 580 | StringRef Contents = *ContentsOrErr; |
| 581 | |
| 582 | if (auto Err = handleCompressedSection(UncompressedSections, Sec: Section, Name, |
| 583 | Contents)) |
| 584 | return Err; |
| 585 | |
| 586 | Name = Name.substr(Start: Name.find_first_not_of(Chars: "._" )); |
| 587 | |
| 588 | auto SectionPair = KnownSections.find(Key: Name); |
| 589 | if (SectionPair == KnownSections.end()) |
| 590 | return Error::success(); |
| 591 | |
| 592 | if (DWARFSectionKind Kind = SectionPair->second.second) { |
| 593 | if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) { |
| 594 | SectionLength.push_back(x: std::make_pair(x&: Kind, y: Contents.size())); |
| 595 | } |
| 596 | |
| 597 | if (Kind == DW_SECT_ABBREV) { |
| 598 | AbbrevSection = Contents; |
| 599 | } |
| 600 | } |
| 601 | |
| 602 | MCSection *OutSection = SectionPair->second.first; |
| 603 | if (OutSection == StrOffsetSection) |
| 604 | CurStrOffsetSection = Contents; |
| 605 | else if (OutSection == StrSection) |
| 606 | CurStrSection = Contents; |
| 607 | else if (OutSection == TypesSection) |
| 608 | CurTypesSection.push_back(x: Contents); |
| 609 | else if (OutSection == CUIndexSection) |
| 610 | CurCUIndexSection = Contents; |
| 611 | else if (OutSection == TUIndexSection) |
| 612 | CurTUIndexSection = Contents; |
| 613 | else if (OutSection == InfoSection) |
| 614 | CurInfoSection.push_back(x: Contents); |
| 615 | else { |
| 616 | Out.switchSection(Section: OutSection); |
| 617 | Out.emitBytes(Data: Contents); |
| 618 | } |
| 619 | return Error::success(); |
| 620 | } |
| 621 | |
| 622 | Error write(MCStreamer &Out, ArrayRef<std::string> Inputs, |
| 623 | OnCuIndexOverflow OverflowOptValue) { |
| 624 | const auto &MCOFI = *Out.getContext().getObjectFileInfo(); |
| 625 | MCSection *const StrSection = MCOFI.getDwarfStrDWOSection(); |
| 626 | MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection(); |
| 627 | MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection(); |
| 628 | MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection(); |
| 629 | MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection(); |
| 630 | MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection(); |
| 631 | const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = { |
| 632 | {"debug_info.dwo" , {InfoSection, DW_SECT_INFO}}, |
| 633 | {"debug_types.dwo" , {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}}, |
| 634 | {"debug_str_offsets.dwo" , {StrOffsetSection, DW_SECT_STR_OFFSETS}}, |
| 635 | {"debug_str.dwo" , {StrSection, static_cast<DWARFSectionKind>(0)}}, |
| 636 | {"debug_loc.dwo" , {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}}, |
| 637 | {"debug_line.dwo" , {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}}, |
| 638 | {"debug_macro.dwo" , {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}}, |
| 639 | {"debug_abbrev.dwo" , {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}}, |
| 640 | {"debug_loclists.dwo" , |
| 641 | {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}}, |
| 642 | {"debug_rnglists.dwo" , |
| 643 | {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}}, |
| 644 | {"debug_cu_index" , {CUIndexSection, static_cast<DWARFSectionKind>(0)}}, |
| 645 | {"debug_tu_index" , {TUIndexSection, static_cast<DWARFSectionKind>(0)}}}; |
| 646 | |
| 647 | MapVector<uint64_t, UnitIndexEntry> IndexEntries; |
| 648 | MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries; |
| 649 | |
| 650 | uint32_t ContributionOffsets[8] = {}; |
| 651 | uint16_t Version = 0; |
| 652 | uint32_t IndexVersion = 0; |
| 653 | bool AnySectionOverflow = false; |
| 654 | |
| 655 | DWPStringPool Strings(Out, StrSection); |
| 656 | |
| 657 | SmallVector<OwningBinary<object::ObjectFile>, 128> Objects; |
| 658 | Objects.reserve(N: Inputs.size()); |
| 659 | |
| 660 | std::deque<SmallString<32>> UncompressedSections; |
| 661 | |
| 662 | for (const auto &Input : Inputs) { |
| 663 | auto ErrOrObj = object::ObjectFile::createObjectFile(ObjectPath: Input); |
| 664 | if (!ErrOrObj) { |
| 665 | return handleErrors(E: ErrOrObj.takeError(), |
| 666 | Hs: [&](std::unique_ptr<ECError> EC) -> Error { |
| 667 | return createFileError(F: Input, E: Error(std::move(EC))); |
| 668 | }); |
| 669 | } |
| 670 | |
| 671 | auto &Obj = *ErrOrObj->getBinary(); |
| 672 | Objects.push_back(Elt: std::move(*ErrOrObj)); |
| 673 | |
| 674 | UnitIndexEntry CurEntry = {}; |
| 675 | |
| 676 | StringRef CurStrSection; |
| 677 | StringRef CurStrOffsetSection; |
| 678 | std::vector<StringRef> CurTypesSection; |
| 679 | std::vector<StringRef> CurInfoSection; |
| 680 | StringRef AbbrevSection; |
| 681 | StringRef CurCUIndexSection; |
| 682 | StringRef CurTUIndexSection; |
| 683 | |
| 684 | // This maps each section contained in this file to its length. |
| 685 | // This information is later on used to calculate the contributions, |
| 686 | // i.e. offset and length, of each compile/type unit to a section. |
| 687 | std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength; |
| 688 | |
| 689 | for (const auto &Section : Obj.sections()) |
| 690 | if (auto Err = handleSection( |
| 691 | KnownSections, StrSection, StrOffsetSection, TypesSection, |
| 692 | CUIndexSection, TUIndexSection, InfoSection, Section, Out, |
| 693 | UncompressedSections, ContributionOffsets, CurEntry, |
| 694 | CurStrSection, CurStrOffsetSection, CurTypesSection, |
| 695 | CurInfoSection, AbbrevSection, CurCUIndexSection, |
| 696 | CurTUIndexSection, SectionLength)) |
| 697 | return Err; |
| 698 | |
| 699 | if (CurInfoSection.empty()) |
| 700 | continue; |
| 701 | |
| 702 | Expected<InfoSectionUnitHeader> = |
| 703 | parseInfoSectionUnitHeader(Info: CurInfoSection.front()); |
| 704 | if (!HeaderOrErr) |
| 705 | return HeaderOrErr.takeError(); |
| 706 | InfoSectionUnitHeader & = *HeaderOrErr; |
| 707 | |
| 708 | if (Version == 0) { |
| 709 | Version = Header.Version; |
| 710 | IndexVersion = Version < 5 ? 2 : 5; |
| 711 | } else if (Version != Header.Version) { |
| 712 | return make_error<DWPError>(Args: "incompatible DWARF compile unit versions." ); |
| 713 | } |
| 714 | |
| 715 | writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection, |
| 716 | CurStrOffsetSection, Version: Header.Version); |
| 717 | |
| 718 | for (auto Pair : SectionLength) { |
| 719 | auto Index = getContributionIndex(Kind: Pair.first, IndexVersion); |
| 720 | CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]); |
| 721 | CurEntry.Contributions[Index].setLength(Pair.second); |
| 722 | uint32_t OldOffset = ContributionOffsets[Index]; |
| 723 | ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32(); |
| 724 | if (OldOffset > ContributionOffsets[Index]) { |
| 725 | uint32_t SectionIndex = 0; |
| 726 | for (auto &Section : Obj.sections()) { |
| 727 | if (SectionIndex == Index) { |
| 728 | if (Error Err = sectionOverflowErrorOrWarning( |
| 729 | PrevOffset: OldOffset, OverflowedOffset: ContributionOffsets[Index], SectionName: *Section.getName(), |
| 730 | OverflowOptValue, AnySectionOverflow)) |
| 731 | return Err; |
| 732 | } |
| 733 | ++SectionIndex; |
| 734 | } |
| 735 | if (AnySectionOverflow) |
| 736 | break; |
| 737 | } |
| 738 | } |
| 739 | |
| 740 | uint32_t &InfoSectionOffset = |
| 741 | ContributionOffsets[getContributionIndex(Kind: DW_SECT_INFO, IndexVersion)]; |
| 742 | if (CurCUIndexSection.empty()) { |
| 743 | bool FoundCUUnit = false; |
| 744 | Out.switchSection(Section: InfoSection); |
| 745 | for (StringRef Info : CurInfoSection) { |
| 746 | uint64_t UnitOffset = 0; |
| 747 | while (Info.size() > UnitOffset) { |
| 748 | Expected<InfoSectionUnitHeader> = |
| 749 | parseInfoSectionUnitHeader(Info: Info.substr(Start: UnitOffset, N: Info.size())); |
| 750 | if (!HeaderOrError) |
| 751 | return HeaderOrError.takeError(); |
| 752 | InfoSectionUnitHeader & = *HeaderOrError; |
| 753 | |
| 754 | UnitIndexEntry Entry = CurEntry; |
| 755 | auto &C = Entry.Contributions[getContributionIndex(Kind: DW_SECT_INFO, |
| 756 | IndexVersion)]; |
| 757 | C.setOffset(InfoSectionOffset); |
| 758 | C.setLength(Header.Length + 4); |
| 759 | |
| 760 | if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset < |
| 761 | C.getLength32()) { |
| 762 | if (Error Err = sectionOverflowErrorOrWarning( |
| 763 | PrevOffset: InfoSectionOffset, OverflowedOffset: InfoSectionOffset + C.getLength32(), |
| 764 | SectionName: "debug_info" , OverflowOptValue, AnySectionOverflow)) |
| 765 | return Err; |
| 766 | if (AnySectionOverflow) { |
| 767 | if (Header.Version < 5 || |
| 768 | Header.UnitType == dwarf::DW_UT_split_compile) |
| 769 | FoundCUUnit = true; |
| 770 | break; |
| 771 | } |
| 772 | } |
| 773 | |
| 774 | UnitOffset += C.getLength32(); |
| 775 | if (Header.Version < 5 || |
| 776 | Header.UnitType == dwarf::DW_UT_split_compile) { |
| 777 | Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( |
| 778 | Header, Abbrev: AbbrevSection, |
| 779 | Info: Info.substr(Start: UnitOffset - C.getLength32(), N: C.getLength32()), |
| 780 | StrOffsets: CurStrOffsetSection, Str: CurStrSection); |
| 781 | |
| 782 | if (!EID) |
| 783 | return createFileError(F: Input, E: EID.takeError()); |
| 784 | const auto &ID = *EID; |
| 785 | auto P = IndexEntries.insert(KV: std::make_pair(x: ID.Signature, y&: Entry)); |
| 786 | if (!P.second) |
| 787 | return buildDuplicateError(PrevE: *P.first, ID, DWPName: "" ); |
| 788 | P.first->second.Name = ID.Name; |
| 789 | P.first->second.DWOName = ID.DWOName; |
| 790 | |
| 791 | FoundCUUnit = true; |
| 792 | } else if (Header.UnitType == dwarf::DW_UT_split_type) { |
| 793 | auto P = TypeIndexEntries.insert( |
| 794 | KV: std::make_pair(x&: *Header.Signature, y&: Entry)); |
| 795 | if (!P.second) |
| 796 | continue; |
| 797 | } |
| 798 | Out.emitBytes( |
| 799 | Data: Info.substr(Start: UnitOffset - C.getLength32(), N: C.getLength32())); |
| 800 | InfoSectionOffset += C.getLength32(); |
| 801 | } |
| 802 | if (AnySectionOverflow) |
| 803 | break; |
| 804 | } |
| 805 | |
| 806 | if (!FoundCUUnit) |
| 807 | return make_error<DWPError>(Args: "no compile unit found in file: " + Input); |
| 808 | |
| 809 | if (IndexVersion == 2) { |
| 810 | // Add types from the .debug_types section from DWARF < 5. |
| 811 | if (Error Err = addAllTypesFromTypesSection( |
| 812 | Out, TypeIndexEntries, OutputTypes: TypesSection, TypesSections: CurTypesSection, CUEntry: CurEntry, |
| 813 | TypesOffset&: ContributionOffsets[getContributionIndex(Kind: DW_SECT_EXT_TYPES, IndexVersion: 2)], |
| 814 | OverflowOptValue, AnySectionOverflow)) |
| 815 | return Err; |
| 816 | } |
| 817 | if (AnySectionOverflow) |
| 818 | break; |
| 819 | continue; |
| 820 | } |
| 821 | |
| 822 | if (CurInfoSection.size() != 1) |
| 823 | return make_error<DWPError>(Args: "expected exactly one occurrence of a debug " |
| 824 | "info section in a .dwp file" ); |
| 825 | StringRef DwpSingleInfoSection = CurInfoSection.front(); |
| 826 | |
| 827 | DWARFUnitIndex CUIndex(DW_SECT_INFO); |
| 828 | DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0); |
| 829 | if (!CUIndex.parse(IndexData: CUIndexData)) |
| 830 | return make_error<DWPError>(Args: "failed to parse cu_index" ); |
| 831 | if (CUIndex.getVersion() != IndexVersion) |
| 832 | return make_error<DWPError>(Args: "incompatible cu_index versions, found " + |
| 833 | utostr(X: CUIndex.getVersion()) + |
| 834 | " and expecting " + utostr(X: IndexVersion)); |
| 835 | |
| 836 | Out.switchSection(Section: InfoSection); |
| 837 | for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) { |
| 838 | auto *I = E.getContributions(); |
| 839 | if (!I) |
| 840 | continue; |
| 841 | auto P = IndexEntries.insert(KV: std::make_pair(x: E.getSignature(), y&: CurEntry)); |
| 842 | StringRef CUInfoSection = |
| 843 | getSubsection(Section: DwpSingleInfoSection, Entry: E, Kind: DW_SECT_INFO); |
| 844 | Expected<InfoSectionUnitHeader> = |
| 845 | parseInfoSectionUnitHeader(Info: CUInfoSection); |
| 846 | if (!HeaderOrError) |
| 847 | return HeaderOrError.takeError(); |
| 848 | InfoSectionUnitHeader & = *HeaderOrError; |
| 849 | |
| 850 | Expected<CompileUnitIdentifiers> EID = getCUIdentifiers( |
| 851 | Header, Abbrev: getSubsection(Section: AbbrevSection, Entry: E, Kind: DW_SECT_ABBREV), |
| 852 | Info: CUInfoSection, |
| 853 | StrOffsets: getSubsection(Section: CurStrOffsetSection, Entry: E, Kind: DW_SECT_STR_OFFSETS), |
| 854 | Str: CurStrSection); |
| 855 | if (!EID) |
| 856 | return createFileError(F: Input, E: EID.takeError()); |
| 857 | const auto &ID = *EID; |
| 858 | if (!P.second) |
| 859 | return buildDuplicateError(PrevE: *P.first, ID, DWPName: Input); |
| 860 | auto &NewEntry = P.first->second; |
| 861 | NewEntry.Name = ID.Name; |
| 862 | NewEntry.DWOName = ID.DWOName; |
| 863 | NewEntry.DWPName = Input; |
| 864 | for (auto Kind : CUIndex.getColumnKinds()) { |
| 865 | if (!isSupportedSectionKind(Kind)) |
| 866 | continue; |
| 867 | auto &C = |
| 868 | NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)]; |
| 869 | C.setOffset(C.getOffset() + I->getOffset()); |
| 870 | C.setLength(I->getLength()); |
| 871 | ++I; |
| 872 | } |
| 873 | unsigned Index = getContributionIndex(Kind: DW_SECT_INFO, IndexVersion); |
| 874 | auto &C = NewEntry.Contributions[Index]; |
| 875 | Out.emitBytes(Data: CUInfoSection); |
| 876 | C.setOffset(InfoSectionOffset); |
| 877 | InfoSectionOffset += C.getLength32(); |
| 878 | } |
| 879 | |
| 880 | if (!CurTUIndexSection.empty()) { |
| 881 | llvm::DWARFSectionKind TUSectionKind; |
| 882 | MCSection *OutSection; |
| 883 | StringRef TypeInputSection; |
| 884 | // Write type units into debug info section for DWARFv5. |
| 885 | if (Version >= 5) { |
| 886 | TUSectionKind = DW_SECT_INFO; |
| 887 | OutSection = InfoSection; |
| 888 | TypeInputSection = DwpSingleInfoSection; |
| 889 | } else { |
| 890 | // Write type units into debug types section for DWARF < 5. |
| 891 | if (CurTypesSection.size() != 1) |
| 892 | return make_error<DWPError>( |
| 893 | Args: "multiple type unit sections in .dwp file" ); |
| 894 | |
| 895 | TUSectionKind = DW_SECT_EXT_TYPES; |
| 896 | OutSection = TypesSection; |
| 897 | TypeInputSection = CurTypesSection.front(); |
| 898 | } |
| 899 | |
| 900 | DWARFUnitIndex TUIndex(TUSectionKind); |
| 901 | DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0); |
| 902 | if (!TUIndex.parse(IndexData: TUIndexData)) |
| 903 | return make_error<DWPError>(Args: "failed to parse tu_index" ); |
| 904 | if (TUIndex.getVersion() != IndexVersion) |
| 905 | return make_error<DWPError>(Args: "incompatible tu_index versions, found " + |
| 906 | utostr(X: TUIndex.getVersion()) + |
| 907 | " and expecting " + utostr(X: IndexVersion)); |
| 908 | |
| 909 | unsigned TypesContributionIndex = |
| 910 | getContributionIndex(Kind: TUSectionKind, IndexVersion); |
| 911 | if (Error Err = addAllTypesFromDWP( |
| 912 | Out, TypeIndexEntries, TUIndex, OutputTypes: OutSection, Types: TypeInputSection, |
| 913 | TUEntry: CurEntry, TypesOffset&: ContributionOffsets[TypesContributionIndex], |
| 914 | TypesContributionIndex, OverflowOptValue, AnySectionOverflow)) |
| 915 | return Err; |
| 916 | } |
| 917 | if (AnySectionOverflow) |
| 918 | break; |
| 919 | } |
| 920 | |
| 921 | if (Version < 5) { |
| 922 | // Lie about there being no info contributions so the TU index only includes |
| 923 | // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a |
| 924 | // contribution to the info section, so we do not want to lie about it. |
| 925 | ContributionOffsets[0] = 0; |
| 926 | } |
| 927 | writeIndex(Out, Section: MCOFI.getDwarfTUIndexSection(), ContributionOffsets, |
| 928 | IndexEntries: TypeIndexEntries, IndexVersion); |
| 929 | |
| 930 | if (Version < 5) { |
| 931 | // Lie about the type contribution for DWARF < 5. In DWARFv5 the type |
| 932 | // section does not exist, so no need to do anything about this. |
| 933 | ContributionOffsets[getContributionIndex(Kind: DW_SECT_EXT_TYPES, IndexVersion: 2)] = 0; |
| 934 | // Unlie about the info contribution |
| 935 | ContributionOffsets[0] = 1; |
| 936 | } |
| 937 | |
| 938 | writeIndex(Out, Section: MCOFI.getDwarfCUIndexSection(), ContributionOffsets, |
| 939 | IndexEntries, IndexVersion); |
| 940 | |
| 941 | return Error::success(); |
| 942 | } |
| 943 | } // namespace llvm |
| 944 | |