1a580b014SDimitry Andric //===- DebugCrossImpSubsection.cpp ----------------------------------------===//
2db17bf38SDimitry Andric //
3db17bf38SDimitry Andric // The LLVM Compiler Infrastructure
4db17bf38SDimitry Andric //
5db17bf38SDimitry Andric // This file is distributed under the University of Illinois Open Source
6db17bf38SDimitry Andric // License. See LICENSE.TXT for details.
7db17bf38SDimitry Andric //
8db17bf38SDimitry Andric //===----------------------------------------------------------------------===//
9db17bf38SDimitry Andric
10db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugCrossImpSubsection.h"
11a580b014SDimitry Andric #include "llvm/ADT/ArrayRef.h"
12db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/CodeViewError.h"
13db17bf38SDimitry Andric #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h"
14a580b014SDimitry Andric #include "llvm/Support/BinaryStreamReader.h"
15a580b014SDimitry Andric #include "llvm/Support/BinaryStreamWriter.h"
16a580b014SDimitry Andric #include "llvm/Support/Endian.h"
17a580b014SDimitry Andric #include "llvm/Support/Error.h"
18a580b014SDimitry Andric #include <algorithm>
19a580b014SDimitry Andric #include <cstdint>
20a580b014SDimitry Andric #include <utility>
21a580b014SDimitry Andric #include <vector>
22db17bf38SDimitry Andric
23db17bf38SDimitry Andric using namespace llvm;
24db17bf38SDimitry Andric using namespace llvm::codeview;
25db17bf38SDimitry Andric
26db17bf38SDimitry Andric Error VarStreamArrayExtractor<CrossModuleImportItem>::
operator ()(BinaryStreamRef Stream,uint32_t & Len,codeview::CrossModuleImportItem & Item)27db17bf38SDimitry Andric operator()(BinaryStreamRef Stream, uint32_t &Len,
28db17bf38SDimitry Andric codeview::CrossModuleImportItem &Item) {
29db17bf38SDimitry Andric BinaryStreamReader Reader(Stream);
30db17bf38SDimitry Andric if (Reader.bytesRemaining() < sizeof(CrossModuleImport))
31db17bf38SDimitry Andric return make_error<CodeViewError>(
32db17bf38SDimitry Andric cv_error_code::insufficient_buffer,
33db17bf38SDimitry Andric "Not enough bytes for a Cross Module Import Header!");
34db17bf38SDimitry Andric if (auto EC = Reader.readObject(Item.Header))
35db17bf38SDimitry Andric return EC;
36db17bf38SDimitry Andric if (Reader.bytesRemaining() < Item.Header->Count * sizeof(uint32_t))
37db17bf38SDimitry Andric return make_error<CodeViewError>(
38db17bf38SDimitry Andric cv_error_code::insufficient_buffer,
39db17bf38SDimitry Andric "Not enough to read specified number of Cross Module References!");
40db17bf38SDimitry Andric if (auto EC = Reader.readArray(Item.Imports, Item.Header->Count))
41db17bf38SDimitry Andric return EC;
42db17bf38SDimitry Andric return Error::success();
43db17bf38SDimitry Andric }
44db17bf38SDimitry Andric
initialize(BinaryStreamReader Reader)45db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize(
46db17bf38SDimitry Andric BinaryStreamReader Reader) {
47db17bf38SDimitry Andric return Reader.readArray(References, Reader.bytesRemaining());
48db17bf38SDimitry Andric }
49db17bf38SDimitry Andric
initialize(BinaryStreamRef Stream)50db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsectionRef::initialize(BinaryStreamRef Stream) {
51db17bf38SDimitry Andric BinaryStreamReader Reader(Stream);
52db17bf38SDimitry Andric return initialize(Reader);
53db17bf38SDimitry Andric }
54db17bf38SDimitry Andric
addImport(StringRef Module,uint32_t ImportId)55db17bf38SDimitry Andric void DebugCrossModuleImportsSubsection::addImport(StringRef Module,
56db17bf38SDimitry Andric uint32_t ImportId) {
57db17bf38SDimitry Andric Strings.insert(Module);
58db17bf38SDimitry Andric std::vector<support::ulittle32_t> Targets = {support::ulittle32_t(ImportId)};
59db17bf38SDimitry Andric auto Result = Mappings.insert(std::make_pair(Module, Targets));
60db17bf38SDimitry Andric if (!Result.second)
61db17bf38SDimitry Andric Result.first->getValue().push_back(Targets[0]);
62db17bf38SDimitry Andric }
63db17bf38SDimitry Andric
calculateSerializedSize() const64db17bf38SDimitry Andric uint32_t DebugCrossModuleImportsSubsection::calculateSerializedSize() const {
65db17bf38SDimitry Andric uint32_t Size = 0;
66db17bf38SDimitry Andric for (const auto &Item : Mappings) {
67db17bf38SDimitry Andric Size += sizeof(CrossModuleImport);
68db17bf38SDimitry Andric Size += sizeof(support::ulittle32_t) * Item.second.size();
69db17bf38SDimitry Andric }
70db17bf38SDimitry Andric return Size;
71db17bf38SDimitry Andric }
72db17bf38SDimitry Andric
commit(BinaryStreamWriter & Writer) const73db17bf38SDimitry Andric Error DebugCrossModuleImportsSubsection::commit(
74db17bf38SDimitry Andric BinaryStreamWriter &Writer) const {
75db17bf38SDimitry Andric using T = decltype(&*Mappings.begin());
76db17bf38SDimitry Andric std::vector<T> Ids;
77db17bf38SDimitry Andric Ids.reserve(Mappings.size());
78db17bf38SDimitry Andric
79db17bf38SDimitry Andric for (const auto &M : Mappings)
80db17bf38SDimitry Andric Ids.push_back(&M);
81db17bf38SDimitry Andric
82*b5893f02SDimitry Andric llvm::sort(Ids, [this](const T &L1, const T &L2) {
834ba319b5SDimitry Andric return Strings.getIdForString(L1->getKey()) <
844ba319b5SDimitry Andric Strings.getIdForString(L2->getKey());
85db17bf38SDimitry Andric });
86db17bf38SDimitry Andric
87db17bf38SDimitry Andric for (const auto &Item : Ids) {
88db17bf38SDimitry Andric CrossModuleImport Imp;
894ba319b5SDimitry Andric Imp.ModuleNameOffset = Strings.getIdForString(Item->getKey());
90db17bf38SDimitry Andric Imp.Count = Item->getValue().size();
91db17bf38SDimitry Andric if (auto EC = Writer.writeObject(Imp))
92db17bf38SDimitry Andric return EC;
93db17bf38SDimitry Andric if (auto EC = Writer.writeArray(makeArrayRef(Item->getValue())))
94db17bf38SDimitry Andric return EC;
95db17bf38SDimitry Andric }
96db17bf38SDimitry Andric return Error::success();
97db17bf38SDimitry Andric }
98