xref: /llvm-project/llvm/lib/DebugInfo/GSYM/MergedFunctionsInfo.cpp (revision 6f28b4b5e960e1c4eeebad18b48e667df1e806a8)
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 
17 void MergedFunctionsInfo::clear() { MergedFunctions.clear(); }
18 
19 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>
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>>
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 
93 bool operator==(const MergedFunctionsInfo &LHS,
94                 const MergedFunctionsInfo &RHS) {
95   return LHS.MergedFunctions == RHS.MergedFunctions;
96 }
97