From d699a01fabaa04a1aad60f6ca5777f82ee24839a Mon Sep 17 00:00:00 2001 From: Jay Freeman Date: Sun, 6 Apr 2008 10:28:29 +0000 Subject: Drastic, sweeping modifications to support iPhone 1.2.0/2.0. git-svn-id: http://svn.telesphoreo.org/trunk@199 514c082c-b64e-11dc-b46d-3d985efe055d --- util/catdir.sh | 4 +- util/collect2 | 54 ++++++++++ util/configure.sh | 2 +- util/find.sh | 31 ++++++ util/ldid.cpp | 297 +++++++++++++++++++++++++++++++++++++++++++++++++++ util/libtool.diff | 6 +- util/libtool.m4.diff | 11 ++ util/pkg-config.sh | 64 ++++++++++- util/uname | 12 --- util/uname.sh | 12 +++ 10 files changed, 473 insertions(+), 20 deletions(-) create mode 100755 util/collect2 create mode 100755 util/find.sh create mode 100644 util/ldid.cpp create mode 100644 util/libtool.m4.diff delete mode 100755 util/uname create mode 100755 util/uname.sh (limited to 'util') diff --git a/util/catdir.sh b/util/catdir.sh index dd10be199..b23b94125 100755 --- a/util/catdir.sh +++ b/util/catdir.sh @@ -1,3 +1,3 @@ #!/bin/bash -find -H "$1" -type l -printf '%p -> %l\n' | sort -find -H "$1" -type f -print0 | sort -z | xargs -0 cat +find -H "$@" -type l -printf '%p -> %l\n' -o -printf '%p (%U/%G/%#m)\n' | sort +find -H "$@" -type f -print0 | sort -z | xargs -0 cat diff --git a/util/collect2 b/util/collect2 new file mode 100755 index 000000000..30cacb773 --- /dev/null +++ b/util/collect2 @@ -0,0 +1,54 @@ +#!/bin/bash + +unset GCC_EXEC_PREFIX +unset COMPILER_PATH + +unset aspen_version_min +unset macosx_version_min +unset o + +#export | grep 'GCC\|PATH\|PKG' + +function parse() { + while [[ $# -ne 0 ]]; do + if [[ $1 = -maspen-version-min=* ]]; then + maspen_version_min=${1#-maspen-version-min=} + elif [[ $1 = -mmacosx-version-min=* ]]; then + mmacosx_version_min=${1#-mmacosx-version-min=} + elif [[ $1 == -o ]]; then + o=$2 + shift + fi; shift + done +} + +set -e + +eval "parse ${COLLECT_GCC_OPTIONS}" + +if [[ "${maspen_version_min+@}" || "${mmacosx_version_min+@}" ]]; then + darwin= +else + unset darwin +fi + +declare -a flags +if [[ "${darwin+@}" ]]; then + flags[${#flags[@]}]=-no_uuid + + if [[ "${PKG_PATH+@}" ]]; then + flags=("${flags[@]}"$(echo "${PKG_PATH}:" | while read -r -d ':' path; do + find "${path}" -name '*.dylib' -print0 | while read -r -d $'\0' dylib_file; do + dylib_name=${dylib_file#${path}} + echo " -dylib_file ${dylib_name}:${dylib_file}" + done + done)) + fi +fi + +#echo ::: "$("${COLLECT_GCC}" -print-prog-name=collect2)" "$@" "${flags[@]}" +"$("${COLLECT_GCC}" -print-prog-name=collect2)" "$@" "${flags[@]}" + +if [[ "${o+@}" && "${darwin+@}" ]]; then + ldid -T- "$o" +fi diff --git a/util/configure.sh b/util/configure.sh index 1a7efc6b0..162ea207c 100755 --- a/util/configure.sh +++ b/util/configure.sh @@ -7,4 +7,4 @@ if [[ -z $PKG_CONF ]]; then PKG_CONF=./configure fi -PKG_ROOT=/home/saurik/iphone/sysroot PKG_CONFIG="$(realpath ../../../util/pkg-config.sh) --define-variable=prefix=/home/saurik/iphone/sysroot/usr" PKG_CONFIG_PATH=/home/saurik/iphone/sysroot/usr/lib/pkgconfig $PKG_CONF --prefix=/usr --host=arm-apple-darwin --enable-static=no --enable-shared=yes "$@" +PKG_ROOT=/home/saurik/iphone/sysroot PKG_CONFIG="$(realpath ../../../util/pkg-config.sh) --define-variable=prefix=/home/saurik/iphone/sysroot/usr" PKG_CONFIG_PATH=/home/saurik/iphone/sysroot/usr/lib/pkgconfig $PKG_CONF --prefix=/usr --host=arm-apple-darwin8 --enable-static=no --enable-shared=yes "$@" diff --git a/util/find.sh b/util/find.sh new file mode 100755 index 000000000..d45bea76b --- /dev/null +++ b/util/find.sh @@ -0,0 +1,31 @@ +#!/bin/bash + +#echo 1>&2 +#echo ::: find.sh "$@" 1>&2 + +while [[ $# -ne 0 ]]; do + if [[ $1 == /* ]]; then + unset found + + found=$(echo "${PKG_PATH}:" | while read -r -d ':' path; do + if [[ -e ${path}$1 ]]; then + if [[ ${found+@} ]]; then + echo -n ':' + else + found= + fi + + echo -n "${path}$1" + fi + done) + + #echo "=== ${found:=$1}" 1>&2 + echo "${found:=$1}" + else + echo "$1" + fi + + shift +done + +#echo 1>&2 diff --git a/util/ldid.cpp b/util/ldid.cpp new file mode 100644 index 000000000..b1c114a8c --- /dev/null +++ b/util/ldid.cpp @@ -0,0 +1,297 @@ +/* JocStrap - Java/Objective-C Bootstrap + * Copyright (C) 2007 Jay Freeman (saurik) +*/ + +/* + * Redistribution and use in source and binary + * forms, with or without modification, are permitted + * provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the + * above copyright notice, this list of conditions + * and the following disclaimer. + * 2. Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions + * and the following disclaimer in the documentation + * and/or other materials provided with the + * distribution. + * 3. The name of the author may not be used to endorse + * or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "minimal/stdlib.h" +#include "minimal/mapping.h" + +#include +#include +#include + +struct fat_header { + uint32_t magic; + uint32_t nfat_arch; +}; + +#define FAT_MAGIC 0xcafebabe +#define FAT_CIGAM 0xbebafeca + +struct fat_arch { + uint32_t cputype; + uint32_t cpusubtype; + uint32_t offset; + uint32_t size; + uint32_t align; +}; + +struct mach_header { + uint32_t magic; + uint32_t cputype; + uint32_t cpusubtype; + uint32_t filetype; + uint32_t ncmds; + uint32_t sizeofcmds; + uint32_t flags; +}; + +#define MH_MAGIC 0xfeedface +#define MH_CIGAM 0xcefaedfe + +#define MH_EXECUTE 0x2 +#define MH_DYLIB 0x6 +#define MH_BUNDLE 0x8 + +struct load_command { + uint32_t cmd; + uint32_t cmdsize; +}; + +#define LC_REQ_DYLD 0x80000000 + +#define LC_LOAD_DYLIB 0x0c +#define LC_ID_DYLIB 0x0d +#define LC_UUID 0x1b +#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) + +struct dylib { + uint32_t name; + uint32_t timestamp; + uint32_t current_version; + uint32_t compatibility_version; +}; + +struct dylib_command { + uint32_t cmd; + uint32_t cmdsize; + struct dylib dylib; +}; + +struct uuid_command { + uint32_t cmd; + uint32_t cmdsize; + uint8_t uuid[16]; +}; + +class Framework { + private: + void *base_; + size_t size_; + mach_header *mach_header_; + bool swapped_; + + public: + int16_t Swap(int16_t value) const { + return Swap(static_cast(value)); + } + + int32_t Swap(int32_t value) const { + return Swap(static_cast(value)); + } + + uint16_t Swap(uint16_t value) const { + return !swapped_ ? value : + ((value >> 8) & 0x00ff) | + ((value << 8) & 0xff00); + } + + uint32_t Swap(uint32_t value) const { + if (!swapped_) + return value; + else { + value = ((value >> 8) & 0x00ff00ff) | + ((value << 8) & 0xff00ff00); + value = ((value >> 16) & 0x0000ffff) | + ((value << 16) & 0xffff0000); + return value; + } + } + + Framework(const char *framework_path) : + swapped_(false) + { + base_ = map(framework_path, 0, _not(size_t), &size_, false); + fat_header *fat_header = reinterpret_cast(base_); + + if (Swap(fat_header->magic) == FAT_CIGAM) { + swapped_ = !swapped_; + goto fat; + } else if (Swap(fat_header->magic) != FAT_MAGIC) + mach_header_ = (mach_header *) base_; + else fat: { + size_t fat_narch = Swap(fat_header->nfat_arch); + fat_arch *fat_arch = reinterpret_cast(fat_header + 1); + size_t arch; + for (arch = 0; arch != fat_narch; ++arch) { + uint32_t arch_offset = Swap(fat_arch->offset); + mach_header_ = (mach_header *) ((uint8_t *) base_ + arch_offset); + goto found; + ++fat_arch; + } + + _assert(false); + } + + found: + if (Swap(mach_header_->magic) == MH_CIGAM) + swapped_ = !swapped_; + else _assert(Swap(mach_header_->magic) == MH_MAGIC); + + _assert( + Swap(mach_header_->filetype) == MH_EXECUTE || + Swap(mach_header_->filetype) == MH_DYLIB || + Swap(mach_header_->filetype) == MH_BUNDLE + ); + } + + void *GetBase() { + return base_; + } + + size_t GetSize() { + return size_; + } + + std::vector GetLoadCommands() { + std::vector load_commands; + + struct load_command *load_command = reinterpret_cast(mach_header_ + 1); + for (uint32_t cmd = 0; cmd != Swap(mach_header_->ncmds); ++cmd) { + load_commands.push_back(load_command); + load_command = (struct load_command *) ((uint8_t *) load_command + Swap(load_command->cmdsize)); + } + + return load_commands; + } +}; + +extern "C" uint32_t hash(uint8_t *k, uint32_t length, uint32_t initval); + +int main(int argc, const char *argv[]) { + bool flag_R(false); + bool flag_t(false); + bool flag_p(false); + bool flag_u(false); + + bool flag_T(false); + + bool timeh(false); + uint32_t timev(0); + + std::vector files; + + _assert(argc != 0); + for (int argi(1); argi != argc; ++argi) + if (argv[argi][0] != '-') + files.push_back(argv[argi]); + else switch (argv[argi][1]) { + case 'R': flag_R = true; break; + case 't': flag_t = true; break; + case 'u': flag_u = true; break; + case 'p': flag_p = true; break; + + case 'T': { + flag_T = true; + if (argv[argi][2] == '-') + timeh = true; + else { + char *arge; + timev = strtoul(argv[argi] + 2, &arge, 0); + _assert(arge == argv[argi] + strlen(argv[argi])); + } + } break; + + default: + goto usage; + break; + } + + if (files.empty()) usage: { + exit(0); + } + + size_t filei(0), filee(0); + _foreach (file, files) try { + Framework framework(file->c_str()); + + if (flag_p) + printf("path%zu='%s'\n", filei, file->c_str()); + + _foreach (load_command, framework.GetLoadCommands()) { + uint32_t cmd(framework.Swap((*load_command)->cmd)); + + if (flag_R && cmd == LC_REEXPORT_DYLIB) + (*load_command)->cmd = framework.Swap(LC_LOAD_DYLIB); + else if (cmd == LC_UUID) { + volatile struct uuid_command *uuid_command(reinterpret_cast(*load_command)); + + if (flag_u) { + printf("uuid%zu=%.2x%.2x%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x-%.2x%.2x%.2x%.2x%.2x%.2x\n", filei, + uuid_command->uuid[ 0], uuid_command->uuid[ 1], uuid_command->uuid[ 2], uuid_command->uuid[ 3], + uuid_command->uuid[ 4], uuid_command->uuid[ 5], uuid_command->uuid[ 6], uuid_command->uuid[ 7], + uuid_command->uuid[ 8], uuid_command->uuid[ 9], uuid_command->uuid[10], uuid_command->uuid[11], + uuid_command->uuid[12], uuid_command->uuid[13], uuid_command->uuid[14], uuid_command->uuid[15] + ); + } + } else if (cmd == LC_ID_DYLIB) { + volatile struct dylib_command *dylib_command(reinterpret_cast(*load_command)); + + if (flag_t) + printf("time%zu=0x%.8x\n", filei, framework.Swap(dylib_command->dylib.timestamp)); + + if (flag_T) { + uint32_t timed; + + if (!timeh) + timed = timev; + else { + dylib_command->dylib.timestamp = 0; + timed = hash(reinterpret_cast(framework.GetBase()), framework.GetSize(), timev); + } + + dylib_command->dylib.timestamp = framework.Swap(timed); + } + } + } + + ++filei; + } catch (const char *) { + ++filee; + ++filei; + } + + return filee; +} diff --git a/util/libtool.diff b/util/libtool.diff index a3b4513ee..59e210084 100644 --- a/util/libtool.diff +++ b/util/libtool.diff @@ -5,7 +5,7 @@ continue ;; - *.la) lib="$deplib" ;; -+ *.la) if [[ ${deplib:0:1} == '/' ]]; then lib="$PKG_ROOT$deplib"; else lib="$deplib"; fi ;; ++ *.la) lib="$("${PKG_BASE}/util/find.sh" "$deplib")" ;; *.$libext) if test "$pass" = conv; then deplibs="$deplib $deplibs" @@ -14,7 +14,7 @@ path="$absdir/$objdir" else - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` -+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $PKG_ROOT$deplib` ++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' "$("${PKG_BASE}/util/find.sh" "$deplib")"` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE @@ -23,7 +23,7 @@ *.la) name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` - eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` -+ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' $PKG_ROOT$deplib` ++ eval libdir=`${SED} -n -e 's/^libdir=\(.*\)$/\1/p' "$("${PKG_BASE}/util/find.sh" "$deplib")"` if test -z "$libdir"; then $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 exit $EXIT_FAILURE diff --git a/util/libtool.m4.diff b/util/libtool.m4.diff new file mode 100644 index 000000000..ac837e4fc --- /dev/null +++ b/util/libtool.m4.diff @@ -0,0 +1,11 @@ +--- m4/libtool.m4 2005-07-29 13:31:15.000000000 +0000 ++++ m4/libtool.m4_ 2008-03-28 15:05:28.000000000 +0000 +@@ -1267,7 +1267,7 @@ + shrext_cmds='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if test "$GCC" = yes; then +- sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` ++ sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g"` + else + sys_lib_search_path_spec='/lib /usr/lib /usr/local/lib' + fi diff --git a/util/pkg-config.sh b/util/pkg-config.sh index d9e64d22d..22d2815b3 100755 --- a/util/pkg-config.sh +++ b/util/pkg-config.sh @@ -1,3 +1,63 @@ #!/bin/bash -echo "$@" | grep -- --atleast >/dev/null && exit 0 -exec pkg-config "$@" + +#echo 1>&2 +#echo ::: "$@" 1>&2 + +declare -a args +declare -a pkgs +unset dbpf + +while [[ $# -ne 0 ]]; do case "$1" in + (--atleast-pkgconfig-version) + exec pkg-config "$1" "$2" + ;; + + (--cflags|--libs|--variable=*) + dbpf= + args[${#args[@]}]=$1 + ;; + + (--errors-to-stdout|--exists|--modversion|--print-errors|--short-errors|--uninstalled) + args[${#args[@]}]=$1 + ;; + + (--atleast-version|--exact-version|--max-version) + args[${#args[@]}]=$1 + args[${#args[@]}]=$2 + shift + ;; + + (--*) + echo "unknown pkg-config option $1" 1>&2 + exit 1 + ;; + + (*) + pkgs[${#pkgs[@]}]=$1 + ;; +esac; shift; done + +if [[ ${dbpf+@} ]]; then + source "${PKG_BASE}/folders.sh" +fi + +outs= +for pkg in "${pkgs[@]}"; do + args_=("${args[@]}") + + if [[ ${dbpf+@} ]]; then + dest=$(for dep in $(find -L "${PKG_DATA}"/_metadata -name '*.dep' | cut -d '/' -f -); do + DEP_NAME=$(basename "${dep}" .dep) + DEP_DEST=$(PKG_DEST_ "${DEP_NAME}") + + find "${DEP_DEST}" -name "${pkg}.pc" -printf "${DEP_DEST}\n" + done) && args_=(--define-variable=prefix="${dest}/usr" "${args_[@]}") + fi + + #echo @@@ pkg-config "${args_[@]}" "${pkg}" 1>&2 + out=$(pkg-config "${args_[@]}" "${pkg}") || exit $? + #echo "=== ${out}" 1>&2 + outs+=\ ${out} +done + +echo "${out#\ }" diff --git a/util/uname b/util/uname deleted file mode 100755 index db07673fc..000000000 --- a/util/uname +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash -OPTIND=1 -while getopts mnprsv OPTKEY; do - case $OPTKEY in - (m) echo 'iPhone1,1';; - (n) echo 'transponder';; - (p) echo 'unknown';; - (r) echo '9.0.0d1';; - (s) echo 'Darwin';; - (v) echo 'Darwin Kernel Version 9.0.0d1: Wed Sep 19 00:08:43 PDT 2007; root:xnu-933.0.0.203.obj~21/RELEASE_ARM_S5L8900XRB';; - esac -done diff --git a/util/uname.sh b/util/uname.sh new file mode 100755 index 000000000..db07673fc --- /dev/null +++ b/util/uname.sh @@ -0,0 +1,12 @@ +#!/bin/bash +OPTIND=1 +while getopts mnprsv OPTKEY; do + case $OPTKEY in + (m) echo 'iPhone1,1';; + (n) echo 'transponder';; + (p) echo 'unknown';; + (r) echo '9.0.0d1';; + (s) echo 'Darwin';; + (v) echo 'Darwin Kernel Version 9.0.0d1: Wed Sep 19 00:08:43 PDT 2007; root:xnu-933.0.0.203.obj~21/RELEASE_ARM_S5L8900XRB';; + esac +done -- cgit v1.2.3