1f8c65155SAlexander Yermolovich //===-- llvm-dwp.cpp - Split DWARF merging tool for llvm ------------------===//
2f8c65155SAlexander Yermolovich //
3f8c65155SAlexander Yermolovich // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4f8c65155SAlexander Yermolovich // See https://llvm.org/LICENSE.txt for license information.
5f8c65155SAlexander Yermolovich // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f8c65155SAlexander Yermolovich //
7f8c65155SAlexander Yermolovich //===----------------------------------------------------------------------===//
8f8c65155SAlexander Yermolovich //
9f8c65155SAlexander Yermolovich // A utility for merging DWARF 5 Split DWARF .dwo files into .dwp (DWARF
10f8c65155SAlexander Yermolovich // package files).
11f8c65155SAlexander Yermolovich //
12f8c65155SAlexander Yermolovich //===----------------------------------------------------------------------===//
13f8c65155SAlexander Yermolovich #include "llvm/DWP/DWP.h"
1453a483ceSzhuna #include "llvm/ADT/Twine.h"
15f8c65155SAlexander Yermolovich #include "llvm/DWP/DWPError.h"
16f8c65155SAlexander Yermolovich #include "llvm/MC/MCContext.h"
17f8c65155SAlexander Yermolovich #include "llvm/MC/MCObjectFileInfo.h"
18f8c65155SAlexander Yermolovich #include "llvm/MC/MCTargetOptionsCommandFlags.h"
19f8c65155SAlexander Yermolovich #include "llvm/Object/Decompressor.h"
20141c9d77SFangrui Song #include "llvm/Object/ELFObjectFile.h"
2153a483ceSzhuna #include "llvm/Support/CommandLine.h"
22e72c195fSserge-sans-paille #include "llvm/Support/MemoryBuffer.h"
23f8df8114SAlexander Yermolovich #include <limits>
24f8c65155SAlexander Yermolovich
25f8c65155SAlexander Yermolovich using namespace llvm;
26f8c65155SAlexander Yermolovich using namespace llvm::object;
27f8c65155SAlexander Yermolovich
28f8c65155SAlexander Yermolovich static mc::RegisterMCTargetOptionsFlags MCTargetOptionsFlags;
29f8c65155SAlexander Yermolovich
30f8c65155SAlexander Yermolovich // Returns the size of debug_str_offsets section headers in bytes.
debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,uint16_t DwarfVersion)31f8c65155SAlexander Yermolovich static uint64_t debugStrOffsetsHeaderSize(DataExtractor StrOffsetsData,
32f8c65155SAlexander Yermolovich uint16_t DwarfVersion) {
33f8c65155SAlexander Yermolovich if (DwarfVersion <= 4)
34f8c65155SAlexander Yermolovich return 0; // There is no header before dwarf 5.
35f8c65155SAlexander Yermolovich uint64_t Offset = 0;
36f8c65155SAlexander Yermolovich uint64_t Length = StrOffsetsData.getU32(&Offset);
37f8c65155SAlexander Yermolovich if (Length == llvm::dwarf::DW_LENGTH_DWARF64)
38f8c65155SAlexander Yermolovich return 16; // unit length: 12 bytes, version: 2 bytes, padding: 2 bytes.
39f8c65155SAlexander Yermolovich return 8; // unit length: 4 bytes, version: 2 bytes, padding: 2 bytes.
40f8c65155SAlexander Yermolovich }
41f8c65155SAlexander Yermolovich
getCUAbbrev(StringRef Abbrev,uint64_t AbbrCode)42f8c65155SAlexander Yermolovich static uint64_t getCUAbbrev(StringRef Abbrev, uint64_t AbbrCode) {
43f8c65155SAlexander Yermolovich uint64_t Offset = 0;
44f8c65155SAlexander Yermolovich DataExtractor AbbrevData(Abbrev, true, 0);
45f8c65155SAlexander Yermolovich while (AbbrevData.getULEB128(&Offset) != AbbrCode) {
46f8c65155SAlexander Yermolovich // Tag
47f8c65155SAlexander Yermolovich AbbrevData.getULEB128(&Offset);
48f8c65155SAlexander Yermolovich // DW_CHILDREN
49f8c65155SAlexander Yermolovich AbbrevData.getU8(&Offset);
50f8c65155SAlexander Yermolovich // Attributes
51f8c65155SAlexander Yermolovich while (AbbrevData.getULEB128(&Offset) | AbbrevData.getULEB128(&Offset))
52f8c65155SAlexander Yermolovich ;
53f8c65155SAlexander Yermolovich }
54f8c65155SAlexander Yermolovich return Offset;
55f8c65155SAlexander Yermolovich }
56f8c65155SAlexander Yermolovich
57f8c65155SAlexander Yermolovich static Expected<const char *>
getIndexedString(dwarf::Form Form,DataExtractor InfoData,uint64_t & InfoOffset,StringRef StrOffsets,StringRef Str,uint16_t Version)58f8c65155SAlexander Yermolovich getIndexedString(dwarf::Form Form, DataExtractor InfoData, uint64_t &InfoOffset,
59f8c65155SAlexander Yermolovich StringRef StrOffsets, StringRef Str, uint16_t Version) {
60f8c65155SAlexander Yermolovich if (Form == dwarf::DW_FORM_string)
61f8c65155SAlexander Yermolovich return InfoData.getCStr(&InfoOffset);
62f8c65155SAlexander Yermolovich uint64_t StrIndex;
63f8c65155SAlexander Yermolovich switch (Form) {
64f8c65155SAlexander Yermolovich case dwarf::DW_FORM_strx1:
65f8c65155SAlexander Yermolovich StrIndex = InfoData.getU8(&InfoOffset);
66f8c65155SAlexander Yermolovich break;
67f8c65155SAlexander Yermolovich case dwarf::DW_FORM_strx2:
68f8c65155SAlexander Yermolovich StrIndex = InfoData.getU16(&InfoOffset);
69f8c65155SAlexander Yermolovich break;
70f8c65155SAlexander Yermolovich case dwarf::DW_FORM_strx3:
71f8c65155SAlexander Yermolovich StrIndex = InfoData.getU24(&InfoOffset);
72f8c65155SAlexander Yermolovich break;
73f8c65155SAlexander Yermolovich case dwarf::DW_FORM_strx4:
74f8c65155SAlexander Yermolovich StrIndex = InfoData.getU32(&InfoOffset);
75f8c65155SAlexander Yermolovich break;
76f8c65155SAlexander Yermolovich case dwarf::DW_FORM_strx:
77f8c65155SAlexander Yermolovich case dwarf::DW_FORM_GNU_str_index:
78f8c65155SAlexander Yermolovich StrIndex = InfoData.getULEB128(&InfoOffset);
79f8c65155SAlexander Yermolovich break;
80f8c65155SAlexander Yermolovich default:
81f8c65155SAlexander Yermolovich return make_error<DWPError>(
82f8c65155SAlexander Yermolovich "string field must be encoded with one of the following: "
83f8c65155SAlexander Yermolovich "DW_FORM_string, DW_FORM_strx, DW_FORM_strx1, DW_FORM_strx2, "
84f8c65155SAlexander Yermolovich "DW_FORM_strx3, DW_FORM_strx4, or DW_FORM_GNU_str_index.");
85f8c65155SAlexander Yermolovich }
86f8c65155SAlexander Yermolovich DataExtractor StrOffsetsData(StrOffsets, true, 0);
87f8c65155SAlexander Yermolovich uint64_t StrOffsetsOffset = 4 * StrIndex;
88f8c65155SAlexander Yermolovich StrOffsetsOffset += debugStrOffsetsHeaderSize(StrOffsetsData, Version);
89f8c65155SAlexander Yermolovich
90f8c65155SAlexander Yermolovich uint64_t StrOffset = StrOffsetsData.getU32(&StrOffsetsOffset);
91f8c65155SAlexander Yermolovich DataExtractor StrData(Str, true, 0);
92f8c65155SAlexander Yermolovich return StrData.getCStr(&StrOffset);
93f8c65155SAlexander Yermolovich }
94f8c65155SAlexander Yermolovich
95f8c65155SAlexander Yermolovich static Expected<CompileUnitIdentifiers>
getCUIdentifiers(InfoSectionUnitHeader & Header,StringRef Abbrev,StringRef Info,StringRef StrOffsets,StringRef Str)96f8c65155SAlexander Yermolovich getCUIdentifiers(InfoSectionUnitHeader &Header, StringRef Abbrev,
97f8c65155SAlexander Yermolovich StringRef Info, StringRef StrOffsets, StringRef Str) {
98f8c65155SAlexander Yermolovich DataExtractor InfoData(Info, true, 0);
99f8c65155SAlexander Yermolovich uint64_t Offset = Header.HeaderSize;
100f8c65155SAlexander Yermolovich if (Header.Version >= 5 && Header.UnitType != dwarf::DW_UT_split_compile)
101f8c65155SAlexander Yermolovich return make_error<DWPError>(
102f8c65155SAlexander Yermolovich std::string("unit type DW_UT_split_compile type not found in "
103f8c65155SAlexander Yermolovich "debug_info header. Unexpected unit type 0x" +
104f8c65155SAlexander Yermolovich utostr(Header.UnitType) + " found"));
105f8c65155SAlexander Yermolovich
106f8c65155SAlexander Yermolovich CompileUnitIdentifiers ID;
107f8c65155SAlexander Yermolovich
108f8c65155SAlexander Yermolovich uint32_t AbbrCode = InfoData.getULEB128(&Offset);
109f8c65155SAlexander Yermolovich DataExtractor AbbrevData(Abbrev, true, 0);
110f8c65155SAlexander Yermolovich uint64_t AbbrevOffset = getCUAbbrev(Abbrev, AbbrCode);
111f8c65155SAlexander Yermolovich auto Tag = static_cast<dwarf::Tag>(AbbrevData.getULEB128(&AbbrevOffset));
112f8c65155SAlexander Yermolovich if (Tag != dwarf::DW_TAG_compile_unit)
113f8c65155SAlexander Yermolovich return make_error<DWPError>("top level DIE is not a compile unit");
114f8c65155SAlexander Yermolovich // DW_CHILDREN
115f8c65155SAlexander Yermolovich AbbrevData.getU8(&AbbrevOffset);
116f8c65155SAlexander Yermolovich uint32_t Name;
117f8c65155SAlexander Yermolovich dwarf::Form Form;
118f8c65155SAlexander Yermolovich while ((Name = AbbrevData.getULEB128(&AbbrevOffset)) |
119f8c65155SAlexander Yermolovich (Form = static_cast<dwarf::Form>(
120f8c65155SAlexander Yermolovich AbbrevData.getULEB128(&AbbrevOffset))) &&
121f8c65155SAlexander Yermolovich (Name != 0 || Form != 0)) {
122f8c65155SAlexander Yermolovich switch (Name) {
123f8c65155SAlexander Yermolovich case dwarf::DW_AT_name: {
124f8c65155SAlexander Yermolovich Expected<const char *> EName = getIndexedString(
125f8c65155SAlexander Yermolovich Form, InfoData, Offset, StrOffsets, Str, Header.Version);
126f8c65155SAlexander Yermolovich if (!EName)
127f8c65155SAlexander Yermolovich return EName.takeError();
128f8c65155SAlexander Yermolovich ID.Name = *EName;
129f8c65155SAlexander Yermolovich break;
130f8c65155SAlexander Yermolovich }
131f8c65155SAlexander Yermolovich case dwarf::DW_AT_GNU_dwo_name:
132f8c65155SAlexander Yermolovich case dwarf::DW_AT_dwo_name: {
133f8c65155SAlexander Yermolovich Expected<const char *> EName = getIndexedString(
134f8c65155SAlexander Yermolovich Form, InfoData, Offset, StrOffsets, Str, Header.Version);
135f8c65155SAlexander Yermolovich if (!EName)
136f8c65155SAlexander Yermolovich return EName.takeError();
137f8c65155SAlexander Yermolovich ID.DWOName = *EName;
138f8c65155SAlexander Yermolovich break;
139f8c65155SAlexander Yermolovich }
140f8c65155SAlexander Yermolovich case dwarf::DW_AT_GNU_dwo_id:
141f8c65155SAlexander Yermolovich Header.Signature = InfoData.getU64(&Offset);
142f8c65155SAlexander Yermolovich break;
143f8c65155SAlexander Yermolovich default:
144f8c65155SAlexander Yermolovich DWARFFormValue::skipValue(
145f8c65155SAlexander Yermolovich Form, InfoData, &Offset,
146f8c65155SAlexander Yermolovich dwarf::FormParams({Header.Version, Header.AddrSize, Header.Format}));
147f8c65155SAlexander Yermolovich }
148f8c65155SAlexander Yermolovich }
149f8c65155SAlexander Yermolovich if (!Header.Signature)
150f8c65155SAlexander Yermolovich return make_error<DWPError>("compile unit missing dwo_id");
151f8c65155SAlexander Yermolovich ID.Signature = *Header.Signature;
152f8c65155SAlexander Yermolovich return ID;
153f8c65155SAlexander Yermolovich }
154f8c65155SAlexander Yermolovich
isSupportedSectionKind(DWARFSectionKind Kind)155f8c65155SAlexander Yermolovich static bool isSupportedSectionKind(DWARFSectionKind Kind) {
156f8c65155SAlexander Yermolovich return Kind != DW_SECT_EXT_unknown;
157f8c65155SAlexander Yermolovich }
158f8c65155SAlexander Yermolovich
159f8c65155SAlexander Yermolovich namespace llvm {
160f8c65155SAlexander Yermolovich // Convert an internal section identifier into the index to use with
161f8c65155SAlexander Yermolovich // UnitIndexEntry::Contributions.
getContributionIndex(DWARFSectionKind Kind,uint32_t IndexVersion)162f8c65155SAlexander Yermolovich unsigned getContributionIndex(DWARFSectionKind Kind, uint32_t IndexVersion) {
163f8c65155SAlexander Yermolovich assert(serializeSectionKind(Kind, IndexVersion) >= DW_SECT_INFO);
164f8c65155SAlexander Yermolovich return serializeSectionKind(Kind, IndexVersion) - DW_SECT_INFO;
165f8c65155SAlexander Yermolovich }
166f8c65155SAlexander Yermolovich } // namespace llvm
167f8c65155SAlexander Yermolovich
168f8c65155SAlexander Yermolovich // Convert a UnitIndexEntry::Contributions index to the corresponding on-disk
169f8c65155SAlexander Yermolovich // value of the section identifier.
getOnDiskSectionId(unsigned Index)170f8c65155SAlexander Yermolovich static unsigned getOnDiskSectionId(unsigned Index) {
171f8c65155SAlexander Yermolovich return Index + DW_SECT_INFO;
172f8c65155SAlexander Yermolovich }
173f8c65155SAlexander Yermolovich
getSubsection(StringRef Section,const DWARFUnitIndex::Entry & Entry,DWARFSectionKind Kind)174f8c65155SAlexander Yermolovich static StringRef getSubsection(StringRef Section,
175f8c65155SAlexander Yermolovich const DWARFUnitIndex::Entry &Entry,
176f8c65155SAlexander Yermolovich DWARFSectionKind Kind) {
177f8c65155SAlexander Yermolovich const auto *Off = Entry.getContribution(Kind);
178f8c65155SAlexander Yermolovich if (!Off)
179f8c65155SAlexander Yermolovich return StringRef();
1807fc79340SAlexander Yermolovich return Section.substr(Off->getOffset(), Off->getLength());
181f8c65155SAlexander Yermolovich }
182f8c65155SAlexander Yermolovich
sectionOverflowErrorOrWarning(uint32_t PrevOffset,uint32_t OverflowedOffset,StringRef SectionName,OnCuIndexOverflow OverflowOptValue,bool & AnySectionOverflow)18353a483ceSzhuna static Error sectionOverflowErrorOrWarning(uint32_t PrevOffset,
18453a483ceSzhuna uint32_t OverflowedOffset,
18553a483ceSzhuna StringRef SectionName,
1864c44dcffSJinjie Huang OnCuIndexOverflow OverflowOptValue,
1874c44dcffSJinjie Huang bool &AnySectionOverflow) {
18853a483ceSzhuna std::string Msg =
18953a483ceSzhuna (SectionName +
19053a483ceSzhuna Twine(" Section Contribution Offset overflow 4G. Previous Offset ") +
19153a483ceSzhuna Twine(PrevOffset) + Twine(", After overflow offset ") +
19253a483ceSzhuna Twine(OverflowedOffset) + Twine("."))
19353a483ceSzhuna .str();
1944c44dcffSJinjie Huang if (OverflowOptValue == OnCuIndexOverflow::Continue) {
1954c44dcffSJinjie Huang WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
1964c44dcffSJinjie Huang return Error::success();
1974c44dcffSJinjie Huang } else if (OverflowOptValue == OnCuIndexOverflow::SoftStop) {
1984c44dcffSJinjie Huang AnySectionOverflow = true;
19953a483ceSzhuna WithColor::defaultWarningHandler(make_error<DWPError>(Msg));
20053a483ceSzhuna return Error::success();
20153a483ceSzhuna }
20253a483ceSzhuna return make_error<DWPError>(Msg);
20353a483ceSzhuna }
20453a483ceSzhuna
addAllTypesFromDWP(MCStreamer & Out,MapVector<uint64_t,UnitIndexEntry> & TypeIndexEntries,const DWARFUnitIndex & TUIndex,MCSection * OutputTypes,StringRef Types,const UnitIndexEntry & TUEntry,uint32_t & TypesOffset,unsigned TypesContributionIndex,OnCuIndexOverflow OverflowOptValue,bool & AnySectionOverflow)20553a483ceSzhuna static Error addAllTypesFromDWP(
20653a483ceSzhuna MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
20753a483ceSzhuna const DWARFUnitIndex &TUIndex, MCSection *OutputTypes, StringRef Types,
20853a483ceSzhuna const UnitIndexEntry &TUEntry, uint32_t &TypesOffset,
2094c44dcffSJinjie Huang unsigned TypesContributionIndex, OnCuIndexOverflow OverflowOptValue,
2104c44dcffSJinjie Huang bool &AnySectionOverflow) {
211adf4142fSFangrui Song Out.switchSection(OutputTypes);
212f8c65155SAlexander Yermolovich for (const DWARFUnitIndex::Entry &E : TUIndex.getRows()) {
213f8c65155SAlexander Yermolovich auto *I = E.getContributions();
214f8c65155SAlexander Yermolovich if (!I)
215f8c65155SAlexander Yermolovich continue;
216f8c65155SAlexander Yermolovich auto P = TypeIndexEntries.insert(std::make_pair(E.getSignature(), TUEntry));
217f8c65155SAlexander Yermolovich if (!P.second)
218f8c65155SAlexander Yermolovich continue;
219f8c65155SAlexander Yermolovich auto &Entry = P.first->second;
220f8c65155SAlexander Yermolovich // Zero out the debug_info contribution
221f8c65155SAlexander Yermolovich Entry.Contributions[0] = {};
222f8c65155SAlexander Yermolovich for (auto Kind : TUIndex.getColumnKinds()) {
223f8c65155SAlexander Yermolovich if (!isSupportedSectionKind(Kind))
224f8c65155SAlexander Yermolovich continue;
225f8c65155SAlexander Yermolovich auto &C =
226f8c65155SAlexander Yermolovich Entry.Contributions[getContributionIndex(Kind, TUIndex.getVersion())];
2277fc79340SAlexander Yermolovich C.setOffset(C.getOffset() + I->getOffset());
2287fc79340SAlexander Yermolovich C.setLength(I->getLength());
229f8c65155SAlexander Yermolovich ++I;
230f8c65155SAlexander Yermolovich }
231f8c65155SAlexander Yermolovich auto &C = Entry.Contributions[TypesContributionIndex];
232f8c65155SAlexander Yermolovich Out.emitBytes(Types.substr(
2337fc79340SAlexander Yermolovich C.getOffset() -
2347fc79340SAlexander Yermolovich TUEntry.Contributions[TypesContributionIndex].getOffset(),
2357fc79340SAlexander Yermolovich C.getLength()));
2367fc79340SAlexander Yermolovich C.setOffset(TypesOffset);
23753a483ceSzhuna uint32_t OldOffset = TypesOffset;
23853a483ceSzhuna static_assert(sizeof(OldOffset) == sizeof(TypesOffset));
2397fc79340SAlexander Yermolovich TypesOffset += C.getLength();
24053a483ceSzhuna if (OldOffset > TypesOffset) {
2414c44dcffSJinjie Huang if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,
2424c44dcffSJinjie Huang "Types", OverflowOptValue,
2434c44dcffSJinjie Huang AnySectionOverflow))
24453a483ceSzhuna return Err;
2454c44dcffSJinjie Huang if (AnySectionOverflow) {
2464c44dcffSJinjie Huang TypesOffset = OldOffset;
2474c44dcffSJinjie Huang return Error::success();
2484c44dcffSJinjie Huang }
249f8c65155SAlexander Yermolovich }
250f8c65155SAlexander Yermolovich }
25153a483ceSzhuna return Error::success();
25253a483ceSzhuna }
253f8c65155SAlexander Yermolovich
addAllTypesFromTypesSection(MCStreamer & Out,MapVector<uint64_t,UnitIndexEntry> & TypeIndexEntries,MCSection * OutputTypes,const std::vector<StringRef> & TypesSections,const UnitIndexEntry & CUEntry,uint32_t & TypesOffset,OnCuIndexOverflow OverflowOptValue,bool & AnySectionOverflow)25453a483ceSzhuna static Error addAllTypesFromTypesSection(
255f8c65155SAlexander Yermolovich MCStreamer &Out, MapVector<uint64_t, UnitIndexEntry> &TypeIndexEntries,
256f8c65155SAlexander Yermolovich MCSection *OutputTypes, const std::vector<StringRef> &TypesSections,
25753a483ceSzhuna const UnitIndexEntry &CUEntry, uint32_t &TypesOffset,
2584c44dcffSJinjie Huang OnCuIndexOverflow OverflowOptValue, bool &AnySectionOverflow) {
259f8c65155SAlexander Yermolovich for (StringRef Types : TypesSections) {
260adf4142fSFangrui Song Out.switchSection(OutputTypes);
261f8c65155SAlexander Yermolovich uint64_t Offset = 0;
262f8c65155SAlexander Yermolovich DataExtractor Data(Types, true, 0);
263f8c65155SAlexander Yermolovich while (Data.isValidOffset(Offset)) {
264f8c65155SAlexander Yermolovich UnitIndexEntry Entry = CUEntry;
265f8c65155SAlexander Yermolovich // Zero out the debug_info contribution
266f8c65155SAlexander Yermolovich Entry.Contributions[0] = {};
267f8c65155SAlexander Yermolovich auto &C = Entry.Contributions[getContributionIndex(DW_SECT_EXT_TYPES, 2)];
2687fc79340SAlexander Yermolovich C.setOffset(TypesOffset);
269f8c65155SAlexander Yermolovich auto PrevOffset = Offset;
270f8c65155SAlexander Yermolovich // Length of the unit, including the 4 byte length field.
2717fc79340SAlexander Yermolovich C.setLength(Data.getU32(&Offset) + 4);
272f8c65155SAlexander Yermolovich
273f8c65155SAlexander Yermolovich Data.getU16(&Offset); // Version
274f8c65155SAlexander Yermolovich Data.getU32(&Offset); // Abbrev offset
275f8c65155SAlexander Yermolovich Data.getU8(&Offset); // Address size
276f8c65155SAlexander Yermolovich auto Signature = Data.getU64(&Offset);
2777fc79340SAlexander Yermolovich Offset = PrevOffset + C.getLength32();
278f8c65155SAlexander Yermolovich
279f8c65155SAlexander Yermolovich auto P = TypeIndexEntries.insert(std::make_pair(Signature, Entry));
280f8c65155SAlexander Yermolovich if (!P.second)
281f8c65155SAlexander Yermolovich continue;
282f8c65155SAlexander Yermolovich
2837fc79340SAlexander Yermolovich Out.emitBytes(Types.substr(PrevOffset, C.getLength32()));
28453a483ceSzhuna uint32_t OldOffset = TypesOffset;
2857fc79340SAlexander Yermolovich TypesOffset += C.getLength32();
28653a483ceSzhuna if (OldOffset > TypesOffset) {
2874c44dcffSJinjie Huang if (Error Err = sectionOverflowErrorOrWarning(OldOffset, TypesOffset,
2884c44dcffSJinjie Huang "Types", OverflowOptValue,
2894c44dcffSJinjie Huang AnySectionOverflow))
29053a483ceSzhuna return Err;
2914c44dcffSJinjie Huang if (AnySectionOverflow) {
2924c44dcffSJinjie Huang TypesOffset = OldOffset;
2934c44dcffSJinjie Huang return Error::success();
2944c44dcffSJinjie Huang }
295f8c65155SAlexander Yermolovich }
296f8c65155SAlexander Yermolovich }
297f8c65155SAlexander Yermolovich }
29853a483ceSzhuna return Error::success();
29953a483ceSzhuna }
300f8c65155SAlexander Yermolovich
buildDWODescription(StringRef Name,StringRef DWPName,StringRef DWOName)301f8c65155SAlexander Yermolovich static std::string buildDWODescription(StringRef Name, StringRef DWPName,
302f8c65155SAlexander Yermolovich StringRef DWOName) {
303f8c65155SAlexander Yermolovich std::string Text = "\'";
304f8c65155SAlexander Yermolovich Text += Name;
305f8c65155SAlexander Yermolovich Text += '\'';
3066139626dSDavid Blaikie bool HasDWO = !DWOName.empty();
3076139626dSDavid Blaikie bool HasDWP = !DWPName.empty();
3086139626dSDavid Blaikie if (HasDWO || HasDWP) {
309f8c65155SAlexander Yermolovich Text += " (from ";
3106139626dSDavid Blaikie if (HasDWO) {
311f8c65155SAlexander Yermolovich Text += '\'';
312f8c65155SAlexander Yermolovich Text += DWOName;
3136139626dSDavid Blaikie Text += '\'';
314f8c65155SAlexander Yermolovich }
3156139626dSDavid Blaikie if (HasDWO && HasDWP)
3166139626dSDavid Blaikie Text += " in ";
3176139626dSDavid Blaikie if (!DWPName.empty()) {
318f8c65155SAlexander Yermolovich Text += '\'';
319f8c65155SAlexander Yermolovich Text += DWPName;
3206139626dSDavid Blaikie Text += '\'';
3216139626dSDavid Blaikie }
3226139626dSDavid Blaikie Text += ")";
323f8c65155SAlexander Yermolovich }
324f8c65155SAlexander Yermolovich return Text;
325f8c65155SAlexander Yermolovich }
326f8c65155SAlexander Yermolovich
createError(StringRef Name,Error E)327f8c65155SAlexander Yermolovich static Error createError(StringRef Name, Error E) {
328f8c65155SAlexander Yermolovich return make_error<DWPError>(
329f8c65155SAlexander Yermolovich ("failure while decompressing compressed section: '" + Name + "', " +
330f8c65155SAlexander Yermolovich llvm::toString(std::move(E)))
331f8c65155SAlexander Yermolovich .str());
332f8c65155SAlexander Yermolovich }
333f8c65155SAlexander Yermolovich
334f8c65155SAlexander Yermolovich static Error
handleCompressedSection(std::deque<SmallString<32>> & UncompressedSections,SectionRef Sec,StringRef Name,StringRef & Contents)335f8c65155SAlexander Yermolovich handleCompressedSection(std::deque<SmallString<32>> &UncompressedSections,
336141c9d77SFangrui Song SectionRef Sec, StringRef Name, StringRef &Contents) {
337141c9d77SFangrui Song auto *Obj = dyn_cast<ELFObjectFileBase>(Sec.getObject());
338141c9d77SFangrui Song if (!Obj ||
339141c9d77SFangrui Song !(static_cast<ELFSectionRef>(Sec).getFlags() & ELF::SHF_COMPRESSED))
340f8c65155SAlexander Yermolovich return Error::success();
341141c9d77SFangrui Song bool IsLE = isa<object::ELF32LEObjectFile>(Obj) ||
342141c9d77SFangrui Song isa<object::ELF64LEObjectFile>(Obj);
343141c9d77SFangrui Song bool Is64 = isa<object::ELF64LEObjectFile>(Obj) ||
344141c9d77SFangrui Song isa<object::ELF64BEObjectFile>(Obj);
345141c9d77SFangrui Song Expected<Decompressor> Dec = Decompressor::create(Name, Contents, IsLE, Is64);
346f8c65155SAlexander Yermolovich if (!Dec)
347f8c65155SAlexander Yermolovich return createError(Name, Dec.takeError());
348f8c65155SAlexander Yermolovich
349f8c65155SAlexander Yermolovich UncompressedSections.emplace_back();
350f8c65155SAlexander Yermolovich if (Error E = Dec->resizeAndDecompress(UncompressedSections.back()))
351f8c65155SAlexander Yermolovich return createError(Name, std::move(E));
352f8c65155SAlexander Yermolovich
353f8c65155SAlexander Yermolovich Contents = UncompressedSections.back();
354f8c65155SAlexander Yermolovich return Error::success();
355f8c65155SAlexander Yermolovich }
356f8c65155SAlexander Yermolovich
357f8c65155SAlexander Yermolovich namespace llvm {
358f8c65155SAlexander Yermolovich // Parse and return the header of an info section compile/type unit.
parseInfoSectionUnitHeader(StringRef Info)359f8c65155SAlexander Yermolovich Expected<InfoSectionUnitHeader> parseInfoSectionUnitHeader(StringRef Info) {
360f8c65155SAlexander Yermolovich InfoSectionUnitHeader Header;
361f8c65155SAlexander Yermolovich Error Err = Error::success();
362f8c65155SAlexander Yermolovich uint64_t Offset = 0;
363f8c65155SAlexander Yermolovich DWARFDataExtractor InfoData(Info, true, 0);
364f8c65155SAlexander Yermolovich std::tie(Header.Length, Header.Format) =
365f8c65155SAlexander Yermolovich InfoData.getInitialLength(&Offset, &Err);
366f8c65155SAlexander Yermolovich if (Err)
367f8c65155SAlexander Yermolovich return make_error<DWPError>("cannot parse compile unit length: " +
368f8c65155SAlexander Yermolovich llvm::toString(std::move(Err)));
369f8c65155SAlexander Yermolovich
370f8c65155SAlexander Yermolovich if (!InfoData.isValidOffset(Offset + (Header.Length - 1))) {
371f8c65155SAlexander Yermolovich return make_error<DWPError>(
372f8c65155SAlexander Yermolovich "compile unit exceeds .debug_info section range: " +
373f8c65155SAlexander Yermolovich utostr(Offset + Header.Length) + " >= " + utostr(InfoData.size()));
374f8c65155SAlexander Yermolovich }
375f8c65155SAlexander Yermolovich
376f8c65155SAlexander Yermolovich Header.Version = InfoData.getU16(&Offset, &Err);
377f8c65155SAlexander Yermolovich if (Err)
378f8c65155SAlexander Yermolovich return make_error<DWPError>("cannot parse compile unit version: " +
379f8c65155SAlexander Yermolovich llvm::toString(std::move(Err)));
380f8c65155SAlexander Yermolovich
381f8c65155SAlexander Yermolovich uint64_t MinHeaderLength;
382f8c65155SAlexander Yermolovich if (Header.Version >= 5) {
383f8c65155SAlexander Yermolovich // Size: Version (2), UnitType (1), AddrSize (1), DebugAbbrevOffset (4),
384f8c65155SAlexander Yermolovich // Signature (8)
385f8c65155SAlexander Yermolovich MinHeaderLength = 16;
386f8c65155SAlexander Yermolovich } else {
387f8c65155SAlexander Yermolovich // Size: Version (2), DebugAbbrevOffset (4), AddrSize (1)
388f8c65155SAlexander Yermolovich MinHeaderLength = 7;
389f8c65155SAlexander Yermolovich }
390f8c65155SAlexander Yermolovich if (Header.Length < MinHeaderLength) {
391f8c65155SAlexander Yermolovich return make_error<DWPError>("unit length is too small: expected at least " +
392f8c65155SAlexander Yermolovich utostr(MinHeaderLength) + " got " +
393f8c65155SAlexander Yermolovich utostr(Header.Length) + ".");
394f8c65155SAlexander Yermolovich }
395f8c65155SAlexander Yermolovich if (Header.Version >= 5) {
396f8c65155SAlexander Yermolovich Header.UnitType = InfoData.getU8(&Offset);
397f8c65155SAlexander Yermolovich Header.AddrSize = InfoData.getU8(&Offset);
398f8c65155SAlexander Yermolovich Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
399f8c65155SAlexander Yermolovich Header.Signature = InfoData.getU64(&Offset);
400f8c65155SAlexander Yermolovich if (Header.UnitType == dwarf::DW_UT_split_type) {
401f8c65155SAlexander Yermolovich // Type offset.
402f8c65155SAlexander Yermolovich MinHeaderLength += 4;
403f8c65155SAlexander Yermolovich if (Header.Length < MinHeaderLength)
404f8c65155SAlexander Yermolovich return make_error<DWPError>("type unit is missing type offset");
405f8c65155SAlexander Yermolovich InfoData.getU32(&Offset);
406f8c65155SAlexander Yermolovich }
407f8c65155SAlexander Yermolovich } else {
408f8c65155SAlexander Yermolovich // Note that, address_size and debug_abbrev_offset fields have switched
409f8c65155SAlexander Yermolovich // places between dwarf version 4 and 5.
410f8c65155SAlexander Yermolovich Header.DebugAbbrevOffset = InfoData.getU32(&Offset);
411f8c65155SAlexander Yermolovich Header.AddrSize = InfoData.getU8(&Offset);
412f8c65155SAlexander Yermolovich }
413f8c65155SAlexander Yermolovich
414f8c65155SAlexander Yermolovich Header.HeaderSize = Offset;
415f8c65155SAlexander Yermolovich return Header;
416f8c65155SAlexander Yermolovich }
417f8c65155SAlexander Yermolovich
writeNewOffsetsTo(MCStreamer & Out,DataExtractor & Data,DenseMap<uint64_t,uint32_t> & OffsetRemapping,uint64_t & Offset,uint64_t & Size)418*699cd9acSMorten larsen static void writeNewOffsetsTo(MCStreamer &Out, DataExtractor &Data,
419*699cd9acSMorten larsen DenseMap<uint64_t, uint32_t> &OffsetRemapping,
420*699cd9acSMorten larsen uint64_t &Offset, uint64_t &Size) {
421*699cd9acSMorten larsen
422*699cd9acSMorten larsen while (Offset < Size) {
423*699cd9acSMorten larsen auto OldOffset = Data.getU32(&Offset);
424*699cd9acSMorten larsen auto NewOffset = OffsetRemapping[OldOffset];
425*699cd9acSMorten larsen Out.emitIntValue(NewOffset, 4);
426*699cd9acSMorten larsen }
427*699cd9acSMorten larsen }
428*699cd9acSMorten larsen
writeStringsAndOffsets(MCStreamer & Out,DWPStringPool & Strings,MCSection * StrOffsetSection,StringRef CurStrSection,StringRef CurStrOffsetSection,uint16_t Version)429f8c65155SAlexander Yermolovich void writeStringsAndOffsets(MCStreamer &Out, DWPStringPool &Strings,
430f8c65155SAlexander Yermolovich MCSection *StrOffsetSection,
431f8c65155SAlexander Yermolovich StringRef CurStrSection,
432f8c65155SAlexander Yermolovich StringRef CurStrOffsetSection, uint16_t Version) {
433f8c65155SAlexander Yermolovich // Could possibly produce an error or warning if one of these was non-null but
434f8c65155SAlexander Yermolovich // the other was null.
435f8c65155SAlexander Yermolovich if (CurStrSection.empty() || CurStrOffsetSection.empty())
436f8c65155SAlexander Yermolovich return;
437f8c65155SAlexander Yermolovich
438f8c65155SAlexander Yermolovich DenseMap<uint64_t, uint32_t> OffsetRemapping;
439f8c65155SAlexander Yermolovich
440f8c65155SAlexander Yermolovich DataExtractor Data(CurStrSection, true, 0);
441f8c65155SAlexander Yermolovich uint64_t LocalOffset = 0;
442f8c65155SAlexander Yermolovich uint64_t PrevOffset = 0;
443f8c65155SAlexander Yermolovich while (const char *S = Data.getCStr(&LocalOffset)) {
444f8c65155SAlexander Yermolovich OffsetRemapping[PrevOffset] =
445f8c65155SAlexander Yermolovich Strings.getOffset(S, LocalOffset - PrevOffset);
446f8c65155SAlexander Yermolovich PrevOffset = LocalOffset;
447f8c65155SAlexander Yermolovich }
448f8c65155SAlexander Yermolovich
449f8c65155SAlexander Yermolovich Data = DataExtractor(CurStrOffsetSection, true, 0);
450f8c65155SAlexander Yermolovich
451adf4142fSFangrui Song Out.switchSection(StrOffsetSection);
452f8c65155SAlexander Yermolovich
453f8c65155SAlexander Yermolovich uint64_t Offset = 0;
454f8c65155SAlexander Yermolovich uint64_t Size = CurStrOffsetSection.size();
455*699cd9acSMorten larsen if (Version > 4) {
456f8c65155SAlexander Yermolovich while (Offset < Size) {
457*699cd9acSMorten larsen uint64_t HeaderSize = debugStrOffsetsHeaderSize(Data, Version);
458*699cd9acSMorten larsen assert(HeaderSize <= Size - Offset &&
459*699cd9acSMorten larsen "StrOffsetSection size is less than its header");
460*699cd9acSMorten larsen
461*699cd9acSMorten larsen uint64_t ContributionEnd = 0;
462*699cd9acSMorten larsen uint64_t ContributionSize = 0;
463*699cd9acSMorten larsen uint64_t HeaderLengthOffset = Offset;
464*699cd9acSMorten larsen if (HeaderSize == 8) {
465*699cd9acSMorten larsen ContributionSize = Data.getU32(&HeaderLengthOffset);
466*699cd9acSMorten larsen } else if (HeaderSize == 16) {
467*699cd9acSMorten larsen HeaderLengthOffset += 4; // skip the dwarf64 marker
468*699cd9acSMorten larsen ContributionSize = Data.getU64(&HeaderLengthOffset);
469*699cd9acSMorten larsen }
470*699cd9acSMorten larsen ContributionEnd = ContributionSize + HeaderLengthOffset;
471*699cd9acSMorten larsen Out.emitBytes(Data.getBytes(&Offset, HeaderSize));
472*699cd9acSMorten larsen writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, ContributionEnd);
473*699cd9acSMorten larsen }
474*699cd9acSMorten larsen
475*699cd9acSMorten larsen } else {
476*699cd9acSMorten larsen writeNewOffsetsTo(Out, Data, OffsetRemapping, Offset, Size);
477f8c65155SAlexander Yermolovich }
478f8c65155SAlexander Yermolovich }
479f8c65155SAlexander Yermolovich
4807fc79340SAlexander Yermolovich enum AccessField { Offset, Length };
writeIndexTable(MCStreamer & Out,ArrayRef<unsigned> ContributionOffsets,const MapVector<uint64_t,UnitIndexEntry> & IndexEntries,const AccessField & Field)4817fc79340SAlexander Yermolovich void writeIndexTable(MCStreamer &Out, ArrayRef<unsigned> ContributionOffsets,
482f8c65155SAlexander Yermolovich const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
4837fc79340SAlexander Yermolovich const AccessField &Field) {
484f8c65155SAlexander Yermolovich for (const auto &E : IndexEntries)
4855e96cea1SJoe Loser for (size_t I = 0; I != std::size(E.second.Contributions); ++I)
486f8c65155SAlexander Yermolovich if (ContributionOffsets[I])
4877fc79340SAlexander Yermolovich Out.emitIntValue((Field == AccessField::Offset
4887fc79340SAlexander Yermolovich ? E.second.Contributions[I].getOffset32()
4897fc79340SAlexander Yermolovich : E.second.Contributions[I].getLength32()),
4907fc79340SAlexander Yermolovich 4);
491f8c65155SAlexander Yermolovich }
492f8c65155SAlexander Yermolovich
writeIndex(MCStreamer & Out,MCSection * Section,ArrayRef<unsigned> ContributionOffsets,const MapVector<uint64_t,UnitIndexEntry> & IndexEntries,uint32_t IndexVersion)493f8c65155SAlexander Yermolovich void writeIndex(MCStreamer &Out, MCSection *Section,
494f8c65155SAlexander Yermolovich ArrayRef<unsigned> ContributionOffsets,
495f8c65155SAlexander Yermolovich const MapVector<uint64_t, UnitIndexEntry> &IndexEntries,
496f8c65155SAlexander Yermolovich uint32_t IndexVersion) {
497f8c65155SAlexander Yermolovich if (IndexEntries.empty())
498f8c65155SAlexander Yermolovich return;
499f8c65155SAlexander Yermolovich
500f8c65155SAlexander Yermolovich unsigned Columns = 0;
501f8c65155SAlexander Yermolovich for (auto &C : ContributionOffsets)
502f8c65155SAlexander Yermolovich if (C)
503f8c65155SAlexander Yermolovich ++Columns;
504f8c65155SAlexander Yermolovich
505f8c65155SAlexander Yermolovich std::vector<unsigned> Buckets(NextPowerOf2(3 * IndexEntries.size() / 2));
506f8c65155SAlexander Yermolovich uint64_t Mask = Buckets.size() - 1;
507f8c65155SAlexander Yermolovich size_t I = 0;
508f8c65155SAlexander Yermolovich for (const auto &P : IndexEntries) {
509f8c65155SAlexander Yermolovich auto S = P.first;
510f8c65155SAlexander Yermolovich auto H = S & Mask;
511f8c65155SAlexander Yermolovich auto HP = ((S >> 32) & Mask) | 1;
512f8c65155SAlexander Yermolovich while (Buckets[H]) {
513f8c65155SAlexander Yermolovich assert(S != IndexEntries.begin()[Buckets[H] - 1].first &&
514f8c65155SAlexander Yermolovich "Duplicate unit");
515f8c65155SAlexander Yermolovich H = (H + HP) & Mask;
516f8c65155SAlexander Yermolovich }
517f8c65155SAlexander Yermolovich Buckets[H] = I + 1;
518f8c65155SAlexander Yermolovich ++I;
519f8c65155SAlexander Yermolovich }
520f8c65155SAlexander Yermolovich
521adf4142fSFangrui Song Out.switchSection(Section);
522f8c65155SAlexander Yermolovich Out.emitIntValue(IndexVersion, 4); // Version
523f8c65155SAlexander Yermolovich Out.emitIntValue(Columns, 4); // Columns
524f8c65155SAlexander Yermolovich Out.emitIntValue(IndexEntries.size(), 4); // Num Units
525f8c65155SAlexander Yermolovich Out.emitIntValue(Buckets.size(), 4); // Num Buckets
526f8c65155SAlexander Yermolovich
527f8c65155SAlexander Yermolovich // Write the signatures.
528f8c65155SAlexander Yermolovich for (const auto &I : Buckets)
529f8c65155SAlexander Yermolovich Out.emitIntValue(I ? IndexEntries.begin()[I - 1].first : 0, 8);
530f8c65155SAlexander Yermolovich
531f8c65155SAlexander Yermolovich // Write the indexes.
532f8c65155SAlexander Yermolovich for (const auto &I : Buckets)
533f8c65155SAlexander Yermolovich Out.emitIntValue(I, 4);
534f8c65155SAlexander Yermolovich
535f8c65155SAlexander Yermolovich // Write the column headers (which sections will appear in the table)
536f8c65155SAlexander Yermolovich for (size_t I = 0; I != ContributionOffsets.size(); ++I)
537f8c65155SAlexander Yermolovich if (ContributionOffsets[I])
538f8c65155SAlexander Yermolovich Out.emitIntValue(getOnDiskSectionId(I), 4);
539f8c65155SAlexander Yermolovich
540f8c65155SAlexander Yermolovich // Write the offsets.
5417fc79340SAlexander Yermolovich writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Offset);
542f8c65155SAlexander Yermolovich
543f8c65155SAlexander Yermolovich // Write the lengths.
5447fc79340SAlexander Yermolovich writeIndexTable(Out, ContributionOffsets, IndexEntries, AccessField::Length);
545f8c65155SAlexander Yermolovich }
546f8c65155SAlexander Yermolovich
buildDuplicateError(const std::pair<uint64_t,UnitIndexEntry> & PrevE,const CompileUnitIdentifiers & ID,StringRef DWPName)547f8c65155SAlexander Yermolovich Error buildDuplicateError(const std::pair<uint64_t, UnitIndexEntry> &PrevE,
548f8c65155SAlexander Yermolovich const CompileUnitIdentifiers &ID, StringRef DWPName) {
549f8c65155SAlexander Yermolovich return make_error<DWPError>(
550f8c65155SAlexander Yermolovich std::string("duplicate DWO ID (") + utohexstr(PrevE.first) + ") in " +
551f8c65155SAlexander Yermolovich buildDWODescription(PrevE.second.Name, PrevE.second.DWPName,
552f8c65155SAlexander Yermolovich PrevE.second.DWOName) +
553f8c65155SAlexander Yermolovich " and " + buildDWODescription(ID.Name, DWPName, ID.DWOName));
554f8c65155SAlexander Yermolovich }
555f8c65155SAlexander Yermolovich
handleSection(const StringMap<std::pair<MCSection *,DWARFSectionKind>> & KnownSections,const MCSection * StrSection,const MCSection * StrOffsetSection,const MCSection * TypesSection,const MCSection * CUIndexSection,const MCSection * TUIndexSection,const MCSection * InfoSection,const SectionRef & Section,MCStreamer & Out,std::deque<SmallString<32>> & UncompressedSections,uint32_t (& ContributionOffsets)[8],UnitIndexEntry & CurEntry,StringRef & CurStrSection,StringRef & CurStrOffsetSection,std::vector<StringRef> & CurTypesSection,std::vector<StringRef> & CurInfoSection,StringRef & AbbrevSection,StringRef & CurCUIndexSection,StringRef & CurTUIndexSection,std::vector<std::pair<DWARFSectionKind,uint32_t>> & SectionLength)556f8c65155SAlexander Yermolovich Error handleSection(
557f8c65155SAlexander Yermolovich const StringMap<std::pair<MCSection *, DWARFSectionKind>> &KnownSections,
558f8c65155SAlexander Yermolovich const MCSection *StrSection, const MCSection *StrOffsetSection,
559f8c65155SAlexander Yermolovich const MCSection *TypesSection, const MCSection *CUIndexSection,
560f8c65155SAlexander Yermolovich const MCSection *TUIndexSection, const MCSection *InfoSection,
561f8c65155SAlexander Yermolovich const SectionRef &Section, MCStreamer &Out,
562f8c65155SAlexander Yermolovich std::deque<SmallString<32>> &UncompressedSections,
563f8c65155SAlexander Yermolovich uint32_t (&ContributionOffsets)[8], UnitIndexEntry &CurEntry,
564f8c65155SAlexander Yermolovich StringRef &CurStrSection, StringRef &CurStrOffsetSection,
565f8c65155SAlexander Yermolovich std::vector<StringRef> &CurTypesSection,
566f8c65155SAlexander Yermolovich std::vector<StringRef> &CurInfoSection, StringRef &AbbrevSection,
567f8c65155SAlexander Yermolovich StringRef &CurCUIndexSection, StringRef &CurTUIndexSection,
568f8c65155SAlexander Yermolovich std::vector<std::pair<DWARFSectionKind, uint32_t>> &SectionLength) {
569f8c65155SAlexander Yermolovich if (Section.isBSS())
570f8c65155SAlexander Yermolovich return Error::success();
571f8c65155SAlexander Yermolovich
572f8c65155SAlexander Yermolovich if (Section.isVirtual())
573f8c65155SAlexander Yermolovich return Error::success();
574f8c65155SAlexander Yermolovich
575f8c65155SAlexander Yermolovich Expected<StringRef> NameOrErr = Section.getName();
576f8c65155SAlexander Yermolovich if (!NameOrErr)
577f8c65155SAlexander Yermolovich return NameOrErr.takeError();
578f8c65155SAlexander Yermolovich StringRef Name = *NameOrErr;
579f8c65155SAlexander Yermolovich
580f8c65155SAlexander Yermolovich Expected<StringRef> ContentsOrErr = Section.getContents();
581f8c65155SAlexander Yermolovich if (!ContentsOrErr)
582f8c65155SAlexander Yermolovich return ContentsOrErr.takeError();
583f8c65155SAlexander Yermolovich StringRef Contents = *ContentsOrErr;
584f8c65155SAlexander Yermolovich
585141c9d77SFangrui Song if (auto Err = handleCompressedSection(UncompressedSections, Section, Name,
586141c9d77SFangrui Song Contents))
587f8c65155SAlexander Yermolovich return Err;
588f8c65155SAlexander Yermolovich
589f8c65155SAlexander Yermolovich Name = Name.substr(Name.find_first_not_of("._"));
590f8c65155SAlexander Yermolovich
591f8c65155SAlexander Yermolovich auto SectionPair = KnownSections.find(Name);
592f8c65155SAlexander Yermolovich if (SectionPair == KnownSections.end())
593f8c65155SAlexander Yermolovich return Error::success();
594f8c65155SAlexander Yermolovich
595f8c65155SAlexander Yermolovich if (DWARFSectionKind Kind = SectionPair->second.second) {
596f8c65155SAlexander Yermolovich if (Kind != DW_SECT_EXT_TYPES && Kind != DW_SECT_INFO) {
597f8c65155SAlexander Yermolovich SectionLength.push_back(std::make_pair(Kind, Contents.size()));
598f8c65155SAlexander Yermolovich }
599f8c65155SAlexander Yermolovich
600f8c65155SAlexander Yermolovich if (Kind == DW_SECT_ABBREV) {
601f8c65155SAlexander Yermolovich AbbrevSection = Contents;
602f8c65155SAlexander Yermolovich }
603f8c65155SAlexander Yermolovich }
604f8c65155SAlexander Yermolovich
605f8c65155SAlexander Yermolovich MCSection *OutSection = SectionPair->second.first;
606f8c65155SAlexander Yermolovich if (OutSection == StrOffsetSection)
607f8c65155SAlexander Yermolovich CurStrOffsetSection = Contents;
608f8c65155SAlexander Yermolovich else if (OutSection == StrSection)
609f8c65155SAlexander Yermolovich CurStrSection = Contents;
610f8c65155SAlexander Yermolovich else if (OutSection == TypesSection)
611f8c65155SAlexander Yermolovich CurTypesSection.push_back(Contents);
612f8c65155SAlexander Yermolovich else if (OutSection == CUIndexSection)
613f8c65155SAlexander Yermolovich CurCUIndexSection = Contents;
614f8c65155SAlexander Yermolovich else if (OutSection == TUIndexSection)
615f8c65155SAlexander Yermolovich CurTUIndexSection = Contents;
616f8c65155SAlexander Yermolovich else if (OutSection == InfoSection)
617f8c65155SAlexander Yermolovich CurInfoSection.push_back(Contents);
618f8c65155SAlexander Yermolovich else {
619adf4142fSFangrui Song Out.switchSection(OutSection);
620f8c65155SAlexander Yermolovich Out.emitBytes(Contents);
621f8c65155SAlexander Yermolovich }
622f8c65155SAlexander Yermolovich return Error::success();
623f8c65155SAlexander Yermolovich }
624f8c65155SAlexander Yermolovich
write(MCStreamer & Out,ArrayRef<std::string> Inputs,OnCuIndexOverflow OverflowOptValue)62553a483ceSzhuna Error write(MCStreamer &Out, ArrayRef<std::string> Inputs,
6264c44dcffSJinjie Huang OnCuIndexOverflow OverflowOptValue) {
627f8c65155SAlexander Yermolovich const auto &MCOFI = *Out.getContext().getObjectFileInfo();
628f8c65155SAlexander Yermolovich MCSection *const StrSection = MCOFI.getDwarfStrDWOSection();
629f8c65155SAlexander Yermolovich MCSection *const StrOffsetSection = MCOFI.getDwarfStrOffDWOSection();
630f8c65155SAlexander Yermolovich MCSection *const TypesSection = MCOFI.getDwarfTypesDWOSection();
631f8c65155SAlexander Yermolovich MCSection *const CUIndexSection = MCOFI.getDwarfCUIndexSection();
632f8c65155SAlexander Yermolovich MCSection *const TUIndexSection = MCOFI.getDwarfTUIndexSection();
633f8c65155SAlexander Yermolovich MCSection *const InfoSection = MCOFI.getDwarfInfoDWOSection();
634f8c65155SAlexander Yermolovich const StringMap<std::pair<MCSection *, DWARFSectionKind>> KnownSections = {
635f8c65155SAlexander Yermolovich {"debug_info.dwo", {InfoSection, DW_SECT_INFO}},
636f8c65155SAlexander Yermolovich {"debug_types.dwo", {MCOFI.getDwarfTypesDWOSection(), DW_SECT_EXT_TYPES}},
637f8c65155SAlexander Yermolovich {"debug_str_offsets.dwo", {StrOffsetSection, DW_SECT_STR_OFFSETS}},
638f8c65155SAlexander Yermolovich {"debug_str.dwo", {StrSection, static_cast<DWARFSectionKind>(0)}},
639f8c65155SAlexander Yermolovich {"debug_loc.dwo", {MCOFI.getDwarfLocDWOSection(), DW_SECT_EXT_LOC}},
640f8c65155SAlexander Yermolovich {"debug_line.dwo", {MCOFI.getDwarfLineDWOSection(), DW_SECT_LINE}},
641f8c65155SAlexander Yermolovich {"debug_macro.dwo", {MCOFI.getDwarfMacroDWOSection(), DW_SECT_MACRO}},
642f8c65155SAlexander Yermolovich {"debug_abbrev.dwo", {MCOFI.getDwarfAbbrevDWOSection(), DW_SECT_ABBREV}},
643f8c65155SAlexander Yermolovich {"debug_loclists.dwo",
644f8c65155SAlexander Yermolovich {MCOFI.getDwarfLoclistsDWOSection(), DW_SECT_LOCLISTS}},
645f8c65155SAlexander Yermolovich {"debug_rnglists.dwo",
646f8c65155SAlexander Yermolovich {MCOFI.getDwarfRnglistsDWOSection(), DW_SECT_RNGLISTS}},
647f8c65155SAlexander Yermolovich {"debug_cu_index", {CUIndexSection, static_cast<DWARFSectionKind>(0)}},
648f8c65155SAlexander Yermolovich {"debug_tu_index", {TUIndexSection, static_cast<DWARFSectionKind>(0)}}};
649f8c65155SAlexander Yermolovich
650f8c65155SAlexander Yermolovich MapVector<uint64_t, UnitIndexEntry> IndexEntries;
651f8c65155SAlexander Yermolovich MapVector<uint64_t, UnitIndexEntry> TypeIndexEntries;
652f8c65155SAlexander Yermolovich
653f8c65155SAlexander Yermolovich uint32_t ContributionOffsets[8] = {};
654f8c65155SAlexander Yermolovich uint16_t Version = 0;
655f8c65155SAlexander Yermolovich uint32_t IndexVersion = 0;
6564c44dcffSJinjie Huang bool AnySectionOverflow = false;
657f8c65155SAlexander Yermolovich
658f8c65155SAlexander Yermolovich DWPStringPool Strings(Out, StrSection);
659f8c65155SAlexander Yermolovich
660f8c65155SAlexander Yermolovich SmallVector<OwningBinary<object::ObjectFile>, 128> Objects;
661f8c65155SAlexander Yermolovich Objects.reserve(Inputs.size());
662f8c65155SAlexander Yermolovich
663f8c65155SAlexander Yermolovich std::deque<SmallString<32>> UncompressedSections;
664f8c65155SAlexander Yermolovich
665f8c65155SAlexander Yermolovich for (const auto &Input : Inputs) {
666f8c65155SAlexander Yermolovich auto ErrOrObj = object::ObjectFile::createObjectFile(Input);
667734843ebSZhang Qing Shan if (!ErrOrObj) {
668734843ebSZhang Qing Shan return handleErrors(ErrOrObj.takeError(),
669734843ebSZhang Qing Shan [&](std::unique_ptr<ECError> EC) -> Error {
670734843ebSZhang Qing Shan return createFileError(Input, Error(std::move(EC)));
671734843ebSZhang Qing Shan });
672734843ebSZhang Qing Shan }
673f8c65155SAlexander Yermolovich
674f8c65155SAlexander Yermolovich auto &Obj = *ErrOrObj->getBinary();
675f8c65155SAlexander Yermolovich Objects.push_back(std::move(*ErrOrObj));
676f8c65155SAlexander Yermolovich
677f8c65155SAlexander Yermolovich UnitIndexEntry CurEntry = {};
678f8c65155SAlexander Yermolovich
679f8c65155SAlexander Yermolovich StringRef CurStrSection;
680f8c65155SAlexander Yermolovich StringRef CurStrOffsetSection;
681f8c65155SAlexander Yermolovich std::vector<StringRef> CurTypesSection;
682f8c65155SAlexander Yermolovich std::vector<StringRef> CurInfoSection;
683f8c65155SAlexander Yermolovich StringRef AbbrevSection;
684f8c65155SAlexander Yermolovich StringRef CurCUIndexSection;
685f8c65155SAlexander Yermolovich StringRef CurTUIndexSection;
686f8c65155SAlexander Yermolovich
687f8c65155SAlexander Yermolovich // This maps each section contained in this file to its length.
688f8c65155SAlexander Yermolovich // This information is later on used to calculate the contributions,
689f8c65155SAlexander Yermolovich // i.e. offset and length, of each compile/type unit to a section.
690f8c65155SAlexander Yermolovich std::vector<std::pair<DWARFSectionKind, uint32_t>> SectionLength;
691f8c65155SAlexander Yermolovich
692f8c65155SAlexander Yermolovich for (const auto &Section : Obj.sections())
693f8c65155SAlexander Yermolovich if (auto Err = handleSection(
694f8c65155SAlexander Yermolovich KnownSections, StrSection, StrOffsetSection, TypesSection,
695f8c65155SAlexander Yermolovich CUIndexSection, TUIndexSection, InfoSection, Section, Out,
696f8c65155SAlexander Yermolovich UncompressedSections, ContributionOffsets, CurEntry,
697f8c65155SAlexander Yermolovich CurStrSection, CurStrOffsetSection, CurTypesSection,
698f8c65155SAlexander Yermolovich CurInfoSection, AbbrevSection, CurCUIndexSection,
699f8c65155SAlexander Yermolovich CurTUIndexSection, SectionLength))
700f8c65155SAlexander Yermolovich return Err;
701f8c65155SAlexander Yermolovich
702f8c65155SAlexander Yermolovich if (CurInfoSection.empty())
703f8c65155SAlexander Yermolovich continue;
704f8c65155SAlexander Yermolovich
705f8c65155SAlexander Yermolovich Expected<InfoSectionUnitHeader> HeaderOrErr =
706f8c65155SAlexander Yermolovich parseInfoSectionUnitHeader(CurInfoSection.front());
707f8c65155SAlexander Yermolovich if (!HeaderOrErr)
708f8c65155SAlexander Yermolovich return HeaderOrErr.takeError();
709f8c65155SAlexander Yermolovich InfoSectionUnitHeader &Header = *HeaderOrErr;
710f8c65155SAlexander Yermolovich
711f8c65155SAlexander Yermolovich if (Version == 0) {
712f8c65155SAlexander Yermolovich Version = Header.Version;
713f8c65155SAlexander Yermolovich IndexVersion = Version < 5 ? 2 : 5;
714f8c65155SAlexander Yermolovich } else if (Version != Header.Version) {
715f8c65155SAlexander Yermolovich return make_error<DWPError>("incompatible DWARF compile unit versions.");
716f8c65155SAlexander Yermolovich }
717f8c65155SAlexander Yermolovich
718f8c65155SAlexander Yermolovich writeStringsAndOffsets(Out, Strings, StrOffsetSection, CurStrSection,
719f8c65155SAlexander Yermolovich CurStrOffsetSection, Header.Version);
720f8c65155SAlexander Yermolovich
721f8c65155SAlexander Yermolovich for (auto Pair : SectionLength) {
722f8c65155SAlexander Yermolovich auto Index = getContributionIndex(Pair.first, IndexVersion);
7237fc79340SAlexander Yermolovich CurEntry.Contributions[Index].setOffset(ContributionOffsets[Index]);
7247fc79340SAlexander Yermolovich CurEntry.Contributions[Index].setLength(Pair.second);
72553a483ceSzhuna uint32_t OldOffset = ContributionOffsets[Index];
7267fc79340SAlexander Yermolovich ContributionOffsets[Index] += CurEntry.Contributions[Index].getLength32();
72753a483ceSzhuna if (OldOffset > ContributionOffsets[Index]) {
72853a483ceSzhuna uint32_t SectionIndex = 0;
72953a483ceSzhuna for (auto &Section : Obj.sections()) {
73053a483ceSzhuna if (SectionIndex == Index) {
7314c44dcffSJinjie Huang if (Error Err = sectionOverflowErrorOrWarning(
73253a483ceSzhuna OldOffset, ContributionOffsets[Index], *Section.getName(),
7334c44dcffSJinjie Huang OverflowOptValue, AnySectionOverflow))
7344c44dcffSJinjie Huang return Err;
73553a483ceSzhuna }
73653a483ceSzhuna ++SectionIndex;
73753a483ceSzhuna }
7384c44dcffSJinjie Huang if (AnySectionOverflow)
7394c44dcffSJinjie Huang break;
74053a483ceSzhuna }
741f8c65155SAlexander Yermolovich }
742f8c65155SAlexander Yermolovich
743f8c65155SAlexander Yermolovich uint32_t &InfoSectionOffset =
744f8c65155SAlexander Yermolovich ContributionOffsets[getContributionIndex(DW_SECT_INFO, IndexVersion)];
745f8c65155SAlexander Yermolovich if (CurCUIndexSection.empty()) {
746f8c65155SAlexander Yermolovich bool FoundCUUnit = false;
747adf4142fSFangrui Song Out.switchSection(InfoSection);
748f8c65155SAlexander Yermolovich for (StringRef Info : CurInfoSection) {
749f8c65155SAlexander Yermolovich uint64_t UnitOffset = 0;
750f8c65155SAlexander Yermolovich while (Info.size() > UnitOffset) {
751f8c65155SAlexander Yermolovich Expected<InfoSectionUnitHeader> HeaderOrError =
752f8c65155SAlexander Yermolovich parseInfoSectionUnitHeader(Info.substr(UnitOffset, Info.size()));
753f8c65155SAlexander Yermolovich if (!HeaderOrError)
754f8c65155SAlexander Yermolovich return HeaderOrError.takeError();
755f8c65155SAlexander Yermolovich InfoSectionUnitHeader &Header = *HeaderOrError;
756f8c65155SAlexander Yermolovich
757f8c65155SAlexander Yermolovich UnitIndexEntry Entry = CurEntry;
758f8c65155SAlexander Yermolovich auto &C = Entry.Contributions[getContributionIndex(DW_SECT_INFO,
759f8c65155SAlexander Yermolovich IndexVersion)];
7607fc79340SAlexander Yermolovich C.setOffset(InfoSectionOffset);
7617fc79340SAlexander Yermolovich C.setLength(Header.Length + 4);
762f8df8114SAlexander Yermolovich
763f8df8114SAlexander Yermolovich if (std::numeric_limits<uint32_t>::max() - InfoSectionOffset <
76453a483ceSzhuna C.getLength32()) {
76553a483ceSzhuna if (Error Err = sectionOverflowErrorOrWarning(
76653a483ceSzhuna InfoSectionOffset, InfoSectionOffset + C.getLength32(),
7674c44dcffSJinjie Huang "debug_info", OverflowOptValue, AnySectionOverflow))
76853a483ceSzhuna return Err;
7694c44dcffSJinjie Huang if (AnySectionOverflow) {
7704c44dcffSJinjie Huang if (Header.Version < 5 ||
7714c44dcffSJinjie Huang Header.UnitType == dwarf::DW_UT_split_compile)
7724c44dcffSJinjie Huang FoundCUUnit = true;
7734c44dcffSJinjie Huang break;
7744c44dcffSJinjie Huang }
77553a483ceSzhuna }
776f8df8114SAlexander Yermolovich
7777fc79340SAlexander Yermolovich UnitOffset += C.getLength32();
778f8c65155SAlexander Yermolovich if (Header.Version < 5 ||
779f8c65155SAlexander Yermolovich Header.UnitType == dwarf::DW_UT_split_compile) {
7807fc79340SAlexander Yermolovich Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
7817fc79340SAlexander Yermolovich Header, AbbrevSection,
7827fc79340SAlexander Yermolovich Info.substr(UnitOffset - C.getLength32(), C.getLength32()),
783f8c65155SAlexander Yermolovich CurStrOffsetSection, CurStrSection);
784f8c65155SAlexander Yermolovich
785f8c65155SAlexander Yermolovich if (!EID)
786f8c65155SAlexander Yermolovich return createFileError(Input, EID.takeError());
787f8c65155SAlexander Yermolovich const auto &ID = *EID;
788f8c65155SAlexander Yermolovich auto P = IndexEntries.insert(std::make_pair(ID.Signature, Entry));
789f8c65155SAlexander Yermolovich if (!P.second)
790f8c65155SAlexander Yermolovich return buildDuplicateError(*P.first, ID, "");
791f8c65155SAlexander Yermolovich P.first->second.Name = ID.Name;
792f8c65155SAlexander Yermolovich P.first->second.DWOName = ID.DWOName;
793f8c65155SAlexander Yermolovich
794f8c65155SAlexander Yermolovich FoundCUUnit = true;
795f8c65155SAlexander Yermolovich } else if (Header.UnitType == dwarf::DW_UT_split_type) {
796f8c65155SAlexander Yermolovich auto P = TypeIndexEntries.insert(
7977a47ee51SKazu Hirata std::make_pair(*Header.Signature, Entry));
798f8c65155SAlexander Yermolovich if (!P.second)
799f8c65155SAlexander Yermolovich continue;
800f8c65155SAlexander Yermolovich }
8017fc79340SAlexander Yermolovich Out.emitBytes(
8027fc79340SAlexander Yermolovich Info.substr(UnitOffset - C.getLength32(), C.getLength32()));
8037fc79340SAlexander Yermolovich InfoSectionOffset += C.getLength32();
804f8c65155SAlexander Yermolovich }
8054c44dcffSJinjie Huang if (AnySectionOverflow)
8064c44dcffSJinjie Huang break;
807f8c65155SAlexander Yermolovich }
808f8c65155SAlexander Yermolovich
809f8c65155SAlexander Yermolovich if (!FoundCUUnit)
810f8c65155SAlexander Yermolovich return make_error<DWPError>("no compile unit found in file: " + Input);
811f8c65155SAlexander Yermolovich
812f8c65155SAlexander Yermolovich if (IndexVersion == 2) {
813f8c65155SAlexander Yermolovich // Add types from the .debug_types section from DWARF < 5.
81453a483ceSzhuna if (Error Err = addAllTypesFromTypesSection(
815f8c65155SAlexander Yermolovich Out, TypeIndexEntries, TypesSection, CurTypesSection, CurEntry,
81653a483ceSzhuna ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)],
8174c44dcffSJinjie Huang OverflowOptValue, AnySectionOverflow))
81853a483ceSzhuna return Err;
819f8c65155SAlexander Yermolovich }
8204c44dcffSJinjie Huang if (AnySectionOverflow)
8214c44dcffSJinjie Huang break;
822f8c65155SAlexander Yermolovich continue;
823f8c65155SAlexander Yermolovich }
824f8c65155SAlexander Yermolovich
825f8c65155SAlexander Yermolovich if (CurInfoSection.size() != 1)
826f8c65155SAlexander Yermolovich return make_error<DWPError>("expected exactly one occurrence of a debug "
827f8c65155SAlexander Yermolovich "info section in a .dwp file");
828f8c65155SAlexander Yermolovich StringRef DwpSingleInfoSection = CurInfoSection.front();
829f8c65155SAlexander Yermolovich
830f8c65155SAlexander Yermolovich DWARFUnitIndex CUIndex(DW_SECT_INFO);
831f8c65155SAlexander Yermolovich DataExtractor CUIndexData(CurCUIndexSection, Obj.isLittleEndian(), 0);
832f8c65155SAlexander Yermolovich if (!CUIndex.parse(CUIndexData))
833f8c65155SAlexander Yermolovich return make_error<DWPError>("failed to parse cu_index");
834f8c65155SAlexander Yermolovich if (CUIndex.getVersion() != IndexVersion)
835f8c65155SAlexander Yermolovich return make_error<DWPError>("incompatible cu_index versions, found " +
836f8c65155SAlexander Yermolovich utostr(CUIndex.getVersion()) +
837f8c65155SAlexander Yermolovich " and expecting " + utostr(IndexVersion));
838f8c65155SAlexander Yermolovich
839adf4142fSFangrui Song Out.switchSection(InfoSection);
840f8c65155SAlexander Yermolovich for (const DWARFUnitIndex::Entry &E : CUIndex.getRows()) {
841f8c65155SAlexander Yermolovich auto *I = E.getContributions();
842f8c65155SAlexander Yermolovich if (!I)
843f8c65155SAlexander Yermolovich continue;
844f8c65155SAlexander Yermolovich auto P = IndexEntries.insert(std::make_pair(E.getSignature(), CurEntry));
845f8c65155SAlexander Yermolovich StringRef CUInfoSection =
846f8c65155SAlexander Yermolovich getSubsection(DwpSingleInfoSection, E, DW_SECT_INFO);
847f8c65155SAlexander Yermolovich Expected<InfoSectionUnitHeader> HeaderOrError =
848f8c65155SAlexander Yermolovich parseInfoSectionUnitHeader(CUInfoSection);
849f8c65155SAlexander Yermolovich if (!HeaderOrError)
850f8c65155SAlexander Yermolovich return HeaderOrError.takeError();
851f8c65155SAlexander Yermolovich InfoSectionUnitHeader &Header = *HeaderOrError;
852f8c65155SAlexander Yermolovich
853f8c65155SAlexander Yermolovich Expected<CompileUnitIdentifiers> EID = getCUIdentifiers(
854f8c65155SAlexander Yermolovich Header, getSubsection(AbbrevSection, E, DW_SECT_ABBREV),
855f8c65155SAlexander Yermolovich CUInfoSection,
856f8c65155SAlexander Yermolovich getSubsection(CurStrOffsetSection, E, DW_SECT_STR_OFFSETS),
857f8c65155SAlexander Yermolovich CurStrSection);
858f8c65155SAlexander Yermolovich if (!EID)
859f8c65155SAlexander Yermolovich return createFileError(Input, EID.takeError());
860f8c65155SAlexander Yermolovich const auto &ID = *EID;
861f8c65155SAlexander Yermolovich if (!P.second)
862f8c65155SAlexander Yermolovich return buildDuplicateError(*P.first, ID, Input);
863f8c65155SAlexander Yermolovich auto &NewEntry = P.first->second;
864f8c65155SAlexander Yermolovich NewEntry.Name = ID.Name;
865f8c65155SAlexander Yermolovich NewEntry.DWOName = ID.DWOName;
866f8c65155SAlexander Yermolovich NewEntry.DWPName = Input;
867f8c65155SAlexander Yermolovich for (auto Kind : CUIndex.getColumnKinds()) {
868f8c65155SAlexander Yermolovich if (!isSupportedSectionKind(Kind))
869f8c65155SAlexander Yermolovich continue;
870f8c65155SAlexander Yermolovich auto &C =
871f8c65155SAlexander Yermolovich NewEntry.Contributions[getContributionIndex(Kind, IndexVersion)];
8727fc79340SAlexander Yermolovich C.setOffset(C.getOffset() + I->getOffset());
8737fc79340SAlexander Yermolovich C.setLength(I->getLength());
874f8c65155SAlexander Yermolovich ++I;
875f8c65155SAlexander Yermolovich }
876f8c65155SAlexander Yermolovich unsigned Index = getContributionIndex(DW_SECT_INFO, IndexVersion);
877f8c65155SAlexander Yermolovich auto &C = NewEntry.Contributions[Index];
878f8c65155SAlexander Yermolovich Out.emitBytes(CUInfoSection);
8797fc79340SAlexander Yermolovich C.setOffset(InfoSectionOffset);
8807fc79340SAlexander Yermolovich InfoSectionOffset += C.getLength32();
881f8c65155SAlexander Yermolovich }
882f8c65155SAlexander Yermolovich
883f8c65155SAlexander Yermolovich if (!CurTUIndexSection.empty()) {
884f8c65155SAlexander Yermolovich llvm::DWARFSectionKind TUSectionKind;
885f8c65155SAlexander Yermolovich MCSection *OutSection;
886f8c65155SAlexander Yermolovich StringRef TypeInputSection;
887f8c65155SAlexander Yermolovich // Write type units into debug info section for DWARFv5.
888f8c65155SAlexander Yermolovich if (Version >= 5) {
889f8c65155SAlexander Yermolovich TUSectionKind = DW_SECT_INFO;
890f8c65155SAlexander Yermolovich OutSection = InfoSection;
891f8c65155SAlexander Yermolovich TypeInputSection = DwpSingleInfoSection;
892f8c65155SAlexander Yermolovich } else {
893f8c65155SAlexander Yermolovich // Write type units into debug types section for DWARF < 5.
894f8c65155SAlexander Yermolovich if (CurTypesSection.size() != 1)
895f8c65155SAlexander Yermolovich return make_error<DWPError>(
896f8c65155SAlexander Yermolovich "multiple type unit sections in .dwp file");
897f8c65155SAlexander Yermolovich
898f8c65155SAlexander Yermolovich TUSectionKind = DW_SECT_EXT_TYPES;
899f8c65155SAlexander Yermolovich OutSection = TypesSection;
900f8c65155SAlexander Yermolovich TypeInputSection = CurTypesSection.front();
901f8c65155SAlexander Yermolovich }
902f8c65155SAlexander Yermolovich
903f8c65155SAlexander Yermolovich DWARFUnitIndex TUIndex(TUSectionKind);
904f8c65155SAlexander Yermolovich DataExtractor TUIndexData(CurTUIndexSection, Obj.isLittleEndian(), 0);
905f8c65155SAlexander Yermolovich if (!TUIndex.parse(TUIndexData))
906f8c65155SAlexander Yermolovich return make_error<DWPError>("failed to parse tu_index");
907f8c65155SAlexander Yermolovich if (TUIndex.getVersion() != IndexVersion)
908f8c65155SAlexander Yermolovich return make_error<DWPError>("incompatible tu_index versions, found " +
909f8c65155SAlexander Yermolovich utostr(TUIndex.getVersion()) +
910f8c65155SAlexander Yermolovich " and expecting " + utostr(IndexVersion));
911f8c65155SAlexander Yermolovich
912f8c65155SAlexander Yermolovich unsigned TypesContributionIndex =
913f8c65155SAlexander Yermolovich getContributionIndex(TUSectionKind, IndexVersion);
91453a483ceSzhuna if (Error Err = addAllTypesFromDWP(
91553a483ceSzhuna Out, TypeIndexEntries, TUIndex, OutSection, TypeInputSection,
91653a483ceSzhuna CurEntry, ContributionOffsets[TypesContributionIndex],
9174c44dcffSJinjie Huang TypesContributionIndex, OverflowOptValue, AnySectionOverflow))
91853a483ceSzhuna return Err;
919f8c65155SAlexander Yermolovich }
9204c44dcffSJinjie Huang if (AnySectionOverflow)
9214c44dcffSJinjie Huang break;
922f8c65155SAlexander Yermolovich }
923f8c65155SAlexander Yermolovich
924f8c65155SAlexander Yermolovich if (Version < 5) {
925f8c65155SAlexander Yermolovich // Lie about there being no info contributions so the TU index only includes
926f8c65155SAlexander Yermolovich // the type unit contribution for DWARF < 5. In DWARFv5 the TU index has a
927f8c65155SAlexander Yermolovich // contribution to the info section, so we do not want to lie about it.
928f8c65155SAlexander Yermolovich ContributionOffsets[0] = 0;
929f8c65155SAlexander Yermolovich }
930f8c65155SAlexander Yermolovich writeIndex(Out, MCOFI.getDwarfTUIndexSection(), ContributionOffsets,
931f8c65155SAlexander Yermolovich TypeIndexEntries, IndexVersion);
932f8c65155SAlexander Yermolovich
933f8c65155SAlexander Yermolovich if (Version < 5) {
934f8c65155SAlexander Yermolovich // Lie about the type contribution for DWARF < 5. In DWARFv5 the type
935f8c65155SAlexander Yermolovich // section does not exist, so no need to do anything about this.
936f8c65155SAlexander Yermolovich ContributionOffsets[getContributionIndex(DW_SECT_EXT_TYPES, 2)] = 0;
937f8c65155SAlexander Yermolovich // Unlie about the info contribution
938f8c65155SAlexander Yermolovich ContributionOffsets[0] = 1;
939f8c65155SAlexander Yermolovich }
940f8c65155SAlexander Yermolovich
941f8c65155SAlexander Yermolovich writeIndex(Out, MCOFI.getDwarfCUIndexSection(), ContributionOffsets,
942f8c65155SAlexander Yermolovich IndexEntries, IndexVersion);
943f8c65155SAlexander Yermolovich
944f8c65155SAlexander Yermolovich return Error::success();
945f8c65155SAlexander Yermolovich }
946f8c65155SAlexander Yermolovich } // namespace llvm
947