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