1 //===- MergedFunctionsInfo.cpp ----------------------------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8
9 #include "llvm/DebugInfo/GSYM/MergedFunctionsInfo.h"
10 #include "llvm/DebugInfo/GSYM/FileWriter.h"
11 #include "llvm/DebugInfo/GSYM/FunctionInfo.h"
12 #include "llvm/Support/DataExtractor.h"
13
14 using namespace llvm;
15 using namespace gsym;
16
clear()17 void MergedFunctionsInfo::clear() { MergedFunctions.clear(); }
18
encode(FileWriter & Out) const19 llvm::Error MergedFunctionsInfo::encode(FileWriter &Out) const {
20 Out.writeU32(MergedFunctions.size());
21 for (const auto &F : MergedFunctions) {
22 Out.writeU32(0);
23 const auto StartOffset = Out.tell();
24 // Encode the FunctionInfo with no padding so later we can just read them
25 // one after the other without knowing the offset in the stream for each.
26 llvm::Expected<uint64_t> result = F.encode(Out, /*NoPadding =*/true);
27 if (!result)
28 return result.takeError();
29 const auto Length = Out.tell() - StartOffset;
30 Out.fixup32(static_cast<uint32_t>(Length), StartOffset - 4);
31 }
32 return Error::success();
33 }
34
35 llvm::Expected<MergedFunctionsInfo>
decode(DataExtractor & Data,uint64_t BaseAddr)36 MergedFunctionsInfo::decode(DataExtractor &Data, uint64_t BaseAddr) {
37 MergedFunctionsInfo MFI;
38 auto FuncExtractorsOrError = MFI.getFuncsDataExtractors(Data);
39
40 if (!FuncExtractorsOrError)
41 return FuncExtractorsOrError.takeError();
42
43 for (DataExtractor &FuncData : *FuncExtractorsOrError) {
44 llvm::Expected<FunctionInfo> FI = FunctionInfo::decode(FuncData, BaseAddr);
45 if (!FI)
46 return FI.takeError();
47 MFI.MergedFunctions.push_back(std::move(*FI));
48 }
49
50 return MFI;
51 }
52
53 llvm::Expected<std::vector<DataExtractor>>
getFuncsDataExtractors(DataExtractor & Data)54 MergedFunctionsInfo::getFuncsDataExtractors(DataExtractor &Data) {
55 std::vector<DataExtractor> Results;
56 uint64_t Offset = 0;
57
58 // Ensure there is enough data to read the function count.
59 if (!Data.isValidOffsetForDataOfSize(Offset, 4))
60 return createStringError(
61 std::errc::io_error,
62 "unable to read the function count at offset 0x%8.8" PRIx64, Offset);
63
64 uint32_t Count = Data.getU32(&Offset);
65
66 for (uint32_t i = 0; i < Count; ++i) {
67 // Ensure there is enough data to read the function size.
68 if (!Data.isValidOffsetForDataOfSize(Offset, 4))
69 return createStringError(
70 std::errc::io_error,
71 "unable to read size of function %u at offset 0x%8.8" PRIx64, i,
72 Offset);
73
74 uint32_t FnSize = Data.getU32(&Offset);
75
76 // Ensure there is enough data for the function content.
77 if (!Data.isValidOffsetForDataOfSize(Offset, FnSize))
78 return createStringError(
79 std::errc::io_error,
80 "function data is truncated for function %u at offset 0x%8.8" PRIx64
81 ", expected size %u",
82 i, Offset, FnSize);
83
84 // Extract the function data.
85 Results.emplace_back(Data.getData().substr(Offset, FnSize),
86 Data.isLittleEndian(), Data.getAddressSize());
87
88 Offset += FnSize;
89 }
90 return Results;
91 }
92
operator ==(const MergedFunctionsInfo & LHS,const MergedFunctionsInfo & RHS)93 bool operator==(const MergedFunctionsInfo &LHS,
94 const MergedFunctionsInfo &RHS) {
95 return LHS.MergedFunctions == RHS.MergedFunctions;
96 }
97