From 08414886fb6de935d20cd852da4b8e70b0824579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20P=C3=B6chtrager?= Date: Mon, 31 Aug 2015 21:02:38 +0200 Subject: [PATCH] Add llvm-dsymutil build script + re-add 7e9f85 This finally makes proper debugging possible --- CHANGELOG | 2 + README.COMPILER-RT.md | 6 +- README.DEBUGGING.md | 22 +++++++ build_llvm_dsymutil.sh | 37 ++++++++++++ tools/tools.sh | 4 +- wrapper/Makefile | 3 +- wrapper/main.cpp | 6 +- wrapper/programs/dsymutil.cpp | 108 ++++++++++++++++++++++++++++++++++ wrapper/programs/proginc.h | 3 + wrapper/progs.h | 3 +- wrapper/tools.cpp | 31 ++++++++++ wrapper/tools.h | 15 ++++- wrapper/wrapper.project | 1 + 13 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 README.DEBUGGING.md create mode 100755 build_llvm_dsymutil.sh mode change 100755 => 100644 tools/tools.sh create mode 100644 wrapper/programs/dsymutil.cpp diff --git a/CHANGELOG b/CHANGELOG index 3cae48c..d6b5710 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -14,6 +14,8 @@ added: o32-clang++-stdc++ --> uses the SDK's libstdc++ o32-clang++-gstdc++ --> uses gcc's (build_gcc.sh) libstdc++ * unit tests (wrapper) +* llvm-dsymutil build script +* dsymutil is now wrapped to llvm-dsymutil (LLVM >= 3.8 only) /****************************** v0.10 ********************************/ diff --git a/README.COMPILER-RT.md b/README.COMPILER-RT.md index 893fa6c..b2754df 100644 --- a/README.COMPILER-RT.md +++ b/README.COMPILER-RT.md @@ -1,8 +1,8 @@ ## COMPILER-RT ## -### WHAT IS COMPILER-RT: ### +### WHAT IS COMPILER-RT? ### -Please see http://compiler-rt.llvm.org/. +Please see http://compiler-rt.llvm.org. ### INSTALLATION: ### @@ -24,6 +24,8 @@ You do not need to do anything, clang's doing the job for you. However, `-fsanitize=address` is a bit annoying because the address sanitizer library is linked dynamically, and thus requires you to copy the ASAN runtime library onto the target system. +\[See [README.DEBUGGING](README.DEBUGGING.md) in how to get a backtrace with line numbers and symbol names] + The following example illustrates how to achieve this: # Example source code. diff --git a/README.DEBUGGING.md b/README.DEBUGGING.md new file mode 100644 index 0000000..1997f10 --- /dev/null +++ b/README.DEBUGGING.md @@ -0,0 +1,22 @@ +### Requirements: ### + +* llvm-dsymutil (>= 3.8) +* A Mac OS X system with lldb / gdb installed + +### Setting up llvm-dsymutil: ### + +First of all, you **really** need llvm-dsymutil from llvm 3.8 (trunk as of writing), +llvm 3.7 or earlier **is not** sufficient. + +Run `./build_llvm_dsymutil.sh` to build and install llvm-dsymutil to target/bin. + +`dsymutil` is a no-op if you do not have [osxcross-]llvm-dsymutil >= 3.8 in PATH. + +### Debug Example: ### + +* Build your application with `-g` +* [LTO only] Add `-Wl,-object_path_lto,lto.o` to the linker flags +* After linking run: `dsymutil binary` +* [Optional] Strip the binary: `x86_64-apple-darwinXX-strip binary` +* Copy the binary **and** the created `.dSYM` "folder" onto the target Mac OS X system +* Debug the binary as usual diff --git a/build_llvm_dsymutil.sh b/build_llvm_dsymutil.sh new file mode 100755 index 0000000..3fd6738 --- /dev/null +++ b/build_llvm_dsymutil.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash + +pushd "${0%/*}" &>/dev/null + +DESC="llvm-dsymutil" +source tools/tools.sh +eval $(tools/osxcross_conf.sh) + +require git +require cmake + +pushd $OSXCROSS_BUILD_DIR &>/dev/null + +if [ ! -e llvm-dsymutil/.clone_complete ]; then + rm -rf llvm-dsymutil + # Vanilla llvm-dsymutil with a few patches on top for OSXCross + git clone https://github.com/tpoechtrager/llvm-dsymutil.git --depth 1 +fi + +pushd llvm-dsymutil &>/dev/null + +git clean -fdx +touch .clone_complete +git pull + +mkdir build +pushd build &>/dev/null + +cmake .. \ + -DCMAKE_BUILD_TYPE=Release \ + -DLLVM_TARGETS_TO_BUILD="X86;ARM;AArch64" \ + -DLLVM_ENABLE_ASSERTIONS=Off + +$MAKE -f tools/dsymutil/Makefile -j$JOBS +cp bin/llvm-dsymutil $OSXCROSS_TARGET_DIR/bin/osxcross-llvm-dsymutil + +echo "installed llvm-dsymutil to $OSXCROSS_TARGET_DIR/bin/osxcross-llvm-dsymutil" diff --git a/tools/tools.sh b/tools/tools.sh old mode 100755 new mode 100644 index 0e39736..66d546a --- a/tools/tools.sh +++ b/tools/tools.sh @@ -67,13 +67,15 @@ if [[ $SCRIPT != *wrapper/build.sh ]]; then $SCRIPT != "mount_xcode_image.sh" -a \ $SCRIPT != "gen_sdk_package_darling_dmg.sh" -a \ $SCRIPT != "gen_sdk_package_p7zip.sh" ]; then - eval $(tools/osxcross_conf.sh) + res=$(tools/osxcross_conf.sh) if [ $? -ne 0 ]; then echo -n "you need to complete ./build.sh first, before you can start " echo "building $DESC" exit 1 fi + + eval "$res" fi fi diff --git a/wrapper/Makefile b/wrapper/Makefile index 767cd96..ab0162d 100644 --- a/wrapper/Makefile +++ b/wrapper/Makefile @@ -57,7 +57,8 @@ SRCS= \ programs/osxcross-man.cpp \ programs/sw_vers.cpp \ programs/pkg-config.cpp \ - programs/xcrun.cpp + programs/xcrun.cpp \ + programs/dsymutil.cpp OBJS=$(subst .cpp,.o,$(SRCS)) diff --git a/wrapper/main.cpp b/wrapper/main.cpp index ab56f60..0aef128 100644 --- a/wrapper/main.cpp +++ b/wrapper/main.cpp @@ -47,9 +47,10 @@ using namespace tools; using namespace target; -namespace { - int unittest = 0; +int debug = 0; + +namespace { void warnExtension(const char *extension) { static bool noextwarnings = !!getenv("OSXCROSS_NO_EXTENSION_WARNINGS"); @@ -441,7 +442,6 @@ int main(int argc, char **argv) { auto b = new (bbuf) benchmark; Target target; char **cargs = nullptr; - int debug = 0; int rc = -1; if (char *p = getenv("OCDEBUG")) diff --git a/wrapper/programs/dsymutil.cpp b/wrapper/programs/dsymutil.cpp new file mode 100644 index 0000000..7974e9a --- /dev/null +++ b/wrapper/programs/dsymutil.cpp @@ -0,0 +1,108 @@ +/*********************************************************************** + * OSXCross Compiler Wrapper * + * Copyright (C) 2014, 2015 by Thomas Poechtrager * + * t.poechtrager@gmail.com * + * * + * This program is free software; you can redistribute it and/or * + * modify it under the terms of the GNU General Public License * + * as published by the Free Software Foundation; either version 2 * + * of the License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program; if not, write to the Free Software * + * Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * + ***********************************************************************/ + +#include "proginc.h" + +#ifndef _WIN32 +#include +#endif + +using namespace tools; + +namespace program { + +int dsymutil(int argc, char **argv, Target &target) { + (void)argc; + + std::string dsymutil; + char LLVMDsymutilVersionOutput[1024]; + const char *LLVMDsymutilVersionStr; + LLVMVersion LLVMDsymutilVersion; + + const std::string &ParentProcessName = getParentProcessName(); + + if (!debug && ParentProcessName.find("clang") == std::string::npos && + ParentProcessName != "collect2" && ParentProcessName != "unknown") + debug = 1; + + if (char *p = getenv("OSXCROSS_LLVM_DSYMUTIL")) { + dsymutil = p; + debug = 1; + } else { + if (!realPath("osxcross-llvm-dsymutil", dsymutil) && + !realPath("llvm-dsymutil", dsymutil)) { + if (debug) + dbg << "dsymutil: cannot find [osxcross-]llvm-dsymutil in PATH" + << dbg.endl(); + return 0; + } + } + + std::string command = dsymutil + " -version"; + + if (runcommand(command.c_str(), LLVMDsymutilVersionOutput, + sizeof(LLVMDsymutilVersionOutput)) == RUNCOMMAND_ERROR) { + if (debug) + dbg << "dsymutil: executing \"" << command << "\" failed" + << dbg.endl(); + return 0; + } + + LLVMDsymutilVersionStr = strstr(LLVMDsymutilVersionOutput, "LLVM version "); + + if (!LLVMDsymutilVersionStr) { + if (debug) + dbg << "dsymutil: unable to parse llvm-dsymutil version" + << dbg.endl(); + return 0; + } + + LLVMDsymutilVersionStr += 13; // strlen("LLVM version "); + + LLVMDsymutilVersion = parseLLVMVersion(LLVMDsymutilVersionStr); + + constexpr LLVMVersion RequiredLLVMDsymutilVersion(3, 8); + + if (LLVMDsymutilVersion < RequiredLLVMDsymutilVersion) { + if (debug) + dbg << "ignoring dsymutil invocation: '" + << dsymutil << "' is too old (" + << LLVMDsymutilVersion.Str() << " < " + << RequiredLLVMDsymutilVersion.Str() << ")" + << dbg.endl(); + return 0; + } + + std::stringstream lipo; + std::string triple; + + lipo << target.execpath << PATHDIV + << target.getDefaultTriple(triple) << "-lipo"; + + setenv("LIPO", lipo.str().c_str(), 1); + + if (execvp(dsymutil.c_str(), argv)) + err << "cannot execute '" << dsymutil << "'" << err.endl(); + + return 1; +} + +} // namespace program diff --git a/wrapper/programs/proginc.h b/wrapper/programs/proginc.h index 7a3fc71..7df7fc4 100644 --- a/wrapper/programs/proginc.h +++ b/wrapper/programs/proginc.h @@ -11,3 +11,6 @@ #include "tools.h" #include "target.h" #include "progs.h" + +extern int debug; +extern int unittest; diff --git a/wrapper/progs.h b/wrapper/progs.h index bd5321e..0c6d80a 100644 --- a/wrapper/progs.h +++ b/wrapper/progs.h @@ -78,6 +78,7 @@ private: int sw_vers(int argc, char **argv, target::Target &target); int xcrun(int argc, char **argv, Target &target); +int dsymutil(int argc, char **argv, target::Target &target); namespace osxcross { int version(); @@ -93,7 +94,7 @@ static int dummy() { return 0; } constexpr prog programs[] = { { "sw_vers", sw_vers }, { "xcrun", xcrun }, - { "dsymutil", dummy }, + { "dsymutil", dsymutil }, { "osxcross", osxcross::version }, { "osxcross-env", osxcross::env }, { "osxcross-conf", osxcross::conf }, diff --git a/wrapper/tools.cpp b/wrapper/tools.cpp index f5d62c5..faea75e 100644 --- a/wrapper/tools.cpp +++ b/wrapper/tools.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include #include @@ -538,6 +539,36 @@ const char *getFileExtension(const char *file) { return p; } +// +// Shell Commands +// + +size_t runcommand(const char *command, char *buf, size_t len) { +#define RETURN(v) \ + do { \ + if (p) \ + pclose(p); \ + return (v); \ + } while (0) + + if (!len) + return RUNCOMMAND_ERROR; + + FILE *p; + size_t outputlen; + + if (!(p = popen(command, "r"))) + RETURN(RUNCOMMAND_ERROR); + + if (!(outputlen = fread(buf, sizeof(char), len - 1, p))) + RETURN(RUNCOMMAND_ERROR); + + buf[outputlen] = '\0'; + + RETURN(outputlen); +#undef RETURN +} + // // Time // diff --git a/wrapper/tools.h b/wrapper/tools.h index fd1ad81..aa7d924 100644 --- a/wrapper/tools.h +++ b/wrapper/tools.h @@ -213,6 +213,14 @@ template struct ArgParser { } }; +// +// Shell Commands +// + +constexpr size_t RUNCOMMAND_ERROR = -1; + +size_t runcommand(const char *command, char *buf, size_t len); + // // Time // @@ -325,10 +333,13 @@ static_assert(OSVersion(10, 6) != OSVersion(10, 5), ""); OSVersion parseOSVersion(const char *OSVer); typedef OSVersion GCCVersion; -#define parseGCCVersion parseOSVersion +static const auto &parseGCCVersion = parseOSVersion; typedef OSVersion ClangVersion; -#define parseClangVersion parseOSVersion +static const auto &parseClangVersion = parseOSVersion; + +typedef OSVersion LLVMVersion; +static const auto &parseLLVMVersion = parseOSVersion; // // OS Compat diff --git a/wrapper/wrapper.project b/wrapper/wrapper.project index f7799dc..333a4ca 100644 --- a/wrapper/wrapper.project +++ b/wrapper/wrapper.project @@ -46,6 +46,7 @@ +