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/DWP/DWPError.h"
15 #include "llvm/MC/MCContext.h"
16 #include "llvm/MC/MCObjectFileInfo.h"
17 #include "llvm/MC/MCTargetOptionsCommandFlags.h"
18 #include "llvm/Object/Decompressor.h"
21 using namespace llvm::object
;
23 static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags
;
25 // Returns the size of debug_str_offsets section headers in bytes.
26 static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData
,
27 uint16_t DwarfVersion
) {
28 if (DwarfVersion
<= 4)
29 return 0; // There is no header before dwarf 5.
31 uint64_t Length
= StrOffsetsData
.getU32(&Offset
);
32 if (Length
== llvm::dwarf::DW_LENGTH_DWARF64
)
33 return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
34 return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
37 static uint64_t getCUAbbrev(StringRef Abbrev
, uint64_t AbbrCode
) {
39 DataExtractor
AbbrevData(Abbrev
, true, 0);
40 while (AbbrevData
.getULEB128(&Offset
) != AbbrCode
) {
42 AbbrevData
.getULEB128(&Offset
);
44 AbbrevData
.getU8(&Offset
);
46 while (AbbrevData
.getULEB128(&Offset
) | AbbrevData
.getULEB128(&Offset
))
52 static Expected
<const char *>
53 getIndexedString(dwarf::Form Form
, DataExtractor InfoData
, uint64_t &InfoOffset
,
54 StringRef StrOffsets
, StringRef Str
, uint16_t Version
) {
55 if (Form
== dwarf::DW_FORM_string
)
56 return InfoData
.getCStr(&InfoOffset
);
59 case dwarf::DW_FORM_strx1
:
60 StrIndex
= InfoData
.getU8(&InfoOffset
);
62 case dwarf::DW_FORM_strx2
:
63 StrIndex
= InfoData
.getU16(&InfoOffset
);
65 case dwarf::DW_FORM_strx3
:
66 StrIndex
= InfoData
.getU24(&InfoOffset
);
68 case dwarf::DW_FORM_strx4
:
69 StrIndex
= InfoData
.getU32(&InfoOffset
);
71 case dwarf::DW_FORM_strx
:
72 case dwarf::DW_FORM_GNU_str_index
:
73 StrIndex
= InfoData
.getULEB128(&InfoOffset
);
76 return make_error
<DWPError
>(
77 "string field must be encoded with one of the following: "
78 "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
79 "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
81 DataExtractor
StrOffsetsData(StrOffsets
, true, 0);
82 uint64_t StrOffsetsOffset
= 4 * StrIndex
;
83 StrOffsetsOffset
+= debugStrOffsetsHeaderSize(StrOffsetsData
, Version
);
85 uint64_t StrOffset
= StrOffsetsData
.getU32(&StrOffsetsOffset
);
86 DataExtractor
StrData(Str
, true, 0);
87 return StrData
.getCStr(&StrOffset
);
90 static Expected
<CompileUnitIdentifiers
>
91 getCUIdentifiers(InfoSectionUnitHeader
&Header
, StringRef Abbrev
,
92 StringRef Info
, StringRef StrOffsets
, StringRef Str
) {
93 DataExtractor
InfoData(Info
, true, 0);
94 uint64_t Offset
= Header
.HeaderSize
;
95 if (Header
.Version
>= 5 && Header
.UnitType
!= dwarf::DW_UT_split_compile
)
96 return make_error
<DWPError
>(
97 std::string("unit type DW_UT_split_compile type not found in "
98 "debug_info header. Unexpected unit type 0x" +
99 utostr(Header
.UnitType
) + " found"));
101 CompileUnitIdentifiers ID
;
103 uint32_t AbbrCode
= InfoData
.getULEB128(&Offset
);
104 DataExtractor
AbbrevData(Abbrev
, true, 0);
105 uint64_t AbbrevOffset
= getCUAbbrev(Abbrev
, AbbrCode
);
106 auto Tag
= static_cast<dwarf::Tag
>(AbbrevData
.getULEB128(&AbbrevOffset
));
107 if (Tag
!= dwarf::DW_TAG_compile_unit
)
108 return make_error
<DWPError
>("top level DIE is not a compile unit");
110 AbbrevData
.getU8(&AbbrevOffset
);
113 while ((Name
= AbbrevData
.getULEB128(&AbbrevOffset
)) |
114 (Form
= static_cast<dwarf::Form
>(
115 AbbrevData
.getULEB128(&AbbrevOffset
))) &&
116 (Name
!= 0 || Form
!= 0)) {
118 case dwarf::DW_AT_name
: {
119 Expected
<const char *> EName
= getIndexedString(
120 Form
, InfoData
, Offset
, StrOffsets
, Str
, Header
.Version
);
122 return EName
.takeError();
126 case dwarf::DW_AT_GNU_dwo_name
:
127 case dwarf::DW_AT_dwo_name
: {
128 Expected
<const char *> EName
= getIndexedString(
129 Form
, InfoData
, Offset
, StrOffsets
, Str
, Header
.Version
);
131 return EName
.takeError();
135 case dwarf::DW_AT_GNU_dwo_id
:
136 Header
.Signature
= InfoData
.getU64(&Offset
);
139 DWARFFormValue::skipValue(
140 Form
, InfoData
, &Offset
,
141 dwarf::FormParams({Header
.Version
, Header
.AddrSize
, Header
.Format
}));
144 if (!Header
.Signature
)
145 return make_error
<DWPError
>("compile unit missing dwo_id");
146 ID
.Signature
= *Header
.Signature
;
150 static bool isSupportedSectionKind(DWARFSectionKind Kind
) {
151 return Kind
!= DW_SECT_EXT_unknown
;
155 // Convert an internal section identifier into the index to use with
156 // UnitIndexEntry::Contributions.
157 unsigned getContributionIndex(DWARFSectionKind Kind
, uint32_t IndexVersion
) {
158 assert(serializeSectionKind(Kind
, IndexVersion
) >= DW_SECT_INFO
);
159 return serializeSectionKind(Kind
, IndexVersion
) - DW_SECT_INFO
;
163 // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
164 // value of the section identifier.
165 static unsigned getOnDiskSectionId(unsigned Index
) {
166 return Index
+ DW_SECT_INFO
;
169 static StringRef
getSubsection(StringRef Section
,
170 const DWARFUnitIndex::Entry
&Entry
,
171 DWARFSectionKind Kind
) {
172 const auto *Off
= Entry
.getContribution(Kind
);
175 return Section
.substr(Off
->Offset
, Off
->Length
);
179 addAllTypesFromDWP(MCStreamer
&Out
,
180 MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
181 const DWARFUnitIndex
&TUIndex
, MCSection
*OutputTypes
,
182 StringRef Types
, const UnitIndexEntry
&TUEntry
,
183 uint32_t &TypesOffset
, unsigned TypesContributionIndex
) {
184 Out
.SwitchSection(OutputTypes
);
185 for (const DWARFUnitIndex::Entry
&E
: TUIndex
.getRows()) {
186 auto *I
= E
.getContributions();
189 auto P
= TypeIndexEntries
.insert(std::make_pair(E
.getSignature(), TUEntry
));
192 auto &Entry
= P
.first
->second
;
193 // Zero out the debug_info contribution
194 Entry
.Contributions
[0] = {};
195 for (auto Kind
: TUIndex
.getColumnKinds()) {
196 if (!isSupportedSectionKind(Kind
))
199 Entry
.Contributions
[getContributionIndex(Kind
, TUIndex
.getVersion())];
200 C
.Offset
+= I
->Offset
;
201 C
.Length
= I
->Length
;
204 auto &C
= Entry
.Contributions
[TypesContributionIndex
];
205 Out
.emitBytes(Types
.substr(
206 C
.Offset
- TUEntry
.Contributions
[TypesContributionIndex
].Offset
,
208 C
.Offset
= TypesOffset
;
209 TypesOffset
+= C
.Length
;
213 static void addAllTypesFromTypesSection(
214 MCStreamer
&Out
, MapVector
<uint64_t, UnitIndexEntry
> &TypeIndexEntries
,
215 MCSection
*OutputTypes
, const std::vector
<StringRef
> &TypesSections
,
216 const UnitIndexEntry
&CUEntry
, uint32_t &TypesOffset
) {
217 for (StringRef Types
: TypesSections
) {
218 Out
.SwitchSection(OutputTypes
);
220 DataExtractor
Data(Types
, true, 0);
221 while (Data
.isValidOffset(Offset
)) {
222 UnitIndexEntry Entry
= CUEntry
;
223 // Zero out the debug_info contribution
224 Entry
.Contributions
[0] = {};
225 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)];
226 C
.Offset
= TypesOffset
;
227 auto PrevOffset
= Offset
;
228 // Length of the unit, including the 4 byte length field.
229 C
.Length
= Data
.getU32(&Offset
) + 4;
231 Data
.getU16(&Offset
); // Version
232 Data
.getU32(&Offset
); // Abbrev offset
233 Data
.getU8(&Offset
); // Address size
234 auto Signature
= Data
.getU64(&Offset
);
235 Offset
= PrevOffset
+ C
.Length
;
237 auto P
= TypeIndexEntries
.insert(std::make_pair(Signature
, Entry
));
241 Out
.emitBytes(Types
.substr(PrevOffset
, C
.Length
));
242 TypesOffset
+= C
.Length
;
247 static std::string
buildDWODescription(StringRef Name
, StringRef DWPName
,
249 std::string Text
= "\'";
252 if (!DWPName
.empty()) {
254 if (!DWOName
.empty()) {
266 static Error
createError(StringRef Name
, Error E
) {
267 return make_error
<DWPError
>(
268 ("failure while decompressing compressed section: '" + Name
+ "', " +
269 llvm::toString(std::move(E
)))
274 handleCompressedSection(std::deque
<SmallString
<32>> &UncompressedSections
,
275 StringRef
&Name
, StringRef
&Contents
) {
276 if (!Decompressor::isGnuStyle(Name
))
277 return Error::success();
279 Expected
<Decompressor
> Dec
=
280 Decompressor::create(Name
, Contents
, false /*IsLE*/, false /*Is64Bit*/);
282 return createError(Name
, Dec
.takeError());
284 UncompressedSections
.emplace_back();
285 if (Error E
= Dec
->resizeAndDecompress(UncompressedSections
.back()))
286 return createError(Name
, std::move(E
));
288 Name
= Name
.substr(2); // Drop ".z"
289 Contents
= UncompressedSections
.back();
290 return Error::success();
294 // Parse and return the header of an info section compile/type unit.
295 Expected
<InfoSectionUnitHeader
> parseInfoSectionUnitHeader(StringRef Info
) {
296 InfoSectionUnitHeader Header
;
297 Error Err
= Error::success();
299 DWARFDataExtractor
InfoData(Info
, true, 0);
300 std::tie(Header
.Length
, Header
.Format
) =
301 InfoData
.getInitialLength(&Offset
, &Err
);
303 return make_error
<DWPError
>("cannot parse compile unit length: " +
304 llvm::toString(std::move(Err
)));
306 if (!InfoData
.isValidOffset(Offset
+ (Header
.Length
- 1))) {
307 return make_error
<DWPError
>(
308 "compile unit exceeds .debug_info section range: " +
309 utostr(Offset
+ Header
.Length
) + " >= " + utostr(InfoData
.size()));
312 Header
.Version
= InfoData
.getU16(&Offset
, &Err
);
314 return make_error
<DWPError
>("cannot parse compile unit version: " +
315 llvm::toString(std::move(Err
)));
317 uint64_t MinHeaderLength
;
318 if (Header
.Version
>= 5) {
319 // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
321 MinHeaderLength
= 16;
323 // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
326 if (Header
.Length
< MinHeaderLength
) {
327 return make_error
<DWPError
>("unit length is too small: expected at least " +
328 utostr(MinHeaderLength
) + " got " +
329 utostr(Header
.Length
) + ".");
331 if (Header
.Version
>= 5) {
332 Header
.UnitType
= InfoData
.getU8(&Offset
);
333 Header
.AddrSize
= InfoData
.getU8(&Offset
);
334 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
335 Header
.Signature
= InfoData
.getU64(&Offset
);
336 if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
338 MinHeaderLength
+= 4;
339 if (Header
.Length
< MinHeaderLength
)
340 return make_error
<DWPError
>("type unit is missing type offset");
341 InfoData
.getU32(&Offset
);
344 // Note that, address_size and debug_abbrev_offset fields have switched
345 // places between dwarf version 4 and 5.
346 Header
.DebugAbbrevOffset
= InfoData
.getU32(&Offset
);
347 Header
.AddrSize
= InfoData
.getU8(&Offset
);
350 Header
.HeaderSize
= Offset
;
354 void writeStringsAndOffsets(MCStreamer
&Out
, DWPStringPool
&Strings
,
355 MCSection
*StrOffsetSection
,
356 StringRef CurStrSection
,
357 StringRef CurStrOffsetSection
, uint16_t Version
) {
358 // Could possibly produce an error or warning if one of these was non-null but
359 // the other was null.
360 if (CurStrSection
.empty() || CurStrOffsetSection
.empty())
363 DenseMap
<uint64_t, uint32_t> OffsetRemapping
;
365 DataExtractor
Data(CurStrSection
, true, 0);
366 uint64_t LocalOffset
= 0;
367 uint64_t PrevOffset
= 0;
368 while (const char *S
= Data
.getCStr(&LocalOffset
)) {
369 OffsetRemapping
[PrevOffset
] =
370 Strings
.getOffset(S
, LocalOffset
- PrevOffset
);
371 PrevOffset
= LocalOffset
;
374 Data
= DataExtractor(CurStrOffsetSection
, true, 0);
376 Out
.SwitchSection(StrOffsetSection
);
378 uint64_t HeaderSize
= debugStrOffsetsHeaderSize(Data
, Version
);
380 uint64_t Size
= CurStrOffsetSection
.size();
381 // FIXME: This can be caused by bad input and should be handled as such.
382 assert(HeaderSize
<= Size
&& "StrOffsetSection size is less than its header");
383 // Copy the header to the output.
384 Out
.emitBytes(Data
.getBytes(&Offset
, HeaderSize
));
385 while (Offset
< Size
) {
386 auto OldOffset
= Data
.getU32(&Offset
);
387 auto NewOffset
= OffsetRemapping
[OldOffset
];
388 Out
.emitIntValue(NewOffset
, 4);
392 void writeIndexTable(
393 MCStreamer
&Out
, ArrayRef
<unsigned> ContributionOffsets
,
394 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
395 uint32_t DWARFUnitIndex::Entry::SectionContribution::*Field
) {
396 for (const auto &E
: IndexEntries
)
397 for (size_t I
= 0; I
!= array_lengthof(E
.second
.Contributions
); ++I
)
398 if (ContributionOffsets
[I
])
399 Out
.emitIntValue(E
.second
.Contributions
[I
].*Field
, 4);
402 void writeIndex(MCStreamer
&Out
, MCSection
*Section
,
403 ArrayRef
<unsigned> ContributionOffsets
,
404 const MapVector
<uint64_t, UnitIndexEntry
> &IndexEntries
,
405 uint32_t IndexVersion
) {
406 if (IndexEntries
.empty())
409 unsigned Columns
= 0;
410 for (auto &C
: ContributionOffsets
)
414 std::vector
<unsigned> Buckets(NextPowerOf2(3 * IndexEntries
.size() / 2));
415 uint64_t Mask
= Buckets
.size() - 1;
417 for (const auto &P
: IndexEntries
) {
420 auto HP
= ((S
>> 32) & Mask
) | 1;
422 assert(S
!= IndexEntries
.begin()[Buckets
[H
] - 1].first
&&
430 Out
.SwitchSection(Section
);
431 Out
.emitIntValue(IndexVersion
, 4); // Version
432 Out
.emitIntValue(Columns
, 4); // Columns
433 Out
.emitIntValue(IndexEntries
.size(), 4); // Num Units
434 Out
.emitIntValue(Buckets
.size(), 4); // Num Buckets
436 // Write the signatures.
437 for (const auto &I
: Buckets
)
438 Out
.emitIntValue(I
? IndexEntries
.begin()[I
- 1].first
: 0, 8);
440 // Write the indexes.
441 for (const auto &I
: Buckets
)
442 Out
.emitIntValue(I
, 4);
444 // Write the column headers (which sections will appear in the table)
445 for (size_t I
= 0; I
!= ContributionOffsets
.size(); ++I
)
446 if (ContributionOffsets
[I
])
447 Out
.emitIntValue(getOnDiskSectionId(I
), 4);
449 // Write the offsets.
450 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
,
451 &DWARFUnitIndex::Entry::SectionContribution::Offset
);
453 // Write the lengths.
454 writeIndexTable(Out
, ContributionOffsets
, IndexEntries
,
455 &DWARFUnitIndex::Entry::SectionContribution::Length
);
458 Error
buildDuplicateError(const std::pair
<uint64_t, UnitIndexEntry
> &PrevE
,
459 const CompileUnitIdentifiers
&ID
, StringRef DWPName
) {
460 return make_error
<DWPError
>(
461 std::string("duplicate DWO ID (") + utohexstr(PrevE
.first
) + ") in " +
462 buildDWODescription(PrevE
.second
.Name
, PrevE
.second
.DWPName
,
463 PrevE
.second
.DWOName
) +
464 " and " + buildDWODescription(ID
.Name
, DWPName
, ID
.DWOName
));
468 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> &KnownSections
,
469 const MCSection
*StrSection
, const MCSection
*StrOffsetSection
,
470 const MCSection
*TypesSection
, const MCSection
*CUIndexSection
,
471 const MCSection
*TUIndexSection
, const MCSection
*InfoSection
,
472 const SectionRef
&Section
, MCStreamer
&Out
,
473 std::deque
<SmallString
<32>> &UncompressedSections
,
474 uint32_t (&ContributionOffsets
)[8], UnitIndexEntry
&CurEntry
,
475 StringRef
&CurStrSection
, StringRef
&CurStrOffsetSection
,
476 std::vector
<StringRef
> &CurTypesSection
,
477 std::vector
<StringRef
> &CurInfoSection
, StringRef
&AbbrevSection
,
478 StringRef
&CurCUIndexSection
, StringRef
&CurTUIndexSection
,
479 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> &SectionLength
) {
481 return Error::success();
483 if (Section
.isVirtual())
484 return Error::success();
486 Expected
<StringRef
> NameOrErr
= Section
.getName();
488 return NameOrErr
.takeError();
489 StringRef Name
= *NameOrErr
;
491 Expected
<StringRef
> ContentsOrErr
= Section
.getContents();
493 return ContentsOrErr
.takeError();
494 StringRef Contents
= *ContentsOrErr
;
496 if (auto Err
= handleCompressedSection(UncompressedSections
, Name
, Contents
))
499 Name
= Name
.substr(Name
.find_first_not_of("._"));
501 auto SectionPair
= KnownSections
.find(Name
);
502 if (SectionPair
== KnownSections
.end())
503 return Error::success();
505 if (DWARFSectionKind Kind
= SectionPair
->second
.second
) {
506 if (Kind
!= DW_SECT_EXT_TYPES
&& Kind
!= DW_SECT_INFO
) {
507 SectionLength
.push_back(std::make_pair(Kind
, Contents
.size()));
510 if (Kind
== DW_SECT_ABBREV
) {
511 AbbrevSection
= Contents
;
515 MCSection
*OutSection
= SectionPair
->second
.first
;
516 if (OutSection
== StrOffsetSection
)
517 CurStrOffsetSection
= Contents
;
518 else if (OutSection
== StrSection
)
519 CurStrSection
= Contents
;
520 else if (OutSection
== TypesSection
)
521 CurTypesSection
.push_back(Contents
);
522 else if (OutSection
== CUIndexSection
)
523 CurCUIndexSection
= Contents
;
524 else if (OutSection
== TUIndexSection
)
525 CurTUIndexSection
= Contents
;
526 else if (OutSection
== InfoSection
)
527 CurInfoSection
.push_back(Contents
);
529 Out
.SwitchSection(OutSection
);
530 Out
.emitBytes(Contents
);
532 return Error::success();
535 Error
write(MCStreamer
&Out
, ArrayRef
<std::string
> Inputs
) {
536 const auto &MCOFI
= *Out
.getContext().getObjectFileInfo();
537 MCSection
*const StrSection
= MCOFI
.getDwarfStrDWOSection();
538 MCSection
*const StrOffsetSection
= MCOFI
.getDwarfStrOffDWOSection();
539 MCSection
*const TypesSection
= MCOFI
.getDwarfTypesDWOSection();
540 MCSection
*const CUIndexSection
= MCOFI
.getDwarfCUIndexSection();
541 MCSection
*const TUIndexSection
= MCOFI
.getDwarfTUIndexSection();
542 MCSection
*const InfoSection
= MCOFI
.getDwarfInfoDWOSection();
543 const StringMap
<std::pair
<MCSection
*, DWARFSectionKind
>> KnownSections
= {
544 {"debug_info.dwo", {InfoSection
, DW_SECT_INFO
}},
545 {"debug_types.dwo", {MCOFI
.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES
}},
546 {"debug_str_offsets.dwo", {StrOffsetSection
, DW_SECT_STR_OFFSETS
}},
547 {"debug_str.dwo", {StrSection
, static_cast<DWARFSectionKind
>(0)}},
548 {"debug_loc.dwo", {MCOFI
.getDwarfLocDWOSection(), DW_SECT_EXT_LOC
}},
549 {"debug_line.dwo", {MCOFI
.getDwarfLineDWOSection(), DW_SECT_LINE
}},
550 {"debug_macro.dwo", {MCOFI
.getDwarfMacroDWOSection(), DW_SECT_MACRO
}},
551 {"debug_abbrev.dwo", {MCOFI
.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV
}},
552 {"debug_loclists.dwo",
553 {MCOFI
.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS
}},
554 {"debug_rnglists.dwo",
555 {MCOFI
.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS
}},
556 {"debug_cu_index", {CUIndexSection
, static_cast<DWARFSectionKind
>(0)}},
557 {"debug_tu_index", {TUIndexSection
, static_cast<DWARFSectionKind
>(0)}}};
559 MapVector
<uint64_t, UnitIndexEntry
> IndexEntries
;
560 MapVector
<uint64_t, UnitIndexEntry
> TypeIndexEntries
;
562 uint32_t ContributionOffsets
[8] = {};
563 uint16_t Version
= 0;
564 uint32_t IndexVersion
= 0;
566 DWPStringPool
Strings(Out
, StrSection
);
568 SmallVector
<OwningBinary
<object::ObjectFile
>, 128> Objects
;
569 Objects
.reserve(Inputs
.size());
571 std::deque
<SmallString
<32>> UncompressedSections
;
573 for (const auto &Input
: Inputs
) {
574 auto ErrOrObj
= object::ObjectFile::createObjectFile(Input
);
576 return ErrOrObj
.takeError();
578 auto &Obj
= *ErrOrObj
->getBinary();
579 Objects
.push_back(std::move(*ErrOrObj
));
581 UnitIndexEntry CurEntry
= {};
583 StringRef CurStrSection
;
584 StringRef CurStrOffsetSection
;
585 std::vector
<StringRef
> CurTypesSection
;
586 std::vector
<StringRef
> CurInfoSection
;
587 StringRef AbbrevSection
;
588 StringRef CurCUIndexSection
;
589 StringRef CurTUIndexSection
;
591 // This maps each section contained in this file to its length.
592 // This information is later on used to calculate the contributions,
593 // i.e. offset and length, of each compile/type unit to a section.
594 std::vector
<std::pair
<DWARFSectionKind
, uint32_t>> SectionLength
;
596 for (const auto &Section
: Obj
.sections())
597 if (auto Err
= handleSection(
598 KnownSections
, StrSection
, StrOffsetSection
, TypesSection
,
599 CUIndexSection
, TUIndexSection
, InfoSection
, Section
, Out
,
600 UncompressedSections
, ContributionOffsets
, CurEntry
,
601 CurStrSection
, CurStrOffsetSection
, CurTypesSection
,
602 CurInfoSection
, AbbrevSection
, CurCUIndexSection
,
603 CurTUIndexSection
, SectionLength
))
606 if (CurInfoSection
.empty())
609 Expected
<InfoSectionUnitHeader
> HeaderOrErr
=
610 parseInfoSectionUnitHeader(CurInfoSection
.front());
612 return HeaderOrErr
.takeError();
613 InfoSectionUnitHeader
&Header
= *HeaderOrErr
;
616 Version
= Header
.Version
;
617 IndexVersion
= Version
< 5 ? 2 : 5;
618 } else if (Version
!= Header
.Version
) {
619 return make_error
<DWPError
>("incompatible DWARF compile unit versions.");
622 writeStringsAndOffsets(Out
, Strings
, StrOffsetSection
, CurStrSection
,
623 CurStrOffsetSection
, Header
.Version
);
625 for (auto Pair
: SectionLength
) {
626 auto Index
= getContributionIndex(Pair
.first
, IndexVersion
);
627 CurEntry
.Contributions
[Index
].Offset
= ContributionOffsets
[Index
];
628 ContributionOffsets
[Index
] +=
629 (CurEntry
.Contributions
[Index
].Length
= Pair
.second
);
632 uint32_t &InfoSectionOffset
=
633 ContributionOffsets
[getContributionIndex(DW_SECT_INFO
, IndexVersion
)];
634 if (CurCUIndexSection
.empty()) {
635 bool FoundCUUnit
= false;
636 Out
.SwitchSection(InfoSection
);
637 for (StringRef Info
: CurInfoSection
) {
638 uint64_t UnitOffset
= 0;
639 while (Info
.size() > UnitOffset
) {
640 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
641 parseInfoSectionUnitHeader(Info
.substr(UnitOffset
, Info
.size()));
643 return HeaderOrError
.takeError();
644 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
646 UnitIndexEntry Entry
= CurEntry
;
647 auto &C
= Entry
.Contributions
[getContributionIndex(DW_SECT_INFO
,
649 C
.Offset
= InfoSectionOffset
;
650 C
.Length
= Header
.Length
+ 4;
651 UnitOffset
+= C
.Length
;
652 if (Header
.Version
< 5 ||
653 Header
.UnitType
== dwarf::DW_UT_split_compile
) {
654 Expected
<CompileUnitIdentifiers
> EID
=
655 getCUIdentifiers(Header
, AbbrevSection
,
656 Info
.substr(UnitOffset
- C
.Length
, C
.Length
),
657 CurStrOffsetSection
, CurStrSection
);
660 return createFileError(Input
, EID
.takeError());
661 const auto &ID
= *EID
;
662 auto P
= IndexEntries
.insert(std::make_pair(ID
.Signature
, Entry
));
664 return buildDuplicateError(*P
.first
, ID
, "");
665 P
.first
->second
.Name
= ID
.Name
;
666 P
.first
->second
.DWOName
= ID
.DWOName
;
669 } else if (Header
.UnitType
== dwarf::DW_UT_split_type
) {
670 auto P
= TypeIndexEntries
.insert(
671 std::make_pair(Header
.Signature
.getValue(), Entry
));
675 Out
.emitBytes(Info
.substr(UnitOffset
- C
.Length
, C
.Length
));
676 InfoSectionOffset
+= C
.Length
;
681 return make_error
<DWPError
>("no compile unit found in file: " + Input
);
683 if (IndexVersion
== 2) {
684 // Add types from the .debug_types section from DWARF < 5.
685 addAllTypesFromTypesSection(
686 Out
, TypeIndexEntries
, TypesSection
, CurTypesSection
, CurEntry
,
687 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)]);
692 if (CurInfoSection
.size() != 1)
693 return make_error
<DWPError
>("expected exactly one occurrence of a debug "
694 "info section in a .dwp file");
695 StringRef DwpSingleInfoSection
= CurInfoSection
.front();
697 DWARFUnitIndex
CUIndex(DW_SECT_INFO
);
698 DataExtractor
CUIndexData(CurCUIndexSection
, Obj
.isLittleEndian(), 0);
699 if (!CUIndex
.parse(CUIndexData
))
700 return make_error
<DWPError
>("failed to parse cu_index");
701 if (CUIndex
.getVersion() != IndexVersion
)
702 return make_error
<DWPError
>("incompatible cu_index versions, found " +
703 utostr(CUIndex
.getVersion()) +
704 " and expecting " + utostr(IndexVersion
));
706 Out
.SwitchSection(InfoSection
);
707 for (const DWARFUnitIndex::Entry
&E
: CUIndex
.getRows()) {
708 auto *I
= E
.getContributions();
711 auto P
= IndexEntries
.insert(std::make_pair(E
.getSignature(), CurEntry
));
712 StringRef CUInfoSection
=
713 getSubsection(DwpSingleInfoSection
, E
, DW_SECT_INFO
);
714 Expected
<InfoSectionUnitHeader
> HeaderOrError
=
715 parseInfoSectionUnitHeader(CUInfoSection
);
717 return HeaderOrError
.takeError();
718 InfoSectionUnitHeader
&Header
= *HeaderOrError
;
720 Expected
<CompileUnitIdentifiers
> EID
= getCUIdentifiers(
721 Header
, getSubsection(AbbrevSection
, E
, DW_SECT_ABBREV
),
723 getSubsection(CurStrOffsetSection
, E
, DW_SECT_STR_OFFSETS
),
726 return createFileError(Input
, EID
.takeError());
727 const auto &ID
= *EID
;
729 return buildDuplicateError(*P
.first
, ID
, Input
);
730 auto &NewEntry
= P
.first
->second
;
731 NewEntry
.Name
= ID
.Name
;
732 NewEntry
.DWOName
= ID
.DWOName
;
733 NewEntry
.DWPName
= Input
;
734 for (auto Kind
: CUIndex
.getColumnKinds()) {
735 if (!isSupportedSectionKind(Kind
))
738 NewEntry
.Contributions
[getContributionIndex(Kind
, IndexVersion
)];
739 C
.Offset
+= I
->Offset
;
740 C
.Length
= I
->Length
;
743 unsigned Index
= getContributionIndex(DW_SECT_INFO
, IndexVersion
);
744 auto &C
= NewEntry
.Contributions
[Index
];
745 Out
.emitBytes(CUInfoSection
);
746 C
.Offset
= InfoSectionOffset
;
747 InfoSectionOffset
+= C
.Length
;
750 if (!CurTUIndexSection
.empty()) {
751 llvm::DWARFSectionKind TUSectionKind
;
752 MCSection
*OutSection
;
753 StringRef TypeInputSection
;
754 // Write type units into debug info section for DWARFv5.
756 TUSectionKind
= DW_SECT_INFO
;
757 OutSection
= InfoSection
;
758 TypeInputSection
= DwpSingleInfoSection
;
760 // Write type units into debug types section for DWARF < 5.
761 if (CurTypesSection
.size() != 1)
762 return make_error
<DWPError
>(
763 "multiple type unit sections in .dwp file");
765 TUSectionKind
= DW_SECT_EXT_TYPES
;
766 OutSection
= TypesSection
;
767 TypeInputSection
= CurTypesSection
.front();
770 DWARFUnitIndex
TUIndex(TUSectionKind
);
771 DataExtractor
TUIndexData(CurTUIndexSection
, Obj
.isLittleEndian(), 0);
772 if (!TUIndex
.parse(TUIndexData
))
773 return make_error
<DWPError
>("failed to parse tu_index");
774 if (TUIndex
.getVersion() != IndexVersion
)
775 return make_error
<DWPError
>("incompatible tu_index versions, found " +
776 utostr(TUIndex
.getVersion()) +
777 " and expecting " + utostr(IndexVersion
));
779 unsigned TypesContributionIndex
=
780 getContributionIndex(TUSectionKind
, IndexVersion
);
781 addAllTypesFromDWP(Out
, TypeIndexEntries
, TUIndex
, OutSection
,
782 TypeInputSection
, CurEntry
,
783 ContributionOffsets
[TypesContributionIndex
],
784 TypesContributionIndex
);
789 // Lie about there being no info contributions so the TU index only includes
790 // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
791 // contribution to the info section, so we do not want to lie about it.
792 ContributionOffsets
[0] = 0;
794 writeIndex(Out
, MCOFI
.getDwarfTUIndexSection(), ContributionOffsets
,
795 TypeIndexEntries
, IndexVersion
);
798 // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
799 // section does not exist, so no need to do anything about this.
800 ContributionOffsets
[getContributionIndex(DW_SECT_EXT_TYPES
, 2)] = 0;
801 // Unlie about the info contribution
802 ContributionOffsets
[0] = 1;
805 writeIndex(Out
, MCOFI
.getDwarfCUIndexSection(), ContributionOffsets
,
806 IndexEntries
, IndexVersion
);
808 return Error::success();