diff options
Diffstat (limited to 'utils/llvm-symbolizer/llvm-symbolizer.cc')
-rw-r--r-- | utils/llvm-symbolizer/llvm-symbolizer.cc | 237 |
1 files changed, 0 insertions, 237 deletions
diff --git a/utils/llvm-symbolizer/llvm-symbolizer.cc b/utils/llvm-symbolizer/llvm-symbolizer.cc deleted file mode 100644 index d9bcf2a68..000000000 --- a/utils/llvm-symbolizer/llvm-symbolizer.cc +++ /dev/null @@ -1,237 +0,0 @@ -//===-- llvm-symbolizer.cpp - Simple addr2line-like symbolizer ------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// This utility works much like "addr2line". It is able of transforming -// tuples (module name, module offset) to code locations (function name, -// file, line number, column number). It is targeted for compiler-rt tools -// (especially AddressSanitizer and ThreadSanitizer) that can use it -// to symbolize stack traces in their error reports. -// -//===----------------------------------------------------------------------===// - -#include "llvm/ADT/OwningPtr.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/DebugInfo/DIContext.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/raw_ostream.h" - -#include <cstdio> -#include <cstring> -#include <iostream> // NOLINT -#include <map> -#include <string> - -using namespace llvm; -using namespace object; -using std::string; - -static cl::opt<bool> -UseSymbolTable("use-symbol-table", cl::init(true), - cl::desc("Prefer names in symbol table to names " - "in debug info")); - -static cl::opt<bool> -PrintFunctions("functions", cl::init(true), - cl::desc("Print function names as well as line " - "information for a given address")); - -static StringRef ToolInvocationPath; - -static bool error(error_code ec) { - if (!ec) return false; - errs() << ToolInvocationPath << ": error reading file: " - << ec.message() << ".\n"; - return true; -} - -namespace { -class ModuleInfo { - OwningPtr<ObjectFile> Module; - OwningPtr<DIContext> DebugInfoContext; - public: - ModuleInfo(ObjectFile *obj, DIContext *di_ctx) - : Module(obj), DebugInfoContext(di_ctx) {} - DILineInfo symbolizeCode(uint64_t module_offset) const { - DILineInfo dli; - if (DebugInfoContext) { - uint32_t flags = llvm::DILineInfoSpecifier::FileLineInfo | - llvm::DILineInfoSpecifier::AbsoluteFilePath; - if (PrintFunctions) - flags |= llvm::DILineInfoSpecifier::FunctionName; - dli = DebugInfoContext->getLineInfoForAddress( - module_offset, flags); - } - // Override function name from symbol table if necessary. - if (PrintFunctions && UseSymbolTable) { - string filename = dli.getFileName(); - string function = dli.getFunctionName(); - if (getFunctionNameFromSymbolTable(module_offset, function)) { - dli = DILineInfo(StringRef(filename), StringRef(function), - dli.getLine(), dli.getColumn()); - } - } - return dli; - } - private: - bool getFunctionNameFromSymbolTable(size_t address, - string &function_name) const { - assert(Module); - error_code ec; - for (symbol_iterator si = Module->begin_symbols(), - se = Module->end_symbols(); - si != se; si.increment(ec)) { - if (error(ec)) return false; - uint64_t Address; - uint64_t Size; - if (error(si->getAddress(Address))) continue; - if (error(si->getSize(Size))) continue; - // FIXME: If a function has alias, there are two entries in symbol table - // with same address size. Make sure we choose the correct one. - if (Address <= address && address < Address + Size) { - StringRef Name; - if (error(si->getName(Name))) continue; - function_name = Name.str(); - return true; - } - } - return false; - } -}; - -typedef std::map<string, ModuleInfo*> ModuleMapTy; -typedef ModuleMapTy::iterator ModuleMapIter; -typedef ModuleMapTy::const_iterator ModuleMapConstIter; -} // namespace - -static ModuleMapTy modules; - -static bool isFullNameOfDwarfSection(const StringRef &full_name, - const StringRef &short_name) { - static const char kDwarfPrefix[] = "__DWARF,"; - StringRef name = full_name; - // Skip "__DWARF," prefix. - if (name.startswith(kDwarfPrefix)) - name = name.substr(strlen(kDwarfPrefix)); - // Skip . and _ prefixes. - name = name.substr(name.find_first_not_of("._")); - return (name == short_name); -} - -// Returns true if the object endianness is known. -static bool getObjectEndianness(const ObjectFile *obj, - bool &is_little_endian) { - // FIXME: Implement this when libLLVMObject allows to do it easily. - is_little_endian = true; - return true; -} - -static ModuleInfo *getOrCreateModuleInfo(const string &module_name) { - ModuleMapIter I = modules.find(module_name); - if (I != modules.end()) - return I->second; - - OwningPtr<MemoryBuffer> Buff; - MemoryBuffer::getFile(module_name, Buff); - ObjectFile *obj = ObjectFile::createObjectFile(Buff.take()); - assert(obj); - - DIContext *di_context = 0; - bool IsLittleEndian; - if (getObjectEndianness(obj, IsLittleEndian)) { - StringRef DebugInfoSection; - StringRef DebugAbbrevSection; - StringRef DebugLineSection; - StringRef DebugArangesSection; - StringRef DebugStringSection; - error_code ec; - for (section_iterator i = obj->begin_sections(), - e = obj->end_sections(); - i != e; i.increment(ec)) { - if (error(ec)) break; - StringRef name; - if (error(i->getName(name))) continue; - StringRef data; - if (error(i->getContents(data))) continue; - if (isFullNameOfDwarfSection(name, "debug_info")) - DebugInfoSection = data; - else if (isFullNameOfDwarfSection(name, "debug_abbrev")) - DebugAbbrevSection = data; - else if (isFullNameOfDwarfSection(name, "debug_line")) - DebugLineSection = data; - // Don't use debug_aranges for now, as address ranges contained - // there may not cover all instructions in the module - // else if (isFullNameOfDwarfSection(name, "debug_aranges")) - // DebugArangesSection = data; - else if (isFullNameOfDwarfSection(name, "debug_str")) - DebugStringSection = data; - } - - di_context = DIContext::getDWARFContext( - IsLittleEndian, DebugInfoSection, DebugAbbrevSection, - DebugArangesSection, DebugLineSection, DebugStringSection); - assert(di_context); - } - - ModuleInfo *module_info = new ModuleInfo(obj, di_context); - modules.insert(make_pair(module_name, module_info)); - return module_info; -} - -static void symbolize(const string &module_name, - const string &module_offset_str) { - // FIXME: check that module_name points to valid file. - ModuleInfo *module_info = getOrCreateModuleInfo(module_name); - DILineInfo line_info; - uint64_t module_offset; - if (!StringRef(module_offset_str).getAsInteger(0, module_offset)) { - line_info = module_info->symbolizeCode(module_offset); - } - // By default, DILineInfo contains "<invalid>" for function/filename it - // cannot fetch. We replace it to "??" to make our output closer to addr2line. - static const string kDILineInfoBadString = "<invalid>"; - static const string kSymbolizerBadString = "??"; - - if (PrintFunctions) { - string function_name = line_info.getFunctionName(); - if (function_name == kDILineInfoBadString) - function_name = kSymbolizerBadString; - outs() << function_name << "\n"; - } - string filename = line_info.getFileName(); - if (filename == kDILineInfoBadString) - filename = kSymbolizerBadString; - outs() << filename << - ":" << line_info.getLine() << - ":" << line_info.getColumn() << - "\n\n"; // Print extra empty line to mark the end of output. - outs().flush(); -} - -int main(int argc, char **argv) { - // Print stack trace if we signal out. - sys::PrintStackTraceOnErrorSignal(); - PrettyStackTraceProgram X(argc, argv); - llvm_shutdown_obj Y; // Call llvm_shutdown() on exit. - - cl::ParseCommandLineOptions(argc, argv, "llvm symbolizer for compiler-rt\n"); - ToolInvocationPath = argv[0]; - - string module_name; - string module_offset_str; - while (std::cin >> module_name >> module_offset_str) { - symbolize(module_name, module_offset_str); - } - return 0; -} |