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