From 9448581d9e02c8ab964fbfe73431aecbf7fad128 Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Mon, 12 Nov 2012 11:32:42 +0000 Subject: [PATCH] [ASan] Remove llvm-symbolizer from compiler-rt/utils/ This is the first (1/2) part of a change that moves llvm-symbolizer to llvm/tools/, which will allow to build it with both cmake and configure+make. llvm-svn: 167722 --- compiler-rt/CMakeLists.txt | 3 - compiler-rt/lib/asan/lit_tests/lit.cfg | 4 +- compiler-rt/utils/CMakeLists.txt | 1 - .../utils/llvm-symbolizer/CMakeLists.txt | 17 - .../utils/llvm-symbolizer/llvm-symbolizer.cpp | 379 ------------------ 5 files changed, 2 insertions(+), 402 deletions(-) delete mode 100644 compiler-rt/utils/CMakeLists.txt delete mode 100644 compiler-rt/utils/llvm-symbolizer/CMakeLists.txt delete mode 100644 compiler-rt/utils/llvm-symbolizer/llvm-symbolizer.cpp diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 44f116e08242..4544f15805ef 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -146,9 +146,6 @@ endmacro(add_clang_compiler_rt_libraries) # Add the public header's directory to the includes for all of compiler-rt. include_directories(include) -# Build utils before building compiler-rt library. -add_subdirectory(utils) - add_subdirectory(lib) if(LLVM_INCLUDE_TESTS) diff --git a/compiler-rt/lib/asan/lit_tests/lit.cfg b/compiler-rt/lib/asan/lit_tests/lit.cfg index c98ec2618627..90cab107c82d 100644 --- a/compiler-rt/lib/asan/lit_tests/lit.cfg +++ b/compiler-rt/lib/asan/lit_tests/lit.cfg @@ -70,9 +70,9 @@ config.substitutions.append( ("%clangxx_asan ", (" " + config.clang + " " + # Setup path to external LLVM symbolizer to run AddressSanitizer output tests. llvm_obj_root = getattr(config, 'llvm_obj_root', None) if llvm_obj_root: + llvm_tools_dir = getattr(config, 'llvm_tools_dir', None) config.environment['LLVM_SYMBOLIZER_PATH'] = os.path.join( - config.llvm_obj_root, "projects", "compiler-rt", "utils", - "llvm-symbolizer", "llvm-symbolizer") + llvm_tools_dir, "llvm-symbolizer") # Setup path to symbolizer script. # FIXME: Instead we should copy this script to the build tree and point diff --git a/compiler-rt/utils/CMakeLists.txt b/compiler-rt/utils/CMakeLists.txt deleted file mode 100644 index cb75012a6008..000000000000 --- a/compiler-rt/utils/CMakeLists.txt +++ /dev/null @@ -1 +0,0 @@ -add_subdirectory(llvm-symbolizer) diff --git a/compiler-rt/utils/llvm-symbolizer/CMakeLists.txt b/compiler-rt/utils/llvm-symbolizer/CMakeLists.txt deleted file mode 100644 index a01ed53a0d2c..000000000000 --- a/compiler-rt/utils/llvm-symbolizer/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -# FIXME: As we plan to execute llvm-symbolizer binary from Sanitizer -# runtime, it has to be compiled for all supported targets (x86_64, i386 etc). -# This means that we need LLVM libraries to be compiled for these -# targets as well. Currently, there is no support for such a build strategy. - -set(LLVM_LINK_COMPONENTS - DebugInfo - Object - ) - -add_llvm_tool(llvm-symbolizer - llvm-symbolizer.cpp - ) - -# FIXME: Set sane output directory for llvm-symbolizer -set_target_properties(llvm-symbolizer PROPERTIES - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/compiler-rt/utils/llvm-symbolizer/llvm-symbolizer.cpp b/compiler-rt/utils/llvm-symbolizer/llvm-symbolizer.cpp deleted file mode 100644 index 79bdcedd3b64..000000000000 --- a/compiler-rt/utils/llvm-symbolizer/llvm-symbolizer.cpp +++ /dev/null @@ -1,379 +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/MachO.h" -#include "llvm/Object/ObjectFile.h" -#include "llvm/Support/Casting.h" -#include "llvm/Support/CommandLine.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ManagedStatic.h" -#include "llvm/Support/MemoryBuffer.h" -#include "llvm/Support/Path.h" -#include "llvm/Support/PrettyStackTrace.h" -#include "llvm/Support/Signals.h" -#include "llvm/Support/raw_ostream.h" - -#include -#include -#include -#include - -using namespace llvm; -using namespace object; - -static cl::opt -UseSymbolTable("use-symbol-table", cl::init(true), - cl::desc("Prefer names in symbol table to names " - "in debug info")); - -static cl::opt -PrintFunctions("functions", cl::init(true), - cl::desc("Print function names as well as line " - "information for a given address")); - -static cl::opt -PrintInlining("inlining", cl::init(true), - cl::desc("Print all inlined frames for a given address")); - -static cl::opt -Demangle("demangle", cl::init(true), - cl::desc("Demangle function names")); - -static StringRef ToolInvocationPath; - -static bool error(error_code ec) { - if (!ec) return false; - errs() << ToolInvocationPath << ": error reading file: " - << ec.message() << ".\n"; - return true; -} - -static uint32_t getDILineInfoSpecifierFlags() { - uint32_t Flags = llvm::DILineInfoSpecifier::FileLineInfo | - llvm::DILineInfoSpecifier::AbsoluteFilePath; - if (PrintFunctions) - Flags |= llvm::DILineInfoSpecifier::FunctionName; - return Flags; -} - -static void patchFunctionNameInDILineInfo(const std::string &NewFunctionName, - DILineInfo &LineInfo) { - std::string FileName = LineInfo.getFileName(); - LineInfo = DILineInfo(StringRef(FileName), StringRef(NewFunctionName), - LineInfo.getLine(), LineInfo.getColumn()); -} - -namespace { -class ModuleInfo { - OwningPtr Module; - OwningPtr DebugInfoContext; - public: - ModuleInfo(ObjectFile *Obj, DIContext *DICtx) - : Module(Obj), DebugInfoContext(DICtx) {} - - DILineInfo symbolizeCode(uint64_t ModuleOffset) const { - DILineInfo LineInfo; - if (DebugInfoContext) { - LineInfo = DebugInfoContext->getLineInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags()); - } - // Override function name from symbol table if necessary. - if (PrintFunctions && UseSymbolTable) { - std::string Function; - if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) { - patchFunctionNameInDILineInfo(Function, LineInfo); - } - } - return LineInfo; - } - - DIInliningInfo symbolizeInlinedCode(uint64_t ModuleOffset) const { - DIInliningInfo InlinedContext; - if (DebugInfoContext) { - InlinedContext = DebugInfoContext->getInliningInfoForAddress( - ModuleOffset, getDILineInfoSpecifierFlags()); - } - // Make sure there is at least one frame in context. - if (InlinedContext.getNumberOfFrames() == 0) { - InlinedContext.addFrame(DILineInfo()); - } - // Override the function name in lower frame with name from symbol table. - if (PrintFunctions && UseSymbolTable) { - DIInliningInfo PatchedInlinedContext; - for (uint32_t i = 0, n = InlinedContext.getNumberOfFrames(); - i != n; i++) { - DILineInfo LineInfo = InlinedContext.getFrame(i); - if (i == n - 1) { - std::string Function; - if (getFunctionNameFromSymbolTable(ModuleOffset, Function)) { - patchFunctionNameInDILineInfo(Function, LineInfo); - } - } - PatchedInlinedContext.addFrame(LineInfo); - } - InlinedContext = PatchedInlinedContext; - } - return InlinedContext; - } - - private: - bool getFunctionNameFromSymbolTable(uint64_t Address, - std::string &FunctionName) 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 SymbolAddress; - uint64_t SymbolSize; - SymbolRef::Type SymbolType; - if (error(si->getAddress(SymbolAddress)) || - SymbolAddress == UnknownAddressOrSize) continue; - if (error(si->getSize(SymbolSize)) || - SymbolSize == UnknownAddressOrSize) continue; - if (error(si->getType(SymbolType))) 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 (SymbolAddress <= Address && Address < SymbolAddress + SymbolSize && - SymbolType == SymbolRef::ST_Function) { - StringRef Name; - if (error(si->getName(Name))) continue; - FunctionName = Name.str(); - return true; - } - } - return false; - } -}; - -typedef std::map ModuleMapTy; -typedef ModuleMapTy::iterator ModuleMapIter; -} // namespace - -static ModuleMapTy Modules; - -static bool isFullNameOfDwarfSection(const StringRef &FullName, - const StringRef &ShortName) { - static const char kDwarfPrefix[] = "__DWARF,"; - StringRef Name = FullName; - // 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 == ShortName); -} - -// Returns true if the object endianness is known. -static bool getObjectEndianness(const ObjectFile *Obj, - bool &IsLittleEndian) { - // FIXME: Implement this when libLLVMObject allows to do it easily. - IsLittleEndian = true; - return true; -} - -static void getDebugInfoSections(const ObjectFile *Obj, - StringRef &DebugInfoSection, - StringRef &DebugAbbrevSection, - StringRef &DebugLineSection, - StringRef &DebugArangesSection, - StringRef &DebugStringSection, - StringRef &DebugRangesSection) { - if (Obj == 0) - return; - 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; - else if (isFullNameOfDwarfSection(Name, "debug_ranges")) - DebugRangesSection = Data; - } -} - -static ObjectFile *getObjectFile(const std::string &Path) { - OwningPtr Buff; - MemoryBuffer::getFile(Path, Buff); - return ObjectFile::createObjectFile(Buff.take()); -} - -static std::string getDarwinDWARFResourceForModule(const std::string &Path) { - StringRef Basename = sys::path::filename(Path); - const std::string &DSymDirectory = Path + ".dSYM"; - SmallString<16> ResourceName = StringRef(DSymDirectory); - sys::path::append(ResourceName, "Contents", "Resources", "DWARF"); - sys::path::append(ResourceName, Basename); - return ResourceName.str(); -} - -static ModuleInfo *getOrCreateModuleInfo(const std::string &ModuleName) { - ModuleMapIter I = Modules.find(ModuleName); - if (I != Modules.end()) - return I->second; - - ObjectFile *Obj = getObjectFile(ModuleName); - if (Obj == 0) { - // Module name doesn't point to a valid object file. - Modules.insert(make_pair(ModuleName, (ModuleInfo*)0)); - return 0; - } - - DIContext *Context = 0; - bool IsLittleEndian; - if (getObjectEndianness(Obj, IsLittleEndian)) { - StringRef DebugInfo; - StringRef DebugAbbrev; - StringRef DebugLine; - StringRef DebugAranges; - StringRef DebugString; - StringRef DebugRanges; - getDebugInfoSections(Obj, DebugInfo, DebugAbbrev, DebugLine, - DebugAranges, DebugString, DebugRanges); - - // On Darwin we may find DWARF in separate object file in - // resource directory. - if (isa(Obj)) { - const std::string &ResourceName = getDarwinDWARFResourceForModule( - ModuleName); - ObjectFile *ResourceObj = getObjectFile(ResourceName); - if (ResourceObj != 0) - getDebugInfoSections(ResourceObj, DebugInfo, DebugAbbrev, DebugLine, - DebugAranges, DebugString, DebugRanges); - } - - Context = DIContext::getDWARFContext( - IsLittleEndian, DebugInfo, DebugAbbrev, - DebugAranges, DebugLine, DebugString, - DebugRanges); - assert(Context); - } - - ModuleInfo *Info = new ModuleInfo(Obj, Context); - Modules.insert(make_pair(ModuleName, Info)); - return Info; -} - -// Assume that __cxa_demangle is provided by libcxxabi. -extern "C" char *__cxa_demangle(const char *mangled_name, char *output_buffer, - size_t *length, int *status); - -static void printDILineInfo(DILineInfo LineInfo) { - // By default, DILineInfo contains "" for function/filename it - // cannot fetch. We replace it to "??" to make our output closer to addr2line. - static const std::string kDILineInfoBadString = ""; - static const std::string kSymbolizerBadString = "??"; - if (PrintFunctions) { - std::string FunctionName = LineInfo.getFunctionName(); - if (FunctionName == kDILineInfoBadString) - FunctionName = kSymbolizerBadString; - if (Demangle) { - int status = 0; - char *DemangledName = __cxa_demangle( - FunctionName.c_str(), 0, 0, &status); - if (status == 0) { - FunctionName = DemangledName; - free(DemangledName); - } - } - outs() << FunctionName << "\n"; - } - std::string Filename = LineInfo.getFileName(); - if (Filename == kDILineInfoBadString) - Filename = kSymbolizerBadString; - outs() << Filename << - ":" << LineInfo.getLine() << - ":" << LineInfo.getColumn() << - "\n"; -} - -static void symbolize(std::string ModuleName, std::string ModuleOffsetStr) { - ModuleInfo *Info = getOrCreateModuleInfo(ModuleName); - uint64_t Offset = 0; - if (Info == 0 || - StringRef(ModuleOffsetStr).getAsInteger(0, Offset)) { - printDILineInfo(DILineInfo()); - } else if (PrintInlining) { - DIInliningInfo InlinedContext = Info->symbolizeInlinedCode(Offset); - uint32_t FramesNum = InlinedContext.getNumberOfFrames(); - assert(FramesNum > 0); - for (uint32_t i = 0; i < FramesNum; i++) { - DILineInfo LineInfo = InlinedContext.getFrame(i); - printDILineInfo(LineInfo); - } - } else { - DILineInfo LineInfo = Info->symbolizeCode(Offset); - printDILineInfo(LineInfo); - } - - outs() << "\n"; // Print extra empty line to mark the end of output. - outs().flush(); -} - -static bool parseModuleNameAndOffset(std::string &ModuleName, - std::string &ModuleOffsetStr) { - static const int kMaxInputStringLength = 1024; - static const char kDelimiters[] = " \n"; - char InputString[kMaxInputStringLength]; - if (!fgets(InputString, sizeof(InputString), stdin)) - return false; - ModuleName = ""; - ModuleOffsetStr = ""; - // FIXME: Handle case when filename is given in quotes. - if (char *FilePath = strtok(InputString, kDelimiters)) { - ModuleName = FilePath; - if (char *OffsetStr = strtok((char*)0, kDelimiters)) - ModuleOffsetStr = OffsetStr; - } - return true; -} - -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]; - - std::string ModuleName; - std::string ModuleOffsetStr; - while (parseModuleNameAndOffset(ModuleName, ModuleOffsetStr)) { - symbolize(ModuleName, ModuleOffsetStr); - } - return 0; -} -- 2.34.1