1 //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
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 "llvm/Support/CommandLine.h"
22 #include "llvm/Support/MemoryBuffer.h"
26 using namespace llvm::object
;
28 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags
;
30 // Returns the size of debug_str_offsets section headers in bytes.
31 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData
,
32 uint16_t DwarfVersion
) {
33 if (DwarfVersion
<= 4)
34 return 0; // There is no header before dwarf 5.
36 uint64_t Length
= StrOffsetsData
.getU32(&Offset
);
37 if (Length
== llvm::dwarf::DW_LENGTH_DWARF64
)
38 return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
39 return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
42 static uint64_t getCUAbbrev(StringRef Abbrev
, uint64_t AbbrCode
) {
44 DataExtractor
AbbrevData(Abbrev
, true, 0);
45 while (AbbrevData
.getULEB128(&Offset
) != AbbrCode
) {
47 AbbrevData
.getULEB128(&Offset
);
49 AbbrevData
.getU8(&Offset
);
51 while (AbbrevData
.getULEB128(&Offset
) | AbbrevData
.getULEB128(&Offset
))
57 static Expected
<const char *>
58 getIndexedString(dwarf::Form Form
, DataExtractor InfoData
, uint64_t &InfoOffset
,
59 StringRef StrOffsets
, StringRef Str
, uint16_t Version
) {
60 if (Form
== dwarf::DW_FORM_string
)
61 return InfoData
.getCStr(&InfoOffset
);
64 case dwarf::DW_FORM_strx1
:
65 StrIndex
= InfoData
.getU8(&InfoOffset
);
67 case dwarf::DW_FORM_strx2
:
68 StrIndex
= InfoData
.getU16(&InfoOffset
);
70 case dwarf::DW_FORM_strx3
:
71 StrIndex
= InfoData
.getU24(&InfoOffset
);
73 case dwarf::DW_FORM_strx4
:
74 StrIndex
= InfoData
.getU32(&InfoOffset
);
76 case dwarf::DW_FORM_strx
:
77 case dwarf::DW_FORM_GNU_str_index
:
78 StrIndex
= InfoData
.getULEB128(&InfoOffset
);
81 return make_error
<DWPError
>(
82 "string field must be encoded with one of the following: "
83 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
86 DataExtractor
StrOffsetsData(StrOffsets
, true, 0);
87 uint64_t StrOffsetsOffset
= 4 * StrIndex
;
88 StrOffsetsOffset
+= debugStrOffsetsHeaderSize(StrOffsetsData
, Version
);
90 uint64_t StrOffset
= StrOffsetsData
.getU32(&StrOffsetsOffset
);
91 DataExtractor
StrData(Str
, true, 0);
92 return StrData
.getCStr(&StrOffset
);
95 static Expected
<CompileUnitIdentifiers
>
96 getCUIdentifiers(InfoSectionUnitHeader
&Header
, StringRef Abbrev
,
97 StringRef Info
, StringRef StrOffsets
, StringRef Str
) {
98 DataExtractor
InfoData(Info
, true, 0);
99 uint64_t Offset
= Header
.HeaderSize
;
100 if (Header
.Version
>= 5 && Header
.UnitType
!= dwarf::DW_UT_split_compile
)
101 return make_error
<DWPError
>(
102 std::string("unit type DW_UT_split_compile type not found in "
103 "debug_info header. Unexpected unit type 0x" +
104 utostr(Header
.UnitType
) + " found"));
106 CompileUnitIdentifiers ID
;
108 uint32_t AbbrCode
= InfoData
.getULEB128(&Offset
);
109 DataExtractor
AbbrevData(Abbrev
, true, 0);
110 uint64_t AbbrevOffset
= getCUAbbrev(Abbrev
, AbbrCode
);
111 auto Tag
= static_cast<dwarf::Tag
>(AbbrevData
.getULEB128(&AbbrevOffset
));
112 if (Tag
!= dwarf::DW_TAG_compile_unit
)
113 return make_error
<DWPError
>("top level DIE is not a compile unit");
115 AbbrevData
.getU8(&AbbrevOffset
);
118 while ((Name
= AbbrevData
.getULEB128(&AbbrevOffset
)) |
119 (Form
= static_cast<dwarf::Form
>(
120 AbbrevData
.getULEB128(&AbbrevOffset
))) &&
121 (Name
!= 0 || Form
!= 0)) {
123 case dwarf::DW_AT_name
: {
124 Expected
<const char *> EName
= getIndexedString(
125 Form
, InfoData
, Offset
, StrOffsets
, Str
, Header
.Version
);
127 return EName
.takeError();
131 case dwarf::DW_AT_GNU_dwo_name
:
132 case dwarf::DW_AT_dwo_name
: {
133 Expected
<const char *> EName
= getIndexedString(
134 Form
, InfoData
, Offset
, StrOffsets
, Str
, Header
.Version
);
136 return EName
.takeError();
140 case dwarf::DW_AT_GNU_dwo_id
:
141 Header
.Signature
= InfoData
.getU64(&Offset
);
144 DWARFFormValue::skipValue(
145 Form
, InfoData
, &Offset
,
146 dwarf::FormParams({Header
.Version
, Header
.AddrSize
, Header
.Format
}));
149 if (!Header
.Signature
)
150 return make_error
<DWPError
>("compile unit missing dwo_id");
151 ID
.Signature
= *Header
.Signature
;
155 static bool isSupportedSectionKind(DWARFSectionKind Kind
) {
156 return Kind
!= DW_SECT_EXT_unknown
;
160 // Convert an internal section identifier into the index to use with
161 // UnitIndexEntry::Contributions.
162 unsigned getContributionIndex(DWARFSectionKind Kind
, uint32_t IndexVersion
) {
163 assert(serializeSectionKind(Kind
, IndexVersion
) >= DW_SECT_INFO
);
164 return serializeSectionKind(Kind
, IndexVersion
) - DW_SECT_INFO
;
168 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
169 // value of the section identifier.
170 static unsigned getOnDiskSectionId(unsigned Index
) {
171 return Index
+ DW_SECT_INFO
;
174 static StringRef
getSubsection(StringRef Section
,
175 const DWARFUnitIndex::Entry
&Entry
,
176 DWARFSectionKind Kind
) {
177 const auto *Off
= Entry
.getContribution(Kind
);
180 return Section
.substr(Off
->getOffset(), Off
->getLength());
183 static Error
sectionOverflowErrorOrWarning(uint32_t PrevOffset
,
184 uint32_t OverflowedOffset
,
185 StringRef SectionName
,
186 OnCuIndexOverflow OverflowOptValue
,
187 bool &AnySectionOverflow
) {
190 Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
191 Twine(PrevOffset
) + Twine(", After overflow offset ") +
192 Twine(OverflowedOffset
) + Twine("."))
194 if (OverflowOptValue
== OnCuIndexOverflow::Continue
) {
195 WithColor::defaultWarningHandler(make_error
<DWPError
>(Msg
));
196 return Error::success();
197 } else if (OverflowOptValue
== OnCuIndexOverflow::SoftStop
) {
198 AnySectionOverflow
= true;
199 WithColor::defaultWarningHandler(make_error
<DWPError
>(Msg
));
200 return Error::success();
202 return make_error
<DWPError
>(Msg
);
205 static Error
addAllTypesFromDWP(
206 MCStreamer
&Out
, MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
207 const DWARFUnitIndex
&TUIndex
, MCSection
*OutputTypes
, StringRef Types
,
208 const UnitIndexEntry
&TUEntry
, uint32_t &TypesOffset
,
209 unsigned TypesContributionIndex
, OnCuIndexOverflow OverflowOptValue
,
210 bool &AnySectionOverflow
) {
211 Out
.switchSection(OutputTypes
);
212 for (const DWARFUnitIndex::Entry
&E
: TUIndex
.getRows()) {
213 auto *I
= E
.getContributions();
216 auto P
= TypeIndexEntries
.insert(std::make_pair(E
.getSignature(), TUEntry
));
219 auto &Entry
= P
.first
->second
;
220 // Zero out the debug_info contribution
221 Entry
.Contributions
[0] = {};
222 for (auto Kind
: TUIndex
.getColumnKinds()) {
223 if (!isSupportedSectionKind(Kind
))
226 Entry
.Contributions
[getContributionIndex(Kind
, TUIndex
.getVersion())];
227 C
.setOffset(C
.getOffset() + I
->getOffset());
228 C
.setLength(I
->getLength());
231 auto &C
= Entry
.Contributions
[TypesContributionIndex
];
232 Out
.emitBytes(Types
.substr(
234 TUEntry
.Contributions
[TypesContributionIndex
].getOffset(),
236 C
.setOffset(TypesOffset
);
237 uint32_t OldOffset
= TypesOffset
;
238 static_assert(sizeof(OldOffset
) == sizeof(TypesOffset
));
239 TypesOffset
+= C
.getLength();
240 if (OldOffset
> TypesOffset
) {
241 if (Error Err
= sectionOverflowErrorOrWarning(OldOffset
, TypesOffset
,
242 "Types", OverflowOptValue
,
245 if (AnySectionOverflow
) {
246 TypesOffset
= OldOffset
;
247 return Error::success();
251 return Error::success();
254 static Error
addAllTypesFromTypesSection(
255 MCStreamer
&Out
, MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
256 MCSection
*OutputTypes
, const std::vector
<StringRef
> &TypesSections
,
257 const UnitIndexEntry
&CUEntry
, uint32_t &TypesOffset
,
258 OnCuIndexOverflow OverflowOptValue
, bool &AnySectionOverflow
) {
259 for (StringRef Types
: TypesSections
) {
260 Out
.switchSection(OutputTypes
);
262 DataExtractor
Data(Types
, true, 0);
263 while (Data
.isValidOffset(Offset
)) {
264 UnitIndexEntry Entry
= CUEntry
;
265 // Zero out the debug_info contribution
266 Entry
.Contributions
[0] = {};
267 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)];
268 C
.setOffset(TypesOffset
);
269 auto PrevOffset
= Offset
;
270 // Length of the unit, including the 4 byte length field.
271 C
.setLength(Data
.getU32(&Offset
) + 4);
273 Data
.getU16(&Offset
); // Version
274 Data
.getU32(&Offset
); // Abbrev offset
275 Data
.getU8(&Offset
); // Address size
276 auto Signature
= Data
.getU64(&Offset
);
277 Offset
= PrevOffset
+ C
.getLength32();
279 auto P
= TypeIndexEntries
.insert(std::make_pair(Signature
, Entry
));
283 Out
.emitBytes(Types
.substr(PrevOffset
, C
.getLength32()));
284 uint32_t OldOffset
= TypesOffset
;
285 TypesOffset
+= C
.getLength32();
286 if (OldOffset
> TypesOffset
) {
287 if (Error Err
= sectionOverflowErrorOrWarning(OldOffset
, TypesOffset
,
288 "Types", OverflowOptValue
,
291 if (AnySectionOverflow
) {
292 TypesOffset
= OldOffset
;
293 return Error::success();
298 return Error::success();
301 static std::string
buildDWODescription(StringRef Name
, StringRef DWPName
,
303 std::string Text
= "\'";
306 bool HasDWO
= !DWOName
.empty();
307 bool HasDWP
= !DWPName
.empty();
308 if (HasDWO
|| HasDWP
) {
315 if (HasDWO
&& HasDWP
)
317 if (!DWPName
.empty()) {
327 static Error
createError(StringRef Name
, Error E
) {
328 return make_error
<DWPError
>(
329 ("failure while decompressing compressed section: '" + Name
+ "', " +
330 llvm::toString(std::move(E
)))
335 handleCompressedSection(std::deque
<SmallString
<32>> &UncompressedSections
,
336 SectionRef Sec
, StringRef Name
, StringRef
&Contents
) {
337 auto *Obj
= dyn_cast
<ELFObjectFileBase
>(Sec
.getObject());
339 !(static_cast<ELFSectionRef
>(Sec
).getFlags() & ELF::SHF_COMPRESSED
))
340 return Error::success();
341 bool IsLE
= isa
<object::ELF32LEObjectFile
>(Obj
) ||
342 isa
<object::ELF64LEObjectFile
>(Obj
);
343 bool Is64
= isa
<object::ELF64LEObjectFile
>(Obj
) ||
344 isa
<object::ELF64BEObjectFile
>(Obj
);
345 Expected
<Decompressor
> Dec
= Decompressor::create(Name
, Contents
, IsLE
, Is64
);
347 return createError(Name
, Dec
.takeError());
349 UncompressedSections
.emplace_back();
350 if (Error E
= Dec
->resizeAndDecompress(UncompressedSections
.back()))
351 return createError(Name
, std::move(E
));
353 Contents
= UncompressedSections
.back();
354 return Error::success();
358 // Parse and return the header of an info section compile/type unit.
359 Expected
<InfoSectionUnitHeader
> parseInfoSectionUnitHeader(StringRef Info
) {
360 InfoSectionUnitHeader Header
;
361 Error Err
= Error::success();
363 DWARFDataExtractor
InfoData(Info
, true, 0);
364 std::tie(Header
.Length
, Header
.Format
) =
365 InfoData
.getInitialLength(&Offset
, &Err
);
367 return make_error
<DWPError
>("cannot parse compile unit length: " +
368 llvm::toString(std::move(Err
)));
370 if (!InfoData
.isValidOffset(Offset
+ (Header
.Length
- 1))) {
371 return make_error
<DWPError
>(
372 "compile unit exceeds .debug_info section range: " +
373 utostr(Offset
+ Header
.Length
) + " >= " + utostr(InfoData
.size()));
376 Header
.Version
= InfoData
.getU16(&Offset
, &Err
);
378 return make_error
<DWPError
>("cannot parse compile unit version: " +
379 llvm::toString(std::move(Err
)));
381 uint64_t MinHeaderLength
;
382 if (Header
.Version
>= 5) {
383 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
385 MinHeaderLength
= 16;
387 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
390 if (Header
.Length
< MinHeaderLength
) {
391 return make_error
<DWPError
>("unit length is too small: expected at least " +
392 utostr(MinHeaderLength
) + " got " +
393 utostr(Header
.Length
) + ".");
395 if (Header
.Version
>= 5) {
396 Header
.UnitType
= InfoData
.getU8(&Offset
);
397 Header
.AddrSize
= InfoData
.getU8(&Offset
);
398 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
399 Header
.Signature
= InfoData
.getU64(&Offset
);
400 if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
402 MinHeaderLength
+= 4;
403 if (Header
.Length
< MinHeaderLength
)
404 return make_error
<DWPError
>("type unit is missing type offset");
405 InfoData
.getU32(&Offset
);
408 // Note that, address_size and debug_abbrev_offset fields have switched
409 // places between dwarf version 4 and 5.
410 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
411 Header
.AddrSize
= InfoData
.getU8(&Offset
);
414 Header
.HeaderSize
= Offset
;
418 static void writeNewOffsetsTo(MCStreamer
&Out
, DataExtractor
&Data
,
419 DenseMap
<uint64_t, uint32_t> &OffsetRemapping
,
420 uint64_t &Offset
, uint64_t &Size
) {
422 while (Offset
< Size
) {
423 auto OldOffset
= Data
.getU32(&Offset
);
424 auto NewOffset
= OffsetRemapping
[OldOffset
];
425 Out
.emitIntValue(NewOffset
, 4);
429 void writeStringsAndOffsets(MCStreamer
&Out
, DWPStringPool
&Strings
,
430 MCSection
*StrOffsetSection
,
431 StringRef CurStrSection
,
432 StringRef CurStrOffsetSection
, uint16_t Version
) {
433 // Could possibly produce an error or warning if one of these was non-null but
434 // the other was null.
435 if (CurStrSection
.empty() || CurStrOffsetSection
.empty())
438 DenseMap
<uint64_t, uint32_t> OffsetRemapping
;
440 DataExtractor
Data(CurStrSection
, true, 0);
441 uint64_t LocalOffset
= 0;
442 uint64_t PrevOffset
= 0;
443 while (const char *S
= Data
.getCStr(&LocalOffset
)) {
444 OffsetRemapping
[PrevOffset
] =
445 Strings
.getOffset(S
, LocalOffset
- PrevOffset
);
446 PrevOffset
= LocalOffset
;
449 Data
= DataExtractor(CurStrOffsetSection
, true, 0);
451 Out
.switchSection(StrOffsetSection
);
454 uint64_t Size
= CurStrOffsetSection
.size();
456 while (Offset
< Size
) {
457 uint64_t HeaderSize
= debugStrOffsetsHeaderSize(Data
, Version
);
458 assert(HeaderSize
<= Size
- Offset
&&
459 "StrOffsetSection size is less than its header");
461 uint64_t ContributionEnd
= 0;
462 uint64_t ContributionSize
= 0;
463 uint64_t HeaderLengthOffset
= Offset
;
464 if (HeaderSize
== 8) {
465 ContributionSize
= Data
.getU32(&HeaderLengthOffset
);
466 } else if (HeaderSize
== 16) {
467 HeaderLengthOffset
+= 4; // skip the dwarf64 marker
468 ContributionSize
= Data
.getU64(&HeaderLengthOffset
);
470 ContributionEnd
= ContributionSize
+ HeaderLengthOffset
;
471 Out
.emitBytes(Data
.getBytes(&Offset
, HeaderSize
));
472 writeNewOffsetsTo(Out
, Data
, OffsetRemapping
, Offset
, ContributionEnd
);
476 writeNewOffsetsTo(Out
, Data
, OffsetRemapping
, Offset
, Size
);
480 enum AccessField
{ Offset
, Length
};
481 void writeIndexTable(MCStreamer
&Out
, ArrayRef
<unsigned> ContributionOffsets
,
482 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
483 const AccessField
&Field
) {
484 for (const auto &E
: IndexEntries
)
485 for (size_t I
= 0; I
!= std::size(E
.second
.Contributions
); ++I
)
486 if (ContributionOffsets
[I
])
487 Out
.emitIntValue((Field
== AccessField::Offset
488 ? E
.second
.Contributions
[I
].getOffset32()
489 : E
.second
.Contributions
[I
].getLength32()),
493 void writeIndex(MCStreamer
&Out
, MCSection
*Section
,
494 ArrayRef
<unsigned> ContributionOffsets
,
495 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
496 uint32_t IndexVersion
) {
497 if (IndexEntries
.empty())
500 unsigned Columns
= 0;
501 for (auto &C
: ContributionOffsets
)
505 std::vector
<unsigned> Buckets(NextPowerOf2(3 * IndexEntries
.size() / 2));
506 uint64_t Mask
= Buckets
.size() - 1;
508 for (const auto &P
: IndexEntries
) {
511 auto HP
= ((S
>> 32) & Mask
) | 1;
513 assert(S
!= IndexEntries
.begin()[Buckets
[H
] - 1].first
&&
521 Out
.switchSection(Section
);
522 Out
.emitIntValue(IndexVersion
, 4); // Version
523 Out
.emitIntValue(Columns
, 4); // Columns
524 Out
.emitIntValue(IndexEntries
.size(), 4); // Num Units
525 Out
.emitIntValue(Buckets
.size(), 4); // Num Buckets
527 // Write the signatures.
528 for (const auto &I
: Buckets
)
529 Out
.emitIntValue(I
? IndexEntries
.begin()[I
- 1].first
: 0, 8);
531 // Write the indexes.
532 for (const auto &I
: Buckets
)
533 Out
.emitIntValue(I
, 4);
535 // Write the column headers (which sections will appear in the table)
536 for (size_t I
= 0; I
!= ContributionOffsets
.size(); ++I
)
537 if (ContributionOffsets
[I
])
538 Out
.emitIntValue(getOnDiskSectionId(I
), 4);
540 // Write the offsets.
541 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Offset
);
543 // Write the lengths.
544 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Length
);
547 Error
buildDuplicateError(const std::pair
<uint64_t, UnitIndexEntry
> &PrevE
,
548 const CompileUnitIdentifiers
&ID
, StringRef DWPName
) {
549 return make_error
<DWPError
>(
550 std::string("duplicate DWO ID (") + utohexstr(PrevE
.first
) + ") in " +
551 buildDWODescription(PrevE
.second
.Name
, PrevE
.second
.DWPName
,
552 PrevE
.second
.DWOName
) +
553 " and " + buildDWODescription(ID
.Name
, DWPName
, ID
.DWOName
));
557 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> &KnownSections
,
558 const MCSection
*StrSection
, const MCSection
*StrOffsetSection
,
559 const MCSection
*TypesSection
, const MCSection
*CUIndexSection
,
560 const MCSection
*TUIndexSection
, const MCSection
*InfoSection
,
561 const SectionRef
&Section
, MCStreamer
&Out
,
562 std::deque
<SmallString
<32>> &UncompressedSections
,
563 uint32_t (&ContributionOffsets
)[8], UnitIndexEntry
&CurEntry
,
564 StringRef
&CurStrSection
, StringRef
&CurStrOffsetSection
,
565 std::vector
<StringRef
> &CurTypesSection
,
566 std::vector
<StringRef
> &CurInfoSection
, StringRef
&AbbrevSection
,
567 StringRef
&CurCUIndexSection
, StringRef
&CurTUIndexSection
,
568 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> &SectionLength
) {
570 return Error::success();
572 if (Section
.isVirtual())
573 return Error::success();
575 Expected
<StringRef
> NameOrErr
= Section
.getName();
577 return NameOrErr
.takeError();
578 StringRef Name
= *NameOrErr
;
580 Expected
<StringRef
> ContentsOrErr
= Section
.getContents();
582 return ContentsOrErr
.takeError();
583 StringRef Contents
= *ContentsOrErr
;
585 if (auto Err
= handleCompressedSection(UncompressedSections
, Section
, Name
,
589 Name
= Name
.substr(Name
.find_first_not_of("._"));
591 auto SectionPair
= KnownSections
.find(Name
);
592 if (SectionPair
== KnownSections
.end())
593 return Error::success();
595 if (DWARFSectionKind Kind
= SectionPair
->second
.second
) {
596 if (Kind
!= DW_SECT_EXT_TYPES
&& Kind
!= DW_SECT_INFO
) {
597 SectionLength
.push_back(std::make_pair(Kind
, Contents
.size()));
600 if (Kind
== DW_SECT_ABBREV
) {
601 AbbrevSection
= Contents
;
605 MCSection
*OutSection
= SectionPair
->second
.first
;
606 if (OutSection
== StrOffsetSection
)
607 CurStrOffsetSection
= Contents
;
608 else if (OutSection
== StrSection
)
609 CurStrSection
= Contents
;
610 else if (OutSection
== TypesSection
)
611 CurTypesSection
.push_back(Contents
);
612 else if (OutSection
== CUIndexSection
)
613 CurCUIndexSection
= Contents
;
614 else if (OutSection
== TUIndexSection
)
615 CurTUIndexSection
= Contents
;
616 else if (OutSection
== InfoSection
)
617 CurInfoSection
.push_back(Contents
);
619 Out
.switchSection(OutSection
);
620 Out
.emitBytes(Contents
);
622 return Error::success();
625 Error
write(MCStreamer
&Out
, ArrayRef
<std::string
> Inputs
,
626 OnCuIndexOverflow OverflowOptValue
) {
627 const auto &MCOFI
= *Out
.getContext().getObjectFileInfo();
628 MCSection
*const StrSection
= MCOFI
.getDwarfStrDWOSection();
629 MCSection
*const StrOffsetSection
= MCOFI
.getDwarfStrOffDWOSection();
630 MCSection
*const TypesSection
= MCOFI
.getDwarfTypesDWOSection();
631 MCSection
*const CUIndexSection
= MCOFI
.getDwarfCUIndexSection();
632 MCSection
*const TUIndexSection
= MCOFI
.getDwarfTUIndexSection();
633 MCSection
*const InfoSection
= MCOFI
.getDwarfInfoDWOSection();
634 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> KnownSections
= {
635 {"debug_info.dwo", {InfoSection
, DW_SECT_INFO
}},
636 {"debug_types.dwo", {MCOFI
.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES
}},
637 {"debug_str_offsets.dwo", {StrOffsetSection
, DW_SECT_STR_OFFSETS
}},
638 {"debug_str.dwo", {StrSection
, static_cast<DWARFSectionKind
>(0)}},
639 {"debug_loc.dwo", {MCOFI
.getDwarfLocDWOSection(), DW_SECT_EXT_LOC
}},
640 {"debug_line.dwo", {MCOFI
.getDwarfLineDWOSection(), DW_SECT_LINE
}},
641 {"debug_macro.dwo", {MCOFI
.getDwarfMacroDWOSection(), DW_SECT_MACRO
}},
642 {"debug_abbrev.dwo", {MCOFI
.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV
}},
643 {"debug_loclists.dwo",
644 {MCOFI
.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS
}},
645 {"debug_rnglists.dwo",
646 {MCOFI
.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS
}},
647 {"debug_cu_index", {CUIndexSection
, static_cast<DWARFSectionKind
>(0)}},
648 {"debug_tu_index", {TUIndexSection
, static_cast<DWARFSectionKind
>(0)}}};
650 MapVector
<uint64_t, UnitIndexEntry
> IndexEntries
;
651 MapVector
<uint64_t, UnitIndexEntry
> TypeIndexEntries
;
653 uint32_t ContributionOffsets
[8] = {};
654 uint16_t Version
= 0;
655 uint32_t IndexVersion
= 0;
656 bool AnySectionOverflow
= false;
658 DWPStringPool
Strings(Out
, StrSection
);
660 SmallVector
<OwningBinary
<object::ObjectFile
>, 128> Objects
;
661 Objects
.reserve(Inputs
.size());
663 std::deque
<SmallString
<32>> UncompressedSections
;
665 for (const auto &Input
: Inputs
) {
666 auto ErrOrObj
= object::ObjectFile::createObjectFile(Input
);
668 return handleErrors(ErrOrObj
.takeError(),
669 [&](std::unique_ptr
<ECError
> EC
) -> Error
{
670 return createFileError(Input
, Error(std::move(EC
)));
674 auto &Obj
= *ErrOrObj
->getBinary();
675 Objects
.push_back(std::move(*ErrOrObj
));
677 UnitIndexEntry CurEntry
= {};
679 StringRef CurStrSection
;
680 StringRef CurStrOffsetSection
;
681 std::vector
<StringRef
> CurTypesSection
;
682 std::vector
<StringRef
> CurInfoSection
;
683 StringRef AbbrevSection
;
684 StringRef CurCUIndexSection
;
685 StringRef CurTUIndexSection
;
687 // This maps each section contained in this file to its length.
688 // This information is later on used to calculate the contributions,
689 // i.e. offset and length, of each compile/type unit to a section.
690 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> SectionLength
;
692 for (const auto &Section
: Obj
.sections())
693 if (auto Err
= handleSection(
694 KnownSections
, StrSection
, StrOffsetSection
, TypesSection
,
695 CUIndexSection
, TUIndexSection
, InfoSection
, Section
, Out
,
696 UncompressedSections
, ContributionOffsets
, CurEntry
,
697 CurStrSection
, CurStrOffsetSection
, CurTypesSection
,
698 CurInfoSection
, AbbrevSection
, CurCUIndexSection
,
699 CurTUIndexSection
, SectionLength
))
702 if (CurInfoSection
.empty())
705 Expected
<InfoSectionUnitHeader
> HeaderOrErr
=
706 parseInfoSectionUnitHeader(CurInfoSection
.front());
708 return HeaderOrErr
.takeError();
709 InfoSectionUnitHeader
&Header
= *HeaderOrErr
;
712 Version
= Header
.Version
;
713 IndexVersion
= Version
< 5 ? 2 : 5;
714 } else if (Version
!= Header
.Version
) {
715 return make_error
<DWPError
>("incompatible DWARF compile unit versions.");
718 writeStringsAndOffsets(Out
, Strings
, StrOffsetSection
, CurStrSection
,
719 CurStrOffsetSection
, Header
.Version
);
721 for (auto Pair
: SectionLength
) {
722 auto Index
= getContributionIndex(Pair
.first
, IndexVersion
);
723 CurEntry
.Contributions
[Index
].setOffset(ContributionOffsets
[Index
]);
724 CurEntry
.Contributions
[Index
].setLength(Pair
.second
);
725 uint32_t OldOffset
= ContributionOffsets
[Index
];
726 ContributionOffsets
[Index
] += CurEntry
.Contributions
[Index
].getLength32();
727 if (OldOffset
> ContributionOffsets
[Index
]) {
728 uint32_t SectionIndex
= 0;
729 for (auto &Section
: Obj
.sections()) {
730 if (SectionIndex
== Index
) {
731 if (Error Err
= sectionOverflowErrorOrWarning(
732 OldOffset
, ContributionOffsets
[Index
], *Section
.getName(),
733 OverflowOptValue
, AnySectionOverflow
))
738 if (AnySectionOverflow
)
743 uint32_t &InfoSectionOffset
=
744 ContributionOffsets
[getContributionIndex(DW_SECT_INFO
, IndexVersion
)];
745 if (CurCUIndexSection
.empty()) {
746 bool FoundCUUnit
= false;
747 Out
.switchSection(InfoSection
);
748 for (StringRef Info
: CurInfoSection
) {
749 uint64_t UnitOffset
= 0;
750 while (Info
.size() > UnitOffset
) {
751 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
752 parseInfoSectionUnitHeader(Info
.substr(UnitOffset
, Info
.size()));
754 return HeaderOrError
.takeError();
755 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
757 UnitIndexEntry Entry
= CurEntry
;
758 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_INFO
,
760 C
.setOffset(InfoSectionOffset
);
761 C
.setLength(Header
.Length
+ 4);
763 if (std::numeric_limits
<uint32_t>::max() - InfoSectionOffset
<
765 if (Error Err
= sectionOverflowErrorOrWarning(
766 InfoSectionOffset
, InfoSectionOffset
+ C
.getLength32(),
767 "debug_info", OverflowOptValue
, AnySectionOverflow
))
769 if (AnySectionOverflow
) {
770 if (Header
.Version
< 5 ||
771 Header
.UnitType
== dwarf::DW_UT_split_compile
)
777 UnitOffset
+= C
.getLength32();
778 if (Header
.Version
< 5 ||
779 Header
.UnitType
== dwarf::DW_UT_split_compile
) {
780 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
781 Header
, AbbrevSection
,
782 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()),
783 CurStrOffsetSection
, CurStrSection
);
786 return createFileError(Input
, EID
.takeError());
787 const auto &ID
= *EID
;
788 auto P
= IndexEntries
.insert(std::make_pair(ID
.Signature
, Entry
));
790 return buildDuplicateError(*P
.first
, ID
, "");
791 P
.first
->second
.Name
= ID
.Name
;
792 P
.first
->second
.DWOName
= ID
.DWOName
;
795 } else if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
796 auto P
= TypeIndexEntries
.insert(
797 std::make_pair(*Header
.Signature
, Entry
));
802 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()));
803 InfoSectionOffset
+= C
.getLength32();
805 if (AnySectionOverflow
)
810 return make_error
<DWPError
>("no compile unit found in file: " + Input
);
812 if (IndexVersion
== 2) {
813 // Add types from the .debug_types section from DWARF < 5.
814 if (Error Err
= addAllTypesFromTypesSection(
815 Out
, TypeIndexEntries
, TypesSection
, CurTypesSection
, CurEntry
,
816 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)],
817 OverflowOptValue
, AnySectionOverflow
))
820 if (AnySectionOverflow
)
825 if (CurInfoSection
.size() != 1)
826 return make_error
<DWPError
>("expected exactly one occurrence of a debug "
827 "info section in a .dwp file");
828 StringRef DwpSingleInfoSection
= CurInfoSection
.front();
830 DWARFUnitIndex
CUIndex(DW_SECT_INFO
);
831 DataExtractor
CUIndexData(CurCUIndexSection
, Obj
.isLittleEndian(), 0);
832 if (!CUIndex
.parse(CUIndexData
))
833 return make_error
<DWPError
>("failed to parse cu_index");
834 if (CUIndex
.getVersion() != IndexVersion
)
835 return make_error
<DWPError
>("incompatible cu_index versions, found " +
836 utostr(CUIndex
.getVersion()) +
837 " and expecting " + utostr(IndexVersion
));
839 Out
.switchSection(InfoSection
);
840 for (const DWARFUnitIndex::Entry
&E
: CUIndex
.getRows()) {
841 auto *I
= E
.getContributions();
844 auto P
= IndexEntries
.insert(std::make_pair(E
.getSignature(), CurEntry
));
845 StringRef CUInfoSection
=
846 getSubsection(DwpSingleInfoSection
, E
, DW_SECT_INFO
);
847 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
848 parseInfoSectionUnitHeader(CUInfoSection
);
850 return HeaderOrError
.takeError();
851 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
853 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
854 Header
, getSubsection(AbbrevSection
, E
, DW_SECT_ABBREV
),
856 getSubsection(CurStrOffsetSection
, E
, DW_SECT_STR_OFFSETS
),
859 return createFileError(Input
, EID
.takeError());
860 const auto &ID
= *EID
;
862 return buildDuplicateError(*P
.first
, ID
, Input
);
863 auto &NewEntry
= P
.first
->second
;
864 NewEntry
.Name
= ID
.Name
;
865 NewEntry
.DWOName
= ID
.DWOName
;
866 NewEntry
.DWPName
= Input
;
867 for (auto Kind
: CUIndex
.getColumnKinds()) {
868 if (!isSupportedSectionKind(Kind
))
871 NewEntry
.Contributions
[getContributionIndex(Kind
, IndexVersion
)];
872 C
.setOffset(C
.getOffset() + I
->getOffset());
873 C
.setLength(I
->getLength());
876 unsigned Index
= getContributionIndex(DW_SECT_INFO
, IndexVersion
);
877 auto &C
= NewEntry
.Contributions
[Index
];
878 Out
.emitBytes(CUInfoSection
);
879 C
.setOffset(InfoSectionOffset
);
880 InfoSectionOffset
+= C
.getLength32();
883 if (!CurTUIndexSection
.empty()) {
884 llvm::DWARFSectionKind TUSectionKind
;
885 MCSection
*OutSection
;
886 StringRef TypeInputSection
;
887 // Write type units into debug info section for DWARFv5.
889 TUSectionKind
= DW_SECT_INFO
;
890 OutSection
= InfoSection
;
891 TypeInputSection
= DwpSingleInfoSection
;
893 // Write type units into debug types section for DWARF < 5.
894 if (CurTypesSection
.size() != 1)
895 return make_error
<DWPError
>(
896 "multiple type unit sections in .dwp file");
898 TUSectionKind
= DW_SECT_EXT_TYPES
;
899 OutSection
= TypesSection
;
900 TypeInputSection
= CurTypesSection
.front();
903 DWARFUnitIndex
TUIndex(TUSectionKind
);
904 DataExtractor
TUIndexData(CurTUIndexSection
, Obj
.isLittleEndian(), 0);
905 if (!TUIndex
.parse(TUIndexData
))
906 return make_error
<DWPError
>("failed to parse tu_index");
907 if (TUIndex
.getVersion() != IndexVersion
)
908 return make_error
<DWPError
>("incompatible tu_index versions, found " +
909 utostr(TUIndex
.getVersion()) +
910 " and expecting " + utostr(IndexVersion
));
912 unsigned TypesContributionIndex
=
913 getContributionIndex(TUSectionKind
, IndexVersion
);
914 if (Error Err
= addAllTypesFromDWP(
915 Out
, TypeIndexEntries
, TUIndex
, OutSection
, TypeInputSection
,
916 CurEntry
, ContributionOffsets
[TypesContributionIndex
],
917 TypesContributionIndex
, OverflowOptValue
, AnySectionOverflow
))
920 if (AnySectionOverflow
)
925 // Lie about there being no info contributions so the TU index only includes
926 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
927 // contribution to the info section, so we do not want to lie about it.
928 ContributionOffsets
[0] = 0;
930 writeIndex(Out
, MCOFI
.getDwarfTUIndexSection(), ContributionOffsets
,
931 TypeIndexEntries
, IndexVersion
);
934 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
935 // section does not exist, so no need to do anything about this.
936 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)] = 0;
937 // Unlie about the info contribution
938 ContributionOffsets
[0] = 1;
941 writeIndex(Out
, MCOFI
.getDwarfCUIndexSection(), ContributionOffsets
,
942 IndexEntries
, IndexVersion
);
944 return Error::success();