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 bool ContinueOnCuIndexOverflow
) {
189 Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
190 Twine(PrevOffset
) + Twine(", After overflow offset ") +
191 Twine(OverflowedOffset
) + Twine("."))
193 if (ContinueOnCuIndexOverflow
) {
194 WithColor::defaultWarningHandler(make_error
<DWPError
>(Msg
));
195 return Error::success();
197 return make_error
<DWPError
>(Msg
);
200 static Error
addAllTypesFromDWP(
201 MCStreamer
&Out
, MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
202 const DWARFUnitIndex
&TUIndex
, MCSection
*OutputTypes
, StringRef Types
,
203 const UnitIndexEntry
&TUEntry
, uint32_t &TypesOffset
,
204 unsigned TypesContributionIndex
, bool ContinueOnCuIndexOverflow
) {
205 Out
.switchSection(OutputTypes
);
206 for (const DWARFUnitIndex::Entry
&E
: TUIndex
.getRows()) {
207 auto *I
= E
.getContributions();
210 auto P
= TypeIndexEntries
.insert(std::make_pair(E
.getSignature(), TUEntry
));
213 auto &Entry
= P
.first
->second
;
214 // Zero out the debug_info contribution
215 Entry
.Contributions
[0] = {};
216 for (auto Kind
: TUIndex
.getColumnKinds()) {
217 if (!isSupportedSectionKind(Kind
))
220 Entry
.Contributions
[getContributionIndex(Kind
, TUIndex
.getVersion())];
221 C
.setOffset(C
.getOffset() + I
->getOffset());
222 C
.setLength(I
->getLength());
225 auto &C
= Entry
.Contributions
[TypesContributionIndex
];
226 Out
.emitBytes(Types
.substr(
228 TUEntry
.Contributions
[TypesContributionIndex
].getOffset(),
230 C
.setOffset(TypesOffset
);
231 uint32_t OldOffset
= TypesOffset
;
232 static_assert(sizeof(OldOffset
) == sizeof(TypesOffset
));
233 TypesOffset
+= C
.getLength();
234 if (OldOffset
> TypesOffset
) {
235 if (Error Err
= sectionOverflowErrorOrWarning(
236 OldOffset
, TypesOffset
, "Types", ContinueOnCuIndexOverflow
))
240 return Error::success();
243 static Error
addAllTypesFromTypesSection(
244 MCStreamer
&Out
, MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
245 MCSection
*OutputTypes
, const std::vector
<StringRef
> &TypesSections
,
246 const UnitIndexEntry
&CUEntry
, uint32_t &TypesOffset
,
247 bool ContinueOnCuIndexOverflow
) {
248 for (StringRef Types
: TypesSections
) {
249 Out
.switchSection(OutputTypes
);
251 DataExtractor
Data(Types
, true, 0);
252 while (Data
.isValidOffset(Offset
)) {
253 UnitIndexEntry Entry
= CUEntry
;
254 // Zero out the debug_info contribution
255 Entry
.Contributions
[0] = {};
256 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)];
257 C
.setOffset(TypesOffset
);
258 auto PrevOffset
= Offset
;
259 // Length of the unit, including the 4 byte length field.
260 C
.setLength(Data
.getU32(&Offset
) + 4);
262 Data
.getU16(&Offset
); // Version
263 Data
.getU32(&Offset
); // Abbrev offset
264 Data
.getU8(&Offset
); // Address size
265 auto Signature
= Data
.getU64(&Offset
);
266 Offset
= PrevOffset
+ C
.getLength32();
268 auto P
= TypeIndexEntries
.insert(std::make_pair(Signature
, Entry
));
272 Out
.emitBytes(Types
.substr(PrevOffset
, C
.getLength32()));
273 uint32_t OldOffset
= TypesOffset
;
274 TypesOffset
+= C
.getLength32();
275 if (OldOffset
> TypesOffset
) {
276 if (Error Err
= sectionOverflowErrorOrWarning(
277 OldOffset
, TypesOffset
, "types", ContinueOnCuIndexOverflow
))
282 return Error::success();
285 static std::string
buildDWODescription(StringRef Name
, StringRef DWPName
,
287 std::string Text
= "\'";
290 bool HasDWO
= !DWOName
.empty();
291 bool HasDWP
= !DWPName
.empty();
292 if (HasDWO
|| HasDWP
) {
299 if (HasDWO
&& HasDWP
)
301 if (!DWPName
.empty()) {
311 static Error
createError(StringRef Name
, Error E
) {
312 return make_error
<DWPError
>(
313 ("failure while decompressing compressed section: '" + Name
+ "', " +
314 llvm::toString(std::move(E
)))
319 handleCompressedSection(std::deque
<SmallString
<32>> &UncompressedSections
,
320 SectionRef Sec
, StringRef Name
, StringRef
&Contents
) {
321 auto *Obj
= dyn_cast
<ELFObjectFileBase
>(Sec
.getObject());
323 !(static_cast<ELFSectionRef
>(Sec
).getFlags() & ELF::SHF_COMPRESSED
))
324 return Error::success();
325 bool IsLE
= isa
<object::ELF32LEObjectFile
>(Obj
) ||
326 isa
<object::ELF64LEObjectFile
>(Obj
);
327 bool Is64
= isa
<object::ELF64LEObjectFile
>(Obj
) ||
328 isa
<object::ELF64BEObjectFile
>(Obj
);
329 Expected
<Decompressor
> Dec
= Decompressor::create(Name
, Contents
, IsLE
, Is64
);
331 return createError(Name
, Dec
.takeError());
333 UncompressedSections
.emplace_back();
334 if (Error E
= Dec
->resizeAndDecompress(UncompressedSections
.back()))
335 return createError(Name
, std::move(E
));
337 Contents
= UncompressedSections
.back();
338 return Error::success();
342 // Parse and return the header of an info section compile/type unit.
343 Expected
<InfoSectionUnitHeader
> parseInfoSectionUnitHeader(StringRef Info
) {
344 InfoSectionUnitHeader Header
;
345 Error Err
= Error::success();
347 DWARFDataExtractor
InfoData(Info
, true, 0);
348 std::tie(Header
.Length
, Header
.Format
) =
349 InfoData
.getInitialLength(&Offset
, &Err
);
351 return make_error
<DWPError
>("cannot parse compile unit length: " +
352 llvm::toString(std::move(Err
)));
354 if (!InfoData
.isValidOffset(Offset
+ (Header
.Length
- 1))) {
355 return make_error
<DWPError
>(
356 "compile unit exceeds .debug_info section range: " +
357 utostr(Offset
+ Header
.Length
) + " >= " + utostr(InfoData
.size()));
360 Header
.Version
= InfoData
.getU16(&Offset
, &Err
);
362 return make_error
<DWPError
>("cannot parse compile unit version: " +
363 llvm::toString(std::move(Err
)));
365 uint64_t MinHeaderLength
;
366 if (Header
.Version
>= 5) {
367 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
369 MinHeaderLength
= 16;
371 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
374 if (Header
.Length
< MinHeaderLength
) {
375 return make_error
<DWPError
>("unit length is too small: expected at least " +
376 utostr(MinHeaderLength
) + " got " +
377 utostr(Header
.Length
) + ".");
379 if (Header
.Version
>= 5) {
380 Header
.UnitType
= InfoData
.getU8(&Offset
);
381 Header
.AddrSize
= InfoData
.getU8(&Offset
);
382 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
383 Header
.Signature
= InfoData
.getU64(&Offset
);
384 if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
386 MinHeaderLength
+= 4;
387 if (Header
.Length
< MinHeaderLength
)
388 return make_error
<DWPError
>("type unit is missing type offset");
389 InfoData
.getU32(&Offset
);
392 // Note that, address_size and debug_abbrev_offset fields have switched
393 // places between dwarf version 4 and 5.
394 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
395 Header
.AddrSize
= InfoData
.getU8(&Offset
);
398 Header
.HeaderSize
= Offset
;
402 void writeStringsAndOffsets(MCStreamer
&Out
, DWPStringPool
&Strings
,
403 MCSection
*StrOffsetSection
,
404 StringRef CurStrSection
,
405 StringRef CurStrOffsetSection
, uint16_t Version
) {
406 // Could possibly produce an error or warning if one of these was non-null but
407 // the other was null.
408 if (CurStrSection
.empty() || CurStrOffsetSection
.empty())
411 DenseMap
<uint64_t, uint32_t> OffsetRemapping
;
413 DataExtractor
Data(CurStrSection
, true, 0);
414 uint64_t LocalOffset
= 0;
415 uint64_t PrevOffset
= 0;
416 while (const char *S
= Data
.getCStr(&LocalOffset
)) {
417 OffsetRemapping
[PrevOffset
] =
418 Strings
.getOffset(S
, LocalOffset
- PrevOffset
);
419 PrevOffset
= LocalOffset
;
422 Data
= DataExtractor(CurStrOffsetSection
, true, 0);
424 Out
.switchSection(StrOffsetSection
);
426 uint64_t HeaderSize
= debugStrOffsetsHeaderSize(Data
, Version
);
428 uint64_t Size
= CurStrOffsetSection
.size();
429 // FIXME: This can be caused by bad input and should be handled as such.
430 assert(HeaderSize
<= Size
&& "StrOffsetSection size is less than its header");
431 // Copy the header to the output.
432 Out
.emitBytes(Data
.getBytes(&Offset
, HeaderSize
));
433 while (Offset
< Size
) {
434 auto OldOffset
= Data
.getU32(&Offset
);
435 auto NewOffset
= OffsetRemapping
[OldOffset
];
436 Out
.emitIntValue(NewOffset
, 4);
440 enum AccessField
{ Offset
, Length
};
441 void writeIndexTable(MCStreamer
&Out
, ArrayRef
<unsigned> ContributionOffsets
,
442 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
443 const AccessField
&Field
) {
444 for (const auto &E
: IndexEntries
)
445 for (size_t I
= 0; I
!= std::size(E
.second
.Contributions
); ++I
)
446 if (ContributionOffsets
[I
])
447 Out
.emitIntValue((Field
== AccessField::Offset
448 ? E
.second
.Contributions
[I
].getOffset32()
449 : E
.second
.Contributions
[I
].getLength32()),
453 void writeIndex(MCStreamer
&Out
, MCSection
*Section
,
454 ArrayRef
<unsigned> ContributionOffsets
,
455 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
456 uint32_t IndexVersion
) {
457 if (IndexEntries
.empty())
460 unsigned Columns
= 0;
461 for (auto &C
: ContributionOffsets
)
465 std::vector
<unsigned> Buckets(NextPowerOf2(3 * IndexEntries
.size() / 2));
466 uint64_t Mask
= Buckets
.size() - 1;
468 for (const auto &P
: IndexEntries
) {
471 auto HP
= ((S
>> 32) & Mask
) | 1;
473 assert(S
!= IndexEntries
.begin()[Buckets
[H
] - 1].first
&&
481 Out
.switchSection(Section
);
482 Out
.emitIntValue(IndexVersion
, 4); // Version
483 Out
.emitIntValue(Columns
, 4); // Columns
484 Out
.emitIntValue(IndexEntries
.size(), 4); // Num Units
485 Out
.emitIntValue(Buckets
.size(), 4); // Num Buckets
487 // Write the signatures.
488 for (const auto &I
: Buckets
)
489 Out
.emitIntValue(I
? IndexEntries
.begin()[I
- 1].first
: 0, 8);
491 // Write the indexes.
492 for (const auto &I
: Buckets
)
493 Out
.emitIntValue(I
, 4);
495 // Write the column headers (which sections will appear in the table)
496 for (size_t I
= 0; I
!= ContributionOffsets
.size(); ++I
)
497 if (ContributionOffsets
[I
])
498 Out
.emitIntValue(getOnDiskSectionId(I
), 4);
500 // Write the offsets.
501 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Offset
);
503 // Write the lengths.
504 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
, AccessField::Length
);
507 Error
buildDuplicateError(const std::pair
<uint64_t, UnitIndexEntry
> &PrevE
,
508 const CompileUnitIdentifiers
&ID
, StringRef DWPName
) {
509 return make_error
<DWPError
>(
510 std::string("duplicate DWO ID (") + utohexstr(PrevE
.first
) + ") in " +
511 buildDWODescription(PrevE
.second
.Name
, PrevE
.second
.DWPName
,
512 PrevE
.second
.DWOName
) +
513 " and " + buildDWODescription(ID
.Name
, DWPName
, ID
.DWOName
));
517 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> &KnownSections
,
518 const MCSection
*StrSection
, const MCSection
*StrOffsetSection
,
519 const MCSection
*TypesSection
, const MCSection
*CUIndexSection
,
520 const MCSection
*TUIndexSection
, const MCSection
*InfoSection
,
521 const SectionRef
&Section
, MCStreamer
&Out
,
522 std::deque
<SmallString
<32>> &UncompressedSections
,
523 uint32_t (&ContributionOffsets
)[8], UnitIndexEntry
&CurEntry
,
524 StringRef
&CurStrSection
, StringRef
&CurStrOffsetSection
,
525 std::vector
<StringRef
> &CurTypesSection
,
526 std::vector
<StringRef
> &CurInfoSection
, StringRef
&AbbrevSection
,
527 StringRef
&CurCUIndexSection
, StringRef
&CurTUIndexSection
,
528 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> &SectionLength
) {
530 return Error::success();
532 if (Section
.isVirtual())
533 return Error::success();
535 Expected
<StringRef
> NameOrErr
= Section
.getName();
537 return NameOrErr
.takeError();
538 StringRef Name
= *NameOrErr
;
540 Expected
<StringRef
> ContentsOrErr
= Section
.getContents();
542 return ContentsOrErr
.takeError();
543 StringRef Contents
= *ContentsOrErr
;
545 if (auto Err
= handleCompressedSection(UncompressedSections
, Section
, Name
,
549 Name
= Name
.substr(Name
.find_first_not_of("._"));
551 auto SectionPair
= KnownSections
.find(Name
);
552 if (SectionPair
== KnownSections
.end())
553 return Error::success();
555 if (DWARFSectionKind Kind
= SectionPair
->second
.second
) {
556 if (Kind
!= DW_SECT_EXT_TYPES
&& Kind
!= DW_SECT_INFO
) {
557 SectionLength
.push_back(std::make_pair(Kind
, Contents
.size()));
560 if (Kind
== DW_SECT_ABBREV
) {
561 AbbrevSection
= Contents
;
565 MCSection
*OutSection
= SectionPair
->second
.first
;
566 if (OutSection
== StrOffsetSection
)
567 CurStrOffsetSection
= Contents
;
568 else if (OutSection
== StrSection
)
569 CurStrSection
= Contents
;
570 else if (OutSection
== TypesSection
)
571 CurTypesSection
.push_back(Contents
);
572 else if (OutSection
== CUIndexSection
)
573 CurCUIndexSection
= Contents
;
574 else if (OutSection
== TUIndexSection
)
575 CurTUIndexSection
= Contents
;
576 else if (OutSection
== InfoSection
)
577 CurInfoSection
.push_back(Contents
);
579 Out
.switchSection(OutSection
);
580 Out
.emitBytes(Contents
);
582 return Error::success();
585 Error
write(MCStreamer
&Out
, ArrayRef
<std::string
> Inputs
,
586 bool ContinueOnCuIndexOverflow
) {
587 const auto &MCOFI
= *Out
.getContext().getObjectFileInfo();
588 MCSection
*const StrSection
= MCOFI
.getDwarfStrDWOSection();
589 MCSection
*const StrOffsetSection
= MCOFI
.getDwarfStrOffDWOSection();
590 MCSection
*const TypesSection
= MCOFI
.getDwarfTypesDWOSection();
591 MCSection
*const CUIndexSection
= MCOFI
.getDwarfCUIndexSection();
592 MCSection
*const TUIndexSection
= MCOFI
.getDwarfTUIndexSection();
593 MCSection
*const InfoSection
= MCOFI
.getDwarfInfoDWOSection();
594 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> KnownSections
= {
595 {"debug_info.dwo", {InfoSection
, DW_SECT_INFO
}},
596 {"debug_types.dwo", {MCOFI
.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES
}},
597 {"debug_str_offsets.dwo", {StrOffsetSection
, DW_SECT_STR_OFFSETS
}},
598 {"debug_str.dwo", {StrSection
, static_cast<DWARFSectionKind
>(0)}},
599 {"debug_loc.dwo", {MCOFI
.getDwarfLocDWOSection(), DW_SECT_EXT_LOC
}},
600 {"debug_line.dwo", {MCOFI
.getDwarfLineDWOSection(), DW_SECT_LINE
}},
601 {"debug_macro.dwo", {MCOFI
.getDwarfMacroDWOSection(), DW_SECT_MACRO
}},
602 {"debug_abbrev.dwo", {MCOFI
.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV
}},
603 {"debug_loclists.dwo",
604 {MCOFI
.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS
}},
605 {"debug_rnglists.dwo",
606 {MCOFI
.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS
}},
607 {"debug_cu_index", {CUIndexSection
, static_cast<DWARFSectionKind
>(0)}},
608 {"debug_tu_index", {TUIndexSection
, static_cast<DWARFSectionKind
>(0)}}};
610 MapVector
<uint64_t, UnitIndexEntry
> IndexEntries
;
611 MapVector
<uint64_t, UnitIndexEntry
> TypeIndexEntries
;
613 uint32_t ContributionOffsets
[8] = {};
614 uint16_t Version
= 0;
615 uint32_t IndexVersion
= 0;
617 DWPStringPool
Strings(Out
, StrSection
);
619 SmallVector
<OwningBinary
<object::ObjectFile
>, 128> Objects
;
620 Objects
.reserve(Inputs
.size());
622 std::deque
<SmallString
<32>> UncompressedSections
;
624 for (const auto &Input
: Inputs
) {
625 auto ErrOrObj
= object::ObjectFile::createObjectFile(Input
);
627 return handleErrors(ErrOrObj
.takeError(),
628 [&](std::unique_ptr
<ECError
> EC
) -> Error
{
629 return createFileError(Input
, Error(std::move(EC
)));
633 auto &Obj
= *ErrOrObj
->getBinary();
634 Objects
.push_back(std::move(*ErrOrObj
));
636 UnitIndexEntry CurEntry
= {};
638 StringRef CurStrSection
;
639 StringRef CurStrOffsetSection
;
640 std::vector
<StringRef
> CurTypesSection
;
641 std::vector
<StringRef
> CurInfoSection
;
642 StringRef AbbrevSection
;
643 StringRef CurCUIndexSection
;
644 StringRef CurTUIndexSection
;
646 // This maps each section contained in this file to its length.
647 // This information is later on used to calculate the contributions,
648 // i.e. offset and length, of each compile/type unit to a section.
649 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> SectionLength
;
651 for (const auto &Section
: Obj
.sections())
652 if (auto Err
= handleSection(
653 KnownSections
, StrSection
, StrOffsetSection
, TypesSection
,
654 CUIndexSection
, TUIndexSection
, InfoSection
, Section
, Out
,
655 UncompressedSections
, ContributionOffsets
, CurEntry
,
656 CurStrSection
, CurStrOffsetSection
, CurTypesSection
,
657 CurInfoSection
, AbbrevSection
, CurCUIndexSection
,
658 CurTUIndexSection
, SectionLength
))
661 if (CurInfoSection
.empty())
664 Expected
<InfoSectionUnitHeader
> HeaderOrErr
=
665 parseInfoSectionUnitHeader(CurInfoSection
.front());
667 return HeaderOrErr
.takeError();
668 InfoSectionUnitHeader
&Header
= *HeaderOrErr
;
671 Version
= Header
.Version
;
672 IndexVersion
= Version
< 5 ? 2 : 5;
673 } else if (Version
!= Header
.Version
) {
674 return make_error
<DWPError
>("incompatible DWARF compile unit versions.");
677 writeStringsAndOffsets(Out
, Strings
, StrOffsetSection
, CurStrSection
,
678 CurStrOffsetSection
, Header
.Version
);
680 for (auto Pair
: SectionLength
) {
681 auto Index
= getContributionIndex(Pair
.first
, IndexVersion
);
682 CurEntry
.Contributions
[Index
].setOffset(ContributionOffsets
[Index
]);
683 CurEntry
.Contributions
[Index
].setLength(Pair
.second
);
684 uint32_t OldOffset
= ContributionOffsets
[Index
];
685 ContributionOffsets
[Index
] += CurEntry
.Contributions
[Index
].getLength32();
686 if (OldOffset
> ContributionOffsets
[Index
]) {
687 uint32_t SectionIndex
= 0;
688 for (auto &Section
: Obj
.sections()) {
689 if (SectionIndex
== Index
) {
690 return sectionOverflowErrorOrWarning(
691 OldOffset
, ContributionOffsets
[Index
], *Section
.getName(),
692 ContinueOnCuIndexOverflow
);
699 uint32_t &InfoSectionOffset
=
700 ContributionOffsets
[getContributionIndex(DW_SECT_INFO
, IndexVersion
)];
701 if (CurCUIndexSection
.empty()) {
702 bool FoundCUUnit
= false;
703 Out
.switchSection(InfoSection
);
704 for (StringRef Info
: CurInfoSection
) {
705 uint64_t UnitOffset
= 0;
706 while (Info
.size() > UnitOffset
) {
707 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
708 parseInfoSectionUnitHeader(Info
.substr(UnitOffset
, Info
.size()));
710 return HeaderOrError
.takeError();
711 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
713 UnitIndexEntry Entry
= CurEntry
;
714 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_INFO
,
716 C
.setOffset(InfoSectionOffset
);
717 C
.setLength(Header
.Length
+ 4);
719 if (std::numeric_limits
<uint32_t>::max() - InfoSectionOffset
<
721 if (Error Err
= sectionOverflowErrorOrWarning(
722 InfoSectionOffset
, InfoSectionOffset
+ C
.getLength32(),
723 "debug_info", ContinueOnCuIndexOverflow
))
727 UnitOffset
+= C
.getLength32();
728 if (Header
.Version
< 5 ||
729 Header
.UnitType
== dwarf::DW_UT_split_compile
) {
730 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
731 Header
, AbbrevSection
,
732 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()),
733 CurStrOffsetSection
, CurStrSection
);
736 return createFileError(Input
, EID
.takeError());
737 const auto &ID
= *EID
;
738 auto P
= IndexEntries
.insert(std::make_pair(ID
.Signature
, Entry
));
740 return buildDuplicateError(*P
.first
, ID
, "");
741 P
.first
->second
.Name
= ID
.Name
;
742 P
.first
->second
.DWOName
= ID
.DWOName
;
745 } else if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
746 auto P
= TypeIndexEntries
.insert(
747 std::make_pair(*Header
.Signature
, Entry
));
752 Info
.substr(UnitOffset
- C
.getLength32(), C
.getLength32()));
753 InfoSectionOffset
+= C
.getLength32();
758 return make_error
<DWPError
>("no compile unit found in file: " + Input
);
760 if (IndexVersion
== 2) {
761 // Add types from the .debug_types section from DWARF < 5.
762 if (Error Err
= addAllTypesFromTypesSection(
763 Out
, TypeIndexEntries
, TypesSection
, CurTypesSection
, CurEntry
,
764 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)],
765 ContinueOnCuIndexOverflow
))
771 if (CurInfoSection
.size() != 1)
772 return make_error
<DWPError
>("expected exactly one occurrence of a debug "
773 "info section in a .dwp file");
774 StringRef DwpSingleInfoSection
= CurInfoSection
.front();
776 DWARFUnitIndex
CUIndex(DW_SECT_INFO
);
777 DataExtractor
CUIndexData(CurCUIndexSection
, Obj
.isLittleEndian(), 0);
778 if (!CUIndex
.parse(CUIndexData
))
779 return make_error
<DWPError
>("failed to parse cu_index");
780 if (CUIndex
.getVersion() != IndexVersion
)
781 return make_error
<DWPError
>("incompatible cu_index versions, found " +
782 utostr(CUIndex
.getVersion()) +
783 " and expecting " + utostr(IndexVersion
));
785 Out
.switchSection(InfoSection
);
786 for (const DWARFUnitIndex::Entry
&E
: CUIndex
.getRows()) {
787 auto *I
= E
.getContributions();
790 auto P
= IndexEntries
.insert(std::make_pair(E
.getSignature(), CurEntry
));
791 StringRef CUInfoSection
=
792 getSubsection(DwpSingleInfoSection
, E
, DW_SECT_INFO
);
793 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
794 parseInfoSectionUnitHeader(CUInfoSection
);
796 return HeaderOrError
.takeError();
797 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
799 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
800 Header
, getSubsection(AbbrevSection
, E
, DW_SECT_ABBREV
),
802 getSubsection(CurStrOffsetSection
, E
, DW_SECT_STR_OFFSETS
),
805 return createFileError(Input
, EID
.takeError());
806 const auto &ID
= *EID
;
808 return buildDuplicateError(*P
.first
, ID
, Input
);
809 auto &NewEntry
= P
.first
->second
;
810 NewEntry
.Name
= ID
.Name
;
811 NewEntry
.DWOName
= ID
.DWOName
;
812 NewEntry
.DWPName
= Input
;
813 for (auto Kind
: CUIndex
.getColumnKinds()) {
814 if (!isSupportedSectionKind(Kind
))
817 NewEntry
.Contributions
[getContributionIndex(Kind
, IndexVersion
)];
818 C
.setOffset(C
.getOffset() + I
->getOffset());
819 C
.setLength(I
->getLength());
822 unsigned Index
= getContributionIndex(DW_SECT_INFO
, IndexVersion
);
823 auto &C
= NewEntry
.Contributions
[Index
];
824 Out
.emitBytes(CUInfoSection
);
825 C
.setOffset(InfoSectionOffset
);
826 InfoSectionOffset
+= C
.getLength32();
829 if (!CurTUIndexSection
.empty()) {
830 llvm::DWARFSectionKind TUSectionKind
;
831 MCSection
*OutSection
;
832 StringRef TypeInputSection
;
833 // Write type units into debug info section for DWARFv5.
835 TUSectionKind
= DW_SECT_INFO
;
836 OutSection
= InfoSection
;
837 TypeInputSection
= DwpSingleInfoSection
;
839 // Write type units into debug types section for DWARF < 5.
840 if (CurTypesSection
.size() != 1)
841 return make_error
<DWPError
>(
842 "multiple type unit sections in .dwp file");
844 TUSectionKind
= DW_SECT_EXT_TYPES
;
845 OutSection
= TypesSection
;
846 TypeInputSection
= CurTypesSection
.front();
849 DWARFUnitIndex
TUIndex(TUSectionKind
);
850 DataExtractor
TUIndexData(CurTUIndexSection
, Obj
.isLittleEndian(), 0);
851 if (!TUIndex
.parse(TUIndexData
))
852 return make_error
<DWPError
>("failed to parse tu_index");
853 if (TUIndex
.getVersion() != IndexVersion
)
854 return make_error
<DWPError
>("incompatible tu_index versions, found " +
855 utostr(TUIndex
.getVersion()) +
856 " and expecting " + utostr(IndexVersion
));
858 unsigned TypesContributionIndex
=
859 getContributionIndex(TUSectionKind
, IndexVersion
);
860 if (Error Err
= addAllTypesFromDWP(
861 Out
, TypeIndexEntries
, TUIndex
, OutSection
, TypeInputSection
,
862 CurEntry
, ContributionOffsets
[TypesContributionIndex
],
863 TypesContributionIndex
, ContinueOnCuIndexOverflow
))
869 // Lie about there being no info contributions so the TU index only includes
870 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
871 // contribution to the info section, so we do not want to lie about it.
872 ContributionOffsets
[0] = 0;
874 writeIndex(Out
, MCOFI
.getDwarfTUIndexSection(), ContributionOffsets
,
875 TypeIndexEntries
, IndexVersion
);
878 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
879 // section does not exist, so no need to do anything about this.
880 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)] = 0;
881 // Unlie about the info contribution
882 ContributionOffsets
[0] = 1;
885 writeIndex(Out
, MCOFI
.getDwarfCUIndexSection(), ContributionOffsets
,
886 IndexEntries
, IndexVersion
);
888 return Error::success();