LLVM  15.0.0git
FunctionInfo.cpp
Go to the documentation of this file.
1 //===- FunctionInfo.cpp ---------------------------------------------------===//
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 
15 
16 using namespace llvm;
17 using namespace gsym;
18 
19 /// FunctionInfo information type that is used to encode the optional data
20 /// that is associated with a FunctionInfo object.
22  EndOfList = 0u,
25 };
26 
28  OS << FI.Range << ": " << "Name=" << HEX32(FI.Name) << '\n';
29  if (FI.OptLineTable)
30  OS << FI.OptLineTable << '\n';
31  if (FI.Inline)
32  OS << FI.Inline << '\n';
33  return OS;
34 }
35 
37  uint64_t BaseAddr) {
38  FunctionInfo FI;
39  uint64_t Offset = 0;
40  if (!Data.isValidOffsetForDataOfSize(Offset, 4))
41  return createStringError(std::errc::io_error,
42  "0x%8.8" PRIx64 ": missing FunctionInfo Size", Offset);
43  FI.Range = {BaseAddr, BaseAddr + Data.getU32(&Offset)};
44  if (!Data.isValidOffsetForDataOfSize(Offset, 4))
45  return createStringError(std::errc::io_error,
46  "0x%8.8" PRIx64 ": missing FunctionInfo Name", Offset);
47  FI.Name = Data.getU32(&Offset);
48  if (FI.Name == 0)
49  return createStringError(std::errc::io_error,
50  "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x%8.8x",
51  Offset - 4, FI.Name);
52  bool Done = false;
53  while (!Done) {
54  if (!Data.isValidOffsetForDataOfSize(Offset, 4))
55  return createStringError(std::errc::io_error,
56  "0x%8.8" PRIx64 ": missing FunctionInfo InfoType value", Offset);
57  const uint32_t IT = Data.getU32(&Offset);
58  if (!Data.isValidOffsetForDataOfSize(Offset, 4))
59  return createStringError(std::errc::io_error,
60  "0x%8.8" PRIx64 ": missing FunctionInfo InfoType length", Offset);
61  const uint32_t InfoLength = Data.getU32(&Offset);
62  if (!Data.isValidOffsetForDataOfSize(Offset, InfoLength))
63  return createStringError(std::errc::io_error,
64  "0x%8.8" PRIx64 ": missing FunctionInfo data for InfoType %u",
65  Offset, IT);
66  DataExtractor InfoData(Data.getData().substr(Offset, InfoLength),
67  Data.isLittleEndian(),
68  Data.getAddressSize());
69  switch (IT) {
71  Done = true;
72  break;
73 
75  if (Expected<LineTable> LT = LineTable::decode(InfoData, BaseAddr))
76  FI.OptLineTable = std::move(LT.get());
77  else
78  return LT.takeError();
79  break;
80 
82  if (Expected<InlineInfo> II = InlineInfo::decode(InfoData, BaseAddr))
83  FI.Inline = std::move(II.get());
84  else
85  return II.takeError();
86  break;
87 
88  default:
89  return createStringError(std::errc::io_error,
90  "0x%8.8" PRIx64 ": unsupported InfoType %u",
91  Offset-8, IT);
92  }
93  Offset += InfoLength;
94  }
95  return std::move(FI);
96 }
97 
99  if (!isValid())
100  return createStringError(std::errc::invalid_argument,
101  "attempted to encode invalid FunctionInfo object");
102  // Align FunctionInfo data to a 4 byte alignment.
103  O.alignTo(4);
104  const uint64_t FuncInfoOffset = O.tell();
105  // Write the size in bytes of this function as a uint32_t. This can be zero
106  // if we just have a symbol from a symbol table and that symbol has no size.
107  O.writeU32(size());
108  // Write the name of this function as a uint32_t string table offset.
109  O.writeU32(Name);
110 
111  if (OptLineTable.hasValue()) {
112  O.writeU32(InfoType::LineTableInfo);
113  // Write a uint32_t length as zero for now, we will fix this up after
114  // writing the LineTable out with the number of bytes that were written.
115  O.writeU32(0);
116  const auto StartOffset = O.tell();
117  llvm::Error err = OptLineTable->encode(O, Range.start());
118  if (err)
119  return std::move(err);
120  const auto Length = O.tell() - StartOffset;
121  if (Length > UINT32_MAX)
122  return createStringError(std::errc::invalid_argument,
123  "LineTable length is greater than UINT32_MAX");
124  // Fixup the size of the LineTable data with the correct size.
125  O.fixup32(static_cast<uint32_t>(Length), StartOffset - 4);
126  }
127 
128  // Write out the inline function info if we have any and if it is valid.
129  if (Inline.hasValue()) {
130  O.writeU32(InfoType::InlineInfo);
131  // Write a uint32_t length as zero for now, we will fix this up after
132  // writing the LineTable out with the number of bytes that were written.
133  O.writeU32(0);
134  const auto StartOffset = O.tell();
135  llvm::Error err = Inline->encode(O, Range.start());
136  if (err)
137  return std::move(err);
138  const auto Length = O.tell() - StartOffset;
139  if (Length > UINT32_MAX)
140  return createStringError(std::errc::invalid_argument,
141  "InlineInfo length is greater than UINT32_MAX");
142  // Fixup the size of the InlineInfo data with the correct size.
143  O.fixup32(static_cast<uint32_t>(Length), StartOffset - 4);
144  }
145 
146  // Terminate the data chunks with and end of list with zero size
147  O.writeU32(InfoType::EndOfList);
148  O.writeU32(0);
149  return FuncInfoOffset;
150 }
151 
152 
154  const GsymReader &GR,
155  uint64_t FuncAddr,
156  uint64_t Addr) {
157  LookupResult LR;
158  LR.LookupAddr = Addr;
159  uint64_t Offset = 0;
160  LR.FuncRange = {FuncAddr, FuncAddr + Data.getU32(&Offset)};
161  uint32_t NameOffset = Data.getU32(&Offset);
162  // The "lookup" functions doesn't report errors as accurately as the "decode"
163  // function as it is meant to be fast. For more accurage errors we could call
164  // "decode".
165  if (!Data.isValidOffset(Offset))
166  return createStringError(std::errc::io_error,
167  "FunctionInfo data is truncated");
168  // This function will be called with the result of a binary search of the
169  // address table, we must still make sure the address does not fall into a
170  // gap between functions are after the last function.
171  if (LR.FuncRange.size() > 0 && !LR.FuncRange.contains(Addr))
172  return createStringError(std::errc::io_error,
173  "address 0x%" PRIx64 " is not in GSYM", Addr);
174 
175  if (NameOffset == 0)
176  return createStringError(std::errc::io_error,
177  "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x00000000",
178  Offset - 4);
179  LR.FuncName = GR.getString(NameOffset);
180  bool Done = false;
182  Optional<DataExtractor> InlineInfoData;
183  while (!Done) {
184  if (!Data.isValidOffsetForDataOfSize(Offset, 8))
185  return createStringError(std::errc::io_error,
186  "FunctionInfo data is truncated");
187  const uint32_t IT = Data.getU32(&Offset);
188  const uint32_t InfoLength = Data.getU32(&Offset);
189  const StringRef InfoBytes = Data.getData().substr(Offset, InfoLength);
190  if (InfoLength != InfoBytes.size())
191  return createStringError(std::errc::io_error,
192  "FunctionInfo data is truncated");
193  DataExtractor InfoData(InfoBytes, Data.isLittleEndian(),
194  Data.getAddressSize());
195  switch (IT) {
196  case InfoType::EndOfList:
197  Done = true;
198  break;
199 
201  if (auto ExpectedLE = LineTable::lookup(InfoData, FuncAddr, Addr))
202  LineEntry = ExpectedLE.get();
203  else
204  return ExpectedLE.takeError();
205  break;
206 
208  // We will parse the inline info after our line table, but only if
209  // we have a line entry.
210  InlineInfoData = InfoData;
211  break;
212 
213  default:
214  break;
215  }
216  Offset += InfoLength;
217  }
218 
219  if (!LineEntry) {
220  // We don't have a valid line entry for our address, fill in our source
221  // location as best we can and return.
222  SourceLocation SrcLoc;
223  SrcLoc.Name = LR.FuncName;
224  SrcLoc.Offset = Addr - FuncAddr;
225  LR.Locations.push_back(SrcLoc);
226  return LR;
227  }
228 
229  Optional<FileEntry> LineEntryFile = GR.getFile(LineEntry->File);
230  if (!LineEntryFile)
231  return createStringError(std::errc::invalid_argument,
232  "failed to extract file[%" PRIu32 "]",
233  LineEntry->File);
234 
235  SourceLocation SrcLoc;
236  SrcLoc.Name = LR.FuncName;
237  SrcLoc.Offset = Addr - FuncAddr;
238  SrcLoc.Dir = GR.getString(LineEntryFile->Dir);
239  SrcLoc.Base = GR.getString(LineEntryFile->Base);
240  SrcLoc.Line = LineEntry->Line;
241  LR.Locations.push_back(SrcLoc);
242  // If we don't have inline information, we are done.
243  if (!InlineInfoData)
244  return LR;
245  // We have inline information. Try to augment the lookup result with this
246  // data.
247  llvm::Error Err = InlineInfo::lookup(GR, *InlineInfoData, FuncAddr, Addr,
248  LR.Locations);
249  if (Err)
250  return std::move(Err);
251  return LR;
252 }
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:17
llvm::gsym::FunctionInfo::size
uint64_t size() const
Definition: FunctionInfo.h:175
InlineInfo.h
llvm::gsym::FunctionInfo::Name
uint32_t Name
String table offset in the string table.
Definition: FunctionInfo.h:91
llvm::gsym::LineEntry
Line entries are used to encode the line tables in FunctionInfo objects.
Definition: LineEntry.h:22
llvm::gsym::FunctionInfo::isValid
bool isValid() const
Query if a FunctionInfo object is valid.
Definition: FunctionInfo.h:118
llvm::gsym::LookupResult
Definition: LookupResult.h:38
llvm::gsym::FunctionInfo::OptLineTable
llvm::Optional< LineTable > OptLineTable
Definition: FunctionInfo.h:92
llvm::gsym::LookupResult::Locations
SourceLocations Locations
The source locations that match this address.
Definition: LookupResult.h:51
llvm::Optional
Definition: APInt.h:33
llvm::gsym::SourceLocation::Name
StringRef Name
Function or symbol name.
Definition: LookupResult.h:22
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:41
FunctionInfo.h
llvm::gsym::InlineInfo
Inline information stores the name of the inline function along with an array of address ranges.
Definition: InlineInfo.h:60
llvm::Data
@ Data
Definition: SIMachineScheduler.h:55
llvm::gsym::SourceLocation::Dir
StringRef Dir
Line entry source file directory path.
Definition: LookupResult.h:23
llvm::gsym::SourceLocation::Offset
uint32_t Offset
Byte size offset within the named function.
Definition: LookupResult.h:26
llvm::gsym::LineEntry::File
uint32_t File
1 based index of file in FileTable
Definition: LineEntry.h:24
llvm::AArch64CC::LT
@ LT
Definition: AArch64BaseInfo.h:266
llvm::gsym::FileEntry::Dir
uint32_t Dir
Offsets in the string table.
Definition: FileEntry.h:28
llvm::gsym::GsymReader
GsymReader is used to read GSYM data from a file or buffer.
Definition: GsymReader.h:44
llvm::gsym::operator<<
raw_ostream & operator<<(raw_ostream &OS, const FunctionInfo &R)
Definition: FunctionInfo.cpp:27
llvm::gsym::InlineInfo::decode
static llvm::Expected< InlineInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an InlineInfo object from a binary data stream.
Definition: InlineInfo.cpp:222
llvm::gsym::GsymReader::getFile
Optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
Definition: GsymReader.h:141
llvm::gsym::GsymReader::getString
StringRef getString(uint32_t Offset) const
Get a string from the string table.
Definition: GsymReader.h:130
InfoType
InfoType
FunctionInfo information type that is used to encode the optional data that is associated with a Func...
Definition: FunctionInfo.cpp:21
llvm::gsym::FunctionInfo::lookup
static llvm::Expected< LookupResult > lookup(DataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr)
Lookup an address within a FunctionInfo object's data stream.
Definition: FunctionInfo.cpp:153
InlineInfo
@ InlineInfo
Definition: FunctionInfo.cpp:24
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:54
llvm::gsym::FunctionInfo::Range
AddressRange Range
Definition: FunctionInfo.h:90
llvm::gsym::FunctionInfo::Inline
llvm::Optional< InlineInfo > Inline
Definition: FunctionInfo.h:93
llvm::gsym::FunctionInfo
Function information in GSYM files encodes information for one contiguous address range.
Definition: FunctionInfo.h:89
llvm::gsym::LineTable::lookup
static Expected< LineEntry > lookup(DataExtractor &Data, uint64_t BaseAddr, uint64_t Addr)
Lookup a single address within a line table's data.
Definition: LineTable.cpp:266
llvm::gsym::LookupResult::FuncRange
AddressRange FuncRange
The concrete function address range.
Definition: LookupResult.h:40
llvm::gsym::LineEntry::Line
uint32_t Line
Source line number.
Definition: LineEntry.h:25
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:239
LineTableInfo
@ LineTableInfo
Definition: FunctionInfo.cpp:23
uint64_t
llvm::gsym::FunctionInfo::decode
static llvm::Expected< FunctionInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an object from a binary data stream.
Definition: FunctionInfo.cpp:36
Addr
uint64_t Addr
Definition: ELFObjHandler.cpp:78
move
compiles ldr LCPI1_0 ldr ldr mov lsr tst moveq r1 ldr LCPI1_1 and r0 bx lr It would be better to do something like to fold the shift into the conditional move
Definition: README.txt:546
llvm::gsym::FunctionInfo::encode
llvm::Expected< uint64_t > encode(FileWriter &O) const
Encode this object into FileWriter stream.
Definition: FunctionInfo.cpp:98
llvm::gsym::LookupResult::LookupAddr
uint64_t LookupAddr
The address that this lookup pertains to.
Definition: LookupResult.h:39
llvm::gsym::FileEntry::Base
uint32_t Base
Definition: FileEntry.h:29
FileWriter.h
llvm::gsym::FileWriter
A simplified binary data writer class that doesn't require targets, target definitions,...
Definition: FileWriter.h:29
HEX32
#define HEX32(v)
Definition: ExtractRanges.h:20
IT
static cl::opt< ITMode > IT(cl::desc("IT block support"), cl::Hidden, cl::init(DefaultIT), cl::ZeroOrMore, cl::values(clEnumValN(DefaultIT, "arm-default-it", "Generate any type of IT block"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow complex IT blocks")))
llvm::gsym::SourceLocation::Base
StringRef Base
Line entry source file basename.
Definition: LookupResult.h:24
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
uint32_t
GsymReader.h
LineTable.h
llvm::StringRef::size
constexpr LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:157
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1239
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:155
DataExtractor.h
llvm::gsym::LookupResult::FuncName
StringRef FuncName
The concrete function name that contains LookupAddr.
Definition: LookupResult.h:41
EndOfList
@ EndOfList
Definition: FunctionInfo.cpp:22
llvm::AddressRange::size
uint64_t size() const
Definition: AddressRanges.h:29
llvm::gsym::InlineInfo::lookup
static llvm::Error lookup(const GsymReader &GR, DataExtractor &Data, uint64_t BaseAddr, uint64_t Addr, SourceLocations &SrcLocs)
Lookup a single address within the inline info data.
Definition: InlineInfo.cpp:159
llvm::DataExtractor
Definition: DataExtractor.h:41
llvm::gsym::SourceLocation
Definition: LookupResult.h:21
llvm::AddressRange::start
uint64_t start() const
Definition: AddressRanges.h:27
llvm::AddressRange::contains
bool contains(uint64_t Addr) const
Definition: AddressRanges.h:30
llvm::gsym::SourceLocation::Line
uint32_t Line
Source file line number.
Definition: LookupResult.h:25
llvm::gsym::LineTable::decode
static llvm::Expected< LineTable > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an LineTable object from a binary data stream.
Definition: LineTable.cpp:251