From 866cdd590de5c5b172be2735a643d4c36a691193 Mon Sep 17 00:00:00 2001 From: Kevin Enderby Date: Mon, 23 May 2016 21:34:12 +0000 Subject: [PATCH] Add the printing the Mach-O (__LLVM,__bundle) xar archive file section "verbosely" to llvm-objdump. This section is created with -fembed-bitcode option. This requires the use of libxar and the Cmake and lit support were crafted by Chris Bieneman! rdar://26202242 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@270491 91177308-0d34-0410-b5e6-96231b3b80d8 --- cmake/config-ix.cmake | 5 + include/llvm/Config/config.h.cmake | 3 + lib/Object/CMakeLists.txt | 2 + test/lit.cfg | 3 + test/lit.site.cfg.in | 1 + .../llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 | Bin 0 -> 16624 bytes test/tools/llvm-objdump/macho-LLVM-bundle.test | 60 ++++ tools/llvm-objdump/MachODump.cpp | 383 +++++++++++++++++++++ 8 files changed, 457 insertions(+) create mode 100755 test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 create mode 100644 test/tools/llvm-objdump/macho-LLVM-bundle.test diff --git a/cmake/config-ix.cmake b/cmake/config-ix.cmake index 7149e13b07e..a40dddfc1c8 100755 --- a/cmake/config-ix.cmake +++ b/cmake/config-ix.cmake @@ -141,6 +141,11 @@ if( NOT PURE_WINDOWS AND NOT LLVM_USE_SANITIZER MATCHES "Memory.*") endif() endif() +check_library_exists(xar xar_open "" HAVE_LIBXAR) +if(HAVE_LIBXAR) + set(XAR_LIB xar) +endif() + # function checks check_symbol_exists(arc4random "stdlib.h" HAVE_DECL_ARC4RANDOM) check_symbol_exists(backtrace "execinfo.h" HAVE_BACKTRACE) diff --git a/include/llvm/Config/config.h.cmake b/include/llvm/Config/config.h.cmake index f6b7d386fd9..45b30d9171d 100644 --- a/include/llvm/Config/config.h.cmake +++ b/include/llvm/Config/config.h.cmake @@ -322,6 +322,9 @@ /* Define if the setupterm() function is supported this platform. */ #cmakedefine HAVE_TERMINFO ${HAVE_TERMINFO} +/* Define if the xar_open() function is supported this platform. */ +#cmakedefine HAVE_LIBXAR ${HAVE_LIBXAR} + /* Define to 1 if you have the header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} diff --git a/lib/Object/CMakeLists.txt b/lib/Object/CMakeLists.txt index 0a37cc360fe..b293d1c1f4e 100644 --- a/lib/Object/CMakeLists.txt +++ b/lib/Object/CMakeLists.txt @@ -21,4 +21,6 @@ add_llvm_library(LLVMObject DEPENDS intrinsics_gen + + LINK_LIBS ${XAR_LIB} ) diff --git a/test/lit.cfg b/test/lit.cfg index 32bf788ae53..78c5422f3aa 100644 --- a/test/lit.cfg +++ b/test/lit.cfg @@ -497,3 +497,6 @@ except OSError: if re.search(r'ON', llvm_config_cmd.stdout.read().decode('ascii')): config.available_features.add('global-isel') llvm_config_cmd.wait() + +if config.have_libxar: + config.available_features.add('xar') diff --git a/test/lit.site.cfg.in b/test/lit.site.cfg.in index 47699e25840..1ce3df7dd73 100644 --- a/test/lit.site.cfg.in +++ b/test/lit.site.cfg.in @@ -34,6 +34,7 @@ config.host_ldflags = "@HOST_LDFLAGS@" config.llvm_use_intel_jitevents = "@LLVM_USE_INTEL_JITEVENTS@" config.llvm_use_sanitizer = "@LLVM_USE_SANITIZER@" config.have_zlib = "@HAVE_LIBZ@" +config.have_libxar = "@HAVE_LIBXAR@" config.have_dia_sdk = @HAVE_DIA_SDK@ config.enable_ffi = "@LLVM_ENABLE_FFI@" config.test_examples = "@ENABLE_EXAMPLES@" diff --git a/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 b/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 new file mode 100755 index 0000000000000000000000000000000000000000..8a7e4ef39e11c3e7fcdac6ab439e4a9056801305 GIT binary patch literal 16624 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 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-objdump/macho-LLVM-bundle.test b/test/tools/llvm-objdump/macho-LLVM-bundle.test new file mode 100644 index 00000000000..b7134307257 --- /dev/null +++ b/test/tools/llvm-objdump/macho-LLVM-bundle.test @@ -0,0 +1,60 @@ +# REQUIRES: xar +# RUN: llvm-objdump -macho -archive-headers -section __LLVM,__bundle %p/Inputs/LLVM-bundle.macho-x86_64 | FileCheck %s + +# CHECK: For (__LLVM,__bundle) section: xar header +# CHECK: magic XAR_HEADER_MAGIC +# CHECK: size 28 +# CHECK: version 1 +# CHECK: toc_length_compressed 542 +# CHECK: toc_length_uncompressed 1250 +# CHECK: cksum_alg XAR_CKSUM_SHA1 +# CHECK: For (__LLVM,__bundle) section: xar archive files: +# CHECK: 1664 1 +# CHECK: For (__LLVM,__bundle) section: xar table of contents: +# CHECK: +# CHECK: +# CHECK: +# CHECK: 1.0 +# CHECK: x86_64 +# CHECK: MacOSX +# CHECK: 10.11.0 +# CHECK: +# CHECK: libSystem.dylib +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: +# CHECK: 20 +# CHECK: 0 +# CHECK: +# CHECK: 2016-05-23T20:49:10 +# CHECK: +# CHECK: 1 +# CHECK: file +# CHECK: +# CHECK: a319940ff5f5248ca8b44cf7b4b65e7dd49a47ab +# CHECK: a319940ff5f5248ca8b44cf7b4b65e7dd49a47ab +# CHECK: 1664 +# CHECK: 20 +# CHECK: +# CHECK: 1664 +# CHECK: +# CHECK: Bitcode +# CHECK: +# CHECK: -triple +# CHECK: x86_64-apple-macosx10.11.0 +# CHECK: -emit-obj +# CHECK: -disable-llvm-optzns +# CHECK: +# CHECK: +# CHECK: +# CHECK: diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp index d94bf07f9e8..2bafe559987 100644 --- a/tools/llvm-objdump/MachODump.cpp +++ b/tools/llvm-objdump/MachODump.cpp @@ -42,6 +42,7 @@ #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/TargetSelect.h" +#include "llvm/Support/ToolOutputFile.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -51,6 +52,12 @@ #include #endif +#ifdef HAVE_LIBXAR +extern "C" { +#include +} +#endif + using namespace llvm; using namespace object; @@ -1041,6 +1048,12 @@ static void DisassembleMachO(StringRef Filename, MachOObjectFile *MachOOF, StringRef DisSegName, StringRef DisSectName); static void DumpProtocolSection(MachOObjectFile *O, const char *sect, uint32_t size, uint32_t addr); +#ifdef HAVE_LIBXAR +static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, + uint32_t size, bool verbose, + bool PrintXarHeader, bool PrintXarFileHeaders, + std::string XarMemberName); +#endif // defined(HAVE_LIBXAR) static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, bool verbose) { @@ -1102,6 +1115,13 @@ static void DumpSectionContents(StringRef Filename, MachOObjectFile *O, DumpProtocolSection(O, sect, sect_size, sect_addr); continue; } +#ifdef HAVE_LIBXAR + if (SegName == "__LLVM" && SectName == "__bundle") { + DumpBitcodeSection(O, sect, sect_size, verbose, !NoSymbolicOperands, + ArchiveHeaders, ""); + continue; + } +#endif // defined(HAVE_LIBXAR) switch (section_type) { case MachO::S_REGULAR: DumpRawSectionContents(O, sect, sect_size, sect_addr); @@ -5645,6 +5665,369 @@ static void DumpProtocolSection(MachOObjectFile *O, const char *sect, } } +#ifdef HAVE_LIBXAR +inline void swapStruct(struct xar_header &xar) { + sys::swapByteOrder(xar.magic); + sys::swapByteOrder(xar.size); + sys::swapByteOrder(xar.version); + sys::swapByteOrder(xar.toc_length_compressed); + sys::swapByteOrder(xar.toc_length_uncompressed); + sys::swapByteOrder(xar.cksum_alg); +} + +static void PrintModeVerbose(uint32_t mode) { + switch(mode & S_IFMT){ + case S_IFDIR: + outs() << "d"; + break; + case S_IFCHR: + outs() << "c"; + break; + case S_IFBLK: + outs() << "b"; + break; + case S_IFREG: + outs() << "-"; + break; + case S_IFLNK: + outs() << "l"; + break; + case S_IFSOCK: + outs() << "s"; + break; + default: + outs() << "?"; + break; + } + + /* owner permissions */ + if(mode & S_IREAD) + outs() << "r"; + else + outs() << "-"; + if(mode & S_IWRITE) + outs() << "w"; + else + outs() << "-"; + if(mode & S_ISUID) + outs() << "s"; + else if(mode & S_IEXEC) + outs() << "x"; + else + outs() << "-"; + + /* group permissions */ + if(mode & (S_IREAD >> 3)) + outs() << "r"; + else + outs() << "-"; + if(mode & (S_IWRITE >> 3)) + outs() << "w"; + else + outs() << "-"; + if(mode & S_ISGID) + outs() << "s"; + else if(mode & (S_IEXEC >> 3)) + outs() << "x"; + else + outs() << "-"; + + /* other permissions */ + if(mode & (S_IREAD >> 6)) + outs() << "r"; + else + outs() << "-"; + if(mode & (S_IWRITE >> 6)) + outs() << "w"; + else + outs() << "-"; + if(mode & S_ISVTX) + outs() << "t"; + else if(mode & (S_IEXEC >> 6)) + outs() << "x"; + else + outs() << "-"; +} + +static void PrintXarFilesSummary(const char *XarFilename, xar_t xar) { + xar_iter_t xi; + xar_file_t xf; + xar_iter_t xp; + const char *key, *type, *mode, *user, *group, *size, *mtime, *name, *m; + char *endp; + uint32_t mode_value; + + xi = xar_iter_new(); + if (!xi) { + errs() << "Can't obtain an xar iterator for xar archive " + << XarFilename << "\n"; + return; + } + + // Go through the xar's files. + for (xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)) { + xp = xar_iter_new(); + if(!xp){ + errs() << "Can't obtain an xar iterator for xar archive " + << XarFilename << "\n"; + return; + } + type = nullptr; + mode = nullptr; + user = nullptr; + group = nullptr; + size = nullptr; + mtime = nullptr; + name = nullptr; + for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ + const char *val = nullptr; + xar_prop_get(xf, key, &val); +#if 0 // Useful for debugging. + outs() << "key: " << key << " value: " << val << "\n"; +#endif + if(strcmp(key, "type") == 0) + type = val; + if(strcmp(key, "mode") == 0) + mode = val; + if(strcmp(key, "user") == 0) + user = val; + if(strcmp(key, "group") == 0) + group = val; + if(strcmp(key, "data/size") == 0) + size = val; + if(strcmp(key, "mtime") == 0) + mtime = val; + if(strcmp(key, "name") == 0) + name = val; + } + if(mode != nullptr){ + mode_value = strtoul(mode, &endp, 8); + if(*endp != '\0') + outs() << "(mode: \"" << mode << "\" contains non-octal chars) "; + if(strcmp(type, "file") == 0) + mode_value |= S_IFREG; + PrintModeVerbose(mode_value); + outs() << " "; + } + if(user != nullptr) + outs() << format("%10s/", user); + if(group != nullptr) + outs() << format("%-10s ", group); + if(size != nullptr) + outs() << format("%7s ", size); + if(mtime != nullptr){ + for(m = mtime; *m != 'T' && *m != '\0'; m++) + outs() << *m; + if(*m == 'T') + m++; + outs() << " "; + for( ; *m != 'Z' && *m != '\0'; m++) + outs() << *m; + outs() << " "; + } + if(name != nullptr) + outs() << name; + outs() << "\n"; + } +} + +static void DumpBitcodeSection(MachOObjectFile *O, const char *sect, + uint32_t size, bool verbose, + bool PrintXarHeader, bool PrintXarFileHeaders, + std::string XarMemberName) { + if(size < sizeof(struct xar_header)) { + outs() << "size of (__LLVM,__bundle) section too small (smaller than size " + "of struct xar_header)\n"; + return; + } + struct xar_header XarHeader; + memcpy(&XarHeader, sect, sizeof(struct xar_header)); + if (sys::IsLittleEndianHost) + swapStruct(XarHeader); + if (PrintXarHeader) { + if (!XarMemberName.empty()) + outs() << "In xar member " << XarMemberName << ": "; + else + outs() << "For (__LLVM,__bundle) section: "; + outs() << "xar header\n"; + if (XarHeader.magic == XAR_HEADER_MAGIC) + outs() << " magic XAR_HEADER_MAGIC\n"; + else + outs() << " magic " + << format_hex(XarHeader.magic, 10, true) + << " (not XAR_HEADER_MAGIC)\n"; + outs() << " size " << XarHeader.size << "\n"; + outs() << " version " << XarHeader.version << "\n"; + outs() << " toc_length_compressed " << XarHeader.toc_length_compressed + << "\n"; + outs() << "toc_length_uncompressed " << XarHeader.toc_length_uncompressed + << "\n"; + outs() << " cksum_alg "; + switch (XarHeader.cksum_alg) { + case XAR_CKSUM_NONE: + outs() << "XAR_CKSUM_NONE\n"; + break; + case XAR_CKSUM_SHA1: + outs() << "XAR_CKSUM_SHA1\n"; + break; + case XAR_CKSUM_MD5: + outs() << "XAR_CKSUM_MD5\n"; + break; + case XAR_CKSUM_SHA256: + outs() << "XAR_CKSUM_SHA256\n"; + break; + case XAR_CKSUM_SHA512: + outs() << "XAR_CKSUM_SHA512\n"; + break; + default: + outs() << XarHeader.cksum_alg << "\n"; + } + } + + SmallString<128> XarFilename; + int FD; + std::error_code XarEC = + sys::fs::createTemporaryFile("llvm-objdump", "xar", FD, XarFilename); + if (XarEC) { + errs() << XarEC.message() << "\n"; + return; + } + tool_output_file XarFile(XarFilename, FD); + raw_fd_ostream &XarOut = XarFile.os(); + StringRef XarContents(sect, size); + XarOut << XarContents; + XarOut.close(); + if (XarOut.has_error()) + return; + + xar_t xar = xar_open(XarFilename.c_str(), READ); + if (!xar) { + errs() << "Can't create temporary xar archive " << XarFilename << "\n"; + return; + } + + SmallString<128> TocFilename; + std::error_code TocEC = + sys::fs::createTemporaryFile("llvm-objdump", "toc", TocFilename); + if (TocEC) { + errs() << TocEC.message() << "\n"; + return; + } + xar_serialize(xar, TocFilename.c_str()); + + if (PrintXarFileHeaders) { + if (!XarMemberName.empty()) + outs() << "In xar member " << XarMemberName << ": "; + else + outs() << "For (__LLVM,__bundle) section: "; + outs() << "xar archive files:\n"; + PrintXarFilesSummary(XarFilename.c_str(), xar); + } + + ErrorOr> FileOrErr = + MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); + if (std::error_code EC = FileOrErr.getError()) { + errs() << EC.message() << "\n"; + return; + } + std::unique_ptr &Buffer = FileOrErr.get(); + + if (!XarMemberName.empty()) + outs() << "In xar member " << XarMemberName << ": "; + else + outs() << "For (__LLVM,__bundle) section: "; + outs() << "xar table of contents:\n"; + outs() << Buffer->getBuffer() << "\n"; + + // TODO: Go through the xar's files. + xar_iter_t xi = xar_iter_new(); + if(!xi){ + errs() << "Can't obtain an xar iterator for xar archive " + << XarFilename.c_str() << "\n"; + xar_close(xar); + return; + } + for(xar_file_t xf = xar_file_first(xar, xi); xf; xf = xar_file_next(xi)){ + const char *key; + xar_iter_t xp; + const char *member_name, *member_type, *member_size_string; + size_t member_size; + + xp = xar_iter_new(); + if(!xp){ + errs() << "Can't obtain an xar iterator for xar archive " + << XarFilename.c_str() << "\n"; + xar_close(xar); + return; + } + member_name = NULL; + member_type = NULL; + member_size_string = NULL; + for(key = xar_prop_first(xf, xp); key; key = xar_prop_next(xp)){ + const char *val = nullptr; + xar_prop_get(xf, key, &val); +#if 0 // Useful for debugging. + outs() << "key: " << key << " value: " << val << "\n"; +#endif + if(strcmp(key, "name") == 0) + member_name = val; + if(strcmp(key, "type") == 0) + member_type = val; + if(strcmp(key, "data/size") == 0) + member_size_string = val; + } + /* + * If we find a file with a name, date/size and type properties + * and with the type being "file" see if that is a xar file. + */ + if (member_name != NULL && member_type != NULL && + strcmp(member_type, "file") == 0 && + member_size_string != NULL){ + // Extract the file into a buffer. + char *endptr; + member_size = strtoul(member_size_string, &endptr, 10); + if (*endptr == '\0' && member_size != 0) { + char *buffer = (char *) ::operator new (member_size); + if (xar_extract_tobuffersz(xar, xf, &buffer, &member_size) == 0) { +#if 0 // Useful for debugging. + outs() << "xar member: " << member_name << " extracted\n"; +#endif + // Set the XarMemberName we want to see printed in the header. + std::string OldXarMemberName; + // If XarMemberName is already set this is nested. So + // save the old name and create the nested name. + if (!XarMemberName.empty()) { + OldXarMemberName = XarMemberName; + XarMemberName = + (Twine("[") + XarMemberName + "]" + member_name).str(); + } else { + OldXarMemberName = ""; + XarMemberName = member_name; + } + // See if this is could be a xar file (nested). + if (member_size >= sizeof(struct xar_header)) { +#if 0 // Useful for debugging. + outs() << "could be a xar file: " << member_name << "\n"; +#endif + memcpy((char *)&XarHeader, buffer, sizeof(struct xar_header)); + if (sys::IsLittleEndianHost) + swapStruct(XarHeader); + if(XarHeader.magic == XAR_HEADER_MAGIC) + DumpBitcodeSection(O, buffer, member_size, verbose, + PrintXarHeader, PrintXarFileHeaders, + XarMemberName); + } + XarMemberName = OldXarMemberName; + } + delete buffer; + } + } + xar_iter_free(xp); + } + xar_close(xar); +} +#endif // defined(HAVE_LIBXAR) + static void printObjcMetaData(MachOObjectFile *O, bool verbose) { if (O->is64Bit()) printObjc2_64bit_MetaData(O, verbose); -- 2.11.0