[llvm] r223793 - Initial dsymutil tool commit.
Chandler Carruth
chandlerc at google.com
Tue Dec 9 09:14:00 PST 2014
Please revert, see my comment on your review thread. The review had not
concluded.
On Tue, Dec 9, 2014 at 6:03 PM, Frederic Riss <friss at apple.com> wrote:
> Author: friss
> Date: Tue Dec 9 11:03:30 2014
> New Revision: 223793
>
> URL: http://llvm.org/viewvc/llvm-project?rev=223793&view=rev
> Log:
> Initial dsymutil tool commit.
>
> The goal of this tool is to replicate Darwin's dsymutil functionality
> based on LLVM. dsymutil is a DWARF linker. Darwin's linker (ld64) does
> not link the debug information, it leaves it in the object files in
> relocatable form, but embbeds a `debug map` into the executable that
> describes where to find the debug information and how to relocate it.
> When releasing/archiving a binary, dsymutil is called to link all the DWARF
> information into a `dsym bundle` that can distributed/stored along with
> the binary.
>
> With this commit, the LLVM based dsymutil is just able to parse the STABS
> debug maps embedded by ld64 in linked binaries (and not all of them, for
> example archives aren't supported yet).
>
> Note that the tool directory is called dsymutil, but the executable is
> currently called llvm-dsymutil. This discrepancy will disappear once the
> tool will be feature complete. At this point the executable will be renamed
> to dsymutil, but until then you do not want it to override the system one.
>
> Differential Revision: http://reviews.llvm.org/D6242
>
> Added:
> llvm/trunk/test/tools/dsymutil/
> llvm/trunk/test/tools/dsymutil/Inputs/
> llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64 (with
> props)
> llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o
> llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64 (with props)
> llvm/trunk/test/tools/dsymutil/Inputs/basic1.c
> llvm/trunk/test/tools/dsymutil/Inputs/basic1.macho.x86_64.o
> llvm/trunk/test/tools/dsymutil/Inputs/basic2.c
> llvm/trunk/test/tools/dsymutil/Inputs/basic2.macho.x86_64.o
> llvm/trunk/test/tools/dsymutil/Inputs/basic3.c
> llvm/trunk/test/tools/dsymutil/Inputs/basic3.macho.x86_64.o
> llvm/trunk/test/tools/dsymutil/debug-map-parsing.test
> llvm/trunk/tools/dsymutil/
> llvm/trunk/tools/dsymutil/CMakeLists.txt
> llvm/trunk/tools/dsymutil/DebugMap.cpp
> llvm/trunk/tools/dsymutil/DebugMap.h
> llvm/trunk/tools/dsymutil/DwarfLinker.cpp
> llvm/trunk/tools/dsymutil/DwarfLinker.h
> llvm/trunk/tools/dsymutil/LLVMBuild.txt
> - copied, changed from r223790, llvm/trunk/tools/LLVMBuild.txt
> llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
> llvm/trunk/tools/dsymutil/MachODebugMapParser.h
> llvm/trunk/tools/dsymutil/Makefile
> llvm/trunk/tools/dsymutil/dsymutil.cpp
> Modified:
> llvm/trunk/tools/CMakeLists.txt
> llvm/trunk/tools/LLVMBuild.txt
> llvm/trunk/tools/Makefile
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64?rev=223793&view=auto
>
> ==============================================================================
> Binary files llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64
> (added) and llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64
> Tue Dec 9 11:03:30 2014 differ
>
> Propchange: llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o?rev=223793&view=auto
>
> ==============================================================================
> Binary files
> llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o (added) and
> llvm/trunk/test/tools/dsymutil/Inputs/basic-lto.macho.x86_64.o Tue Dec 9
> 11:03:30 2014 differ
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64?rev=223793&view=auto
>
> ==============================================================================
> Binary files llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64
> (added) and llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64 Tue
> Dec 9 11:03:30 2014 differ
>
> Propchange: llvm/trunk/test/tools/dsymutil/Inputs/basic.macho.x86_64
>
> ------------------------------------------------------------------------------
> svn:executable = *
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic1.c
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic1.c?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/basic1.c (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/basic1.c Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,25 @@
> +/* This is the main file used to produce the basic* objects that are
> + used for the dsymutil tests.
> +
> + These are compiled in a couple of different ways (always on a
> + Darwin system):
> + Basic compilation:
> + for FILE in basic1.c basic2.c basic3.c; do
> + clang -g -c $FILE -o ${FILE%.c}.macho.x86_64.o
> + done
> + clang basic1.macho.x86_64.o basic2.macho.x86_64.o
> basic3.macho.x86_64.o -o basic.macho.x86_64 -Wl,-dead_strip
> +
> + LTO compilation:
> + for FILE in basic1.c basic2.c basic3.c; do
> + clang -g -c -flto $FILE -o ${FILE%.c}-lto.o
> + done
> + clang basic1-lto.o basic2-lto.o basic3-lto.o -o
> basic-lto.macho.x86_64 -Wl,-object_path_lto,$PWD/basic-lto.macho.x86_64.o
> -Wl,-dead_strip
> + rm basic1-lto.o basic2-lto.o basic3-lto.o
> +
> +*/
> +
> +int foo(int);
> +
> +int main(int argc, const char *argv[]) {
> + return foo(argc);
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic1.macho.x86_64.o
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic1.macho.x86_64.o?rev=223793&view=auto
>
> ==============================================================================
> Binary files llvm/trunk/test/tools/dsymutil/Inputs/basic1.macho.x86_64.o
> (added) and llvm/trunk/test/tools/dsymutil/Inputs/basic1.macho.x86_64.o Tue
> Dec 9 11:03:30 2014 differ
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic2.c
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic2.c?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/basic2.c (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/basic2.c Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,22 @@
> +/* For compilation instructions see basic1.c. */
> +
> +static int baz = 42;
> +static int private_int;
> +extern volatile int val;
> +int unused_data = 1;
> +
> +int bar(int);
> +
> +void unused1() {
> + bar(baz);
> +}
> +
> +static int inc() {
> + return ++private_int;
> +}
> +
> +__attribute__((noinline))
> +int foo(int arg) {
> + return bar(arg+val) + inc() + baz++;
> +}
> +
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic2.macho.x86_64.o
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic2.macho.x86_64.o?rev=223793&view=auto
>
> ==============================================================================
> Binary files llvm/trunk/test/tools/dsymutil/Inputs/basic2.macho.x86_64.o
> (added) and llvm/trunk/test/tools/dsymutil/Inputs/basic2.macho.x86_64.o Tue
> Dec 9 11:03:30 2014 differ
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic3.c
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic3.c?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/Inputs/basic3.c (added)
> +++ llvm/trunk/test/tools/dsymutil/Inputs/basic3.c Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,20 @@
> +/* For compilation instructions see basic1.c. */
> +
> +volatile int val;
> +
> +extern int foo(int);
> +
> +int unused2() {
> + return foo(val);
> +}
> +
> +static int inc() {
> + return ++val;
> +}
> +
> +__attribute__((noinline))
> +int bar(int arg) {
> + if (arg > 42)
> + return inc();
> + return foo(val + arg);
> +}
>
> Added: llvm/trunk/test/tools/dsymutil/Inputs/basic3.macho.x86_64.o
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/Inputs/basic3.macho.x86_64.o?rev=223793&view=auto
>
> ==============================================================================
> Binary files llvm/trunk/test/tools/dsymutil/Inputs/basic3.macho.x86_64.o
> (added) and llvm/trunk/test/tools/dsymutil/Inputs/basic3.macho.x86_64.o Tue
> Dec 9 11:03:30 2014 differ
>
> Added: llvm/trunk/test/tools/dsymutil/debug-map-parsing.test
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/dsymutil/debug-map-parsing.test?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/tools/dsymutil/debug-map-parsing.test (added)
> +++ llvm/trunk/test/tools/dsymutil/debug-map-parsing.test Tue Dec 9
> 11:03:30 2014
> @@ -0,0 +1,48 @@
> +RUN: llvm-dsymutil -v -parse-only -oso-prepend-path=%p
> %p/Inputs/basic.macho.x86_64 | FileCheck %s
> +RUN: llvm-dsymutil -v -parse-only -oso-prepend-path=%p
> %p/Inputs/basic-lto.macho.x86_64 | FileCheck %s --check-prefix=CHECK-LTO
> +RUN: llvm-dsymutil -v -parse-only %p/Inputs/basic.macho.x86_64 2>&1 |
> FileCheck %s --check-prefix=NOT-FOUND
> +RUN: not llvm-dsymutil -v -parse-only %p/Inputs/inexistant 2>&1 |
> FileCheck %s --check-prefix=NO-EXECUTABLE
> +Check that We can parse the debug map of the basic executable.
> +
> +CHECK-NOT: error
> +CHECK: DEBUG MAP:
> +CHECK: /Inputs/basic1.macho.x86_64.o:
> +CHECK: 0000000000000000 => 0000000100000ea0 _main
> +CHECK: /Inputs/basic2.macho.x86_64.o:
> +CHECK: 0000000000000310 => 0000000100001000 _baz
> +CHECK: 0000000000000020 => 0000000100000ed0 _foo
> +CHECK: 0000000000000070 => 0000000100000f20 _inc
> +CHECK: 0000000000000560 => 0000000100001008 _private_int
> +CHECK: /Inputs/basic3.macho.x86_64.o:
> +CHECK: 0000000000000020 => 0000000100000f40 _bar
> +CHECK: 0000000000000070 => 0000000100000f90 _inc
> +CHECK: 0000000000000004 => 0000000100001004 _val
> +CHECK: END DEBUG MAP
> +
> +
> +Check that we can parse the debug-map of the basic-lto executable
> +
> +CHECK-LTO-NOT: error
> +CHECK-LTO: DEBUG MAP:
> +CHECK-LTO: /Inputs/basic-lto.macho.x86_64.o:
> +CHECK-LTO: 0000000000000050 => 0000000100000f90 _bar
> +CHECK-LTO: 0000000000000658 => 0000000100001000 _baz
> +CHECK-LTO: 0000000000000010 => 0000000100000f50 _foo
> +CHECK-LTO: 0000000000000000 => 0000000100000f40 _main
> +CHECK-LTO: 00000000000008e8 => 0000000100001008 _private_int
> +CHECK-LTO: 00000000000008ec => 0000000100001004 _val
> +CHECK-LTO: END DEBUG MAP
> +
> +Check that we warn about missing object files (this presumes that the
> files aren't
> +present in the machine's /Inputs/ folder, which should be a pretty safe
> bet).
> +
> +NOT-FOUND: cannot open{{.*}}"/Inputs/basic1.macho.x86_64.o": No such file
> +NOT-FOUND: cannot open{{.*}}"/Inputs/basic2.macho.x86_64.o": No such file
> +NOT-FOUND: cannot open{{.*}}"/Inputs/basic3.macho.x86_64.o": No such file
> +NOT-FOUND: DEBUG MAP:
> +NOT-FOUND-NEXT: END DEBUG MAP
> +
> +Check that we correctly error out on invalid executatble.
> +
> +NO-EXECUTABLE: cannot parse{{.*}}/inexistant": No such file
> +NO-EXECUTABLE-NOT: DEBUG MAP
>
> Modified: llvm/trunk/tools/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/CMakeLists.txt?rev=223793&r1=223792&r2=223793&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/CMakeLists.txt (original)
> +++ llvm/trunk/tools/CMakeLists.txt Tue Dec 9 11:03:30 2014
> @@ -36,6 +36,7 @@ add_llvm_tool_subdirectory(llvm-objdump)
> add_llvm_tool_subdirectory(llvm-readobj)
> add_llvm_tool_subdirectory(llvm-rtdyld)
> add_llvm_tool_subdirectory(llvm-dwarfdump)
> +add_llvm_tool_subdirectory(dsymutil)
> add_llvm_tool_subdirectory(llvm-vtabledump)
> if( LLVM_USE_INTEL_JITEVENTS )
> add_llvm_tool_subdirectory(llvm-jitlistener)
>
> Modified: llvm/trunk/tools/LLVMBuild.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/LLVMBuild.txt?rev=223793&r1=223792&r2=223793&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/LLVMBuild.txt (original)
> +++ llvm/trunk/tools/LLVMBuild.txt Tue Dec 9 11:03:30 2014
> @@ -16,7 +16,7 @@
>
> ;===------------------------------------------------------------------------===;
>
> [common]
> -subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer
> llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener
> llvm-link llvm-lto llvm-mc llvm-nm llvm-objdump llvm-profdata llvm-rtdyld
> llvm-size macho-dump opt llvm-mcmarkup verify-uselistorder
> +subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer
> llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener
> llvm-link llvm-lto llvm-mc llvm-nm llvm-objdump llvm-profdata llvm-rtdyld
> llvm-size macho-dump opt llvm-mcmarkup verify-uselistorder dsymutil
>
> [component_0]
> type = Group
>
> Modified: llvm/trunk/tools/Makefile
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/Makefile?rev=223793&r1=223792&r2=223793&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/Makefile (original)
> +++ llvm/trunk/tools/Makefile Tue Dec 9 11:03:30 2014
> @@ -33,7 +33,7 @@ PARALLEL_DIRS := opt llvm-as llvm-dis ll
> macho-dump llvm-objdump llvm-readobj llvm-rtdyld \
> llvm-dwarfdump llvm-cov llvm-size llvm-stress
> llvm-mcmarkup \
> llvm-profdata llvm-symbolizer obj2yaml yaml2obj
> llvm-c-test \
> - llvm-vtabledump verify-uselistorder
> + llvm-vtabledump verify-uselistorder dsymutil
>
> # If Intel JIT Events support is configured, build an extra tool to test
> it.
> ifeq ($(USE_INTEL_JITEVENTS), 1)
>
> Added: llvm/trunk/tools/dsymutil/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/CMakeLists.txt?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/CMakeLists.txt (added)
> +++ llvm/trunk/tools/dsymutil/CMakeLists.txt Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,12 @@
> +set(LLVM_LINK_COMPONENTS
> + Object
> + Support
> + )
> +
> +add_llvm_tool(llvm-dsymutil
> + dsymutil.cpp
> + DebugMap.cpp
> + DwarfLinker.cpp
> + MachODebugMapParser.cpp
> + )
> +
>
> Added: llvm/trunk/tools/dsymutil/DebugMap.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DebugMap.cpp?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DebugMap.cpp (added)
> +++ llvm/trunk/tools/dsymutil/DebugMap.cpp Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,84 @@
> +//===- tools/dsymutil/DebugMap.cpp - Generic debug map representation
> -----===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +#include "DebugMap.h"
> +
> +#include "llvm/ADT/STLExtras.h"
> +#include "llvm/Support/DataTypes.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include <algorithm>
> +
> +namespace llvm {
> +
> +using namespace llvm::object;
> +
> +DebugMapObject::DebugMapObject(StringRef ObjectFilename)
> + : Filename(ObjectFilename) {}
> +
> +bool DebugMapObject::addSymbol(StringRef Name, uint64_t ObjectAddress,
> + uint64_t LinkedAddress) {
> + auto InsertResult = Symbols.insert(std::make_pair(Name,
> +
> SymbolMapping{ObjectAddress,
> +
> LinkedAddress}));
> + return InsertResult.second;
> +}
> +
> +void DebugMapObject::print(raw_ostream& OS) const {
> + OS << getObjectFilename() << ":\n";
> + // Sort the symbols in alphabetical order, like llvm-nm (and to get
> + // deterministic output for testing).
> + typedef StringMapEntry<SymbolMapping> MapEntryTy;
> + std::vector<const MapEntryTy *> Entries;
> + Entries.reserve(Symbols.getNumItems());
> + for (auto SymIt = Symbols.begin(), End = Symbols.end(); SymIt != End;
> ++SymIt)
> + Entries.push_back(&*SymIt);
> + std::sort(Entries.begin(), Entries.end(),
> + [] (const MapEntryTy *LHS, const MapEntryTy *RHS) {
> + return LHS->getKey() < RHS->getKey();
> + });
> + for (const auto *Entry: Entries) {
> + const auto &Sym = Entry->getValue();
> + OS << format("\t%016" PRIx64 " => %016" PRIx64 "\t%s\n",
> + Sym.ObjectAddress, Sym.BinaryAddress,
> Entry->getKeyData());
> + }
> + OS << '\n';
> +}
> +
> +#ifndef NDEBUG
> +void DebugMapObject::dump() const {
> + print(errs());
> +}
> +#endif
> +
> +DebugMapObject& DebugMap::addDebugMapObject(StringRef ObjectFilePath) {
> + Objects.emplace_back(new DebugMapObject(ObjectFilePath));
> + return *Objects.back();
> +}
> +
> +const DebugMapObject::SymbolMapping *
> +DebugMapObject::lookupSymbol(StringRef SymbolName) const {
> + StringMap<SymbolMapping>::const_iterator Sym = Symbols.find(SymbolName);
> + if (Sym == Symbols.end())
> + return nullptr;
> + return &Sym->getValue();
> +}
> +
> +void DebugMap::print(raw_ostream& OS) const {
> + OS << "DEBUG MAP: object addr => executable addr\tsymbol name\n";
> + for (const auto &Obj: objects())
> + Obj->print(OS);
> + OS << "END DEBUG MAP\n";
> +}
> +
> +#ifndef NDEBUG
> +void DebugMap::dump() const {
> + print(errs());
> +}
> +#endif
> +}
>
> Added: llvm/trunk/tools/dsymutil/DebugMap.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DebugMap.h?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DebugMap.h (added)
> +++ llvm/trunk/tools/dsymutil/DebugMap.h Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,131 @@
> +//===- tools/dsymutil/DebugMap.h - Generic debug map representation
> -------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +///
> +/// This file contains the class declaration of the DebugMap
> +/// entity. A DebugMap lists all the object files linked together to
> +/// produce an executable along with the linked address of all the
> +/// atoms used in these object files.
> +/// The DebugMap is an input to the DwarfLinker class that will
> +/// extract the Dwarf debug information from the referenced object
> +/// files and link their usefull debug info together.
> +///
>
> +//===----------------------------------------------------------------------===//
> +#ifndef DSYMUTIL_DEBUGMAP_H
> +#define DSYMUTIL_DEBUGMAP_H
> +
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Object/ObjectFile.h"
> +#include "llvm/Support/ErrorOr.h"
> +#include "llvm/Support/Format.h"
> +#include "llvm/ADT/iterator_range.h"
> +#include <vector>
> +
> +namespace llvm {
> +
> +class raw_ostream;
> +
> +class DebugMapObject;
> +
> +/// \brief The DebugMap object stores the list of object files to
> +/// query for debug information along with the mapping between the
> +/// symbols' addresses in the object file to their linked address in
> +/// the linked binary.
> +///
> +/// A DebugMap producer could look like this:
> +/// DebugMap *DM = new DebugMap();
> +/// for (const auto &Obj: LinkedObjects) {
> +/// DebugMapObject &DMO = DM->addDebugMapObject(Obj.getPath());
> +/// for (const auto &Sym: Obj.getLinkedSymbols())
> +/// DMO.addSymbol(Sym.getName(), Sym.getObjectFileAddress(),
> +/// Sym.getBinaryAddress());
> +/// }
> +///
> +/// A DebugMap consumer can then use the map to link the debug
> +/// information. For example something along the lines of:
> +/// for (const auto &DMO: DM->objects()) {
> +/// auto Obj = createBinary(DMO.getObjectFilename());
> +/// for (auto &DIE: Obj.getDwarfDIEs()) {
> +/// if (SymbolMapping *Sym = DMO.lookup(DIE.getName()))
> +/// DIE.relocate(Sym->ObjectAddress, Sym->BinaryAddress);
> +/// else
> +/// DIE.discardSubtree();
> +/// }
> +/// }
> +class DebugMap
> +{
> + typedef std::vector<std::unique_ptr<DebugMapObject>> ObjectContainer;
> + ObjectContainer Objects;
> +
> +public:
> + typedef ObjectContainer::const_iterator const_iterator;
> +
> + iterator_range<const_iterator> objects() const {
> + return make_range(begin(), end());
> + }
> +
> + const_iterator begin() const {
> + return Objects.begin();
> + }
> +
> + const_iterator end() const {
> + return Objects.end();
> + }
> +
> + /// This function adds an DebugMapObject to the list owned by this
> + /// debug map.
> + DebugMapObject& addDebugMapObject(StringRef ObjectFilePath);
> +
> + void print(raw_ostream& OS) const;
> +
> +#ifndef NDEBUG
> + void dump() const;
> +#endif
> +};
> +
> +/// \brief The DebugMapObject represents one object file described by
> +/// the DebugMap. It contains a list of mappings between addresses in
> +/// the object file and in the linked binary for all the linked atoms
> +/// in this object file.
> +class DebugMapObject {
> +public:
> + struct SymbolMapping {
> + uint64_t ObjectAddress;
> + uint64_t BinaryAddress;
> + };
> +
> + /// \brief Adds a symbol mapping to this DebugMapObject.
> + /// \returns false if the symbol was already registered. The request
> + /// is discarded in this case.
> + bool addSymbol(llvm::StringRef SymName, uint64_t ObjectAddress,
> + uint64_t LinkedAddress);
> +
> + /// \bried Lookup a symbol mapping.
> + /// \returns null if the symbol isn't found.
> + const SymbolMapping *lookupSymbol(StringRef SymbolName) const;
> +
> + llvm::StringRef getObjectFilename() const { return Filename; }
> +
> + void print(raw_ostream& OS) const;
> +#ifndef NDEBUG
> + void dump() const;
> +#endif
> +private:
> + friend class DebugMap;
> + /// DebugMapObjects can only be constructed by the owning DebugMap.
> + DebugMapObject(StringRef ObjectFilename);
> +
> + std::string Filename;
> + StringMap<SymbolMapping> Symbols;
> +};
> +
> +}
> +
> +#endif // DSYMUTIL_DEBUGMAP_H
>
> Added: llvm/trunk/tools/dsymutil/DwarfLinker.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.cpp?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DwarfLinker.cpp (added)
> +++ llvm/trunk/tools/dsymutil/DwarfLinker.cpp Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,22 @@
> +//===- tools/dsymutil/DwarfLinker.cpp - Dwarf debug info linker
> -----------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +#include "DwarfLinker.h"
> +#include "DebugMap.h"
> +
> +namespace llvm {
> +
> +DwarfLinker::DwarfLinker(StringRef OutputFilename)
> + : OutputFilename(OutputFilename)
> +{}
> +
> +bool DwarfLinker::link(const DebugMap &Map) {
> + return true;
> +}
> +
> +}
>
> Added: llvm/trunk/tools/dsymutil/DwarfLinker.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/DwarfLinker.h?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/DwarfLinker.h (added)
> +++ llvm/trunk/tools/dsymutil/DwarfLinker.h Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,40 @@
> +//===- tools/dsymutil/DwarfLinker.h - Dwarf debug info linker
> -------------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +///
> +/// This file contains the class declaration of the DwarfLinker
> +/// object. A DwarfLinker takes a DebugMap as input and links the
> +/// debug information of all the referenced object files together. It
> +/// may drop and rewrite some parts of the debug info tree in the
> +/// process.
> +///
>
> +//===----------------------------------------------------------------------===//
> +#ifndef DSYMUTIL_DWARFLINKER_H
> +#define DSYMUTIL_DWARFLINKER_H
> +
> +#include "llvm/ADT/StringRef.h"
> +
> +namespace llvm {
> +
> +class DebugMap;
> +
> +class DwarfLinker {
> + std::string OutputFilename;
> +public:
> + DwarfLinker(StringRef OutputFilename);
> +
> + /// \brief Link the passed debug map into the ouptut file.
> + /// \returns false if the link encountered a fatal error.
> + bool link(const DebugMap&);
> +};
> +
> +}
> +
> +#endif
>
> Copied: llvm/trunk/tools/dsymutil/LLVMBuild.txt (from r223790,
> llvm/trunk/tools/LLVMBuild.txt)
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/LLVMBuild.txt?p2=llvm/trunk/tools/dsymutil/LLVMBuild.txt&p1=llvm/trunk/tools/LLVMBuild.txt&r1=223790&r2=223793&rev=223793&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/LLVMBuild.txt (original)
> +++ llvm/trunk/tools/dsymutil/LLVMBuild.txt Tue Dec 9 11:03:30 2014
> @@ -1,4 +1,4 @@
> -;===- ./tools/LLVMBuild.txt ------------------------------------*- Conf
> -*--===;
> +;===- ./tools/dsymutil/LLVMBuild.txt ---------------------*- Conf -*--===;
> ;
> ; The LLVM Compiler Infrastructure
> ;
> @@ -15,10 +15,8 @@
> ;
>
> ;===------------------------------------------------------------------------===;
>
> -[common]
> -subdirectories = bugpoint llc lli llvm-ar llvm-as llvm-bcanalyzer
> llvm-cov llvm-diff llvm-dis llvm-dwarfdump llvm-extract llvm-jitlistener
> llvm-link llvm-lto llvm-mc llvm-nm llvm-objdump llvm-profdata llvm-rtdyld
> llvm-size macho-dump opt llvm-mcmarkup verify-uselistorder
> -
> [component_0]
> -type = Group
> -name = Tools
> -parent = $ROOT
> +type = Tool
> +name = dsymutil
> +parent = Tools
> +required_libraries = Object Support
>
> Added: llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp (added)
> +++ llvm/trunk/tools/dsymutil/MachODebugMapParser.cpp Tue Dec 9 11:03:30
> 2014
> @@ -0,0 +1,194 @@
> +//===- tools/dsymutil/MachODebugMapParser.cpp - Parse STABS debug maps
> ----===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "MachODebugMapParser.h"
> +#include "llvm/Support/Path.h"
> +#include "llvm/Support/raw_ostream.h"
> +
> +using namespace llvm::object;
> +
> +namespace llvm {
> +
> +static void Warning(const Twine &Msg) { errs() << "warning: " + Msg +
> "\n"; }
> +
> +static ErrorOr<OwningBinary<MachOObjectFile>> createMachOBinary(StringRef
> file) {
> + ErrorOr<OwningBinary<Binary>> BinaryOrErr = createBinary(file);
> + if (BinaryOrErr.getError())
> + return BinaryOrErr.getError();
> +
> + std::unique_ptr<Binary> Bin;
> + std::unique_ptr<MemoryBuffer> Buf;
> + std::tie(Bin, Buf) = BinaryOrErr->takeBinary();
> + if (!isa<MachOObjectFile>(Bin.get()))
> + return make_error_code(object_error::invalid_file_type);
> +
> + std::unique_ptr<MachOObjectFile>
> MachOFile(cast<MachOObjectFile>(Bin.release()));
> + return OwningBinary<MachOObjectFile>(std::move(MachOFile),
> std::move(Buf));
> +}
> +
> +/// Reset the parser state coresponding to the current object
> +/// file. This is to be called after an object file is finished
> +/// processing.
> +void MachODebugMapParser::resetParserState() {
> + CurrentObjectFile = OwningBinary<object::MachOObjectFile>();
> + CurrentObjectAddresses.clear();
> + CurrentDebugMapObject = nullptr;
> +}
> +
> +/// Create a new DebugMapObject. This function resets the state of the
> +/// parser that was referring to the last object file and sets
> +/// everything up to add symbols to the new one.
> +void MachODebugMapParser::switchToNewDebugMapObject(StringRef Filename) {
> + resetParserState();
> +
> + std::string Path = Filename;
> + if (!PathPrefix.empty())
> + Path = PathPrefix + sys::path::get_separator().data() + Path;
> +
> + auto MachOOrError = createMachOBinary(Path);
> + if (auto Error = MachOOrError.getError()) {
> + Warning(Twine("cannot open debug object \"") + Path + "\": "
> + + Error.message() + "\n");
> + return;
> + }
> +
> + CurrentObjectFile = std::move(*MachOOrError);
> + loadCurrentObjectFileSymbols();
> + CurrentDebugMapObject = &Result->addDebugMapObject(Path);
> +}
> +
> +/// This main parsing routine tries to open the main binary and if
> +/// successful iterates over the STAB entries. The real parsing is
> +/// done in handleStabSymbolTableEntry.
> +ErrorOr<std::unique_ptr<DebugMap>> MachODebugMapParser::parse() {
> + auto MainBinaryOrError = createMachOBinary(BinaryPath);
> + if (MainBinaryOrError.getError())
> + return MainBinaryOrError.getError();
> +
> + MainOwningBinary = std::move(*MainBinaryOrError);
> + Result = make_unique<DebugMap>();
> + const auto &MainBinary = *MainOwningBinary.getBinary();
> + for (const SymbolRef &Symbol : MainBinary.symbols()) {
> + const DataRefImpl &DRI = Symbol.getRawDataRefImpl();
> + if (MainBinary.is64Bit())
> + handleStabDebugMapEntry(MainBinary.getSymbol64TableEntry(DRI));
> + else
> + handleStabDebugMapEntry(MainBinary.getSymbolTableEntry(DRI));
> + }
> +
> + resetParserState();
> + return std::move(Result);
> +}
> +
> +/// Interpret the STAB entries to fill the DebugMap.
> +void MachODebugMapParser::handleStabSymbolTableEntry(uint32_t StringIndex,
> + uint8_t Type,
> + uint8_t SectionIndex,
> + uint16_t Flags,
> + uint64_t Value) {
> + if (!(Type & MachO::N_STAB))
> + return;
> +
> + const MachOObjectFile &MachOBinary = *MainOwningBinary.getBinary();
> + const char *Name =
> &MachOBinary.getStringTableData().data()[StringIndex];
> +
> + // An N_OSO entry represents the start of a new object file description.
> + if (Type == MachO::N_OSO)
> + return switchToNewDebugMapObject(Name);
> +
> + // If the last N_OSO object file wasn't found,
> + // CurrentDebugMapObject will be null. Do not update anything
> + // until we find the next valid N_OSO entry.
> + if (!CurrentDebugMapObject)
> + return;
> +
> + switch (Type) {
> + case MachO::N_GSYM:
> + // This is a global variable. We need to query the main binary
> + // symbol table to find its address as it might not be in the
> + // debug map (for common symbols).
> + Value = getMainBinarySymbolAddress(Name);
> + if (Value == UnknownAddressOrSize)
> + return;
> + break;
> + case MachO::N_FUN:
> + // Functions are scopes in STABS. They have an end marker that we
> + // need to ignore.
> + if (Name[0] == '\0')
> + return;
> + break;
> + case MachO::N_STSYM:
> + break;
> + default:
> + return;
> + }
> +
> + auto ObjectSymIt = CurrentObjectAddresses.find(Name);
> + if (ObjectSymIt == CurrentObjectAddresses.end())
> + return Warning("could not find object file symbol for symbol " +
> + Twine(Name));
> + if (!CurrentDebugMapObject->addSymbol(Name, ObjectSymIt->getValue(),
> Value))
> + return Warning(Twine("failed to insert symbol '") + Name + "' in the
> debug map.");
> +}
> +
> +/// Load the current object file symbols into CurrentObjectAddresses.
> +void MachODebugMapParser::loadCurrentObjectFileSymbols() {
> + CurrentObjectAddresses.clear();
> + const auto &Binary = *CurrentObjectFile.getBinary();
> +
> + for (auto Sym : Binary.symbols()) {
> + StringRef Name;
> + uint64_t Addr;
> + if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
> + Sym.getName(Name))
> + continue;
> + CurrentObjectAddresses[Name] = Addr;
> + }
> +}
> +
> +/// Lookup a symbol address in the main binary symbol table. The
> +/// parser only needs to query common symbols, thus not every symbol's
> +/// address is available through this function.
> +uint64_t MachODebugMapParser::getMainBinarySymbolAddress(StringRef Name) {
> + if (MainBinarySymbolAddresses.empty())
> + loadMainBinarySymbols();
> +
> + auto Sym = MainBinarySymbolAddresses.find(Name);
> + if (Sym == MainBinarySymbolAddresses.end())
> + return UnknownAddressOrSize;
> + return Sym->second;
> +}
> +
> +/// Load the interesting main binary symbols' addresses into
> +/// MainBinarySymbolAddresses.
> +void MachODebugMapParser::loadMainBinarySymbols() {
> + const MachOObjectFile &Binary = *MainOwningBinary.getBinary();
> + section_iterator Section = Binary.section_end();
> + for (const auto &Sym : Binary.symbols()) {
> + SymbolRef::Type Type;
> + // Skip undefined and STAB entries.
> + if (Sym.getType(Type) || (Type & SymbolRef::ST_Debug) ||
> + (Type & SymbolRef::ST_Unknown))
> + continue;
> + StringRef Name;
> + uint64_t Addr;
> + // The only symbols of interest are the global variables. These
> + // are the only ones that need to be queried because the address
> + // of common data won't be described in the debug map. All other
> + // addresses should be fetched for the debug map.
> + if (Sym.getAddress(Addr) || Addr == UnknownAddressOrSize ||
> + !(Sym.getFlags() & SymbolRef::SF_Global) ||
> + Sym.getSection(Section) || Section->isText() || Sym.getName(Name)
> ||
> + Name.size() == 0 || Name[0] == '\0')
> + continue;
> + MainBinarySymbolAddresses[Name] = Addr;
> + }
> +}
> +
> +}
>
> Added: llvm/trunk/tools/dsymutil/MachODebugMapParser.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/MachODebugMapParser.h?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/MachODebugMapParser.h (added)
> +++ llvm/trunk/tools/dsymutil/MachODebugMapParser.h Tue Dec 9 11:03:30
> 2014
> @@ -0,0 +1,76 @@
> +//===- tools/dsymutil/MachODebugMapParser.h - Parse STABS debug maps
> ------===//
> +//
> +// The LLVM Linker
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +///
> +/// \file
> +///
> +/// This file contains the class declaration for the code that parses
> STABS
> +/// debug maps that are embedded in the binaries symbol tables.
> +///
>
> +//===----------------------------------------------------------------------===//
> +#ifndef DSYMUTIL_MACHODEBUGMAPPARSER_H
> +#define DSYMUTIL_MACHODEBUGMAPPARSER_H
> +
> +#include "DebugMap.h"
> +
> +#include "llvm/ADT/StringMap.h"
> +#include "llvm/Object/MachO.h"
> +#include "llvm/Object/Error.h"
> +
> +namespace llvm {
> +
> +class MachODebugMapParser {
> +public:
> + MachODebugMapParser(StringRef BinaryPath)
> + : BinaryPath(BinaryPath) {}
> +
> + /// \brief Add a prefix to every object file path before trying to
> + /// open it.
> + void setPreprendPath(StringRef Prefix) { PathPrefix = Prefix; }
> +
> + /// \brief Parses and returns the DebugMap of the input binary.
> + /// \returns an error in case the provided BinaryPath doesn't exist
> + /// or isn't of a supported type.
> + ErrorOr<std::unique_ptr<DebugMap>> parse();
> +
> +private:
> + std::string BinaryPath;
> + std::string PathPrefix;
> +
> + /// OwningBinary constructed from the BinaryPath.
> + object::OwningBinary<object::MachOObjectFile> MainOwningBinary;
> + /// Map of the binary symbol addresses.
> + StringMap<uint64_t> MainBinarySymbolAddresses;
> + /// The constructed DebugMap.
> + std::unique_ptr<DebugMap> Result;
> +
> + /// Handle to the currently processed object file.
> + object::OwningBinary<object::MachOObjectFile> CurrentObjectFile;
> + /// Map of the currently processed object file symbol addresses.
> + StringMap<uint64_t> CurrentObjectAddresses;
> + /// Element of the debug map corresponfing to the current object file.
> + DebugMapObject *CurrentDebugMapObject;
> +
> + void switchToNewDebugMapObject(StringRef Filename);
> + void resetParserState();
> + uint64_t getMainBinarySymbolAddress(StringRef Name);
> + void loadMainBinarySymbols();
> + void loadCurrentObjectFileSymbols();
> + void handleStabSymbolTableEntry(uint32_t StringIndex, uint8_t Type,
> + uint8_t SectionIndex, uint16_t Flags,
> + uint64_t Value);
> +
> + template <typename STEType> void handleStabDebugMapEntry(const STEType
> &STE) {
> + handleStabSymbolTableEntry(STE.n_strx, STE.n_type, STE.n_sect,
> STE.n_desc,
> + STE.n_value);
> + }
> +};
> +
> +}
> +
> +#endif // DSYMUTIL_MACHODEBUGMAPPARSER_H
>
> Added: llvm/trunk/tools/dsymutil/Makefile
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/Makefile?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/Makefile (added)
> +++ llvm/trunk/tools/dsymutil/Makefile Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,17 @@
> +##===- tools/dsymutil/Makefile -----------------------------*- Makefile
> -*-===##
> +#
> +# The LLVM Compiler Infrastructure
> +#
> +# This file is distributed under the University of Illinois Open Source
> +# License. See LICENSE.TXT for details.
> +#
>
> +##===----------------------------------------------------------------------===##
> +
> +LEVEL := ../..
> +TOOLNAME := llvm-dsymutil
> +LINK_COMPONENTS := Object Support
> +
> +# This tool has no plugins, optimize startup time.
> +TOOL_NO_EXPORTS := 1
> +
> +include $(LEVEL)/Makefile.common
>
> Added: llvm/trunk/tools/dsymutil/dsymutil.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/dsymutil/dsymutil.cpp?rev=223793&view=auto
>
> ==============================================================================
> --- llvm/trunk/tools/dsymutil/dsymutil.cpp (added)
> +++ llvm/trunk/tools/dsymutil/dsymutil.cpp Tue Dec 9 11:03:30 2014
> @@ -0,0 +1,67 @@
> +//===-- dsymutil.cpp - Debug info dumping utility for llvm
> ----------------===//
> +//
> +// The LLVM Compiler Infrastructure
> +//
> +// This file is distributed under the University of Illinois Open Source
> +// License. See LICENSE.TXT for details.
> +//
>
> +//===----------------------------------------------------------------------===//
> +//
> +// This program is a utility that aims to be a dropin replacement for
> +// Darwin's dsymutil.
> +//
>
> +//===----------------------------------------------------------------------===//
> +
> +#include "DebugMap.h"
> +#include "DwarfLinker.h"
> +#include "MachODebugMapParser.h"
> +
> +#include "llvm/Support/ManagedStatic.h"
> +#include "llvm/Support/PrettyStackTrace.h"
> +#include "llvm/Support/Options.h"
> +#include "llvm/Support/raw_ostream.h"
> +#include "llvm/Support/Signals.h"
> +
> +#include <string>
> +
> +static llvm::cl::opt<std::string> InputFile(llvm::cl::Positional,
> + llvm::cl::desc("<input
> file>"),
> + llvm::cl::init("-"));
> +
> +static llvm::cl::opt<std::string> OsoPrependPath("oso-prepend-path",
> +
> llvm::cl::desc("<path>"));
> +
> +static llvm::cl::opt<bool> Verbose("v", llvm::cl::desc("Verbosity level"),
> + llvm::cl::init(false));
> +
> +static llvm::cl::opt<bool> ParseOnly("parse-only",
> + llvm::cl::desc("Only parse the debug
> map, do "
> + "not actaully link
> the DWARF."),
> + llvm::cl::init(false));
> +
> +int main(int argc, char **argv) {
> + llvm::sys::PrintStackTraceOnErrorSignal();
> + llvm::PrettyStackTraceProgram StackPrinter(argc, argv);
> + llvm::llvm_shutdown_obj Shutdown;
> +
> + llvm::cl::ParseCommandLineOptions(argc, argv, "llvm dsymutil\n");
> +
> + llvm::MachODebugMapParser Parser(InputFile);
> + Parser.setPreprendPath(OsoPrependPath);
> + llvm::ErrorOr<std::unique_ptr<llvm::DebugMap>> DebugMap =
> Parser.parse();
> +
> + if (auto EC = DebugMap.getError()) {
> + llvm::errs() << "error: cannot parse the debug map for \"" <<
> InputFile <<
> + "\": " << EC.message() << '\n';
> + return 1;
> + }
> +
> + if (Verbose)
> + (*DebugMap)->print(llvm::outs());
> +
> + if (ParseOnly)
> + return 0;
> +
> + llvm::DwarfLinker Linker(InputFile + ".dwarf");
> + return !Linker.link(*DebugMap.get());
> +}
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20141209/b172ffac/attachment.html>
More information about the llvm-commits
mailing list