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 void writeStringsAndOffsets(MCStreamer
&Out
, DWPStringPool
&Strings
,
419 MCSection
*StrOffsetSection
,
420 StringRef CurStrSection
,
421 StringRef CurStrOffsetSection
, uint16_t Version
) {
422 // Could possibly produce an error or warning if one of these was non-null but
423 // the other was null.
424 if (CurStrSection
.empty() || CurStrOffsetSection
.empty())
427 DenseMap
<uint64_t, uint32_t> OffsetRemapping
;
429 DataExtractor
Data(CurStrSection
, true, 0);
430 uint64_t LocalOffset
= 0;
431 uint64_t PrevOffset
= 0;
432 while (const char *S
= Data
.getCStr(&LocalOffset
)) {
433 OffsetRemapping
[PrevOffset
] =
434 Strings
.getOffset(S
, LocalOffset
- PrevOffset
);
435 PrevOffset
= LocalOffset
;
438 Data
= DataExtractor(CurStrOffsetSection
, true, 0);
440 Out
.switchSection(StrOffsetSection
);
442 uint64_t HeaderSize
= debugStrOffsetsHeaderSize(Data
, Version
);
444 uint64_t Size
= CurStrOffsetSection
.size();
445 // FIXME: This can be caused by bad input and should be handled as such.
446 assert(HeaderSize
<= Size
&& "StrOffsetSection size is less than its header");
447 // Copy the header to the output.
448 Out
.emitBytes(Data
.getBytes(&Offset
, HeaderSize
));
449 while (Offset
< Size
) {
450 auto OldOffset
= Data
.getU32(&Offset
);
451 auto NewOffset
= OffsetRemapping
[OldOffset
];
452 Out
.emitIntValue(NewOffset
, 4);
456 enum AccessField
{ Offset
, Length
};
457 void writeIndexTable(MCStreamer
&Out
, ArrayRef
<unsigned> ContributionOffsets
,
458 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
459 const AccessField
&Field
) {
460 for (const auto &E
: IndexEntries
)
461 for (size_t I
= 0; I
!= std::size(E
.second
.Contributions
); ++I
)
462 if (ContributionOffsets
[I
])
463 Out
.emitIntValue((Field
== AccessField::Offset
464 ? E
.second
.Contributions
[I
].getOffset32()
465 : E
.second
.Contributions
[I
].getLength32()),
469 void writeIndex(MCStreamer
&Out
, MCSection
*Section
,
470 ArrayRef
<unsigned> ContributionOffsets
,
471 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
472 uint32_t IndexVersion
) {
473 if (IndexEntries
.empty())
476 unsigned Columns
= 0;
477 for (auto &C
: ContributionOffsets
)
481 std::vector
<unsigned> Buckets(NextPowerOf2(3 * IndexEntries
.size() / 2));
482 uint64_t Mask
= Buckets
.size() - 1;
484 for (const auto &P
: IndexEntries
) {
487 auto HP
= ((S
>> 32) & Mask
) | 1;
489 assert(S
!= IndexEntries
.begin()[Buckets
[H
] - 1].first
&&
497 Out
.switchSection(Section
);
498 Out
.emitIntValue(IndexVersion
, 4); // Version
499 Out
.emitIntValue(Columns
, 4); // Columns
500 Out
.emitIntValue(IndexEntries
.size(), 4); // Num Units
501 Out
.emitIntValue(Buckets
.size(), 4); // Num Buckets
503 // Write the signatures.
504 for (const auto &I
: Buckets
)
505 Out
.emitIntValue(I
? IndexEntries
.begin()[I
- 1].first
: 0, 8);
507 // Write the indexes.
508 for (const auto &I
: Buckets
)
509 Out
.emitIntValue(I
, 4);
511 // Write the column headers (which sections will appear in the table)
512 for (size_t I
= 0; I
!= ContributionOffsets
.size(); ++I
)
513 if (ContributionOffsets
[I
])
514 Out
.emitIntValue(getOnDiskSectionId(I
), 4);
516 // Write the offsets.
517 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Offset
);
519 // Write the lengths.
520 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Length
);
523 Error
buildDuplicateError(const std::pair
<uint64_t, UnitIndexEntry
> &PrevE
,
524 const CompileUnitIdentifiers
&ID
, StringRef DWPName
) {
525 return make_error
<DWPError
>(
526 std::string("duplicate DWO ID (") + utohexstr(PrevE
.first
) + ") in " +
527 buildDWODescription(PrevE
.second
.Name
, PrevE
.second
.DWPName
,
528 PrevE
.second
.DWOName
) +
529 " and " + buildDWODescription(ID
.Name
, DWPName
, ID
.DWOName
));
533 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> &KnownSections
,
534 const MCSection
*StrSection
, const MCSection
*StrOffsetSection
,
535 const MCSection
*TypesSection
, const MCSection
*CUIndexSection
,
536 const MCSection
*TUIndexSection
, const MCSection
*InfoSection
,
537 const SectionRef
&Section
, MCStreamer
&Out
,
538 std::deque
<SmallString
<32>> &UncompressedSections
,
539 uint32_t (&ContributionOffsets
)[8], UnitIndexEntry
&CurEntry
,
540 StringRef
&CurStrSection
, StringRef
&CurStrOffsetSection
,
541 std::vector
<StringRef
> &CurTypesSection
,
542 std::vector
<StringRef
> &CurInfoSection
, StringRef
&AbbrevSection
,
543 StringRef
&CurCUIndexSection
, StringRef
&CurTUIndexSection
,
544 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> &SectionLength
) {
546 return Error::success();
548 if (Section
.isVirtual())
549 return Error::success();
551 Expected
<StringRef
> NameOrErr
= Section
.getName();
553 return NameOrErr
.takeError();
554 StringRef Name
= *NameOrErr
;
556 Expected
<StringRef
> ContentsOrErr
= Section
.getContents();
558 return ContentsOrErr
.takeError();
559 StringRef Contents
= *ContentsOrErr
;
561 if (auto Err
= handleCompressedSection(UncompressedSections
, Section
, Name
,
565 Name
= Name
.substr(Name
.find_first_not_of("._"));
567 auto SectionPair
= KnownSections
.find(Name
);
568 if (SectionPair
== KnownSections
.end())
569 return Error::success();
571 if (DWARFSectionKind Kind
= SectionPair
->second
.second
) {
572 if (Kind
!= DW_SECT_EXT_TYPES
&& Kind
!= DW_SECT_INFO
) {
573 SectionLength
.push_back(std::make_pair(Kind
, Contents
.size()));
576 if (Kind
== DW_SECT_ABBREV
) {
577 AbbrevSection
= Contents
;
581 MCSection
*OutSection
= SectionPair
->second
.first
;
582 if (OutSection
== StrOffsetSection
)
583 CurStrOffsetSection
= Contents
;
584 else if (OutSection
== StrSection
)
585 CurStrSection
= Contents
;
586 else if (OutSection
== TypesSection
)
587 CurTypesSection
.push_back(Contents
);
588 else if (OutSection
== CUIndexSection
)
589 CurCUIndexSection
= Contents
;
590 else if (OutSection
== TUIndexSection
)
591 CurTUIndexSection
= Contents
;
592 else if (OutSection
== InfoSection
)
593 CurInfoSection
.push_back(Contents
);
595 Out
.switchSection(OutSection
);
596 Out
.emitBytes(Contents
);
598 return Error::success();
601 Error
write(MCStreamer
&Out
, ArrayRef
<std::string
> Inputs
,
602 OnCuIndexOverflow OverflowOptValue
) {
603 const auto &MCOFI
= *Out
.getContext().getObjectFileInfo();
604 MCSection
*const StrSection
= MCOFI
.getDwarfStrDWOSection();
605 MCSection
*const StrOffsetSection
= MCOFI
.getDwarfStrOffDWOSection();
606 MCSection
*const TypesSection
= MCOFI
.getDwarfTypesDWOSection();
607 MCSection
*const CUIndexSection
= MCOFI
.getDwarfCUIndexSection();
608 MCSection
*const TUIndexSection
= MCOFI
.getDwarfTUIndexSection();
609 MCSection
*const InfoSection
= MCOFI
.getDwarfInfoDWOSection();
610 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> KnownSections
= {
611 {"debug_info.dwo", {InfoSection
, DW_SECT_INFO
}},
612 {"debug_types.dwo", {MCOFI
.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES
}},
613 {"debug_str_offsets.dwo", {StrOffsetSection
, DW_SECT_STR_OFFSETS
}},
614 {"debug_str.dwo", {StrSection
, static_cast<DWARFSectionKind
>(0)}},
615 {"debug_loc.dwo", {MCOFI
.getDwarfLocDWOSection(), DW_SECT_EXT_LOC
}},
616 {"debug_line.dwo", {MCOFI
.getDwarfLineDWOSection(), DW_SECT_LINE
}},
617 {"debug_macro.dwo", {MCOFI
.getDwarfMacroDWOSection(), DW_SECT_MACRO
}},
618 {"debug_abbrev.dwo", {MCOFI
.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV
}},
619 {"debug_loclists.dwo",
620 {MCOFI
.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS
}},
621 {"debug_rnglists.dwo",
622 {MCOFI
.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS
}},
623 {"debug_cu_index", {CUIndexSection
, static_cast<DWARFSectionKind
>(0)}},
624 {"debug_tu_index", {TUIndexSection
, static_cast<DWARFSectionKind
>(0)}}};
626 MapVector
<uint64_t, UnitIndexEntry
> IndexEntries
;
627 MapVector
<uint64_t, UnitIndexEntry
> TypeIndexEntries
;
629 uint32_t ContributionOffsets
[8] = {};
630 uint16_t Version
= 0;
631 uint32_t IndexVersion
= 0;
632 bool AnySectionOverflow
= false;
634 DWPStringPool
Strings(Out
, StrSection
);
636 SmallVector
<OwningBinary
<object::ObjectFile
>, 128> Objects
;
637 Objects
.reserve(Inputs
.size());
639 std::deque
<SmallString
<32>> UncompressedSections
;
641 for (const auto &Input
: Inputs
) {
642 auto ErrOrObj
= object::ObjectFile::createObjectFile(Input
);
644 return handleErrors(ErrOrObj
.takeError(),
645 [&](std::unique_ptr
<ECError
> EC
) -> Error
{
646 return createFileError(Input
, Error(std::move(EC
)));
650 auto &Obj
= *ErrOrObj
->getBinary();
651 Objects
.push_back(std::move(*ErrOrObj
));
653 UnitIndexEntry CurEntry
= {};
655 StringRef CurStrSection
;
656 StringRef CurStrOffsetSection
;
657 std::vector
<StringRef
> CurTypesSection
;
658 std::vector
<StringRef
> CurInfoSection
;
659 StringRef AbbrevSection
;
660 StringRef CurCUIndexSection
;
661 StringRef CurTUIndexSection
;
663 // This maps each section contained in this file to its length.
664 // This information is later on used to calculate the contributions,
665 // i.e. offset and length, of each compile/type unit to a section.
666 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> SectionLength
;
668 for (const auto &Section
: Obj
.sections())
669 if (auto Err
= handleSection(
670 KnownSections
, StrSection
, StrOffsetSection
, TypesSection
,
671 CUIndexSection
, TUIndexSection
, InfoSection
, Section
, Out
,
672 UncompressedSections
, ContributionOffsets
, CurEntry
,
673 CurStrSection
, CurStrOffsetSection
, CurTypesSection
,
674 CurInfoSection
, AbbrevSection
, CurCUIndexSection
,
675 CurTUIndexSection
, SectionLength
))
678 if (CurInfoSection
.empty())
681 Expected
<InfoSectionUnitHeader
> HeaderOrErr
=
682 parseInfoSectionUnitHeader(CurInfoSection
.front());
684 return HeaderOrErr
.takeError();
685 InfoSectionUnitHeader
&Header
= *HeaderOrErr
;
688 Version
= Header
.Version
;
689 IndexVersion
= Version
< 5 ? 2 : 5;
690 } else if (Version
!= Header
.Version
) {
691 return make_error
<DWPError
>("incompatible DWARF compile unit versions.");
694 writeStringsAndOffsets(Out
, Strings
, StrOffsetSection
, CurStrSection
,
695 CurStrOffsetSection
, Header
.Version
);
697 for (auto Pair
: SectionLength
) {
698 auto Index
= getContributionIndex(Pair
.first
, IndexVersion
);
699 CurEntry
.Contributions
[Index
].setOffset(ContributionOffsets
[Index
]);
700 CurEntry
.Contributions
[Index
].setLength(Pair
.second
);
701 uint32_t OldOffset
= ContributionOffsets
[Index
];
702 ContributionOffsets
[Index
] += CurEntry
.Contributions
[Index
].getLength32();
703 if (OldOffset
> ContributionOffsets
[Index
]) {
704 uint32_t SectionIndex
= 0;
705 for (auto &Section
: Obj
.sections()) {
706 if (SectionIndex
== Index
) {
707 if (Error Err
= sectionOverflowErrorOrWarning(
708 OldOffset
, ContributionOffsets
[Index
], *Section
.getName(),
709 OverflowOptValue
, AnySectionOverflow
))
714 if (AnySectionOverflow
)
719 uint32_t &InfoSectionOffset
=
720 ContributionOffsets
[getContributionIndex(DW_SECT_INFO
, IndexVersion
)];
721 if (CurCUIndexSection
.empty()) {
722 bool FoundCUUnit
= false;
723 Out
.switchSection(InfoSection
);
724 for (StringRef Info
: CurInfoSection
) {
725 uint64_t UnitOffset
= 0;
726 while (Info
.size() > UnitOffset
) {
727 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
728 parseInfoSectionUnitHeader(Info
.substr(UnitOffset
, Info
.size()));
730 return HeaderOrError
.takeError();
731 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
733 UnitIndexEntry Entry
= CurEntry
;
734 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_INFO
,
736 C
.setOffset(InfoSectionOffset
);
737 C
.setLength(Header
.Length
+ 4);
739 if (std::numeric_limits
<uint32_t>::max() - InfoSectionOffset
<
741 if (Error Err
= sectionOverflowErrorOrWarning(
742 InfoSectionOffset
, InfoSectionOffset
+ C
.getLength32(),
743 "debug_info", OverflowOptValue
, AnySectionOverflow
))
745 if (AnySectionOverflow
) {
746 if (Header
.Version
< 5 ||
747 Header
.UnitType
== dwarf::DW_UT_split_compile
)
753 UnitOffset
+= C
.getLength32();
754 if (Header
.Version
< 5 ||
755 Header
.UnitType
== dwarf::DW_UT_split_compile
) {
756 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
757 Header
, AbbrevSection
,
758 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()),
759 CurStrOffsetSection
, CurStrSection
);
762 return createFileError(Input
, EID
.takeError());
763 const auto &ID
= *EID
;
764 auto P
= IndexEntries
.insert(std::make_pair(ID
.Signature
, Entry
));
766 return buildDuplicateError(*P
.first
, ID
, "");
767 P
.first
->second
.Name
= ID
.Name
;
768 P
.first
->second
.DWOName
= ID
.DWOName
;
771 } else if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
772 auto P
= TypeIndexEntries
.insert(
773 std::make_pair(*Header
.Signature
, Entry
));
778 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()));
779 InfoSectionOffset
+= C
.getLength32();
781 if (AnySectionOverflow
)
786 return make_error
<DWPError
>("no compile unit found in file: " + Input
);
788 if (IndexVersion
== 2) {
789 // Add types from the .debug_types section from DWARF < 5.
790 if (Error Err
= addAllTypesFromTypesSection(
791 Out
, TypeIndexEntries
, TypesSection
, CurTypesSection
, CurEntry
,
792 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)],
793 OverflowOptValue
, AnySectionOverflow
))
796 if (AnySectionOverflow
)
801 if (CurInfoSection
.size() != 1)
802 return make_error
<DWPError
>("expected exactly one occurrence of a debug "
803 "info section in a .dwp file");
804 StringRef DwpSingleInfoSection
= CurInfoSection
.front();
806 DWARFUnitIndex
CUIndex(DW_SECT_INFO
);
807 DataExtractor
CUIndexData(CurCUIndexSection
, Obj
.isLittleEndian(), 0);
808 if (!CUIndex
.parse(CUIndexData
))
809 return make_error
<DWPError
>("failed to parse cu_index");
810 if (CUIndex
.getVersion() != IndexVersion
)
811 return make_error
<DWPError
>("incompatible cu_index versions, found " +
812 utostr(CUIndex
.getVersion()) +
813 " and expecting " + utostr(IndexVersion
));
815 Out
.switchSection(InfoSection
);
816 for (const DWARFUnitIndex::Entry
&E
: CUIndex
.getRows()) {
817 auto *I
= E
.getContributions();
820 auto P
= IndexEntries
.insert(std::make_pair(E
.getSignature(), CurEntry
));
821 StringRef CUInfoSection
=
822 getSubsection(DwpSingleInfoSection
, E
, DW_SECT_INFO
);
823 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
824 parseInfoSectionUnitHeader(CUInfoSection
);
826 return HeaderOrError
.takeError();
827 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
829 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
830 Header
, getSubsection(AbbrevSection
, E
, DW_SECT_ABBREV
),
832 getSubsection(CurStrOffsetSection
, E
, DW_SECT_STR_OFFSETS
),
835 return createFileError(Input
, EID
.takeError());
836 const auto &ID
= *EID
;
838 return buildDuplicateError(*P
.first
, ID
, Input
);
839 auto &NewEntry
= P
.first
->second
;
840 NewEntry
.Name
= ID
.Name
;
841 NewEntry
.DWOName
= ID
.DWOName
;
842 NewEntry
.DWPName
= Input
;
843 for (auto Kind
: CUIndex
.getColumnKinds()) {
844 if (!isSupportedSectionKind(Kind
))
847 NewEntry
.Contributions
[getContributionIndex(Kind
, IndexVersion
)];
848 C
.setOffset(C
.getOffset() + I
->getOffset());
849 C
.setLength(I
->getLength());
852 unsigned Index
= getContributionIndex(DW_SECT_INFO
, IndexVersion
);
853 auto &C
= NewEntry
.Contributions
[Index
];
854 Out
.emitBytes(CUInfoSection
);
855 C
.setOffset(InfoSectionOffset
);
856 InfoSectionOffset
+= C
.getLength32();
859 if (!CurTUIndexSection
.empty()) {
860 llvm::DWARFSectionKind TUSectionKind
;
861 MCSection
*OutSection
;
862 StringRef TypeInputSection
;
863 // Write type units into debug info section for DWARFv5.
865 TUSectionKind
= DW_SECT_INFO
;
866 OutSection
= InfoSection
;
867 TypeInputSection
= DwpSingleInfoSection
;
869 // Write type units into debug types section for DWARF < 5.
870 if (CurTypesSection
.size() != 1)
871 return make_error
<DWPError
>(
872 "multiple type unit sections in .dwp file");
874 TUSectionKind
= DW_SECT_EXT_TYPES
;
875 OutSection
= TypesSection
;
876 TypeInputSection
= CurTypesSection
.front();
879 DWARFUnitIndex
TUIndex(TUSectionKind
);
880 DataExtractor
TUIndexData(CurTUIndexSection
, Obj
.isLittleEndian(), 0);
881 if (!TUIndex
.parse(TUIndexData
))
882 return make_error
<DWPError
>("failed to parse tu_index");
883 if (TUIndex
.getVersion() != IndexVersion
)
884 return make_error
<DWPError
>("incompatible tu_index versions, found " +
885 utostr(TUIndex
.getVersion()) +
886 " and expecting " + utostr(IndexVersion
));
888 unsigned TypesContributionIndex
=
889 getContributionIndex(TUSectionKind
, IndexVersion
);
890 if (Error Err
= addAllTypesFromDWP(
891 Out
, TypeIndexEntries
, TUIndex
, OutSection
, TypeInputSection
,
892 CurEntry
, ContributionOffsets
[TypesContributionIndex
],
893 TypesContributionIndex
, OverflowOptValue
, AnySectionOverflow
))
896 if (AnySectionOverflow
)
901 // Lie about there being no info contributions so the TU index only includes
902 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
903 // contribution to the info section, so we do not want to lie about it.
904 ContributionOffsets
[0] = 0;
906 writeIndex(Out
, MCOFI
.getDwarfTUIndexSection(), ContributionOffsets
,
907 TypeIndexEntries
, IndexVersion
);
910 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
911 // section does not exist, so no need to do anything about this.
912 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)] = 0;
913 // Unlie about the info contribution
914 ContributionOffsets
[0] = 1;
917 writeIndex(Out
, MCOFI
.getDwarfCUIndexSection(), ContributionOffsets
,
918 IndexEntries
, IndexVersion
);
920 return Error::success();