LLVM  13.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  FI.Range.Start = BaseAddr;
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.End = FI.Range.Start + 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.hasValue()) {
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.hasValue()) {
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  LR.FuncRange.Start = FuncAddr;
161  uint64_t Offset = 0;
162  LR.FuncRange.End = FuncAddr + Data.getU32(&Offset);
163  uint32_t NameOffset = Data.getU32(&Offset);
164  // The "lookup" functions doesn't report errors as accurately as the "decode"
165  // function as it is meant to be fast. For more accurage errors we could call
166  // "decode".
167  if (!Data.isValidOffset(Offset))
168  return createStringError(std::errc::io_error,
169  "FunctionInfo data is truncated");
170  // This function will be called with the result of a binary search of the
171  // address table, we must still make sure the address does not fall into a
172  // gap between functions are after the last function.
173  if (LR.FuncRange.size() > 0 && !LR.FuncRange.contains(Addr))
174  return createStringError(std::errc::io_error,
175  "address 0x%" PRIx64 " is not in GSYM", Addr);
176 
177  if (NameOffset == 0)
178  return createStringError(std::errc::io_error,
179  "0x%8.8" PRIx64 ": invalid FunctionInfo Name value 0x00000000",
180  Offset - 4);
181  LR.FuncName = GR.getString(NameOffset);
182  bool Done = false;
184  Optional<DataExtractor> InlineInfoData;
185  while (!Done) {
186  if (!Data.isValidOffsetForDataOfSize(Offset, 8))
187  return createStringError(std::errc::io_error,
188  "FunctionInfo data is truncated");
189  const uint32_t IT = Data.getU32(&Offset);
190  const uint32_t InfoLength = Data.getU32(&Offset);
191  const StringRef InfoBytes = Data.getData().substr(Offset, InfoLength);
192  if (InfoLength != InfoBytes.size())
193  return createStringError(std::errc::io_error,
194  "FunctionInfo data is truncated");
195  DataExtractor InfoData(InfoBytes, Data.isLittleEndian(),
196  Data.getAddressSize());
197  switch (IT) {
198  case InfoType::EndOfList:
199  Done = true;
200  break;
201 
203  if (auto ExpectedLE = LineTable::lookup(InfoData, FuncAddr, Addr))
204  LineEntry = ExpectedLE.get();
205  else
206  return ExpectedLE.takeError();
207  break;
208 
210  // We will parse the inline info after our line table, but only if
211  // we have a line entry.
212  InlineInfoData = InfoData;
213  break;
214 
215  default:
216  break;
217  }
218  Offset += InfoLength;
219  }
220 
221  if (!LineEntry) {
222  // We don't have a valid line entry for our address, fill in our source
223  // location as best we can and return.
224  SourceLocation SrcLoc;
225  SrcLoc.Name = LR.FuncName;
226  SrcLoc.Offset = Addr - FuncAddr;
227  LR.Locations.push_back(SrcLoc);
228  return LR;
229  }
230 
231  Optional<FileEntry> LineEntryFile = GR.getFile(LineEntry->File);
232  if (!LineEntryFile)
233  return createStringError(std::errc::invalid_argument,
234  "failed to extract file[%" PRIu32 "]",
235  LineEntry->File);
236 
237  SourceLocation SrcLoc;
238  SrcLoc.Name = LR.FuncName;
239  SrcLoc.Offset = Addr - FuncAddr;
240  SrcLoc.Dir = GR.getString(LineEntryFile->Dir);
241  SrcLoc.Base = GR.getString(LineEntryFile->Base);
242  SrcLoc.Line = LineEntry->Line;
243  LR.Locations.push_back(SrcLoc);
244  // If we don't have inline information, we are done.
245  if (!InlineInfoData)
246  return LR;
247  // We have inline information. Try to augment the lookup result with this
248  // data.
249  llvm::Error Err = InlineInfo::lookup(GR, *InlineInfoData, FuncAddr, Addr,
250  LR.Locations);
251  if (Err)
252  return std::move(Err);
253  return LR;
254 }
llvm
This class represents lattice values for constants.
Definition: AllocatorList.h:23
llvm::gsym::FunctionInfo::size
uint64_t size() const
Definition: FunctionInfo.h:175
llvm::gsym::AddressRange::size
uint64_t size() const
Definition: Range.h:38
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:41
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:54
llvm::Optional
Definition: APInt.h:33
Offset
uint64_t Offset
Definition: ELFObjHandler.cpp:81
llvm::gsym::SourceLocation::Name
StringRef Name
Function or symbol name.
Definition: LookupResult.h:23
llvm::Expected
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
FunctionInfo.h
llvm::gsym::AddressRange::Start
uint64_t Start
Definition: Range.h:34
llvm::gsym::InlineInfo
Inline information stores the name of the inline function along with an array of address ranges.
Definition: InlineInfo.h:61
llvm::Data
@ Data
Definition: SIMachineScheduler.h:56
llvm::gsym::SourceLocation::Dir
StringRef Dir
Line entry source file directory path.
Definition: LookupResult.h:24
llvm::gsym::SourceLocation::Offset
uint32_t Offset
Byte size offset within the named function.
Definition: LookupResult.h:27
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:247
llvm::gsym::FileEntry::Dir
uint32_t Dir
Offsets in the string table.
Definition: FileEntry.h:29
llvm::gsym::GsymReader
GsymReader is used to read GSYM data from a file or buffer.
Definition: GsymReader.h:47
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:144
llvm::gsym::GsymReader::getString
StringRef getString(uint32_t Offset) const
Get a string from the string table.
Definition: GsymReader.h:133
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:154
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:50
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:43
llvm::gsym::LineEntry::Line
uint32_t Line
Source line number.
Definition: LineEntry.h:25
llvm::RISCVFenceField::O
@ O
Definition: RISCVBaseInfo.h:128
LineTableInfo
@ LineTableInfo
Definition: FunctionInfo.cpp:23
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:80
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:42
llvm::gsym::FileEntry::Base
uint32_t Base
Definition: FileEntry.h:30
FileWriter.h
llvm::gsym::FileWriter
A simplified binary data writer class that doesn't require targets, target definitions,...
Definition: FileWriter.h:29
llvm::gsym::SourceLocation::Base
StringRef Base
Line entry source file basename.
Definition: LookupResult.h:25
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 IT block based on arch"), clEnumValN(RestrictedIT, "arm-restrict-it", "Disallow deprecated IT based on ARMv8"), clEnumValN(NoRestrictedIT, "arm-no-restrict-it", "Allow IT blocks based on ARMv7")))
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
uint32_t
GsymReader.h
LineTable.h
llvm::createStringError
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202
HEX32
#define HEX32(v)
Definition: Range.h:20
llvm::Error
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
DataExtractor.h
llvm::gsym::LookupResult::FuncName
StringRef FuncName
The concrete function name that contains LookupAddr.
Definition: LookupResult.h:44
EndOfList
@ EndOfList
Definition: FunctionInfo.cpp:22
llvm::gsym::AddressRange::End
uint64_t End
Definition: Range.h:35
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::AddressRange::contains
bool contains(uint64_t Addr) const
Definition: Range.h:39
llvm::gsym::SourceLocation
Definition: LookupResult.h:22
llvm::StringRef::size
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
llvm::gsym::SourceLocation::Line
uint32_t Line
Source file line number.
Definition: LookupResult.h:26
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