brintos

brintos / llvm-project-archived public Read only

0
0
Text · 3.8 KiB · 728021b Raw
104 lines · cpp
1//===- DWARF.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "lld/Common/DWARF.h"10#include "lld/Common/ErrorHandler.h"11 12using namespace llvm;13 14namespace lld {15 16DWARFCache::DWARFCache(std::unique_ptr<llvm::DWARFContext> d)17    : dwarf(std::move(d)) {18  for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {19    auto report = [](Error err) {20      handleAllErrors(std::move(err),21                      [](ErrorInfoBase &info) { warn(info.message()); });22    };23    Expected<const DWARFDebugLine::LineTable *> expectedLT =24        dwarf->getLineTableForUnit(cu.get(), report);25    const DWARFDebugLine::LineTable *lt = nullptr;26    if (expectedLT)27      lt = *expectedLT;28    else29      report(expectedLT.takeError());30    if (!lt)31      continue;32    lineTables.push_back(lt);33 34    // Loop over variable records and insert them to variableLoc.35    for (const auto &entry : cu->dies()) {36      DWARFDie die(cu.get(), &entry);37      // Skip all tags that are not variables.38      if (die.getTag() != dwarf::DW_TAG_variable)39        continue;40 41      // Skip if a local variable because we don't need them for generating42      // error messages. In general, only non-local symbols can fail to be43      // linked.44      if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))45        continue;46 47      // Get the source filename index for the variable.48      unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);49      if (!lt->hasFileAtIndex(file))50        continue;51 52      // Get the line number on which the variable is declared.53      unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);54 55      // Here we want to take the variable name to add it into variableLoc.56      // Variable can have regular and linkage name associated. At first, we try57      // to get linkage name as it can be different, for example when we have58      // two variables in different namespaces of the same object. Use common59      // name otherwise, but handle the case when it also absent in case if the60      // input object file lacks some debug info.61      StringRef name =62          dwarf::toString(die.find(dwarf::DW_AT_linkage_name),63                          dwarf::toString(die.find(dwarf::DW_AT_name), ""));64      if (!name.empty())65        variableLoc.insert({name, {lt, file, line}});66    }67  }68}69 70// Returns the pair of file name and line number describing location of data71// object (variable, array, etc) definition.72std::optional<std::pair<std::string, unsigned>>73DWARFCache::getVariableLoc(StringRef name) {74  // Return if we have no debug information about data object.75  auto it = variableLoc.find(name);76  if (it == variableLoc.end())77    return std::nullopt;78 79  // Take file name string from line table.80  std::string fileName;81  if (!it->second.lt->getFileNameByIndex(82          it->second.file, {},83          DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))84    return std::nullopt;85 86  return std::make_pair(fileName, it->second.line);87}88 89// Returns source line information for a given offset90// using DWARF debug info.91std::optional<DILineInfo> DWARFCache::getDILineInfo(uint64_t offset,92                                                    uint64_t sectionIndex) {93  DILineInfo info;94  for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {95    if (lt->getFileLineInfoForAddress(96            {offset, sectionIndex}, false, nullptr,97            DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))98      return info;99  }100  return std::nullopt;101}102 103} // namespace lld104