LLVM  11.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()) {
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()) {
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
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 }
GsymReader is used to read GSYM data from a file or buffer.
Definition: GsymReader.h:47
llvm::Optional< LineTable > OptLineTable
Definition: FunctionInfo.h:91
InfoType
FunctionInfo information type that is used to encode the optional data that is associated with a Func...
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
StringRef Base
Line entry source file basename.
Definition: LookupResult.h:25
StringRef FuncName
The concrete function name that contains LookupAddr.
Definition: LookupResult.h:44
This class represents lattice values for constants.
Definition: AllocatorList.h:23
StringRef Dir
Line entry source file directory path.
Definition: LookupResult.h:24
Inline information stores the name of the inline function along with an array of address ranges...
Definition: InlineInfo.h:61
bool contains(uint64_t Addr) const
Definition: Range.h:39
Line entries are used to encode the line tables in FunctionInfo objects.
Definition: LineEntry.h:22
uint32_t Line
Source file line number.
Definition: LookupResult.h:26
uint32_t getU32(uint64_t *offset_ptr, Error *Err=nullptr) const
Extract a uint32_t value from *offset_ptr.
StringRef getData() const
Get the data pointed to by this extractor.
Definition: DataExtractor.h:92
void alignTo(size_t Align)
Pad with zeroes at the current file position until the current file position matches the specified al...
Definition: FileWriter.cpp:71
llvm::Optional< InlineInfo > Inline
Definition: FunctionInfo.h:92
uint32_t Dir
Offsets in the string table.
Definition: FileEntry.h:29
Function information in GSYM files encodes information for one contiguous address range...
Definition: FunctionInfo.h:88
void fixup32(uint32_t Value, uint64_t Offset)
Fixup a uint32_t value at the specified offset in the stream.
Definition: FileWriter.cpp:53
uint64_t size() const
Definition: FunctionInfo.h:174
void writeU32(uint32_t Value)
Write a single uint32_t value into the stream at the current file position.
Definition: FileWriter.cpp:43
static llvm::Expected< LookupResult > lookup(DataExtractor &Data, const GsymReader &GR, uint64_t FuncAddr, uint64_t Addr)
Lookup an address within a FunctionInfo object&#39;s data stream.
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
LLVM_NODISCARD StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:612
uint64_t LookupAddr
The address that this lookup pertains to.
Definition: LookupResult.h:42
Optional< FileEntry > getFile(uint32_t Index) const
Get the a file entry for the suppplied file index.
Definition: GsymReader.h:144
StringRef getString(uint32_t Offset) const
Get a string from the string table.
Definition: GsymReader.h:133
uint32_t File
1 based index of file in FileTable
Definition: LineEntry.h:24
LLVM_NODISCARD size_t size() const
size - Get the string size.
Definition: StringRef.h:160
bool isLittleEndian() const
Get the endianness for this extractor.
Definition: DataExtractor.h:94
bool isValid() const
Query if a FunctionInfo object is valid.
Definition: FunctionInfo.h:117
SourceLocations Locations
The source locations that match this address.
Definition: LookupResult.h:54
uint8_t getAddressSize() const
Get the address size for this extractor.
Definition: DataExtractor.h:96
A simplified binary data writer class that doesn&#39;t require targets, target definitions, architectures, or require any other optional compile time libraries to be enabled via the build process.
Definition: FileWriter.h:29
static llvm::Expected< InlineInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an InlineInfo object from a binary data stream.
Definition: InlineInfo.cpp:222
StringRef Name
Function or symbol name.
Definition: LookupResult.h:23
uint32_t Offset
Byte size offset within the named function.
Definition: LookupResult.h:27
static llvm::Expected< LineTable > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an LineTable object from a binary data stream.
Definition: LineTable.cpp:251
bool isValidOffsetForDataOfSize(uint64_t offset, uint64_t length) const
Test the availability of length bytes of data from offset.
bool isValidOffset(uint64_t offset) const
Test the validity of offset.
AddressRange FuncRange
The concrete function address range.
Definition: LookupResult.h:43
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")))
static llvm::Expected< FunctionInfo > decode(DataExtractor &Data, uint64_t BaseAddr)
Decode an object from a binary data stream.
uint32_t Name
String table offset in the string table.
Definition: FunctionInfo.h:90
llvm::Expected< uint64_t > encode(FileWriter &O) const
Encode this object into FileWriter stream.
uint64_t tell()
Return the current offset within the file.
Definition: FileWriter.cpp:67
static Expected< LineEntry > lookup(DataExtractor &Data, uint64_t BaseAddr, uint64_t Addr)
Lookup a single address within a line table&#39;s data.
Definition: LineTable.cpp:266
#define HEX32(v)
Definition: Range.h:20
uint64_t size() const
Definition: Range.h:38
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:57
uint32_t Line
Source line number.
Definition: LineEntry.h:25
raw_ostream & operator<<(raw_ostream &OS, const FunctionInfo &R)
Error createStringError(std::error_code EC, char const *Fmt, const Ts &... Vals)
Create formatted StringError object.
Definition: Error.h:1202