From d563e105e580e0071b9e55f079c75498c8013e14 Mon Sep 17 00:00:00 2001 From: Iain Sandoe Date: Wed, 13 May 2015 23:27:10 +0100 Subject: [PATCH] 862 --- cctools/efitools/mtoc.c | 25 ++-- cctools/include/llvm-c/Disassembler.h | 6 + cctools/include/mach-o/loader.h | 3 + cctools/include/mach-o/nlist.h | 6 + cctools/include/stuff/llvm.h | 3 + cctools/libmacho/arch.c | 2 + cctools/libstuff/checkout.c | 21 ++- cctools/libstuff/llvm.c | 61 ++++++-- cctools/libstuff/ofile.c | 14 +- cctools/man/as.1 | 4 +- cctools/man/libtool.1 | 8 +- cctools/man/otool.1 | 32 +++-- cctools/misc/libtool.c | 35 ++++- cctools/misc/lipo.c | 57 ++++++++ cctools/misc/nm.c | 7 +- cctools/misc/strip.c | 261 ++++++++++++++++++++++++++-------- cctools/otool/arm_disasm.c | 2 + cctools/otool/i386_disasm.c | 2 + cctools/otool/main.c | 27 +++- cctools/otool/ofile_print.c | 4 + cctools/otool/print_objc2_32bit.c | 11 +- cctools/otool/print_objc2_64bit.c | 10 +- 22 files changed, 479 insertions(+), 122 deletions(-) diff --git a/cctools/efitools/mtoc.c b/cctools/efitools/mtoc.c index 8c9e23b..2ef3588 100644 --- a/cctools/efitools/mtoc.c +++ b/cctools/efitools/mtoc.c @@ -2497,14 +2497,15 @@ struct arch *arch) if (debug_uuid != NULL) { string_to_uuid (debug_uuid, uuid->uuid); } - mdi->uuid[0] = uuid->uuid[0]; - mdi->uuid[1] = uuid->uuid[1]; - mdi->uuid[2] = uuid->uuid[2]; - mdi->uuid[3] = uuid->uuid[3]; - mdi->uuid[4] = uuid->uuid[4]; - mdi->uuid[5] = uuid->uuid[5]; - mdi->uuid[6] = uuid->uuid[6]; - mdi->uuid[7] = uuid->uuid[7]; + /* Swizzle UUID to match EFI GUID definition */ + mdi->uuid[0] = uuid->uuid[3]; + mdi->uuid[1] = uuid->uuid[2]; + mdi->uuid[2] = uuid->uuid[1]; + mdi->uuid[3] = uuid->uuid[0]; + mdi->uuid[4] = uuid->uuid[5]; + mdi->uuid[5] = uuid->uuid[4]; + mdi->uuid[6] = uuid->uuid[7]; + mdi->uuid[7] = uuid->uuid[6]; mdi->uuid[8] = uuid->uuid[8]; mdi->uuid[9] = uuid->uuid[9]; mdi->uuid[10] = uuid->uuid[10]; @@ -2578,13 +2579,9 @@ uint8_t *uuid) { uint8_t count; - /* - * scanned bytewise to ensure correct endianness of fields - */ count = sscanf (string, UUID_FORMAT_STRING, - &uuid[3], &uuid[2], &uuid[1], &uuid[0], - &uuid[5], &uuid[4], - &uuid[7], &uuid[6], + &uuid[0], &uuid[1], &uuid[2], &uuid[3], + &uuid[4], &uuid[5], &uuid[6], &uuid[7], &uuid[8], &uuid[9], &uuid[10], &uuid[11], &uuid[12], &uuid[13], &uuid[14], &uuid[15]); diff --git a/cctools/include/llvm-c/Disassembler.h b/cctools/include/llvm-c/Disassembler.h index 9d120a2..5fa79fa 100644 --- a/cctools/include/llvm-c/Disassembler.h +++ b/cctools/include/llvm-c/Disassembler.h @@ -202,6 +202,12 @@ int LLVMSetDisasmOptions(LLVMDisasmContextRef DC, uint64_t Options); #define LLVMDisassembler_Option_UseMarkup 1 /* The option to print immediates as hex. */ #define LLVMDisassembler_Option_PrintImmHex 2 +/* The option use the other assembler printer variant */ +#define LLVMDisassembler_Option_AsmPrinterVariant 4 +/* The option to set comment on instructions */ +#define LLVMDisassembler_Option_SetInstrComments 8 + /* The option to print latency information alongside instructions */ +#define LLVMDisassembler_Option_PrintLatency 16 /** * Dispose of a disassembler context. diff --git a/cctools/include/mach-o/loader.h b/cctools/include/mach-o/loader.h index cc17c6f..e5e8258 100644 --- a/cctools/include/mach-o/loader.h +++ b/cctools/include/mach-o/loader.h @@ -207,6 +207,9 @@ struct mach_header_64 { require it. Only used in MH_EXECUTE filetypes. */ +#define MH_APP_EXTENSION_SAFE 0x02000000 /* The code was linked for use in an + application extension. */ + /* * The load commands directly follow the mach_header. The total size of all * of the commands is given by the sizeofcmds field in the mach_header. All diff --git a/cctools/include/mach-o/nlist.h b/cctools/include/mach-o/nlist.h index a5b45a0..133e36b 100644 --- a/cctools/include/mach-o/nlist.h +++ b/cctools/include/mach-o/nlist.h @@ -296,6 +296,12 @@ struct nlist_64 { */ #define N_SYMBOL_RESOLVER 0x0100 +/* + * The N_ALT_ENTRY bit of the n_desc field indicates that the + * symbol is pinned to the previous content. + */ +#define N_ALT_ENTRY 0x0200 + #ifndef __STRICT_BSD__ #ifdef __cplusplus extern "C" { diff --git a/cctools/include/stuff/llvm.h b/cctools/include/stuff/llvm.h index 519c3b8..9f94ba1 100644 --- a/cctools/include/stuff/llvm.h +++ b/cctools/include/stuff/llvm.h @@ -26,4 +26,7 @@ __private_extern__ int llvm_disasm_set_options( LLVMDisasmContextRef DC, uint64_t Options); +__private_extern__ const char *llvm_disasm_version_string( + void); + #endif /* _STUFF_LLVM_H_ */ diff --git a/cctools/libmacho/arch.c b/cctools/libmacho/arch.c index 69ceb86..12031d7 100644 --- a/cctools/libmacho/arch.c +++ b/cctools/libmacho/arch.c @@ -108,6 +108,8 @@ static const NXArchInfo ArchInfoTable[] = { "Intel Pentium II Model 5" }, {"pentium4", CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4, NX_LittleEndian, "Intel Pentium 4" }, + { "x86_64h", CPU_TYPE_I386, CPU_SUBTYPE_X86_64_H, NX_LittleEndian, + "Intel x86-64h Haswell" }, {"ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601, NX_BigEndian, "PowerPC 601" }, {"ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603, NX_BigEndian, diff --git a/cctools/libstuff/checkout.c b/cctools/libstuff/checkout.c index 7404671..889e0f6 100644 --- a/cctools/libstuff/checkout.c +++ b/cctools/libstuff/checkout.c @@ -357,6 +357,13 @@ struct object *object) order_error(arch, member, "dyld_info " "out of place"); } + else if(object->dyld_info->export_off != 0){ + if(object->dyld_info->export_off != offset && + object->dyld_info->weak_bind_size != 0 && + object->dyld_info->lazy_bind_size != 0) + order_error(arch, member, "dyld_info " + "out of place"); + } /* update offset to end of dyld_info contents */ if (object->dyld_info->export_size != 0) offset = object->dyld_info->export_off + @@ -382,17 +389,20 @@ struct object *object) sizeof(struct relocation_info); } if(object->split_info_cmd != NULL){ - if(object->split_info_cmd->dataoff != offset) + if(object->split_info_cmd->dataoff != 0 && + object->split_info_cmd->dataoff != offset) order_error(arch, member, "split info data out of place"); offset += object->split_info_cmd->datasize; } if(object->func_starts_info_cmd != NULL){ - if(object->func_starts_info_cmd->dataoff != offset) + if(object->func_starts_info_cmd->dataoff != 0 && + object->func_starts_info_cmd->dataoff != offset) order_error(arch, member, "function starts data out of place"); offset += object->func_starts_info_cmd->datasize; } if(object->data_in_code_cmd != NULL){ - if(object->data_in_code_cmd->dataoff != offset) + if(object->data_in_code_cmd->dataoff != 0 && + object->data_in_code_cmd->dataoff != offset) order_error(arch, member, "data in code info out of place"); offset += object->data_in_code_cmd->datasize; } @@ -608,9 +618,10 @@ struct object *object) * at the end of the object file change the object_size to be * the end of the string table here. This could be done at the * end of this routine but since all the later checks are fatal - * we'll just do this here. + * we'll just do this here. If there is a code signature after + * string table don't do this. */ - if(rounded_strend != strend) + if(rounded_strend != strend && object->code_sig_cmd == NULL) object->object_size = strend; end = object->st->stroff; } diff --git a/cctools/libstuff/llvm.c b/cctools/libstuff/llvm.c index 04356e5..4d13143 100644 --- a/cctools/libstuff/llvm.c +++ b/cctools/libstuff/llvm.c @@ -26,24 +26,18 @@ static void (*dispose)(LLVMDisasmContextRef) = NULL; static size_t (*disasm)(LLVMDisasmContextRef, uint8_t *, uint64_t, uint64_t, char *, size_t) = NULL; static int (*options)(LLVMDisasmContextRef, uint64_t) = NULL; +static const char * (*version)(void) = NULL; /* - * Wrapper to dynamically load LIB_LLVM and call LLVMCreateDisasm(). + * load_llvm() will dynamically load libLTO.dylib if tried_to_load_llvm is 0, + * and set llvm_handle to the value returned by dlopen() and set the function + * pointers. */ -__private_extern__ -LLVMDisasmContextRef -llvm_create_disasm( -const char *TripleName, -const char *CPU, -void *DisInfo, -int TagType, -LLVMOpInfoCallback GetOpInfo, -LLVMSymbolLookupCallback SymbolLookUp) +static void load_llvm(void) { uint32_t bufsize; char *p, *prefix, *llvm_path, buf[MAXPATHLEN], resolved_name[PATH_MAX]; int i; - LLVMDisasmContextRef DC; if(tried_to_load_llvm == 0){ tried_to_load_llvm = 1; @@ -77,7 +71,7 @@ LLVMSymbolLookupCallback SymbolLookUp) RTLD_NOW); } if(llvm_handle == NULL) - return(0); + return; create = dlsym(llvm_handle, "LLVMCreateDisasm"); dispose = dlsym(llvm_handle, "LLVMDisasmDispose"); @@ -86,6 +80,7 @@ LLVMSymbolLookupCallback SymbolLookUp) /* Note we allow these to not be defined */ options = dlsym(llvm_handle, "LLVMSetDisasmOptions"); createCPU = dlsym(llvm_handle, "LLVMCreateDisasmCPU"); + version = dlsym(llvm_handle, "lto_get_version"); if(create == NULL || dispose == NULL || @@ -100,10 +95,33 @@ LLVMSymbolLookupCallback SymbolLookUp) dispose = NULL; disasm = NULL; options = NULL; - return(NULL); + version = NULL; + return; } } if(llvm_handle == NULL) + return; +} + +/* + * Wrapper to dynamically load LIB_LLVM and call LLVMCreateDisasm(). + */ +__private_extern__ +LLVMDisasmContextRef +llvm_create_disasm( +const char *TripleName, +const char *CPU, +void *DisInfo, +int TagType, +LLVMOpInfoCallback GetOpInfo, +LLVMSymbolLookupCallback SymbolLookUp) +{ + LLVMDisasmContextRef DC; + + if(tried_to_load_llvm == 0){ + load_llvm(); + } + if(llvm_handle == NULL) return(NULL); /* @@ -167,3 +185,20 @@ uint64_t Options) return(0); return(options(DC, Options)); } + +/* + * Wrapper to call lto_get_version(). + */ +__private_extern__ +const char * +llvm_disasm_version_string(void) +{ + if(tried_to_load_llvm == 0){ + load_llvm(); + } + if(llvm_handle == NULL) + return(NULL); + if(version == NULL) + return(NULL); + return(version()); +} diff --git a/cctools/libstuff/ofile.c b/cctools/libstuff/ofile.c index 6e5b7a8..100f4af 100644 --- a/cctools/libstuff/ofile.c +++ b/cctools/libstuff/ofile.c @@ -2925,9 +2925,17 @@ struct ofile *ofile) if(is_llvm_bitcode(ofile, ofile->file_addr + ofile->member_offset + ofile->fat_archs[i].offset, ofile->fat_archs[i].size) == TRUE){ - ofile->member_type = OFILE_LLVM_BITCODE; - ofile->object_addr = ofile->member_addr; - ofile->object_size = ofile->member_size; +#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT + if(archive_64_bit_align_warning == FALSE && + (ofile->member_offset + ofile->fat_archs[i].offset) % + 8 != 0){ + temporary_archive_member_warning(ofile, "fat object " + "file's offset in archive not a multiple of 8) " + "(must be since member is a 64-bit object file)"); + archive_64_bit_align_warning = TRUE; + /* return(CHECK_BAD); */ + } +#endif } else #endif /* LTO_SUPPORT */ diff --git a/cctools/man/as.1 b/cctools/man/as.1 index f6f3446..f4b8245 100644 --- a/cctools/man/as.1 +++ b/cctools/man/as.1 @@ -1,4 +1,4 @@ -.TH AS 1 "March 30, 2012" "Apple, Inc." +.TH AS 1 "March 20, 2014" "Apple Inc." .SH NAME as \- Mac OS X Mach-O GNU-based assemblers .SH SYNOPSIS @@ -172,7 +172,7 @@ such temporary labels. .B \-q Use the .IR clang (1) -intergrated assembler instead of the GNU based system assembler. This is +integrated assembler instead of the GNU based system assembler. This is available for the x86 and arm architectures. .B \-Q Used the GNU based system assembler. diff --git a/cctools/man/libtool.1 b/cctools/man/libtool.1 index 64558cb..2aa4860 100644 --- a/cctools/man/libtool.1 +++ b/cctools/man/libtool.1 @@ -1,4 +1,4 @@ -.TH LIBTOOL 1 "September 24, 2008" "Apple Inc." +.TH LIBTOOL 1 "January 27, 2014" "Apple Inc." .SH NAME libtool \- create libraries .br @@ -16,6 +16,9 @@ ranlib \- add or update the table of contents of archive libraries [ .BI -arch_only " arch_type" ] +[ +.B \-no_warning_for_no_symbols +] .IR file ... [-filelist listfile[,dirname]] .br @@ -422,6 +425,9 @@ and .B \- Treat all remaining arguments as names of files (or archives) and not as options. +.TP +.B \-no_warning_for_no_symbols +Don't warn about file that have no symbols. .SH "SEE ALSO" ld(1), ar(1), otool(1), make(1), redo_prebinding(1), ar(5) .SH BUGS diff --git a/cctools/man/otool.1 b/cctools/man/otool.1 index b49c08a..540b960 100644 --- a/cctools/man/otool.1 +++ b/cctools/man/otool.1 @@ -1,4 +1,4 @@ -.TH OTOOL 1 "November 21, 2013" "Apple, Inc." +.TH OTOOL 1 "January 24, 2014" "Apple Inc." .SH NAME otool \- object file displaying tool .SH SYNOPSIS @@ -11,9 +11,9 @@ otool \- object file displaying tool .SH DESCRIPTION The .I otool -command displays specified parts of object files or libraries. If the, +command displays specified parts of object files or libraries. If the .B \-m -option is not used, the file +option is not used the file arguments may be of the form .IR "libx.a(foo.o)" , to request information about only that object file and not @@ -51,10 +51,12 @@ Display the load commands. .TP .B \-L Display the names and version numbers of the shared libraries that the object -file uses. As well as the shared library ID if the file is a shared library. +file uses, as well as the shared library ID if the file is a shared library. .TP .B \-D -Display just install name of a shared library. +Display just the install name of a shared library. See +.IR install_name_tool (1) +for more info. .TP .BI \-s " segname sectname" Display the contents of the section @@ -72,9 +74,9 @@ flag is specified. .B \-t Display the contents of the (\_\^\_TEXT,\_\^\_text) section. With the .B \-v -flag, this disassembles the text. And with -.BR \-V , -it also symbolically disassembles the operands. +flag, this disassembles the text. With the +.B \-V +flag, it also symbolically disassembles the operands. .TP .B \-d Display the contents of the (\_\^\_DATA,\_\^\_data) section. @@ -138,7 +140,7 @@ option. Don't print leading addresses or headers with disassembly of sections. .TP .B \-q -Use the llvm disassembler when doing disassembly, this is available for the x86 +Use the llvm disassembler when doing disassembly; this is available for the x86 and arm architectures. This is the default. .TP .BI \-mcpu= arg @@ -148,9 +150,9 @@ When doing disassembly using the llvm disassembler use the cpu .B \-function_offsets When doing disassembly print the decimal offset from the last label printed. .TP -.TP .B \-j When doing disassembly print the print the opcode bytes of the instructions. +.TP .B \-Q Use .IR otool (1)'s @@ -161,9 +163,10 @@ Specifies the architecture, .I arch_type, of the file for .IR otool (1) -to operate on when the file is a universal file. (See +to operate on when the file is a universal file (aka a file with multiple +architectures). (See .IR arch (3) -for the currently know +for the currently known .IR arch_type s.) The .I arch_type @@ -174,5 +177,10 @@ otherwise, all architectures in the file are shown. .B \-m The object file names are not assumed to be in the archive(member) syntax, which allows file names containing parenthesis. +.TP +.B \-\-version +Print the +.IR otool (1) +version information. .SH "SEE ALSO" install_name_tool(1), dyld(1) and libtool(1) diff --git a/cctools/misc/libtool.c b/cctools/misc/libtool.c index 18f0d49..2c6c85c 100644 --- a/cctools/misc/libtool.c +++ b/cctools/misc/libtool.c @@ -147,6 +147,8 @@ struct cmd_flags { enum bool noflush; /* don't use the output_flush routine to flush the static library output file by pages */ uint32_t debug; /* debug value to debug output_flush() routine */ + enum bool /* don't warn if members have no symbols */ + no_warning_for_no_symbols; }; static struct cmd_flags cmd_flags = { 0 }; @@ -977,6 +979,9 @@ char **envp) else if(strcmp(argv[i], "-noflush") == 0){ cmd_flags.noflush = TRUE; } + else if(strcmp(argv[i], "-no_warning_for_no_symbols") == 0){ + cmd_flags.no_warning_for_no_symbols = TRUE; + } #ifdef DEBUG else if(strcmp(argv[i], "-debug") == 0){ if(i + 1 >= argc){ @@ -1266,7 +1271,7 @@ void) else{ fprintf(stderr, "Usage: %s -static [-] file [...] " "[-filelist listfile[,dirname]] [-arch_only arch] " - "[-sacLT]\n", progname); + "[-sacLT] [-no_warning_for_no_symbols]\n", progname); fprintf(stderr, "Usage: %s -dynamic [-] file [...] " "[-filelist listfile[,dirname]] [-arch_only arch] " "[-o output] [-install_name name] " @@ -1720,8 +1725,16 @@ struct ofile *ofile) if(ofile->mh != NULL || ofile->mh64 != NULL) size = rnd(ofile->object_size, 8); #ifdef LTO_SUPPORT - else if(ofile->lto != NULL && ofile->file_type == OFILE_LLVM_BITCODE) - size = rnd(ofile->file_size, 8); + else if(ofile->lto != NULL){ + if(ofile->file_type == OFILE_LLVM_BITCODE) + size = rnd(ofile->file_size, 8); + else if(ofile->file_type == OFILE_FAT || + (ofile->file_type == OFILE_ARCHIVE && + ofile->member_type == OFILE_FAT)) + size = rnd(ofile->object_size, 8); + else + size = rnd(ofile->member_size, 8); + } #endif /* LTO_SUPPORT */ else size = rnd(ofile->member_size, 8); @@ -2160,6 +2173,16 @@ struct ofile *ofile) member->lto = ofile->lto; member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag); } + else if((ofile->file_type == OFILE_FAT && + ofile->arch_type == OFILE_LLVM_BITCODE) || + (ofile->file_type == OFILE_ARCHIVE && + ofile->member_type == OFILE_FAT && + ofile->arch_type == OFILE_LLVM_BITCODE)){ + member->object_addr = ofile->object_addr; + member->object_size = ofile->object_size; + member->lto = ofile->lto; + member->object_byte_sex = get_byte_sex_from_flag(&arch->arch_flag); + } #endif /* LTO_SUPPORT */ else{ member->object_addr = ofile->member_addr; @@ -3553,8 +3576,10 @@ char *output) } } } - else - warn_member(arch, member, "has no symbols"); + else{ + if(cmd_flags.no_warning_for_no_symbols == FALSE) + warn_member(arch, member, "has no symbols"); + } } #ifdef LTO_SUPPORT else if(member->lto != NULL){ diff --git a/cctools/misc/lipo.c b/cctools/misc/lipo.c index 6c1dd8e..95d7892 100644 --- a/cctools/misc/lipo.c +++ b/cctools/misc/lipo.c @@ -147,6 +147,10 @@ static struct fat_arch *arm64_fat_arch = NULL; static struct fat_arch *get_arm64_fat_arch( void); +static struct fat_arch *x86_64h_fat_arch = NULL; +static struct fat_arch *get_x86_64h_fat_arch( + void); + static enum bool verify_flag = FALSE; static struct arch_flag *verify_archs = NULL; static uint32_t nverify_archs = 0; @@ -875,6 +879,9 @@ create_fat(void) /* We will order the ARM64 slice last. */ arm64_fat_arch = get_arm64_fat_arch(); + /* We will order the x86_64h slice last too. */ + x86_64h_fat_arch = get_x86_64h_fat_arch(); + /* Fill in the fat header and the fat_arch's offsets. */ fat_header.magic = FAT_MAGIC; fat_header.nfat_arch = nthin_files; @@ -913,6 +920,12 @@ create_fat(void) */ if(arm64_fat_arch == &(thin_files[i].fat_arch)) continue; + /* + * If we are ordering the x86_64h slice last too of the fat_arch + * structs, so skip it in this loop. + */ + if(x86_64h_fat_arch == &(thin_files[i].fat_arch)) + continue; #ifdef __LITTLE_ENDIAN__ swap_fat_arch(&(thin_files[i].fat_arch), 1,BIG_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ @@ -942,6 +955,22 @@ create_fat(void) swap_fat_arch(arm64_fat_arch, 1, LITTLE_ENDIAN_BYTE_SEX); #endif /* __LITTLE_ENDIAN__ */ } + /* + * We are ordering the x86_64h slice so it gets written last too of the + * fat_arch structs, so write it out here as it was skipped above. + */ + if(x86_64h_fat_arch){ +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(x86_64h_fat_arch, 1, BIG_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + if(write(fd, x86_64h_fat_arch, + sizeof(struct fat_arch)) != sizeof(struct fat_arch)) + system_fatal("can't write fat arch to output file: %s", + rename_file); +#ifdef __LITTLE_ENDIAN__ + swap_fat_arch(x86_64h_fat_arch, 1, LITTLE_ENDIAN_BYTE_SEX); +#endif /* __LITTLE_ENDIAN__ */ + } for(i = 0; i < nthin_files; i++){ if(extract_family_flag == FALSE || nthin_files > 1) if(lseek(fd, thin_files[i].fat_arch.offset, L_SET) == -1) @@ -1572,6 +1601,34 @@ void) } /* + * get_x86_64h_fat_arch() will return a pointer to the fat_arch struct for the + * x86_64h slice in the thin_files[i] if it is present. Else it returns + * NULL. + */ +static +struct fat_arch * +get_x86_64h_fat_arch( +void) +{ + uint32_t i; + struct fat_arch *x86_64h_fat_arch; + + /* + * Look for a x86_64h slice. + */ + x86_64h_fat_arch = NULL; + for(i = 0; i < nthin_files; i++){ + if(thin_files[i].fat_arch.cputype == CPU_TYPE_X86_64 && + (thin_files[i].fat_arch.cpusubtype & ~CPU_SUBTYPE_MASK) == + CPU_SUBTYPE_X86_64_H){ + x86_64h_fat_arch = &(thin_files[i].fat_arch); + return(x86_64h_fat_arch); + } + } + return(NULL); +} + +/* * get_align is passed a pointer to a mach header and size of the object. It * returns the segment alignment the object was created with. It guesses but * it is conservative. The maximum alignment is that the link editor will allow diff --git a/cctools/misc/nm.c b/cctools/misc/nm.c index f355437..354c88c 100644 --- a/cctools/misc/nm.c +++ b/cctools/misc/nm.c @@ -1106,8 +1106,6 @@ struct process_flags *process_flags) symbol->nl.n_value == 0) || symbol->nl.n_type == (N_PBUD | N_EXT)) return(FALSE); - else - return(TRUE); } if(cmd_flags->g == TRUE && (symbol->nl.n_type & N_EXT) == 0) return(FALSE); @@ -1366,6 +1364,11 @@ char *arch_name) (symbols[i].nl.n_desc & N_SYMBOL_RESOLVER) == N_SYMBOL_RESOLVER) printf("[symbol resolver] "); + if(ofile->mh_filetype == MH_OBJECT && + ((symbols[i].nl.n_type & N_TYPE) != N_UNDF) && + (symbols[i].nl.n_desc & N_ALT_ENTRY) == N_ALT_ENTRY) + printf("[alt entry] "); + if((symbols[i].nl.n_desc & N_ARM_THUMB_DEF) == N_ARM_THUMB_DEF) printf("[Thumb] "); diff --git a/cctools/misc/strip.c b/cctools/misc/strip.c index e6c236b..94359fd 100644 --- a/cctools/misc/strip.c +++ b/cctools/misc/strip.c @@ -1078,20 +1078,23 @@ struct object *object) for(j = 0; j < sg->nsects; j++){ /* * For section types with indirect tables we - * do not zero out the section size in a stub - * library. As the section size is needed to - * know now many indirect table entries the - * section has. This is a bit odd but programs - * dealing with MH_DYLIB_STUB filetypes special - * case this. + * change the type to S_REGULAR and clear the + * reserved1 and reserved2 fields so not to + * confuse tools that would be trying to look + * at the indirect table since it is now removed + * when creating a stub library. */ section_type = s[j].flags & SECTION_TYPE; - if(section_type != S_SYMBOL_STUBS && - section_type != S_LAZY_SYMBOL_POINTERS && - section_type != S_LAZY_DYLIB_SYMBOL_POINTERS && - section_type != S_NON_LAZY_SYMBOL_POINTERS){ - s[j].size = 0; + if(section_type == S_SYMBOL_STUBS || + section_type == S_LAZY_SYMBOL_POINTERS || + section_type == + S_LAZY_DYLIB_SYMBOL_POINTERS || + section_type == S_NON_LAZY_SYMBOL_POINTERS){ + s[j].flags = S_REGULAR; + s[j].reserved1 = 0; + s[j].reserved2 = 0; } + s[j].size = 0; s[j].addr = 0; s[j].offset = 0; s[j].reloff = 0; @@ -1114,20 +1117,23 @@ struct object *object) for(j = 0; j < sg64->nsects; j++){ /* * For section types with indirect tables we - * do not zero out the section size in a stub - * library. As the section size is needed to - * know now many indirect table entries the - * section has. This is a bit odd but programs - * dealing with MH_DYLIB_STUB filetypes special - * case this. + * change the type to S_REGULAR and clear the + * reserved1 and reserved2 fields so not to + * confuse tools that would be trying to look + * at the indirect table since it is now removed + * when creating a stub library. */ section_type = s64[j].flags & SECTION_TYPE; - if(section_type != S_SYMBOL_STUBS && - section_type != S_LAZY_SYMBOL_POINTERS && - section_type != S_LAZY_DYLIB_SYMBOL_POINTERS && - section_type != S_NON_LAZY_SYMBOL_POINTERS){ - s64[j].size = 0; + if(section_type == S_SYMBOL_STUBS || + section_type == S_LAZY_SYMBOL_POINTERS || + section_type == + S_LAZY_DYLIB_SYMBOL_POINTERS || + section_type == S_NON_LAZY_SYMBOL_POINTERS){ + s64[j].flags = S_REGULAR; + s64[j].reserved1 = 0; + s64[j].reserved2 = 0; } + s64[j].size = 0; s64[j].addr = 0; s64[j].offset = 0; s64[j].reloff = 0; @@ -1250,7 +1256,7 @@ struct object *object) * * Also the parts that make up input_sym_info_size must be added up * in the same way. And must be done here as the input file may - * have been changed to and "ld -r" file and may not be the + * have been changed to an "ld -r" file and may not be the * the original input file. */ object->output_sym_info_size = 0; @@ -1285,6 +1291,23 @@ struct object *object) else if (object->dyld_info->rebase_size != 0) dyld_info_end = object->dyld_info->rebase_off + object->dyld_info->rebase_size; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub we only keep the dyld export data. + */ + if(cflag){ + if(object->dyld_info->export_off != 0){ + dyld_info_start = object->dyld_info->export_off; + dyld_info_end = object->dyld_info->export_off + + object->dyld_info->export_size; + } + else{ + dyld_info_start = 0; + dyld_info_end = 0; + } + } +#endif /* !(NMEDIT) */ object->output_dyld_info = object->object_addr +dyld_info_start; object->output_dyld_info_size = dyld_info_end - dyld_info_start; object->output_sym_info_size += object->output_dyld_info_size; @@ -1303,6 +1326,23 @@ struct object *object) + object->dyld_info->weak_bind_size + object->dyld_info->lazy_bind_size + object->dyld_info->export_size; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub we only keep the dyld export data, + * so zero the offsets and sizes of the other dyld data items. + */ + if(cflag){ + object->dyld_info->rebase_off = 0; + object->dyld_info->rebase_size = 0; + object->dyld_info->bind_off = 0; + object->dyld_info->bind_size = 0; + object->dyld_info->weak_bind_off = 0; + object->dyld_info->weak_bind_size = 0; + object->dyld_info->lazy_bind_off = 0; + object->dyld_info->lazy_bind_size = 0; + } +#endif /* !(NMEDIT) */ } if(object->dyst != NULL){ @@ -1323,35 +1363,63 @@ struct object *object) } if(object->split_info_cmd != NULL){ - object->output_split_info_data = object->object_addr + - object->split_info_cmd->dataoff; - object->output_split_info_data_size = - object->split_info_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub we also remove the split info data. + */ + if(!cflag) +#endif /* !(NMEDIT) */ + { + object->output_split_info_data = object->object_addr + + object->split_info_cmd->dataoff; + object->output_split_info_data_size = + object->split_info_cmd->datasize; + object->output_sym_info_size += + object->split_info_cmd->datasize; + } object->input_sym_info_size += object->split_info_cmd->datasize; - object->output_sym_info_size += - object->split_info_cmd->datasize; } if(object->func_starts_info_cmd != NULL){ - object->output_func_start_info_data = object->object_addr + - object->func_starts_info_cmd->dataoff; - object->output_func_start_info_data_size = - object->func_starts_info_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub we also remove the function starts info. + */ + if(!cflag) +#endif /* !(NMEDIT) */ + { + object->output_func_start_info_data = object->object_addr + + object->func_starts_info_cmd->dataoff; + object->output_func_start_info_data_size = + object->func_starts_info_cmd->datasize; + object->output_sym_info_size += + object->func_starts_info_cmd->datasize; + } object->input_sym_info_size += object->func_starts_info_cmd->datasize; - object->output_sym_info_size += - object->func_starts_info_cmd->datasize; } if(object->data_in_code_cmd != NULL){ - object->output_data_in_code_info_data = object->object_addr + - object->data_in_code_cmd->dataoff; - object->output_data_in_code_info_data_size = - object->data_in_code_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub we also remove the data in code info. + */ + if(!cflag) +#endif /* !(NMEDIT) */ + { + object->output_data_in_code_info_data = + object->object_addr + + object->data_in_code_cmd->dataoff; + object->output_data_in_code_info_data_size = + object->data_in_code_cmd->datasize; + object->output_sym_info_size += + object->data_in_code_cmd->datasize; + } object->input_sym_info_size += object->data_in_code_cmd->datasize; - object->output_sym_info_size += - object->data_in_code_cmd->datasize; } if(object->code_sign_drs_cmd != NULL){ @@ -1418,9 +1486,19 @@ struct object *object) } if(object->dyst != NULL){ - object->output_sym_info_size += - object->dyst->nindirectsyms * sizeof(uint32_t) + - object->input_indirectsym_pad; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the indirect symbol table also gets + * stripped. + */ + if(!cflag) +#endif /* !(NMEDIT) */ + { + object->output_sym_info_size += + object->dyst->nindirectsyms * sizeof(uint32_t) + + object->input_indirectsym_pad; + } if(object->mh != NULL){ object->input_sym_info_size += object->dyst->nindirectsyms * sizeof(uint32_t); @@ -1503,10 +1581,23 @@ struct object *object) object->dyst->iundefsym = new_nlocalsym + new_nextdefsym; object->dyst->nundefsym = new_nundefsym; if(object->dyst->nindirectsyms != 0){ - object->output_indirect_symtab = indirectsyms; - if(object->object_byte_sex != host_byte_sex) - swap_indirect_symbols(indirectsyms, nindirectsyms, - object->object_byte_sex); +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the indirect symbol table also gets + * stripped. + */ + if(cflag){ + object->dyst->nindirectsyms = 0; + } + else +#endif /* !(NMEDIT) */ + { + object->output_indirect_symtab = indirectsyms; + if(object->object_byte_sex != host_byte_sex) + swap_indirect_symbols(indirectsyms, nindirectsyms, + object->object_byte_sex); + } } /* @@ -1604,18 +1695,60 @@ struct object *object) object->dyst->locreloff = 0; if(object->split_info_cmd != NULL){ - object->split_info_cmd->dataoff = offset; - offset += object->split_info_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the split info data gets + * stripped. + */ + if(cflag){ + object->split_info_cmd->dataoff = 0; + object->split_info_cmd->datasize = 0; + } + else +#endif /* defined(NMEDIT) */ + { + object->split_info_cmd->dataoff = offset; + offset += object->split_info_cmd->datasize; + } } if(object->func_starts_info_cmd != NULL){ - object->func_starts_info_cmd->dataoff = offset; - offset += object->func_starts_info_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the function starts info gets + * stripped. + */ + if(cflag){ + object->func_starts_info_cmd->dataoff = 0; + object->func_starts_info_cmd->datasize = 0; + } + else +#endif /* defined(NMEDIT) */ + { + object->func_starts_info_cmd->dataoff = offset; + offset += object->func_starts_info_cmd->datasize; + } } if(object->data_in_code_cmd != NULL){ - object->data_in_code_cmd->dataoff = offset; - offset += object->data_in_code_cmd->datasize; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the data in code info gets + * stripped. + */ + if(cflag){ + object->data_in_code_cmd->dataoff = 0; + object->data_in_code_cmd->datasize = 0; + } + else +#endif /* defined(NMEDIT) */ + { + object->data_in_code_cmd->dataoff = offset; + offset += object->data_in_code_cmd->datasize; + } } if(object->code_sign_drs_cmd != NULL){ @@ -1675,9 +1808,23 @@ struct object *object) object->dyst->extreloff = 0; if(object->dyst->nindirectsyms != 0){ - object->dyst->indirectsymoff = offset; - offset += object->dyst->nindirectsyms * sizeof(uint32_t) + - object->input_indirectsym_pad; +#ifndef NMEDIT + /* + * When stripping out the section contents to create a + * dynamic library stub the indirect symbol table also gets + * stripped. + */ + if(cflag){ + object->dyst->indirectsymoff = 0; + } + else +#endif /* defined(NMEDIT) */ + { + object->dyst->indirectsymoff = offset; + offset += object->dyst->nindirectsyms * + sizeof(uint32_t) + + object->input_indirectsym_pad; + } } else object->dyst->indirectsymoff = 0;; diff --git a/cctools/otool/arm_disasm.c b/cctools/otool/arm_disasm.c index 1f0eba4..0b0ffdf 100644 --- a/cctools/otool/arm_disasm.c +++ b/cctools/otool/arm_disasm.c @@ -838,6 +838,8 @@ const char **ReferenceName) *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; } + else + *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; } else *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; diff --git a/cctools/otool/i386_disasm.c b/cctools/otool/i386_disasm.c index 35e5e04..d467c30 100644 --- a/cctools/otool/i386_disasm.c +++ b/cctools/otool/i386_disasm.c @@ -5276,6 +5276,8 @@ const char **ReferenceName) *ReferenceType = LLVMDisassembler_ReferenceType_DeMangled_Name; } + else + *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; } else *ReferenceType = LLVMDisassembler_ReferenceType_InOut_None; diff --git a/cctools/otool/main.c b/cctools/otool/main.c index 81dfd32..e03b0ec 100644 --- a/cctools/otool/main.c +++ b/cctools/otool/main.c @@ -320,8 +320,9 @@ char **envp) uint32_t j, nfiles; struct arch_flag *arch_flags; uint32_t narch_flags; - enum bool all_archs, use_member_syntax; + enum bool all_archs, use_member_syntax, version; char **files; + const char *disssembler_version; progname = argv[0]; arch_flags = NULL; @@ -329,6 +330,7 @@ char **envp) all_archs = FALSE; use_member_syntax = TRUE; llvm_mc = FALSE; + version = FALSE; if(argc <= 1) usage(); @@ -348,6 +350,15 @@ char **envp) files[nfiles++] = argv[i]; continue; } + if(strcmp(argv[i], "--version") == 0){ + fprintf(stderr, "otool(1): Apple Inc. version %s\n", + apple_version); + disssembler_version = llvm_disasm_version_string(); + if(disssembler_version != NULL) + fprintf(stderr, "disassmbler: %s\n", disssembler_version); + version = TRUE; + continue; + } if(strcmp(argv[i], "-arch") == 0){ if(i + 1 == argc){ error("missing argument(s) to %s option", argv[i]); @@ -549,9 +560,10 @@ char **envp) */ if(!fflag && !aflag && !hflag && !lflag && !Lflag && !tflag && !dflag && !oflag && !Oflag && !rflag && !Tflag && !Mflag && !Rflag && !Iflag && - !Cflag && !print_bind_info && + !Cflag && !print_bind_info && !version && !Hflag && !Gflag && !Sflag && !cflag && !iflag && !Dflag &&!segname){ - error("one of -fahlLtdoOrTMRIHCGScis must be specified"); + error("one of -fahlLtdoOrTMRIHCGScis or --version must be " + "specified"); usage(); } if(qflag && Qflag){ @@ -564,7 +576,7 @@ char **envp) */ if(!Qflag) qflag = TRUE; - if(nfiles == 0){ + if(nfiles == 0 && version == FALSE){ error("at least one file must be specified"); usage(); } @@ -606,7 +618,7 @@ void) { fprintf(stderr, "Usage: %s [-arch arch_type] [-fahlLDtdorSTMRIHGvVcXmqQjC] " - "[-mcpu=arg] ...\n", progname); + "[-mcpu=arg] [--version] ...\n", progname); fprintf(stderr, "\t-f print the fat headers\n"); fprintf(stderr, "\t-a print the archive header\n"); @@ -643,6 +655,7 @@ void) fprintf(stderr, "\t-mcpu=arg use `arg' as the cpu for disassembly\n"); fprintf(stderr, "\t-j print opcode bytes\n"); fprintf(stderr, "\t-C print linker optimization hints\n"); + fprintf(stderr, "\t--version print the version of %s\n", progname); exit(EXIT_FAILURE); } @@ -3179,6 +3192,8 @@ uint64_t seg_addr) } llvm_disasm_set_options(i386_dc, LLVMDisassembler_Option_PrintImmHex); + llvm_disasm_set_options(i386_dc, + LLVMDisassembler_Option_SetInstrComments); if(eflag) llvm_disasm_set_options(i386_dc, LLVMDisassembler_Option_UseMarkup); @@ -3191,6 +3206,8 @@ uint64_t seg_addr) } llvm_disasm_set_options(x86_64_dc, LLVMDisassembler_Option_PrintImmHex); + llvm_disasm_set_options(x86_64_dc, + LLVMDisassembler_Option_SetInstrComments); if(eflag) llvm_disasm_set_options(x86_64_dc, LLVMDisassembler_Option_UseMarkup); diff --git a/cctools/otool/ofile_print.c b/cctools/otool/ofile_print.c index d48b262..3eb6506 100644 --- a/cctools/otool/ofile_print.c +++ b/cctools/otool/ofile_print.c @@ -1812,6 +1812,10 @@ NS32: printf(" MH_NO_HEAP_EXECUTION"); f &= ~MH_NO_HEAP_EXECUTION; } + if(f & MH_APP_EXTENSION_SAFE){ + printf(" APP_EXTENSION_SAFE"); + f &= ~MH_APP_EXTENSION_SAFE; + } if(f != 0 || flags == 0) printf(" 0x%08x", (unsigned int)f); printf("\n"); diff --git a/cctools/otool/print_objc2_32bit.c b/cctools/otool/print_objc2_32bit.c index 4063ba6..8aa6a96 100644 --- a/cctools/otool/print_objc2_32bit.c +++ b/cctools/otool/print_objc2_32bit.c @@ -622,8 +622,15 @@ struct info *info) printf(" %s\n", name); else printf("\n"); - printf(" data 0x%x (struct class_ro_t *)\n", c.data); - print_class_ro_t(c.data, info, &is_meta_class); + printf(" data 0x%x (struct class_ro_t *)", c.data); + /* + * This is a Swift class if some of the low bits of the pointer + * are set. + */ + if(c.data & 0x3) + printf(" Swift class"); + printf("\n"); + print_class_ro_t(c.data & ~0x3, info, &is_meta_class); if(! is_meta_class) { diff --git a/cctools/otool/print_objc2_64bit.c b/cctools/otool/print_objc2_64bit.c index 5572113..7978677 100644 --- a/cctools/otool/print_objc2_64bit.c +++ b/cctools/otool/print_objc2_64bit.c @@ -808,8 +808,14 @@ struct info *info) printf("0x%llx", c.data); } printf(" (struct class_ro_t *)"); + /* + * This is a Swift class if some of the low bits of the pointer + * are set. + */ + if((c.data + n_value) & 0x7) + printf(" Swift class"); printf("\n"); - print_class_ro_t(c.data + n_value, info, &is_meta_class); + print_class_ro_t((c.data + n_value) & ~0x7, info, &is_meta_class); if(is_meta_class == FALSE){ printf("Meta Class\n"); @@ -1776,6 +1782,8 @@ enum bool verbose) object_addr, object_size, &info.sections, &info.nsections, &info.database); o = get_section_64(info.sections, info.nsections, SEG_OBJC, sectname); + if(o == NULL) + return; get_cstring_section_64(load_commands, ncmds, sizeofcmds,object_byte_sex, object_addr, object_size, &cstring_section); -- 2.11.4.GIT