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(Value: MergedFunctions.size()); |
21 | for (const auto &F : MergedFunctions) { |
22 | Out.writeU32(Value: 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(O&: Out, /*NoPadding =*/true); |
27 | if (!result) |
28 | return result.takeError(); |
29 | const auto Length = Out.tell() - StartOffset; |
30 | Out.fixup32(Value: static_cast<uint32_t>(Length), Offset: StartOffset - 4); |
31 | } |
32 | return Error::success(); |
33 | } |
34 | |
35 | llvm::Expected<MergedFunctionsInfo> |
36 | MergedFunctionsInfo::(DataExtractor &Data, uint64_t BaseAddr) { |
37 | MergedFunctionsInfo MFI; |
38 | auto = MFI.getFuncsDataExtractors(Data); |
39 | |
40 | if (!FuncExtractorsOrError) |
41 | return FuncExtractorsOrError.takeError(); |
42 | |
43 | for (DataExtractor &FuncData : *FuncExtractorsOrError) { |
44 | llvm::Expected<FunctionInfo> FI = FunctionInfo::decode(Data&: FuncData, BaseAddr); |
45 | if (!FI) |
46 | return FI.takeError(); |
47 | MFI.MergedFunctions.push_back(x: std::move(*FI)); |
48 | } |
49 | |
50 | return MFI; |
51 | } |
52 | |
53 | llvm::Expected<std::vector<DataExtractor>> |
54 | MergedFunctionsInfo::(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: Offset, length: 4)) |
60 | return createStringError( |
61 | EC: std::errc::io_error, |
62 | Fmt: "unable to read the function count at offset 0x%8.8" PRIx64, Vals: Offset); |
63 | |
64 | uint32_t Count = Data.getU32(offset_ptr: &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: Offset, length: 4)) |
69 | return createStringError( |
70 | EC: std::errc::io_error, |
71 | Fmt: "unable to read size of function %u at offset 0x%8.8" PRIx64, Vals: i, |
72 | Vals: Offset); |
73 | |
74 | uint32_t FnSize = Data.getU32(offset_ptr: &Offset); |
75 | |
76 | // Ensure there is enough data for the function content. |
77 | if (!Data.isValidOffsetForDataOfSize(offset: Offset, length: FnSize)) |
78 | return createStringError( |
79 | EC: std::errc::io_error, |
80 | Fmt: "function data is truncated for function %u at offset 0x%8.8" PRIx64 |
81 | ", expected size %u" , |
82 | Vals: i, Vals: Offset, Vals: FnSize); |
83 | |
84 | // Extract the function data. |
85 | Results.emplace_back(args: Data.getData().substr(Start: Offset, N: FnSize), |
86 | args: Data.isLittleEndian(), args: 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 | |