LLVM: lib/DebugInfo/Symbolize/SymbolizableObjectFile.cpp Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

24

25using namespace llvm;

26using namespace object;

28

31 std::unique_ptr DICtx,

32 bool UntagAddresses) {

34 std::unique_ptr res(

35 new SymbolizableObjectFile(Obj, std::move(DICtx), UntagAddresses));

36 std::unique_ptr OpdExtractor;

38

39

43 if (!NameOrErr)

45

46 if (*NameOrErr == ".opd") {

48 if (!E)

49 return E.takeError();

50 OpdExtractor.reset(new DataExtractor(*E, Obj->isLittleEndian(),

51 Obj->getBytesInAddress()));

52 OpdAddress = Section->getAddress();

53 break;

54 }

55 }

56 }

57 std::vector<std::pair<SymbolRef, uint64_t>> Symbols =

59 for (auto &P : Symbols)

61 res->addSymbol(P.first, P.second, OpdExtractor.get(), OpdAddress))

62 return std::move(E);

63

64

65

66 if (Symbols.empty()) {

68 if (Error E = res->addCoffExportSymbols(CoffObj))

69 return std::move(E);

70 }

71

72 std::vector &SS = res->Symbols;

73

74

75

77 auto I = SS.begin(), E = SS.end(), J = SS.begin();

78 while (I != E) {

79 auto OI = I;

80 while (++I != E && OI->Addr == I->Addr) {

81 }

82 *J++ = I[-1];

83 }

84 SS.erase(J, SS.end());

85

86 return std::move(res);

87}

88

89SymbolizableObjectFile::SymbolizableObjectFile(const ObjectFile *Obj,

90 std::unique_ptr DICtx,

91 bool UntagAddresses)

92 : Module(Obj), DebugInfoContext(std::move(DICtx)),

93 UntagAddresses(UntagAddresses) {}

94

95namespace {

96

97struct OffsetNamePair {

100

101 bool operator<(const OffsetNamePair &R) const {

102 return Offset < R.Offset;

103 }

104};

105

106}

107

108Error SymbolizableObjectFile::addCoffExportSymbols(

110

111 std::vector ExportSyms;

113 StringRef Name;

115 if (auto EC = Ref.getSymbolName(Name))

116 return EC;

117 if (auto EC = Ref.getExportRVA(Offset))

118 return EC;

119 ExportSyms.push_back(OffsetNamePair{Offset, Name});

120 }

121 if (ExportSyms.empty())

123

124

125 array_pod_sort(ExportSyms.begin(), ExportSyms.end());

126

127

128

129 uint64_t ImageBase = CoffObj->getImageBase();

130 for (auto I = ExportSyms.begin(), E = ExportSyms.end(); I != E; ++I) {

131 OffsetNamePair &Export = *I;

132

133 uint32_t NextOffset = I != E ? I->Offset : Export.Offset + 1;

135 uint64_t SymbolSize = NextOffset - Export.Offset;

137 }

139}

140

141Error SymbolizableObjectFile::addSymbol(const SymbolRef &Symbol,

142 uint64_t SymbolSize,

143 DataExtractor *OpdExtractor,

144 uint64_t OpdAddress) {

145

147 Expected SymbolNameOrErr = Symbol.getName();

148 if (!SymbolNameOrErr)

149 return SymbolNameOrErr.takeError();

150 StringRef SymbolName = *SymbolNameOrErr;

151

152 uint32_t ELFSymIdx =

153 Obj.isELF() ? ELFSymbolRef(Symbol).getRawDataRefImpl().d.b : 0;

154 Expected<section_iterator> Sec = Symbol.getSection();

155 if (!Sec || Obj.section_end() == *Sec) {

156 if (Obj.isELF()) {

157

158 ELFSymbolRef ESym(Symbol);

160 FileSymbols.emplace_back(ELFSymIdx, SymbolName);

161 }

163 }

164

165 ExpectedSymbolRef::Type SymbolTypeOrErr = Symbol.getType();

166 if (!SymbolTypeOrErr)

167 return SymbolTypeOrErr.takeError();

169 if (Obj.isELF()) {

170

171

172 if ((elf_section_iterator(*Sec)->getFlags() & ELF::SHF_ALLOC) == 0)

174

175

176

177 uint8_t Type = ELFSymbolRef(Symbol).getELFType();

181

182

184 if (Flags & SymbolRef::SF_FormatSpecific)

189 }

190

191 Expected<uint64_t> SymbolAddressOrErr = Symbol.getAddress();

192 if (!SymbolAddressOrErr)

193 return SymbolAddressOrErr.takeError();

194 uint64_t SymbolAddress = *SymbolAddressOrErr;

195 if (UntagAddresses) {

196

197

198 SymbolAddress &= (1ull << 56) - 1;

199 SymbolAddress = (int64_t(SymbolAddress) << 8) >> 8;

200 }

201 if (OpdExtractor) {

202

203

204

205

206

207 uint64_t OpdOffset = SymbolAddress - OpdAddress;

209 SymbolAddress = OpdExtractor->getAddress(&OpdOffset);

210 }

211

212 if (Module->isMachO())

214

215 if (Obj.isELF() && ELFSymbolRef(Symbol).getBinding() != ELF::STB_LOCAL)

216 ELFSymIdx = 0;

217 Symbols.push_back({SymbolAddress, SymbolSize, SymbolName, ELFSymIdx});

219}

220

221

226

229 return CoffObject->getImageBase();

230 return 0;

231}

232

233bool SymbolizableObjectFile::getNameFromSymbolTable(

235 std::string &FileName) const {

238 if (SymbolIterator == Symbols.begin())

239 return false;

240 --SymbolIterator;

241 if (SymbolIterator->Size != 0 &&

242 SymbolIterator->Addr + SymbolIterator->Size <= Address)

243 return false;

244 Name = SymbolIterator->Name.str();

245 Addr = SymbolIterator->Addr;

246 Size = SymbolIterator->Size;

247

248 if (SymbolIterator->ELFLocalSymIdx != 0) {

249

250

251

254 FileSymbols,

255 std::make_pair(SymbolIterator->ELFLocalSymIdx, StringRef()));

256 if (It != FileSymbols.begin())

257 FileName = It[-1].second.str();

258 }

259 return true;

260}

261

262bool SymbolizableObjectFile::shouldOverrideWithSymbolTable(

264

265

266

267

268 return FNKind == FunctionNameKind::LinkageName && UseSymbolTable &&

270}

271

272DILineInfo

275 bool UseSymbolTable) const {

278 getModuleSectionIndexForAddress(ModuleOffset.Address);

280 std::optional DBGLineInfo =

281 DebugInfoContext->getLineInfoForAddress(ModuleOffset, LineInfoSpecifier);

282 if (DBGLineInfo)

283 LineInfo = *DBGLineInfo;

284

285

286 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {

287 std::string FunctionName, FileName;

289 if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,

290 FileName)) {

291 LineInfo.FunctionName = FunctionName;

292 LineInfo.StartAddress = Start;

293

294

295 if (!DBGLineInfo && !FileName.empty())

296 LineInfo.FileName = FileName;

297 }

298 }

299 return LineInfo;

300}

301

307 getModuleSectionIndexForAddress(ModuleOffset.Address);

309 ModuleOffset, LineInfoSpecifier);

310

311

312 bool EmptyFrameAdded = false;

314 EmptyFrameAdded = true;

316 }

317

318

319 if (shouldOverrideWithSymbolTable(LineInfoSpecifier.FNKind, UseSymbolTable)) {

320 std::string FunctionName, FileName;

322 if (getNameFromSymbolTable(ModuleOffset.Address, FunctionName, Start, Size,

323 FileName)) {

328

329

330 if (EmptyFrameAdded && !FileName.empty())

332 }

333 }

334

336}

337

341 std::string FileName;

343 FileName);

345

346

347 std::optional DL =

348 DebugInfoContext->getLineInfoForDataAddress(ModuleOffset);

349 if (DL && DL->Line != 0) {

352 }

353 return Res;

354}

355

360 getModuleSectionIndexForAddress(ModuleOffset.Address);

361 return DebugInfoContext->getLocalsForAddress(ModuleOffset);

362}

363

364std::vectorobject::SectionedAddress

366 std::vectorobject::SectionedAddress Result;

367 for (const SymbolDesc &Sym : Symbols) {

368 if (Sym.Name == Symbol) {

370 if (Offset < Sym.Size)

373 Result.push_back(A);

374 }

375 }

376 return Result;

377}

378

379

380uint64_t SymbolizableObjectFile::getModuleSectionIndexForAddress(

382

384 if (!Sec.isText() || Sec.isVirtual())

385 continue;

386

387 if (Address >= Sec.getAddress() &&

388 Address < Sec.getAddress() + Sec.getSize())

389 return Sec.getIndex();

390 }

391

393}

assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")

MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL

static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")

static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")

A format-neutral container for inlined code description.

Lightweight error class with error context and mandatory checking.

static ErrorSuccess success()

Create a success value.

Tagged union holding either a T or a Error.

Error takeError()

Take ownership of the stored error.

A Module instance is used to store all the information related to an LLVM module.

StringRef - Represent a constant reference to a string, i.e.

iterator_range< export_directory_iterator > export_directories() const

uint64_t getImageBase() const

This class is the base class for all object file types.

This is a value type class that represents a single section in the list of sections in the object fil...

This is a value type class that represents a single symbol in the list of symbols in the object file.

DIGlobal symbolizeData(object::SectionedAddress ModuleOffset) const override

Definition SymbolizableObjectFile.cpp:338

DILineInfo symbolizeCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override

Definition SymbolizableObjectFile.cpp:273

static Expected< std::unique_ptr< SymbolizableObjectFile > > create(const object::ObjectFile *Obj, std::unique_ptr< DIContext > DICtx, bool UntagAddresses)

Definition SymbolizableObjectFile.cpp:30

std::vector< object::SectionedAddress > findSymbol(StringRef Symbol, uint64_t Offset) const override

Definition SymbolizableObjectFile.cpp:365

uint64_t getModulePreferredBase() const override

Definition SymbolizableObjectFile.cpp:227

std::vector< DILocal > symbolizeFrame(object::SectionedAddress ModuleOffset) const override

Definition SymbolizableObjectFile.cpp:356

bool isWin32Module() const override

Definition SymbolizableObjectFile.cpp:222

DIInliningInfo symbolizeInlinedCode(object::SectionedAddress ModuleOffset, DILineInfoSpecifier LineInfoSpecifier, bool UseSymbolTable) const override

Definition SymbolizableObjectFile.cpp:302

constexpr char SymbolName[]

Key for Kernel::Metadata::mSymbolName.

@ IMAGE_FILE_MACHINE_I386

content_iterator< SectionRef > section_iterator

LLVM_ABI std::vector< std::pair< SymbolRef, uint64_t > > computeSymbolSizes(const ObjectFile &O)

DILineInfoSpecifier::FunctionNameKind FunctionNameKind

This is an optimization pass for GlobalISel generic memory operations.

bool operator<(int64_t V1, const APSInt &V2)

void stable_sort(R &&Range)

decltype(auto) dyn_cast(const From &Val)

dyn_cast - Return the argument parameter cast to the specified type.

@ Export

Export information to summary.

auto upper_bound(R &&Range, T &&Value)

Provide wrappers to std::upper_bound which take ranges instead of having to pass begin/end explicitly...

bool isa(const From &Val)

isa - Return true if the parameter to the template is an instance of one of the template type argu...

@ Ref

The access may reference the value stored in memory.

void cantFail(Error Err, const char *Msg=nullptr)

Report a fatal error if Err is a failure value.

OutputIt move(R &&Range, OutputIt Out)

Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.

void array_pod_sort(IteratorTy Start, IteratorTy End)

array_pod_sort - This sorts an array with the specified start and end extent.

Implement std::hash so that hash_code can be used in STL containers.

Container for description of a global variable.

Controls which fields of DILineInfo container should be filled with data.

A format-neutral container for source line information.

std::optional< uint64_t > StartAddress

static const uint64_t UndefSection