cctools 877.8

This commit is contained in:
Thomas Pöchtrager 2016-05-09 21:29:06 +02:00
parent 7fe1031d40
commit 16e8e127e3
11 changed files with 645 additions and 138 deletions

View File

@ -1,3 +1,15 @@
## cctools 877.5 -> 877.8 ##
patching file include/mach-o/loader.h
patching file libstuff/execute.c
patching file libstuff/ofile.c
patching file libstuff/swap_headers.c
patching file misc/bitcode_strip.c
Hunk #11 NOT MERGED at 364-373, merged at 377, merged at 382-385.
Hunk #20 merged at 547-557.
patching file otool/main.c
patching file otool/ofile_print.c
## ld64 253.3 -> ld64 253.9 ##
patching file src/ld/InputFiles.cpp
@ -27,8 +39,8 @@ The text leading up to this was:
|--- ../cctools-870/Makefile 2015-08-26 07:49:15.000000000 +0200
|+++ ./Makefile 2015-09-15 03:35:14.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
3 out of 3 hunks ignored
patching file ./as/driver.c
@ -64,8 +76,8 @@ The text leading up to this was:
|--- ../cctools-870/misc/Makefile 2013-12-10 20:28:11.000000000 +0100
|+++ ./misc/Makefile 2015-03-10 01:33:19.000000000 +0100
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
7 out of 7 hunks ignored
patching file ./misc/bitcode_strip.c
@ -90,8 +102,8 @@ The text leading up to this was:
|--- ../cctools-870/otool/Makefile 2014-01-14 01:21:55.000000000 +0100
|+++ ./otool/Makefile 2015-03-10 01:33:19.000000000 +0100
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
patching file ./otool/main.c
@ -128,8 +140,8 @@ The text leading up to this was:
|--- ../ld64-242.2/ld64.xcodeproj/project.pbxproj 2014-08-20 00:19:03.000000000 +0200
|+++ ./ld64.xcodeproj/project.pbxproj 2015-05-20 08:11:58.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
22 out of 22 hunks ignored
patching file ./src/abstraction/MachOFileAbstraction.hpp
@ -158,8 +170,8 @@ patching file ./src/ld/ld.cpp
patching file ./src/ld/ld.hpp
Hunk #1 merged at 35-36,38,45-47.
The next patch would delete the file ./src/ld/lto_file.hpp,
which does not exist! Assume -R? [n]
Apply anyway? [n]
which does not exist! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored
patching file ./src/ld/parsers/lto_file.cpp
@ -206,8 +218,8 @@ The text leading up to this was:
|--- ../ld64-242/unit-tests/test-cases/branch-islands/space.s 2013-10-19 03:10:28.000000000 +0200
|+++ ./unit-tests/test-cases/branch-islands/space.s 2015-05-05 21:42:23.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
@ -307,7 +319,7 @@ patching file ./src/ld/parsers/lto_file.cpp
Hunk #2 NOT MERGED at 499-507. # Resolved.
patching file ./src/ld/parsers/lto_file.h
patching file ./src/ld/parsers/macho_relocatable_file.cpp
Hunk #8 merged at 4219-4234.
Hunk #8 merged at 4219-4234.
patching file ./src/ld/parsers/macho_relocatable_file.h
patching file ./src/ld/passes/compact_unwind.cpp
patching file ./src/other/ObjectDump.cpp
@ -318,28 +330,28 @@ patching file ./src/other/unwinddump.cpp
## cctools 855 -> 862 ##
patching file efitools/mtoc.c
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
2 out of 2 hunks ignored -- saving rejects to file efitools/mtoc.c.rej
patching file include/llvm-c/Disassembler.h
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file include/llvm-c/Disassembler.h.rej
patching file include/mach-o/loader.h
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file include/mach-o/loader.h.rej
patching file include/mach-o/nlist.h
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file include/mach-o/nlist.h.rej
patching file include/stuff/llvm.h
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Reversed (or previously applied) patch detected! Assume -R? [n]
Apply anyway? [n]
Skipping patch.
1 out of 1 hunk ignored -- saving rejects to file include/stuff/llvm.h.rej
can't find file to patch at input line 103
@ -350,8 +362,8 @@ The text leading up to this was:
|--- ../cctools-855/libmacho/arch.c 2014-04-05 00:42:22.000000000 +0200
|+++ ./libmacho/arch.c 2014-11-02 06:48:07.000000000 +0100
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
patching file libstuff/checkout.c
@ -399,8 +411,8 @@ The text leading up to this was:
|--- ../ld64-236.3/ld64.xcodeproj/project.pbxproj 2014-04-05 00:42:29.000000000 +0200
|+++ ./ld64.xcodeproj/project.pbxproj 2014-11-04 00:58:03.000000000 +0100
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
3 out of 3 hunks ignored
patching file src/abstraction/MachOFileAbstraction.hpp
@ -525,8 +537,8 @@ The text leading up to this was:
|--- ../ld64-236.3/unit-tests/include/common.makefile 2014-04-05 00:42:29.000000000 +0200
|+++ ./unit-tests/include/common.makefile 2014-09-11 00:24:46.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
2 out of 2 hunks ignored
patching file unit-tests/test-cases/alias-basic/aliases.s
@ -540,8 +552,8 @@ The text leading up to this was:
|--- ../ld64-236.3/unit-tests/test-cases/alias-objects/aliases.s 2014-04-05 00:42:29.000000000 +0200
|+++ ./unit-tests/test-cases/alias-objects/aliases.s 2014-09-11 00:24:46.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
can't find file to patch at input line 3668
@ -552,8 +564,8 @@ The text leading up to this was:
|--- ../ld64-236.3/unit-tests/test-cases/alias-objects/Makefile 2014-04-05 00:42:29.000000000 +0200
|+++ ./unit-tests/test-cases/alias-objects/Makefile 2014-09-11 00:24:46.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
2 out of 2 hunks ignored
patching file unit-tests/test-cases/alt-entry/foo.c
@ -596,8 +608,8 @@ The text leading up to this was:
|--- ../ld64-236.3/unit-tests/test-cases/section-labels/main.c 2014-04-05 00:42:29.000000000 +0200
|+++ ./unit-tests/test-cases/section-labels/main.c 2014-09-11 00:24:46.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored
patching file unit-tests/test-cases/symbol-section-move/main.c
@ -613,7 +625,7 @@ The text leading up to this was:
|--- ../ld64-236.3/unit-tests/test-cases/weak_import-undefined/Makefile 2014-04-05 00:42:29.000000000 +0200
|+++ ./unit-tests/test-cases/weak_import-undefined/Makefile 2014-09-11 00:24:46.000000000 +0200
--------------------------
File to patch:
Skip this patch? [y]
File to patch:
Skip this patch? [y]
Skipping patch.
1 out of 1 hunk ignored

View File

@ -1,6 +1,6 @@
# Apple cctools port for Linux, *BSD and Windows (Cygwin) #
Current Version: 877.5 + ld64-253.9.
Current Version: 877.8 + ld64-253.9.
Originally ported by [cjacker](http://ios-toolchain-based-on-clang-for-linux.googlecode.com).
## SUPPORTED HOSTS ##

View File

@ -1,4 +1,4 @@
AC_INIT([cctools], [877.5], [t.poechtrager@gmail.com])
AC_INIT([cctools], [877.8], [t.poechtrager@gmail.com])
AC_CANONICAL_BUILD
AC_CANONICAL_HOST

View File

@ -300,6 +300,7 @@ struct load_command {
#define LC_ENCRYPTION_INFO_64 0x2C /* 64-bit encrypted segment information */
#define LC_LINKER_OPTION 0x2D /* linker options in MH_OBJECT files */
#define LC_LINKER_OPTIMIZATION_HINT 0x2E /* optimization hints in MH_OBJECT files */
#define LC_VERSION_MIN_TVOS 0x2F /* build for AppleTV min OS version */
#define LC_VERSION_MIN_WATCHOS 0x30 /* build for Watch min OS version */
/*
@ -1202,8 +1203,9 @@ struct encryption_info_command_64 {
*/
struct version_min_command {
uint32_t cmd; /* LC_VERSION_MIN_MACOSX or
LC_VERSION_MIN_IPHONEOS
LC_VERSION_MIN_WATCHOS */
LC_VERSION_MIN_IPHONEOS or
LC_VERSION_MIN_WATCHOS or
LC_VERSION_MIN_TVOS */
uint32_t cmdsize; /* sizeof(struct min_version_command) */
uint32_t version; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */
uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */

View File

@ -27,6 +27,7 @@
#include <signal.h>
#include <sys/wait.h>
#include <sys/file.h>
#include <errno.h>
#include "stuff/errors.h"
#include "stuff/allocate.h"
#include "stuff/execute.h"
@ -71,7 +72,10 @@ int verbose)
return(1); /* can't get here, removes a warning from the compiler */
}
else{
waitpid = wait(&waitstatus);
waitpid = -1;
do{
waitpid = wait(&waitstatus);
} while (waitpid == -1 && errno == EINTR);
if(waitpid == -1)
system_fatal("wait on forked process %d failed", forkpid);
#ifndef __OPENSTEP__

View File

@ -4204,6 +4204,26 @@ check_linkedit_data_command:
}
break;
case LC_VERSION_MIN_TVOS:
if(l.cmdsize < sizeof(struct version_min_command)){
Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
" cmdsize too small) in command %u",i);
goto return_bad;
}
if(vers != NULL){
Mach_O_error(ofile, "malformed object (more than one "
"LC_VERSION_MIN_ command)");
goto return_bad;
}
vers = (struct version_min_command *)lc;
if(swapped)
swap_version_min_command(vers, host_byte_sex);
if(vers->cmdsize < sizeof(struct version_min_command)){
Mach_O_error(ofile, "malformed object (LC_VERSION_MIN_"
" command %u has too small cmdsize field)", i);
goto return_bad;
}
break;
case LC_VERSION_MIN_WATCHOS:
if(l.cmdsize < sizeof(struct version_min_command)){

View File

@ -1171,6 +1171,15 @@ check_dylinker_command:
}
break;
case LC_VERSION_MIN_TVOS:
vc = (struct version_min_command *)lc;
if(vc->cmdsize != sizeof(struct version_min_command)){
error("in swap_object_headers(): malformed load commands "
"(LC_VERSION_MIN_ command %lu has incorrect "
"cmdsize", i);
return(FALSE);
}
break;
case LC_VERSION_MIN_WATCHOS:
vc = (struct version_min_command *)lc;
@ -1760,6 +1769,7 @@ check_dylinker_command:
case LC_VERSION_MIN_MACOSX:
case LC_VERSION_MIN_IPHONEOS:
case LC_VERSION_MIN_WATCHOS:
case LC_VERSION_MIN_TVOS:
vc = (struct version_min_command *)lc;
swap_version_min_command(vc, target_byte_sex);
break;

View File

@ -23,11 +23,13 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libc.h>
#include "stuff/bool.h"
#include "stuff/errors.h"
#include "stuff/breakout.h"
#include "stuff/allocate.h"
#include "stuff/rnd.h"
#include "stuff/execute.h"
/* used by error routines as the name of the program */
char *progname = NULL;
@ -35,6 +37,7 @@ char *progname = NULL;
static enum bool rflag = FALSE; /* remove bitcode segment */
static enum bool mflag = FALSE; /* remove bitcode but leave a marker segment */
static enum bool lflag = FALSE; /* leave only bitcode segment */
static enum bool vflag = FALSE; /* to print internal commands that are run */
/*
* We shortcut bitcode_strip(1) to do nothing with the -r option when there is
@ -53,14 +56,17 @@ static void process(
static enum bool check_object(
struct arch *arch,
struct member *member,
struct object *object);
static void strip_bitcode_segment(
struct arch *arch,
struct member *member,
struct object *object);
static void leave_just_bitcode_segment(
struct arch *arch,
struct member *member,
struct object *object);
static void strip_bitcode_from_load_commands(
@ -75,6 +81,20 @@ static void reset_pointers_for_object_load_commands(
struct arch *arch,
struct object *object);
static void make_ld_process_mh_object(
struct arch *arch,
struct member *member,
struct object *object);
static void make_ld_r_object(
struct arch *arch,
struct object *object);
static void setup_symbolic_info_for_mh_object(
struct arch *arch,
struct member *member,
struct object *object);
/*
* The bitcode_strip(1) program takes one of two options:
* -r remove the bitcode segment
@ -132,6 +152,9 @@ char **envp)
}
mflag = TRUE;
}
else if(strcmp(argv[i], "-v") == 0){
vflag = TRUE;
}
else{
if(input != NULL){
error("more than one input file specified (%s and %s)",
@ -157,13 +180,26 @@ char **envp)
process(archs, narchs);
/*
* We shortcut bitcode_strip(1) to do nothing with the -r option when
* there is no bitcode and the input file is the same as the output
* file.
* We shortcut bitcode_strip(1) with the -r option when there is no
* bitcode.
*/
if(rflag && some_slice_has_bitcode == FALSE &&
strcmp(input, output) == 0)
if(rflag && some_slice_has_bitcode == FALSE){
/* If the input file is the same as the output file do nothing. */
if(strcmp(input, output) == 0)
return(EXIT_SUCCESS);
/*
* Otherwise cp(1) the input to the output to not mess up the
* code signature
*/
reset_execute_list();
add_execute_list("/bin/cp");
add_execute_list(input);
add_execute_list(output);
if(execute_list(vflag) == 0)
fatal("internal /bin/cp command failed");
return(EXIT_SUCCESS);
}
writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL);
@ -197,28 +233,25 @@ struct arch *archs,
uint32_t narchs)
{
uint32_t i;
#ifdef ALLOW_ARCHIVES
uint32_t j, offset, size;
#endif
struct object *object;
for(i = 0; i < narchs; i++){
if(archs[i].type == OFILE_ARCHIVE){
#ifndef ALLOW_ARCHIVES
error_arch(archs + i, NULL, "input file must be a linked "
"Mach-O file not an archive: ");
return;
#else /* defined(ALLOW_ARCHIVES) */
for(j = 0; j < archs[i].nmembers; j++){
if(archs[i].members[j].type == OFILE_Mach_O){
object = archs[i].members[j].object;
if(check_object(archs + i, object) == FALSE)
if(check_object(archs + i, archs[i].members + j,
object) == FALSE)
return;
if(rflag || (object->seg_bitcode == NULL &&
object->seg_bitcode64 == NULL))
strip_bitcode_segment(archs + i, object);
if(rflag || mflag)
strip_bitcode_segment(archs + i,
archs[i].members + j, object);
else
leave_just_bitcode_segment(archs + i, object);
leave_just_bitcode_segment(archs + i,
archs[i].members + j,
object);
}
}
/*
@ -230,13 +263,18 @@ uint32_t narchs)
size = 0;
if(archs[i].members[j].member_long_name == TRUE){
size = rnd(archs[i].members[j].member_name_size,
sizeof(int32_t));
sizeof(int64_t));
size = rnd(archs[i].members[j].member_name_size, 8) +
(rnd(sizeof(struct ar_hdr), 8) -
sizeof(struct ar_hdr));
archs[i].toc_long_name = TRUE;
}
if(archs[i].members[j].object != NULL){
size += archs[i].members[j].object->object_size
- archs[i].members[j].object->input_sym_info_size
+ archs[i].members[j].object->output_sym_info_size;
size +=
rnd(archs[i].members[j].object->object_size -
archs[i].members[j].object->input_sym_info_size +
archs[i].members[j].object->output_sym_info_size,
8);
sprintf(archs[i].members[j].ar_hdr->ar_size, "%-*ld",
(int)sizeof(archs[i].members[j].ar_hdr->ar_size),
(long)(size));
@ -253,17 +291,15 @@ uint32_t narchs)
offset += sizeof(struct ar_hdr) + size;
}
archs[i].library_size = offset;
#endif /* defined(ALLOW_ARCHIVES) */
}
else if(archs[i].type == OFILE_Mach_O){
object = archs[i].object;
if(check_object(archs +i, object) == FALSE)
if(check_object(archs + i, NULL, object) == FALSE)
return;
if(rflag || mflag || (object->seg_bitcode == NULL &&
object->seg_bitcode64 == NULL))
strip_bitcode_segment(archs + i, object);
if(rflag || mflag)
strip_bitcode_segment(archs + i, NULL, object);
else
leave_just_bitcode_segment(archs + i, object);
leave_just_bitcode_segment(archs + i, NULL, object);
}
}
}
@ -271,15 +307,16 @@ uint32_t narchs)
/*
* check_object() checks to make sure the object is one that can processed for
* stripping the bitcode segment or just leaving only the bitcode segment.
* This must be a fully linked Mach-O file for use with the dynamic linker.
* And if built for the Watch OS it must have a bitcode segment.
* And the bitcode segment must not have any relocation entries or symbols
* defined it its sections. And its sections must be of type S_REGULAR.
* If not a .o file this must be a fully linked Mach-O file for use with the
* dynamic linker. And the bitcode segment must not have any relocation
* entries or symbols defined it its sections. And its sections must be of
* type S_REGULAR.
*/
static
enum bool
check_object(
struct arch *arch,
struct member *member,
struct object *object)
{
uint32_t i, mh_ncmds, mh_flags;
@ -295,19 +332,19 @@ struct object *object)
sg64 = NULL; /* cctools-port */
if(arch->object->mh != NULL){
mh_ncmds = arch->object->mh->ncmds;
if(object->mh != NULL){
mh_ncmds = object->mh->ncmds;
mh_flags = object->mh->flags;
}
else{
mh_ncmds = arch->object->mh64->ncmds;
mh_ncmds = object->mh64->ncmds;
mh_flags = object->mh64->flags;
}
if((mh_flags & MH_DYLDLINK) != MH_DYLDLINK)
fatal_arch(arch, NULL, "can't be used on a file not built for use "
"with the dynamic linker: ");
if(object->mh_filetype != MH_OBJECT &&
(mh_flags & MH_DYLDLINK) != MH_DYLDLINK)
fatal_arch(arch, member, "can't be used on a file not built for "
"use with the dynamic linker: ");
/*
* If it has a bitcode segment it can't have any relocation entries.
@ -329,7 +366,7 @@ struct object *object)
if(object->seg_bitcode != NULL || object->seg_bitcode64 != NULL){
section_ordinal = 1;
first_bitcode_section_ordinal = 0;
lc = arch->object->load_commands;
lc = object->load_commands;
for(i = 0; i < mh_ncmds && first_bitcode_section_ordinal == 0; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
@ -338,7 +375,7 @@ struct object *object)
last_bitcode_section_ordinal = section_ordinal +
sg->nsects;
}
section_ordinal += sg64->nsects;
section_ordinal += sg->nsects;
}
else if(lc->cmd == LC_SEGMENT_64){
sg64 = (struct segment_command_64 *)lc;
@ -359,8 +396,8 @@ struct object *object)
if((symbols[i].n_type & N_TYPE) == N_SECT &&
symbols[i].n_sect >= first_bitcode_section_ordinal &&
symbols[i].n_sect < last_bitcode_section_ordinal){
fatal_arch(arch, NULL, "bitcode segment can't have "
"symbols defined it its sections in: ");
fatal_arch(arch, member, "bitcode segment can't "
"have symbols defined it its sections in: ");
}
}
}
@ -372,8 +409,8 @@ struct object *object)
symbols64[i].n_sect >=
first_bitcode_section_ordinal &&
symbols64[i].n_sect < last_bitcode_section_ordinal){
fatal_arch(arch, NULL, "bitcode segment can't have "
"symbols defined it its sections in: ");
fatal_arch(arch, member, "bitcode segment can't "
"have symbols defined it its sections in: ");
}
}
}
@ -389,7 +426,7 @@ struct object *object)
sizeof(struct segment_command));
for(i = 0; i < object->seg_bitcode->nsects; i++){
if((s->flags & SECTION_TYPE) != S_REGULAR)
fatal_arch(arch, NULL, "bitcode segment can't have "
fatal_arch(arch, member, "bitcode segment can't have "
"sections that are not of type S_REGULAR in: ");
s++;
}
@ -399,7 +436,7 @@ struct object *object)
sizeof(struct segment_command_64));
for(i = 0; i < object->seg_bitcode64->nsects; i++){
if((s64->flags & SECTION_TYPE) != S_REGULAR)
fatal_arch(arch, NULL, "bitcode segment can't have "
fatal_arch(arch, member, "bitcode segment can't have "
"sections that are not of type S_REGULAR in: ");
s64++;
}
@ -414,8 +451,8 @@ struct object *object)
#if 0
if(lflag == TRUE &&
object->seg_bitcode == NULL && object->seg_bitcode64 == NULL)
fatal_arch(arch, NULL, "-l to leave only bitcode segment can't be "
"used on a file without a __LLVM segment: ");
fatal_arch(arch, member, "-l to leave only bitcode segment can't "
"be used on a file without a __LLVM segment: ");
#endif
return(TRUE);
@ -440,6 +477,7 @@ static
void
strip_bitcode_segment(
struct arch *arch,
struct member *member,
struct object *object)
{
uint32_t start_offset, offset, end_of_string_table, alignment_padding;
@ -454,6 +492,17 @@ struct object *object)
segalign = 0; /* cctools-port */
/*
* For MH_OBJECT files, .o files, the bitcode info is in two sections
* and requires a static link editor operation to remove or change to
* a marker. So to do this an ld(1) -r is run with an option to
* process the object file as needed.
*/
if(object->mh_filetype == MH_OBJECT){
make_ld_process_mh_object(arch, member, object);
return;
}
/*
* If we are removing the bitcode segment and leaving just a marker
* calculate a minimum sized segment contents with all zeros which
@ -911,6 +960,7 @@ static
void
leave_just_bitcode_segment(
struct arch *arch,
struct member *member,
struct object *object)
{
uint32_t i, start_offset, offset, sect_offset;
@ -920,6 +970,16 @@ struct object *object)
struct section *s;
struct section_64 *s64;
/*
* For MH_OBJECT files, .o files there is no static link editor
* operation to just leave the bitcode. So this is a hard error.
*/
if(object->mh_filetype == MH_OBJECT) {
fatal_arch(arch, member, "Can't use the -l option on .o files "
"(filetypes of MH_OBJECT) for: ");
return;
}
/*
* To get the right amount of the start of the file copied out by
* writeout() before the symbolic information for this case when we
@ -942,8 +1002,8 @@ struct object *object)
*/
if(object->mh != NULL){
start_offset = 0;
lc = arch->object->load_commands;
for(i = 0; i < arch->object->mh->ncmds && start_offset == 0; i++){
lc = object->load_commands;
for(i = 0; i < object->mh->ncmds && start_offset == 0; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
if(sg->filesize != 0 && sg->fileoff == 0){
@ -982,8 +1042,8 @@ struct object *object)
}
else{
start_offset = 0;
lc = arch->object->load_commands;
for(i = 0; i < arch->object->mh64->ncmds && start_offset == 0; i++){
lc = object->load_commands;
for(i = 0; i < object->mh64->ncmds && start_offset == 0; i++){
if(lc->cmd == LC_SEGMENT_64){
sg64 = (struct segment_command_64 *)lc;
if(sg64->filesize != 0 && sg64->fileoff == 0){
@ -1194,13 +1254,13 @@ struct object *object)
* Allocate space for the new load commands and zero it out so any holes
* will be zero bytes.
*/
if(arch->object->mh != NULL){
mh_ncmds = arch->object->mh->ncmds;
mh_sizeofcmds = arch->object->mh->sizeofcmds;
if(object->mh != NULL){
mh_ncmds = object->mh->ncmds;
mh_sizeofcmds = object->mh->sizeofcmds;
}
else{
mh_ncmds = arch->object->mh64->ncmds;
mh_sizeofcmds = arch->object->mh64->sizeofcmds;
mh_ncmds = object->mh64->ncmds;
mh_sizeofcmds = object->mh64->sizeofcmds;
}
new_load_commands = allocate(mh_sizeofcmds);
memset(new_load_commands, '\0', mh_sizeofcmds);
@ -1211,7 +1271,7 @@ struct object *object)
* Unless the -m flag is specified then do copy the bitcode segment
* load command.
*/
lc1 = arch->object->load_commands;
lc1 = object->load_commands;
lc2 = new_load_commands;
new_ncmds = 0;
new_sizeofcmds = 0;
@ -1248,16 +1308,16 @@ struct object *object)
* Finally copy the updated load commands over the existing load
* commands.
*/
memcpy(arch->object->load_commands, new_load_commands, new_sizeofcmds);
memcpy(object->load_commands, new_load_commands, new_sizeofcmds);
if(mh_sizeofcmds > new_sizeofcmds)
memset((char *)arch->object->load_commands + new_sizeofcmds,
memset((char *)object->load_commands + new_sizeofcmds,
'\0', (mh_sizeofcmds - new_sizeofcmds));
if(arch->object->mh != NULL) {
arch->object->mh->sizeofcmds = new_sizeofcmds;
arch->object->mh->ncmds = new_ncmds;
if(object->mh != NULL) {
object->mh->sizeofcmds = new_sizeofcmds;
object->mh->ncmds = new_ncmds;
} else {
arch->object->mh64->sizeofcmds = new_sizeofcmds;
arch->object->mh64->ncmds = new_ncmds;
object->mh64->sizeofcmds = new_sizeofcmds;
object->mh64->ncmds = new_ncmds;
}
free(new_load_commands);
@ -1297,13 +1357,13 @@ struct object *object)
* Allocate space for the new load commands and zero it out so any holes
* will be zero bytes.
*/
if(arch->object->mh != NULL){
mh_ncmds = arch->object->mh->ncmds;
mh_sizeofcmds = arch->object->mh->sizeofcmds;
if(object->mh != NULL){
mh_ncmds = object->mh->ncmds;
mh_sizeofcmds = object->mh->sizeofcmds;
}
else{
mh_ncmds = arch->object->mh64->ncmds;
mh_sizeofcmds = arch->object->mh64->sizeofcmds;
mh_ncmds = object->mh64->ncmds;
mh_sizeofcmds = object->mh64->sizeofcmds;
}
new_load_commands = allocate(mh_sizeofcmds);
memset(new_load_commands, '\0', mh_sizeofcmds);
@ -1313,7 +1373,7 @@ struct object *object)
* LC_DYLIB_CODE_SIGN_DRS. For the segment commands other than the
* bitcode segment and linkedit segment zero out the fields.
*/
lc1 = arch->object->load_commands;
lc1 = object->load_commands;
lc2 = new_load_commands;
new_ncmds = 0;
new_sizeofcmds = 0;
@ -1386,16 +1446,16 @@ struct object *object)
* Finally copy the updated load commands over the existing load
* commands.
*/
memcpy(arch->object->load_commands, new_load_commands, new_sizeofcmds);
memcpy(object->load_commands, new_load_commands, new_sizeofcmds);
if(mh_sizeofcmds > new_sizeofcmds)
memset((char *)arch->object->load_commands + new_sizeofcmds,
memset((char *)object->load_commands + new_sizeofcmds,
'\0', (mh_sizeofcmds - new_sizeofcmds));
if(arch->object->mh != NULL) {
arch->object->mh->sizeofcmds = new_sizeofcmds;
arch->object->mh->ncmds = new_ncmds;
if(object->mh != NULL) {
object->mh->sizeofcmds = new_sizeofcmds;
object->mh->ncmds = new_ncmds;
} else {
arch->object->mh64->sizeofcmds = new_sizeofcmds;
arch->object->mh64->ncmds = new_ncmds;
object->mh64->sizeofcmds = new_sizeofcmds;
object->mh64->ncmds = new_ncmds;
}
free(new_load_commands);
@ -1426,40 +1486,40 @@ struct object *object)
struct segment_command *sg;
struct segment_command_64 *sg64;
if(arch->object->mh != NULL)
mh_ncmds = arch->object->mh->ncmds;
if(object->mh != NULL)
mh_ncmds = object->mh->ncmds;
else
mh_ncmds = arch->object->mh64->ncmds;
mh_ncmds = object->mh64->ncmds;
/* reset the pointers into the load commands */
lc = arch->object->load_commands;
lc = object->load_commands;
for(i = 0; i < mh_ncmds; i++){
switch(lc->cmd){
case LC_SYMTAB:
arch->object->st = (struct symtab_command *)lc;
object->st = (struct symtab_command *)lc;
break;
case LC_DYSYMTAB:
arch->object->dyst = (struct dysymtab_command *)lc;
object->dyst = (struct dysymtab_command *)lc;
break;
case LC_TWOLEVEL_HINTS:
arch->object->hints_cmd = (struct twolevel_hints_command *)lc;
object->hints_cmd = (struct twolevel_hints_command *)lc;
break;
case LC_PREBIND_CKSUM:
arch->object->cs = (struct prebind_cksum_command *)lc;
object->cs = (struct prebind_cksum_command *)lc;
break;
case LC_SEGMENT:
sg = (struct segment_command *)lc;
if(strcmp(sg->segname, SEG_LINKEDIT) == 0)
arch->object->seg_linkedit = sg;
object->seg_linkedit = sg;
else if(strcmp(sg->segname, "__LLVM") == 0)
arch->object->seg_bitcode = sg;
object->seg_bitcode = sg;
break;
case LC_SEGMENT_64:
sg64 = (struct segment_command_64 *)lc;
if(strcmp(sg64->segname, SEG_LINKEDIT) == 0)
arch->object->seg_linkedit64 = sg64;
object->seg_linkedit64 = sg64;
else if(strcmp(sg64->segname, "__LLVM") == 0)
arch->object->seg_bitcode64 = sg64;
object->seg_bitcode64 = sg64;
break;
case LC_SEGMENT_SPLIT_INFO:
object->split_info_cmd = (struct linkedit_data_command *)lc;
@ -1489,3 +1549,385 @@ struct object *object)
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
}
/*
* For MH_OBJECT files, .o files, the bitcode info is in two sections and
* requires a static link editor operation to remove or change to a marker.
* So to do this an ld(1) -r is run with an option to process the object file
* as needed.
*/
static
void
make_ld_process_mh_object(
struct arch *arch,
struct member *member,
struct object *object)
{
/*
* We set this so the optimizations of doing nothing or of copying over
* the input to the output does not happen. See the code at the end
* of main() above.
*/
if(rflag)
some_slice_has_bitcode = TRUE;
make_ld_r_object(arch, object);
setup_symbolic_info_for_mh_object(arch, member, object);
}
/*
* make_ld_r_object() takes the object file contents referenced by the passed
* data structures, writes that to a temporary file. Then runs "ld -r" plus an
* option to get the bitcode removed or replaced with a marker creating a second
* temporary file. This is then read in and replaces the object file contents
* with that.
*/
static
void
make_ld_r_object(
struct arch *arch,
struct object *object)
{
enum byte_sex host_byte_sex;
char *input_file, *output_file;
int fd;
struct ofile *ld_r_ofile;
struct arch *ld_r_archs;
uint32_t ld_r_narchs, save_errors;
host_byte_sex = get_host_byte_sex();
/*
* Swap the object file back into its bytesex before writing it to the
* temporary file if needed.
*/
if(object->object_byte_sex != host_byte_sex){
if(object->mh != NULL){
if(swap_object_headers(object->mh, object->load_commands) ==
FALSE)
fatal("internal error: swap_object_headers() failed");
}
else{
if(swap_object_headers(object->mh64, object->load_commands) ==
FALSE)
fatal("internal error: swap_object_headers() failed");
}
}
/*
* Create an input object file for the ld -r command from the bytes
* of this arch's object file.
*/
input_file = makestr("/tmp/bitcode_strip.XXXXXX", NULL);
input_file = mktemp(input_file);
if((fd = open(input_file, O_WRONLY|O_CREAT, 0600)) < 0)
system_fatal("can't open temporary file: %s", input_file);
if(write(fd, object->object_addr, object->object_size) !=
object->object_size)
system_fatal("can't write temporary file: %s", input_file);
if(close(fd) == -1)
system_fatal("can't close temporary file: %s", input_file);
/*
* Create a temporary name for the output file of the ld -r
*/
output_file = makestr("/tmp/bitcode_strip.XXXXXX", NULL);
output_file = mktemp(output_file);
/*
* Create the ld -r command line and execute it.
*/
reset_execute_list();
add_execute_list_with_prefix("ld");
add_execute_list("-keep_private_externs");
add_execute_list("-r");
if(rflag){
add_execute_list("-bitcode_process_mode");
add_execute_list("strip");
}
else if(mflag){
add_execute_list("-bitcode_process_mode");
add_execute_list("marker");
}
add_execute_list(input_file);
add_execute_list("-o");
add_execute_list(output_file);
if(execute_list(vflag) == 0)
fatal("internal link edit command failed");
save_errors = errors;
errors = 0;
/* breakout the output file of the ld -f for processing */
ld_r_ofile = breakout(output_file, &ld_r_archs, &ld_r_narchs, FALSE);
if(errors)
goto make_ld_r_object_cleanup;
/* checkout the file for processing */
checkout(ld_r_archs, ld_r_narchs);
/*
* Make sure the output of the ld -r is an object file with one arch.
*/
if(ld_r_narchs != 1 ||
ld_r_archs->type != OFILE_Mach_O ||
ld_r_archs->object == NULL ||
ld_r_archs->object->mh_filetype != MH_OBJECT)
fatal("internal link edit command failed to produce a thin Mach-O "
"object file");
/*
* Copy over the object struct from the ld -r object file onto the
* input object file.
*/
*object = *ld_r_archs->object;
/*
* Save the ofile struct for the ld -r output so it can be umapped when
* we are done. And free up the ld_r_archs now that we are done with
* them.
*/
object->ld_r_ofile = ld_r_ofile;
free_archs(ld_r_archs, ld_r_narchs);
make_ld_r_object_cleanup:
errors += save_errors;
/*
* Remove the input and output files and clean up.
*/
if(unlink(input_file) == -1)
system_fatal("can't remove temporary file: %s", input_file);
if(unlink(output_file) == -1)
system_fatal("can't remove temporary file: %s", output_file);
free(input_file);
free(output_file);
}
/*
* setup_symbolic_info_for_mh_object() is called after a .o file has been
* modified as needed by an "ld -r" execution. Here the symbolic info and
* sizes are set into the object struct. So it can be later written out by
* the writeout() call. No processing is done here just setting up the object
* struct's input_sym_info_size and output_sym_info_size value and all the
* output_* fields and offsets to the symbolic info so it is written out
* correctly.
*/
static
void
setup_symbolic_info_for_mh_object(
struct arch *arch,
struct member *member,
struct object *object)
{
uint32_t offset, start_offset;
/*
* Determine the starting offset of the symbolic info in the .o file
* which can be determined because of the order symbolic info has
* already been confirmed when the by previous call to checkout().
* This this routine only deals with MH_OBJECT filetypes so some info
* should not be present in .o files which is consider an error here.
*/
offset = UINT_MAX;
/* There should be no link edit segment in a .o file. */
if(object->seg_linkedit != NULL || object->seg_linkedit64 != NULL)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain a "
"link edit segment");
if(object->dyst != NULL && object->dyst->nlocrel != 0)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain "
"local relocation entries in the dynamic symbol table");
if(object->func_starts_info_cmd != NULL &&
object->func_starts_info_cmd->datasize != 0 &&
object->func_starts_info_cmd->dataoff < offset)
offset = object->func_starts_info_cmd->dataoff;
if(object->data_in_code_cmd != NULL &&
object->data_in_code_cmd->datasize != 0 &&
object->data_in_code_cmd->dataoff < offset)
offset = object->data_in_code_cmd->dataoff;
if(object->link_opt_hint_cmd != NULL &&
object->link_opt_hint_cmd->datasize != 0 &&
object->link_opt_hint_cmd->dataoff < offset)
offset = object->link_opt_hint_cmd->dataoff;
if(object->st->nsyms != 0 &&
object->st->symoff < offset)
offset = object->st->symoff;
if(object->dyst != NULL && object->dyst->nextrel != 0)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain "
"external relocation entries in the dynamic symbol "
"table");
if(object->dyst != NULL &&
object->dyst->nindirectsyms != 0 &&
object->dyst->indirectsymoff < offset)
offset = object->dyst->indirectsymoff;
if(object->dyst != NULL && object->dyst->ntoc)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain "
"toc entries in the dynamic symbol table");
if(object->dyst != NULL && object->dyst->nmodtab != 0)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain "
"module entries in the dynamic symbol table");
if(object->dyst != NULL && object->dyst->nextrefsyms != 0)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain "
"external reference entries in the dynamic symbol "
"table");
if(object->st->strsize != 0 &&
object->st->stroff < offset)
offset = object->st->stroff;
start_offset = offset;
/*
* Size the input symbolic info and set up all the input symbolic info
* to be the output symbolic info except any code signature data which
* will be removed if the input file contains bitcode of we are leaving
* just bitcode.
*
* Assign the offsets to the symbolic data in the proper order and
* increment the local variable offset by the size of each part if the
* the symbolic data. The output_sym_info_size is then determined at
* the end as the difference of the local variable offset from the
* local variable start_offset.
*/
object->input_sym_info_size = 0;
object->output_sym_info_size = 0;
/* There should be no dyld info in a .o file. */
if(object->dyld_info != NULL)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain a "
"dyld info");
/* Local relocation entries off the dynamic symbol table would next in
the output, but there are not in .o files */
/* There should be no split info in a .o file. */
if(object->split_info_cmd != NULL)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain a "
"split info load command");
if(object->func_starts_info_cmd != NULL){
object->input_sym_info_size +=
object->func_starts_info_cmd->datasize;
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->func_starts_info_cmd->dataoff = offset;
offset += object->func_starts_info_cmd->datasize;
}
if(object->data_in_code_cmd != NULL){
object->input_sym_info_size +=
object->data_in_code_cmd->datasize;
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->data_in_code_cmd->dataoff = offset;
offset += object->data_in_code_cmd->datasize;
}
if(object->code_sign_drs_cmd != NULL)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain a "
"code signature load command");
if(object->link_opt_hint_cmd != NULL){
object->input_sym_info_size +=
object->link_opt_hint_cmd->datasize;
object->output_link_opt_hint_info_data = object->object_addr +
object->link_opt_hint_cmd->dataoff;
object->output_link_opt_hint_info_data_size =
object->link_opt_hint_cmd->datasize;
object->link_opt_hint_cmd->dataoff = offset;
offset += object->link_opt_hint_cmd->datasize;
}
if(object->st != NULL && object->st->nsyms != 0){
if(object->mh != NULL){
object->input_sym_info_size +=
object->st->nsyms * sizeof(struct nlist);
object->output_symbols = (struct nlist *)
(object->object_addr + object->st->symoff);
if(object->object_byte_sex != get_host_byte_sex())
swap_nlist(object->output_symbols,
object->st->nsyms,
get_host_byte_sex());
object->output_symbols64 = NULL;
}
else{
object->input_sym_info_size +=
object->st->nsyms * sizeof(struct nlist_64);
object->output_symbols64 = (struct nlist_64 *)
(object->object_addr + object->st->symoff);
if(object->object_byte_sex != get_host_byte_sex())
swap_nlist_64(object->output_symbols64,
object->st->nsyms,
get_host_byte_sex());
object->output_symbols = NULL;
}
object->output_nsymbols = object->st->nsyms;
object->st->symoff = offset;
if(object->mh != NULL)
offset += object->st->nsyms * sizeof(struct nlist);
else
offset += object->st->nsyms * sizeof(struct nlist_64);
}
else if(object->st != NULL && object->st->nsyms == 0)
object->st->symoff = 0;
if(object->hints_cmd != NULL)
fatal_arch(arch, member, "malformed MH_OBJECT should not contain a "
"two level hints load command");
// Note that this should always be true in objects this program
// operates on as it does not need to work on staticly linked images.
if(object->dyst != NULL){
object->output_ilocalsym = object->dyst->ilocalsym;
object->output_nlocalsym = object->dyst->nlocalsym;
object->output_iextdefsym = object->dyst->iextdefsym;
object->output_nextdefsym = object->dyst->nextdefsym;
object->output_iundefsym = object->dyst->iundefsym;
object->output_nundefsym = object->dyst->nundefsym;
/* External relocation entries off the dynamic symbol table would
next in the output, but there are not in .o files */
if(object->dyst->nindirectsyms != 0){
object->input_sym_info_size +=
object->dyst->nindirectsyms * sizeof(uint32_t) +
object->input_indirectsym_pad;
object->output_indirect_symtab = (uint32_t *)
(object->object_addr + object->dyst->indirectsymoff);
object->dyst->indirectsymoff = offset;
offset += object->dyst->nindirectsyms * sizeof(uint32_t) +
object->input_indirectsym_pad;
}
else
object->dyst->indirectsymoff = 0;
/* Toc entries off the dynamic symbol table would
next in the output, but there are not in .o files */
/* Module entries off the dynamic symbol table would
next in the output, but there are not in .o files */
/* External references off the dynamic symbol table would
next in the output, but there are not in .o files */
}
if(object->st != NULL && object->st->strsize != 0){
object->input_sym_info_size += object->st->strsize;
object->output_strings = object->object_addr + object->st->stroff;
object->output_strings_size = object->st->strsize;
object->st->stroff = offset;
offset += object->st->strsize;
}
else{
object->st->stroff = 0;
}
/* The code signature would next in the output, but that is is not in
.o files */
object->output_sym_info_size = offset - start_offset;
}

View File

@ -767,6 +767,7 @@ void *cookie) /* cookie is not used */
uint32_t nloh;
struct dyld_bind_info *dbi;
uint64_t ndbi;
uint64_t big_size;
sorted_symbols = NULL;
nsorted_symbols = 0;
@ -1038,11 +1039,24 @@ void *cookie) /* cookie is not used */
/*
* Load commands.
*/
if(mh_sizeofcmds + sizeof_mach_header > size){
big_size = mh_sizeofcmds;
big_size += sizeof_mach_header;
if(big_size > size){
/*
* For malformed binaries trim the mh_sizeofcmds to be no bigger
* than the size of the file after the mach_header. This will
* limit the printing of the unknown load commands so it does not
* appear to be in an infinite loop printing the zero's we created
* with the memset().
*/
if(size > sizeof_mach_header)
mh_sizeofcmds = size - sizeof_mach_header;
else
mh_sizeofcmds = sizeof(struct load_command);
load_commands = allocate(mh_sizeofcmds);
memset(load_commands, '\0', mh_sizeofcmds);
memcpy(load_commands, ofile->load_commands,
size - sizeof_mach_header);
if(size > sizeof_mach_header)
memcpy(load_commands, ofile->load_commands, mh_sizeofcmds);
ofile->load_commands = load_commands;
}
if(lflag)

View File

@ -2293,6 +2293,7 @@ enum bool very_verbose)
case LC_VERSION_MIN_MACOSX:
case LC_VERSION_MIN_IPHONEOS:
case LC_VERSION_MIN_WATCHOS:
case LC_VERSION_MIN_TVOS:
memset((char *)&vd, '\0', sizeof(struct version_min_command));
size = left < sizeof(struct version_min_command) ?
left : sizeof(struct version_min_command);
@ -3504,6 +3505,8 @@ struct version_min_command *vd)
printf(" cmd LC_VERSION_MIN_IPHONEOS\n");
else if(vd->cmd == LC_VERSION_MIN_WATCHOS)
printf(" cmd LC_VERSION_MIN_WATCHOS\n");
else if(vd->cmd == LC_VERSION_MIN_TVOS)
printf(" cmd LC_VERSION_MIN_TVOS\n");
else
printf(" cmd %u (?)\n", vd->cmd);
printf(" cmdsize %u", vd->cmdsize);
@ -6043,7 +6046,7 @@ enum bool swapped)
uint32_t left, *state, i, j;
left = end - begin;
if(left * sizeof(uint32_t) >= count){
if(left / sizeof(uint32_t) >= count){
state = allocate(count * sizeof(uint32_t));
memcpy((char *)state, begin, count * sizeof(uint32_t));
begin += count * sizeof(uint32_t);

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash
BASE_VERSION=870
NEW_VERSION=877.5
BASE_VERSION=877.5
NEW_VERSION=877.8
set -e