diff options
Diffstat (limited to 'llvm')
-rwxr-xr-x | llvm/cmake/config-ix.cmake | 5 | ||||
-rw-r--r-- | llvm/include/llvm/Config/config.h.cmake | 3 | ||||
-rw-r--r-- | llvm/lib/Object/CMakeLists.txt | 2 | ||||
-rw-r--r-- | llvm/test/lit.cfg | 3 | ||||
-rw-r--r-- | llvm/test/lit.site.cfg.in | 1 | ||||
-rwxr-xr-x | llvm/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 | bin | 0 -> 16624 bytes | |||
-rw-r--r-- | llvm/test/tools/llvm-objdump/macho-LLVM-bundle.test | 60 | ||||
-rw-r--r-- | llvm/tools/llvm-objdump/MachODump.cpp | 383 |
8 files changed, 457 insertions, 0 deletions
diff --git a/llvm/cmake/config-ix.cmake b/llvm/cmake/config-ix.cmake index 7149e13b07e..a40dddfc1c8 100755 --- a/llvm/cmake/config-ix.cmake +++ b/llvm/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/llvm/include/llvm/Config/config.h.cmake b/llvm/include/llvm/Config/config.h.cmake index f6b7d386fd9..45b30d9171d 100644 --- a/llvm/include/llvm/Config/config.h.cmake +++ b/llvm/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 <termios.h> header file. */ #cmakedefine HAVE_TERMIOS_H ${HAVE_TERMIOS_H} diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt index 0a37cc360fe..b293d1c1f4e 100644 --- a/llvm/lib/Object/CMakeLists.txt +++ b/llvm/lib/Object/CMakeLists.txt @@ -21,4 +21,6 @@ add_llvm_library(LLVMObject DEPENDS intrinsics_gen + + LINK_LIBS ${XAR_LIB} ) diff --git a/llvm/test/lit.cfg b/llvm/test/lit.cfg index 32bf788ae53..78c5422f3aa 100644 --- a/llvm/test/lit.cfg +++ b/llvm/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/llvm/test/lit.site.cfg.in b/llvm/test/lit.site.cfg.in index 47699e25840..1ce3df7dd73 100644 --- a/llvm/test/lit.site.cfg.in +++ b/llvm/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/llvm/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 b/llvm/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 Binary files differnew file mode 100755 index 00000000000..8a7e4ef39e1 --- /dev/null +++ b/llvm/test/tools/llvm-objdump/Inputs/LLVM-bundle.macho-x86_64 diff --git a/llvm/test/tools/llvm-objdump/macho-LLVM-bundle.test b/llvm/test/tools/llvm-objdump/macho-LLVM-bundle.test new file mode 100644 index 00000000000..b7134307257 --- /dev/null +++ b/llvm/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: <?xml version="1.0" encoding="UTF-8"?> +# CHECK: <xar> +# CHECK: <subdoc subdoc_name="Ld"> +# CHECK: <version>1.0</version> +# CHECK: <architecture>x86_64</architecture> +# CHECK: <platform>MacOSX</platform> +# CHECK: <sdkversion>10.11.0</sdkversion> +# CHECK: <dylibs> +# CHECK: <lib>libSystem.dylib</lib> +# CHECK: </dylibs> +# CHECK: <link-options> +# CHECK: <option>-execute</option> +# CHECK: <option>-macosx_version_min</option> +# CHECK: <option>10.11.0</option> +# CHECK: <option>-e</option> +# CHECK: <option>_main</option> +# CHECK: <option>-executable_path</option> +# CHECK: <option>hello</option> +# CHECK: </link-options> +# CHECK: </subdoc> +# CHECK: <toc> +# CHECK: <checksum style="sha1"> +# CHECK: <size>20</size> +# CHECK: <offset>0</offset> +# CHECK: </checksum> +# CHECK: <creation-time>2016-05-23T20:49:10</creation-time> +# CHECK: <file id="1"> +# CHECK: <name>1</name> +# CHECK: <type>file</type> +# CHECK: <data> +# CHECK: <archived-checksum style="sha1">a319940ff5f5248ca8b44cf7b4b65e7dd49a47ab</archived-checksum> +# CHECK: <extracted-checksum style="sha1">a319940ff5f5248ca8b44cf7b4b65e7dd49a47ab</extracted-checksum> +# CHECK: <size>1664</size> +# CHECK: <offset>20</offset> +# CHECK: <encoding style="application/octet-stream"/> +# CHECK: <length>1664</length> +# CHECK: </data> +# CHECK: <file-type>Bitcode</file-type> +# CHECK: <clang> +# CHECK: <cmd>-triple</cmd> +# CHECK: <cmd>x86_64-apple-macosx10.11.0</cmd> +# CHECK: <cmd>-emit-obj</cmd> +# CHECK: <cmd>-disable-llvm-optzns</cmd> +# CHECK: </clang> +# CHECK: </file> +# CHECK: </toc> +# CHECK: </xar> diff --git a/llvm/tools/llvm-objdump/MachODump.cpp b/llvm/tools/llvm-objdump/MachODump.cpp index d94bf07f9e8..2bafe559987 100644 --- a/llvm/tools/llvm-objdump/MachODump.cpp +++ b/llvm/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 <algorithm> #include <cstring> @@ -51,6 +52,12 @@ #include <cxxabi.h> #endif +#ifdef HAVE_LIBXAR +extern "C" { +#include <xar/xar.h> +} +#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<std::unique_ptr<MemoryBuffer>> FileOrErr = + MemoryBuffer::getFileOrSTDIN(TocFilename.c_str()); + if (std::error_code EC = FileOrErr.getError()) { + errs() << EC.message() << "\n"; + return; + } + std::unique_ptr<MemoryBuffer> &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); |