411954 I know how to strip a binary's symbol table of all non-global symbols except for text symbols. I also know how to strip LC_CODE_SIGNATURE load commands once they've been added. Introducing striptease. r=smorgan r=ardissone
411954 I know how to strip a binary's symbol table of all non-global symbols except for text symbols. I also know how to strip LC_CODE_SIGNATURE load commands once they've been added. Introducing striptease. r=smorgan r=ardissone
--- a/Makefile.in
+++ b/Makefile.in
@@ -42,16 +42,17 @@ topsrcdir = @top_srcdir@
srcdir = @srcdir@
VPATH = @srcdir@
include $(DEPTH)/config/autoconf.mk
DIRS = \
flashblock \
idl \
+ striptease \
$(NULL)
APP_NAME = Camino
RSYNC_ALL = rsync -aC --exclude .cvsignore --delete
CM_APP_VERSION_FILE = $(srcdir)/config/version.txt
CM_APP_VERSION := $(shell cat $(CM_APP_VERSION_FILE))
new file mode 100644
--- /dev/null
+++ b/striptease/Makefile.in
@@ -0,0 +1,97 @@
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is just a lowly Makefile.
+#
+# The Initial Developer of the Original Code is Google Inc.
+# Portions created by the Initial Developer are Copyright (C) 2008
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+# Mark Mentovai <mark@moxienet.com> (Original Author)
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either the GNU General Public License Version 2 or later (the "GPL"), or
+# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+LIBSTUFF_CSRCS = \
+ libstuff/allocate.c \
+ libstuff/arch.c \
+ libstuff/arch_usage.c \
+ libstuff/breakout.c \
+ libstuff/bytesex.c \
+ libstuff/checkout.c \
+ libstuff/crc32.c \
+ libstuff/errors.c \
+ libstuff/fatal_arch.c \
+ libstuff/fatals.c \
+ libstuff/get_arch_from_host.c \
+ libstuff/ofile.c \
+ libstuff/ofile_error.c \
+ libstuff/print.c \
+ libstuff/reloc.c \
+ libstuff/round.c \
+ libstuff/set_arch_flag_name.c \
+ libstuff/swap_headers.c \
+ libstuff/symbol_list.c \
+ libstuff/unix_standard_mode.c \
+ libstuff/writeout.c \
+ $(NULL)
+
+# It's possible to build strip (the unmodified original version) or tease
+# (the enahnced version) by changing the value of this variable.
+STRIP_OR_TEASE = tease
+
+# Build tease (or strip) as a host program because we only care about running
+# it on the build host. It doesn't need to be built for the target
+# architecture.
+HOST_PROGRAM = $(STRIP_OR_TEASE)
+HOST_CFLAGS += -I$(srcdir)/include
+HOST_CSRCS = \
+ $(STRIP_OR_TEASE).c \
+ $(LIBSTUFF_CSRCS) \
+ $(NULL)
+
+# config/rules.mk has a simpler transformation to derive HOST_OBJS from
+# HOST_CSRCS. It simply prepends host_ to each name. That winds up
+# referencing the host_libstuff directory, which does not exist. This
+# transformation splits each proposed object into its dirname and basename,
+# prepending host_ only to the basename.
+HOST_OBJS = $(foreach obj, \
+ $(HOST_CSRCS:.c=.$(OBJ_SUFFIX)), \
+ $(dir $(obj))$(addprefix host_,$(notdir $(obj))))
+
+# Be sure there's a place to put libstuff objects in an objdir build.
+ifneq ($(ABS_topsrcdir),$(MOZ_BUILD_ROOT))
+libs::
+ mkdir -p libstuff
+endif
+
+include $(topsrcdir)/config/rules.mk
new file mode 100644
--- /dev/null
+++ b/striptease/README
@@ -0,0 +1,36 @@
+striptease (or "tease" for short) is an enhanced version of strip. It's
+capable of stripping a binary's symbol table of non-text local symbols.
+This mode, enabled with the -t switch, is similar to "strip -s", except
+-s strips all local symbols including text symbols. tease -t allows for
+useful CrashReporter stacks to be generated on the deployment host. This
+is important in light of the hidden-visibility default (-fvisibility=hidden)
+that results in many symbols not being marked as global and therefore being
+stripped by an ordinary strip -s.
+
+tease also includes a -no_code_signature option, which strips any
+LC_CODE_SIGNATURE load commands from the target file, in much the same way
+as the ordinary strip's -no_uuid option.
+
+Finally, tease includes an -a option, which instructs it to regenerate the
+symbol table without stripping anything. tease -a is intended to be used
+in conjunction with -no_code_signature (or -no_uuid), to pass over the file
+and only strip the relevant Mach-O load commands without removing anything
+from the symbol table.
+
+striptease is based on strip.c and other supporting files in Apple's
+cctools package. This version of striptease is based on cctools-667.3,
+corresponding to Xcode Tools 3.0 and Mac OS X 10.5.0. It builds properly
+under Xcode Tools 2.x on Mac OS X 10.4, as well. The cctools package is
+available from:
+
+http://www.opensource.apple.com/darwinsource/tarballs/apsl/cctools-667.3.tar.gz
+
+cctools, and therefore strip, are available under the APSL license:
+
+http://www.opensource.apple.com/apsl/
+
+All files from cctools necessary to build strip are included, unmodified.
+This includes strip.c. Changes to strip.c are made in tease.c. Many other
+files from the cctools package not relevant to strip (or tease) are omitted
+from this distribution. This README and an accompanying Makefile.in for
+build system integration are also included.
new file mode 100644
--- /dev/null
+++ b/striptease/include/architecture/m88k/fp_regs.h
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
+ *
+ * File: architecture/m88k/fp_regs.h
+ * Author: Mike DeMoney, NeXT Computer, Inc.
+ *
+ * This include file defines Motorola 88K architecturally defined
+ * floating point control and status registers.
+ *
+ * HISTORY
+ * 23-Jan-91 Mike DeMoney (mike@next.com)
+ * Created.
+ */
+
+#ifndef _ARCH_M88K_FP_REGS_H_
+#define _ARCH_M88K_FP_REGS_H_
+
+#import <architecture/m88k/reg_help.h>
+
+/*
+ * m88k_xrf_t -- data types that MAY be in extended register file
+ * Actual data types supported is implementation dependent
+ */
+typedef union {
+ float f; // 32 bit IEEE single
+ double d; // 64 bit IEEE double
+ /*
+ * NOTE: currently compiler implements long double type
+ * simply as double. In the future, it may implement
+ * this as 80 bit IEEE double extended or 128 bit IEEE quad
+ * as appropriate for the 88K implementation.
+ */
+ long double e; // 80 or 128 bit IEEE format
+ /* Insure compiler aligns struct appropriately */
+#ifdef __GNUC__
+ unsigned x[4] __attribute__(( aligned(16) ));
+#else
+ unsigned x[4];
+#endif
+} m88k_xrf_t;
+
+/*
+ * FPSR -- Floating Point Status Register
+ */
+typedef struct {
+ unsigned :BITS_WIDTH(31,17);
+ unsigned xmod:BIT_WIDTH(16); // extended registers modified
+ unsigned :BITS_WIDTH(15,5);
+ unsigned afinv:BIT_WIDTH(4); // accumulated invalid flag
+ unsigned afdvz:BIT_WIDTH(3); // accumulated div by zero flag
+ unsigned afunf:BIT_WIDTH(2); // accumulated underflow flag
+ unsigned afovf:BIT_WIDTH(1); // accumulated overflow flag
+ unsigned afinx:BIT_WIDTH(0); // accumulated inexact flag
+} m88k_fpsr_t;
+
+/*
+ * FPCR -- Floating Point Control Register
+ * 88K architecturally specified form.
+ * Does not expose implementation-dependent functions
+ */
+typedef enum {
+ M88K_RM_NEAREST = 0, // round toward nearest
+ M88K_RM_ZERO = 1, // round toward zero
+ M88K_RM_NEGINF = 2, // round toward negative infinity
+ M88K_RM_POSINF =3 // round toward positive infinity
+} m88k_fpcr_rm_t;
+
+typedef struct {
+ unsigned :BITS_WIDTH(31,16);
+ m88k_fpcr_rm_t rm:BITS_WIDTH(15,14); // rounding mode
+ unsigned :BITS_WIDTH(13,5);
+ unsigned efinv:BIT_WIDTH(4); // invalid exception enable
+ unsigned efdvz:BIT_WIDTH(3); // div by zero exception enable
+ unsigned efunf:BIT_WIDTH(2); // underflow exception enable
+ unsigned efovf:BIT_WIDTH(1); // overflow exception enable
+ unsigned efinx:BIT_WIDTH(0); // inexact exception enable
+} m88k_fpcr_t;
+
+/*
+ * FPCR -- Floating Point Control Register
+ * 88110 implementation -- includes "TCFP" features.
+ */
+typedef struct {
+ unsigned :BITS_WIDTH(31,22);
+ unsigned tcfp:BIT_WIDTH(21); // def results for INF/NaN
+ unsigned :BITS_WIDTH(20,19);
+ unsigned tcfpunf:BIT_WIDTH(18); // underflow -> zero
+ unsigned tcfpovf:BIT_WIDTH(17); // overflow -> inf
+ unsigned :BIT_WIDTH(16);
+ m88k_fpcr_rm_t rm:BITS_WIDTH(15,14); // rounding mode
+ unsigned :BITS_WIDTH(13,5);
+ unsigned efinv:BIT_WIDTH(4); // invalid exception enable
+ unsigned efdvz:BIT_WIDTH(3); // div by zero exception enable
+ unsigned efunf:BIT_WIDTH(2); // underflow exception enable
+ unsigned efovf:BIT_WIDTH(1); // overflow exception enable
+ unsigned efinx:BIT_WIDTH(0); // inexact exception enable
+} m88110_fpcr_t;
+
+#ifdef m88k
+#ifndef __STRICT_ANSI__
+/*
+ * read and write fpsr and fpcr registers
+ *
+ * FIXME: When the compiler is fixed, convert to style of inlines shown
+ * in m88110_sfu0.h which do not use either CONTENTS() macro or
+ * *(foo_t *)& casts (and therefore, don't force the compiler to generate
+ * a memory reference.
+ */
+static __inline__ m88k_fpsr_t m88k_get_fpsr()
+{
+ unsigned cr_tmp;
+
+ __asm__ volatile ("fldcr %0,fcr62 ; get_fpsr()" : "=r" (cr_tmp));
+ return *(m88k_fpsr_t *)&cr_tmp;
+}
+
+static __inline__ void m88k_set_fpsr(m88k_fpsr_t fpsr_val)
+{
+ /*
+ * Must force xmod to 1, since OS uses this to determine
+ * if XRF must be context switched. Not setting to 1
+ * will NOT corrupt other threads registers, but will
+ * result in loss of this threads register values.
+ */
+ fpsr_val.xmod = 1;
+ __asm__ volatile ("fstcr %0,fcr62 ; set_fpsr()"
+ : : "r" (CONTENTS(fpsr_val)));
+}
+
+static __inline__ m88k_fpcr_t m88k_get_fpcr()
+{
+ unsigned cr_tmp;
+
+ __asm__ volatile ("fldcr %0,fcr63 ; get_fpcr()" : "=r" (cr_tmp));
+ return *(m88k_fpcr_t *)&cr_tmp;
+}
+
+static __inline__ void m88k_set_fpcr(m88k_fpcr_t fpcr_val)
+{
+ __asm__ volatile ("fstcr %0,fcr63 ; set_fpcr()"
+ : : "r" (CONTENTS(fpcr_val)));
+}
+#endif /* __STRICT_ANSI__ */
+#endif /* m88k */
+
+#endif /* _ARCH_M88K_FP_REGS_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/architecture/m88k/reg_help.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
+ *
+ * File: architecture/m88k/reg_help.h
+ * Author: Mike DeMoney, NeXT Computer, Inc.
+ *
+ * This header file defines cpp macros useful for defining
+ * machine register and doing machine-level operations.
+ *
+ * HISTORY
+ * 23-Jan-91 Mike DeMoney (mike@next.com)
+ * Created.
+ */
+
+#ifndef _ARCH_M88K_REG_HELP_H_
+#define _ARCH_M88K_REG_HELP_H_
+
+#import <architecture/nrw/reg_help.h>
+
+/* Stack pointer must always be a multiple of 16 */
+#define STACK_INCR 16
+#define ROUND_FRAME(x) ((((unsigned)(x)) + STACK_INCR - 1) & ~(STACK_INCR-1))
+
+/*
+ * REG_PAIR_DEF -- define a register pair
+ * Register pairs are appropriately aligned to allow access via
+ * ld.d and st.d.
+ *
+ * Usage:
+ * struct foo {
+ * REG_PAIR_DEF(
+ * bar_t *, barp,
+ * afu_t, afu
+ * );
+ * };
+ *
+ * Access to individual entries of the pair is via the REG_PAIR
+ * macro (below).
+ */
+#define REG_PAIR_DEF(type0, name0, type1, name1) \
+ struct { \
+ type0 name0 __attribute__(( aligned(8) )); \
+ type1 name1; \
+ } name0##_##name1
+
+/*
+ * REG_PAIR -- Macro to define names for accessing individual registers
+ * of register pairs.
+ *
+ * Usage:
+ * arg0 is first element of pair
+ * arg1 is second element of pair
+ * arg2 is desired element of pair
+ * eg:
+ * #define foo_barp REG_PAIR(barp, afu, afu)
+ */
+#define REG_PAIR(name0, name1, the_name) \
+ name0##_##name1.the_name
+
+#endif /* _ARCH_M88K_REG_HELP_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/architecture/nrw/reg_help.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
+ *
+ * File: architecture/nrw/reg_help.h
+ * Author: Mike DeMoney, NeXT Computer, Inc.
+ *
+ * This header file defines cpp macros useful for defining
+ * machine register and doing machine-level operations.
+ *
+ * HISTORY
+ * 23-Jan-91 Mike DeMoney (mike@next.com)
+ * Created.
+ */
+
+#ifndef _NRW_REG_HELP_H_
+#define _NRW_REG_HELP_H_
+
+/* Bitfield definition aid */
+#define BITS_WIDTH(msb, lsb) ((msb)-(lsb)+1)
+#define BIT_WIDTH(pos) (1) /* mostly to record the position */
+
+/* Mask creation */
+#define MKMASK(width, offset) (((unsigned)-1)>>(32-(width))<<(offset))
+#define BITSMASK(msb, lsb) MKMASK(BITS_WIDTH(msb, lsb), lsb & 0x1f)
+#define BITMASK(pos) MKMASK(BIT_WIDTH(pos), pos & 0x1f)
+
+/* Register addresses */
+#if __ASSEMBLER__
+# define REG_ADDR(type, addr) (addr)
+#else /* __ASSEMBLER__ */
+# define REG_ADDR(type, addr) (*(volatile type *)(addr))
+#endif /* __ASSEMBLER__ */
+
+/* Cast a register to be an unsigned */
+#define CONTENTS(foo) (*(unsigned *) &(foo))
+
+/* STRINGIFY -- perform all possible substitutions, then stringify */
+#define __STR(x) #x /* just a helper macro */
+#define STRINGIFY(x) __STR(x)
+
+
+#endif /* _NRW_REG_HELP_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/architecture/sparc/reg.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* @(#)reg.h 1.16 92/04/28 SMI */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#ifndef _sparc_reg_h
+#define _sparc_reg_h
+
+/*
+ * Location of the users' stored
+ * registers relative to R0.
+ * Usage is u.u_ar0[XX].
+ */
+#define PSR (0)
+#define PC (1)
+#define nPC (2)
+#define SPARC_Y (3)
+#define G1 (4)
+#define G2 (5)
+#define G3 (6)
+#define G4 (7)
+#define G5 (8)
+#define G6 (9)
+#define G7 (10)
+#define O0 (11)
+#define O1 (12)
+#define O2 (13)
+#define O3 (14)
+#define O4 (15)
+#define O5 (16)
+#define O6 (17)
+#define O7 (18)
+
+/* the following defines are for portability */
+#define PS PSR
+#define SP O6
+#define R0 O0
+#define R1 O1
+
+/*
+ * And now for something completely the same...
+ */
+#ifndef __ASSEMBLER__
+struct regs {
+ int r_psr; /* processor status register */
+ int r_pc; /* program counter */
+ int r_npc; /* next program counter */
+ int r_y; /* the y register */
+ int r_g1; /* user global regs */
+ int r_g2;
+ int r_g3;
+ int r_g4;
+ int r_g5;
+ int r_g6;
+ int r_g7;
+ int r_o0;
+ int r_o1;
+ int r_o2;
+ int r_o3;
+ int r_o4;
+ int r_o5;
+ int r_o6;
+ int r_o7;
+};
+
+#define r_ps r_psr /* for portablility */
+#define r_r0 r_o0
+#define r_sp r_o6
+
+#endif /* !__ASSEMBLER__ */
+
+/*
+ * Floating point definitions.
+ */
+
+#define FPU /* we have an external float unit */
+
+#ifndef __ASSEMBLER__
+
+#define FQ_DEPTH 16 /* maximum instuctions in FQ */
+
+/*
+ * struct fpu_status is the floating point processor state
+ * struct fpu is the sum total of all possible floating point state
+ * which includes the state of external floating point hardware,
+ * fpa registers, etc..., if it exists.
+ */
+struct fpq {
+ unsigned long *addr; /* address */
+ unsigned long instr; /* instruction */
+};
+struct fq {
+ union { /* FPU inst/addr queue */
+ double whole;
+ struct fpq fpq;
+ } FQu;
+};
+
+
+#define FPU_REGS_TYPE unsigned
+#define FPU_FSR_TYPE unsigned
+
+struct fpu {
+ union { /* FPU floating point regs */
+ FPU_REGS_TYPE Fpu_regs[32]; /* 32 singles */
+ double Fpu_dregs[16]; /* 16 doubles */
+ } fpu_fr;
+ FPU_FSR_TYPE Fpu_fsr; /* FPU status register */
+ unsigned Fpu_flags; /* control flags */
+ unsigned Fpu_extra; /* extra word */
+ unsigned Fpu_qcnt; /* count of valid entries in fps_q */
+ struct fq Fpu_q[FQ_DEPTH]; /* FPU instruction address queue */
+};
+
+#define fpu_regs fpu_fr.Fpu_regs
+#define fpu_dregs fpu_fr.Fpu_dregs
+#define fpu_fsr Fpu_fsr
+#define fpu_flags Fpu_flags
+#define fpu_extra Fpu_extra
+#define fpu_q Fpu_q
+#define fpu_qcnt Fpu_qcnt
+
+#endif /* !__ASSEMBLER__ */
+
+
+/*
+ * Definition of bits in the Sun-4 FSR (Floating-point Status Register)
+ * ________________________________________________________________________
+ * | RD | RP | TEM | NS | res | vers | FTT | QNE | PR | FCC | AEXC | CEXC |
+ * |-----|---- |-----|----|-----|------|-----|-----|----|-----|------|------|
+ * 31 30 29 28 27 23 22 21 20 19 17 16 14 13 12 11 10 9 5 4 0
+ */
+#define FSR_CEXC 0x0000001f /* Current Exception */
+#define FSR_AEXC 0x000003e0 /* ieee accrued exceptions */
+#define FSR_FCC 0x00000c00 /* Floating-point Condition Codes */
+#define FSR_PR 0x00001000 /* Partial Remainder */
+#define FSR_QNE 0x00002000 /* Queue not empty */
+#define FSR_FTT 0x0001c000 /* Floating-point Trap Type */
+#define FSR_VERS 0x000e0000 /* version field */
+#define FSR_RESV 0x00300000 /* reserved */
+#define FSR_NS 0x00400000 /* non-standard fp */
+#define FSR_TEM 0x0f800000 /* ieee Trap Enable Mask */
+#define FSR_RP 0x30000000 /* Rounding Precision */
+#define FSR_RD 0xc0000000 /* Rounding Direction */
+
+#define FSR_VERS_SHIFT (17) /* amount to shift version field */
+
+/*
+ * Definition of CEXC (Current EXCeption) bit field of fsr
+ */
+#define FSR_CEXC_NX 0x00000001 /* inexact */
+#define FSR_CEXC_DZ 0x00000002 /* divide-by-zero */
+#define FSR_CEXC_UF 0x00000004 /* underflow */.
+#define FSR_CEXC_OF 0x00000008 /* overflow */
+#define FSR_CEXC_NV 0x00000010 /* invalid */
+
+/*
+ * Definition of AEXC (Accrued EXCeption) bit field of fsr
+ */
+#define FSR_AEXC_NX (0x1 << 5) /* inexact */
+#define FSR_AEXC_DZ (0x2 << 5) /* divide-by-zero */
+#define FSR_AEXC_UF (0x4 << 5) /* underflow */.
+#define FSR_AEXC_OF (0x8 << 5) /* overflow */
+#define FSR_AEXC_NV (0x10 << 5) /* invalid */
+
+/*
+ * Defintion of FTT (Floating-point Trap Type) field within the FSR
+ */
+#define FTT_NONE 0 /* no excepitons */
+#define FTT_IEEE 1 /* IEEE exception */
+#define FTT_UNFIN 2 /* unfinished fpop */
+#define FTT_UNIMP 3 /* unimplemented fpop */
+#define FTT_SEQ 4 /* sequence error */
+#define FTT_ALIGN 5 /* alignment, by software convention */
+#define FTT_DFAULT 6 /* data fault, by software convention */
+#define FSR_FTT_SHIFT 14 /* shift needed to justfy ftt field */
+#define FSR_FTT_IEEE (FTT_IEEE << FSR_FTT_SHIFT)
+#define FSR_FTT_UNFIN (FTT_UNFIN << FSR_FTT_SHIFT)
+#define FSR_FTT_UNIMP (FTT_UNIMP << FSR_FTT_SHIFT)
+#define FSR_FTT_SEQ (FTT_SEQ << FSR_FTT_SHIFT)
+#define FSR_FTT_ALIGN (FTT_ALIGN << FSR_FTT_SHIFT)
+#define FSR_FTT_DFAULT (FTT_DFAULT << FSR_FTT_SHIFT)
+
+/*
+ * Values of VERS (version) field within the FSR
+ * NOTE: these values are overloaded; the cpu type must be used to
+ * further discriminate amongst these. For that reason, no #defines are
+ * provided.
+ *
+ * Version cpu = 21-22, 51-54 cpu = 23-24, 55-57
+ * 0 Weitek 1164/5 (FAB 1-4) TI 8847
+ * 1 Weitek 1164/5 (FAB 5-6) LSI L64814
+ * 2 TI 8847 TI TMS390C602A
+ * 3 Weitek 3170 Weitek 3171
+ * 4 Meiko ?
+ * 5 ? ?
+ * 6 ? ?
+ * 7 No FP Hardware No FP Hardware
+ */
+
+
+/*
+ * Definition of TEM (Trap Enable Mask) bit field of fsr
+ */
+#define FSR_TEM_NX (0x1 << 23) /* inexact */
+#define FSR_TEM_DZ (0x2 << 23) /* divide-by-zero */
+#define FSR_TEM_UF (0x4 << 23) /* underflow */.
+#define FSR_TEM_OF (0x8 << 23) /* overflow */
+#define FSR_TEM_NV (0x10 << 23) /* invalid */
+
+/*
+ * Definition of RP (Rounding Precision) field of fsr
+ */
+#define RP_DBLEXT 0 /* double-extended */
+#define RP_SINGLE 1 /* single */
+#define RP_DOUBLE 2 /* double */
+#define RP_RESERVED 3 /* unused and reserved */
+
+/*
+ * Defintion of RD (Rounding Direction) field of fsr
+ */
+#define RD_NEAR 0 /* nearest or even if tie */
+#define RD_ZER0 1 /* to zero */
+#define RD_POSINF 2 /* positive infinity */
+#define RD_NEGINF 3 /* negative infinity */
+
+/*
+ * Definition of the FP enable flags of the pcb struct
+ * Normal operation, all flags are zero
+ */
+#define FP_UNINITIALIZED 1
+#define FP_STARTSIG 2
+#define FP_DISABLE 4
+#define FP_ENABLE 8
+
+#ifndef __ASSEMBLER__
+/*
+ * How a register window looks on the stack.
+ */
+struct rwindow {
+ int rw_local[8]; /* locals */
+ int rw_in[8]; /* ins */
+};
+
+#define rw_fp rw_in[6] /* frame pointer */
+#define rw_rtn rw_in[7] /* return address */
+
+#endif /* !__ASSEMBLER__ */
+
+
+/*
+ * Definition of bits in the Sun-4 PSR (Processor Status Register)
+ * ____________________________________________________________________
+ * | IMPL | VER | ICC | res | EC | EF | PIL | S | PS | ET | CWP |
+ * |-----------|-----|------|-----|----|----|-------|---|----|----|-----|
+ * 31 28 27 24 23 20 19 14 13 12 11 8 7 6 5 4 0
+ */
+
+
+struct p_status {
+ union {
+ unsigned int psr;
+ struct {
+ unsigned int
+ impl:4,
+ ver:4,
+ icc:4,
+ reserved:6,
+ ec:1,
+ ef:1,
+ pil:4,
+ s:1,
+ ps:1,
+ et:1,
+ cwp:5;
+ } psr_bits;
+ } PSRREG;
+};
+
+struct f_status {
+ union {
+ FPU_FSR_TYPE Fpu_fsr; /* FPU status register */
+ struct {
+ unsigned int
+ rd:2,
+ rp:2,
+ tem:5,
+ res:6,
+ ftt:3,
+ qne:1,
+ pr:1,
+ fcc:2,
+ aexc:5,
+ cexc:5;
+ } Fpu_fsr_bits;
+ } FPUREG;
+};
+
+#endif /*!_sparc_reg_h*/
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/dyld.h
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACH_O_DYLD_H_
+#define _MACH_O_DYLD_H_
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#include <mach-o/loader.h>
+#include <AvailabilityMacros.h>
+#ifndef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
+#define AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER
+#endif
+
+#ifndef ENUM_DYLD_BOOL
+#define ENUM_DYLD_BOOL
+#undef FALSE
+#undef TRUE
+enum DYLD_BOOL {
+ FALSE,
+ TRUE
+};
+#endif /* ENUM_DYLD_BOOL */
+
+/*
+ * The high level NS... API.
+ */
+
+/* Object file image API */
+typedef enum {
+ NSObjectFileImageFailure, /* for this a message is printed on stderr */
+ NSObjectFileImageSuccess,
+ NSObjectFileImageInappropriateFile,
+ NSObjectFileImageArch,
+ NSObjectFileImageFormat, /* for this a message is printed on stderr */
+ NSObjectFileImageAccess
+} NSObjectFileImageReturnCode;
+
+typedef void * NSObjectFileImage;
+
+/* limited implementation, only MH_BUNDLE files can be used */
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
+ const char *pathName,
+ NSObjectFileImage *objectFileImage);
+extern NSObjectFileImageReturnCode NSCreateCoreFileImageFromFile(
+ const char *pathName,
+ NSObjectFileImage *objectFileImage);
+/* not yet implemented */
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(
+ void *address,
+ unsigned long size,
+ NSObjectFileImage *objectFileImage);
+extern enum DYLD_BOOL NSDestroyObjectFileImage(
+ NSObjectFileImage objectFileImage);
+/*
+ * API on NSObjectFileImage's for:
+ * "for Each Symbol Definition In Object File Image" (for Dynamic Bundles)
+ * and the same thing for references
+ */
+extern unsigned long NSSymbolDefinitionCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+extern const char * NSSymbolDefinitionNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long ordinal);
+extern unsigned long NSSymbolReferenceCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+extern const char * NSSymbolReferenceNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long ordinal,
+ enum DYLD_BOOL *tentative_definition); /* can be NULL */
+/*
+ * API on NSObjectFileImage:
+ * "does Object File Image define symbol name X" (using sorted symbol table)
+ * and a way to get the named objective-C section
+ */
+extern enum DYLD_BOOL NSIsSymbolDefinedInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *symbolName);
+extern void * NSGetSectionDataInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *segmentName,
+ const char *sectionName,
+ unsigned long *size); /* can be NULL */
+/* SPI first appeared in Mac OS X 10.3 */
+extern enum DYLD_BOOL NSHasModInitObjectFileImage(
+ NSObjectFileImage objectFileImage)
+ AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+/* module API */
+typedef void * NSModule;
+extern const char * NSNameOfModule(
+ NSModule m);
+extern const char * NSLibraryNameForModule(
+ NSModule m);
+
+/* limited implementation, only MH_BUNDLE files can be linked */
+extern NSModule NSLinkModule(
+ NSObjectFileImage objectFileImage,
+ const char *moduleName,
+ unsigned long options);
+#define NSLINKMODULE_OPTION_NONE 0x0
+#define NSLINKMODULE_OPTION_BINDNOW 0x1
+#define NSLINKMODULE_OPTION_PRIVATE 0x2
+#define NSLINKMODULE_OPTION_RETURN_ON_ERROR 0x4
+#define NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES 0x8
+#define NSLINKMODULE_OPTION_TRAILING_PHYS_NAME 0x10
+
+/* limited implementation, only modules loaded with NSLinkModule() can be
+ unlinked */
+extern enum DYLD_BOOL NSUnLinkModule(
+ NSModule module,
+ unsigned long options);
+#define NSUNLINKMODULE_OPTION_NONE 0x0
+#define NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED 0x1
+#define NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES 0x2
+
+/* not yet implemented */
+extern NSModule NSReplaceModule(
+ NSModule moduleToReplace,
+ NSObjectFileImage newObjectFileImage,
+ unsigned long options);
+
+/* symbol API */
+typedef void * NSSymbol;
+extern enum DYLD_BOOL NSIsSymbolNameDefined(
+ const char *symbolName);
+extern enum DYLD_BOOL NSIsSymbolNameDefinedWithHint(
+ const char *symbolName,
+ const char *libraryNameHint);
+extern enum DYLD_BOOL NSIsSymbolNameDefinedInImage(
+ const struct mach_header *image,
+ const char *symbolName);
+extern NSSymbol NSLookupAndBindSymbol(
+ const char *symbolName);
+extern NSSymbol NSLookupAndBindSymbolWithHint(
+ const char *symbolName,
+ const char *libraryNameHint);
+extern NSSymbol NSLookupSymbolInModule(
+ NSModule module,
+ const char *symbolName);
+extern NSSymbol NSLookupSymbolInImage(
+ const struct mach_header *image,
+ const char *symbolName,
+ unsigned long options);
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND 0x0
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW 0x1
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY 0x2
+#define NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR 0x4
+extern const char * NSNameOfSymbol(
+ NSSymbol symbol);
+extern void * NSAddressOfSymbol(
+ NSSymbol symbol);
+extern NSModule NSModuleForSymbol(
+ NSSymbol symbol);
+
+/* error handling API */
+typedef enum {
+ NSLinkEditFileAccessError,
+ NSLinkEditFileFormatError,
+ NSLinkEditMachResourceError,
+ NSLinkEditUnixResourceError,
+ NSLinkEditOtherError,
+ NSLinkEditWarningError,
+ NSLinkEditMultiplyDefinedError,
+ NSLinkEditUndefinedError
+} NSLinkEditErrors;
+
+/*
+ * For the NSLinkEditErrors value NSLinkEditOtherError these are the values
+ * passed to the link edit error handler as the errorNumber (what would be an
+ * errno value for NSLinkEditUnixResourceError or a kern_return_t value for
+ * NSLinkEditMachResourceError).
+ */
+typedef enum {
+ NSOtherErrorRelocation,
+ NSOtherErrorLazyBind,
+ NSOtherErrorIndrLoop,
+ NSOtherErrorLazyInit,
+ NSOtherErrorInvalidArgs
+} NSOtherErrorNumbers;
+
+extern void NSLinkEditError(
+ NSLinkEditErrors *c,
+ int *errorNumber,
+ const char **fileName,
+ const char **errorString);
+
+typedef struct {
+ void (*undefined)(const char *symbolName);
+ NSModule (*multiple)(NSSymbol s, NSModule oldModule, NSModule newModule);
+ void (*linkEdit)(NSLinkEditErrors errorClass, int errorNumber,
+ const char *fileName, const char *errorString);
+} NSLinkEditErrorHandlers;
+
+extern void NSInstallLinkEditErrorHandlers(
+ NSLinkEditErrorHandlers *handlers);
+
+/* other API */
+extern enum DYLD_BOOL NSAddLibrary(
+ const char *pathName);
+extern enum DYLD_BOOL NSAddLibraryWithSearching(
+ const char *pathName);
+extern const struct mach_header * NSAddImage(
+ const char *image_name,
+ unsigned long options);
+#define NSADDIMAGE_OPTION_NONE 0x0
+#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
+#define NSADDIMAGE_OPTION_WITH_SEARCHING 0x2
+#define NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED 0x4
+#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
+extern long NSVersionOfRunTimeLibrary(
+ const char *libraryName);
+extern long NSVersionOfLinkTimeLibrary(
+ const char *libraryName);
+extern int _NSGetExecutablePath( /* SPI first appeared in Mac OS X 10.2 */
+ char *buf,
+ unsigned long *bufsize);
+
+/*
+ * The low level _dyld_... API.
+ * (used by the objective-C runtime primarily)
+ */
+extern unsigned long _dyld_present(
+ void);
+
+extern unsigned long _dyld_image_count(
+ void);
+#ifdef __LP64__
+extern struct mach_header_64 * _dyld_get_image_header(
+ uint32_t image_index);
+#else /* !defined(__LP64__) */
+extern struct mach_header * _dyld_get_image_header(
+ unsigned long image_index);
+#endif /* !defined(__LP64__) */
+extern unsigned long _dyld_get_image_vmaddr_slide(
+ unsigned long image_index);
+extern char * _dyld_get_image_name(
+ unsigned long image_index);
+
+extern void _dyld_register_func_for_add_image(
+ void (*func)(struct mach_header *mh, unsigned long vmaddr_slide));
+extern void _dyld_register_func_for_remove_image(
+ void (*func)(struct mach_header *mh, unsigned long vmaddr_slide));
+extern void _dyld_register_func_for_link_module(
+ void (*func)(NSModule module));
+/* not yet implemented */
+extern void _dyld_register_func_for_unlink_module(
+ void (*func)(NSModule module));
+/* not yet implemented */
+extern void _dyld_register_func_for_replace_module(
+ void (*func)(NSModule oldmodule, NSModule newmodule));
+extern void _dyld_get_objc_module_sect_for_module(
+ NSModule module,
+ void **objc_module,
+ unsigned long *size);
+extern void _dyld_bind_objc_module(
+ void *objc_module);
+extern enum DYLD_BOOL _dyld_bind_fully_image_containing_address(
+ unsigned long *address);
+extern enum DYLD_BOOL _dyld_image_containing_address(
+ unsigned long address);
+/* SPI first appeared in Mac OS X 10.3 */
+extern struct mach_header * _dyld_get_image_header_containing_address(
+ unsigned long address)
+ AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+extern void _dyld_moninit(
+ void (*monaddition)(char *lowpc, char *highpc));
+extern enum DYLD_BOOL _dyld_launched_prebound(
+ void);
+/* SPI first appeared in Mac OS X 10.3 */
+extern enum DYLD_BOOL _dyld_all_twolevel_modules_prebound(
+ void)
+ AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+extern void _dyld_lookup_and_bind(
+ const char *symbol_name,
+ unsigned long *address,
+ void **module);
+extern void _dyld_lookup_and_bind_with_hint(
+ const char *symbol_name,
+ const char *library_name_hint,
+ unsigned long *address,
+ void **module);
+extern void _dyld_lookup_and_bind_objc(
+ const char *symbol_name,
+ unsigned long *address,
+ void **module);
+extern void _dyld_lookup_and_bind_fully(
+ const char *symbol_name,
+ unsigned long *address,
+ void **module);
+
+__private_extern__ int _dyld_func_lookup(
+ const char *dyld_func_name,
+ unsigned long *address);
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_DYLD_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/fat.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACH_O_FAT_H_
+#define _MACH_O_FAT_H_
+/*
+ * This header file describes the structures of the file format for "fat"
+ * architecture specific file (wrapper design). At the begining of the file
+ * there is one fat_header structure followed by a number of fat_arch
+ * structures. For each architecture in the file, specified by a pair of
+ * cputype and cpusubtype, the fat_header describes the file offset, file
+ * size and alignment in the file of the architecture specific member.
+ * The padded bytes in the file to place each member on it's specific alignment
+ * are defined to be read as zeros and can be left as "holes" if the file system
+ * can support them as long as they read as zeros.
+ *
+ * All structures defined here are always written and read to/from disk
+ * in big-endian order.
+ */
+
+/*
+ * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
+ * and contains the constants for the possible values of these types.
+ */
+#include <stdint.h>
+#include <mach/machine.h>
+#include <architecture/byte_order.h>
+
+#define FAT_MAGIC 0xcafebabe
+#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
+
+struct fat_header {
+ uint32_t magic; /* FAT_MAGIC */
+ uint32_t nfat_arch; /* number of structs that follow */
+};
+
+struct fat_arch {
+ cpu_type_t cputype; /* cpu specifier (int) */
+ cpu_subtype_t cpusubtype; /* machine specifier (int) */
+ uint32_t offset; /* file offset to this object file */
+ uint32_t size; /* size of this object file */
+ uint32_t align; /* alignment as a power of 2 */
+};
+
+#endif /* _MACH_O_FAT_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/hppa/reloc.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* reloc.h - assemble for HP-PA */
+/* Defines machine specific relocation entries */
+
+#ifndef HPPA_RELOC_INCLUDED
+#define HPPA_RELOC_INCLUDED
+
+/*
+ * Relocation types used in the hppa implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * in <mach-o/reloc.h> and their r_type is HPPA_RELOC_VANILLA. The rest of the
+ * relocation types are for instructions. Since they are for instructions the
+ * r_address field indicates the 32 bit instruction that the relocation is to
+ * be preformed on. The field r_pcrel is set only for the HPPA_RELOC_BR17.
+ * And r_length is set to long for all non-RELOC_VANILLA r_types.
+ */
+enum reloc_type_hppa
+{
+ HPPA_RELOC_VANILLA, /* generic relocation as discribed in <mach-o/reloc.h>*/
+ HPPA_RELOC_PAIR, /* the second relocation entry of a pair */
+ HPPA_RELOC_HI21, /* a PAIR follows with the low part */
+ HPPA_RELOC_LO14, /* a PAIR follows with the high part */
+ HPPA_RELOC_BR17, /* 17 bit branch displacement (to a word address)
+ a PAIR follows with the high part */
+ HPPA_RELOC_BL17, /* a bl instruction (overlow causes an error) */
+ HPPA_RELOC_JBSR, /* a bl instruction that is targeted at a long branch
+ stub, a PAIR follows with the high part */
+ HPPA_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_HI21_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_LO14_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_PB_LA_PTR /* prebound lazy pointer */
+};
+
+/*
+ * For the HI and LO relocation types the two parts of the relocated expression
+ * (symbol + offset) are calculated as follows:
+ *
+ * rounded = round(offset, 0x2000);
+ * left21 = (symbol + rounded) & 0xfffff800;
+ * right14 = ((symbol + rounded) & 0x000007ff) + (offset - rounded);
+ *
+ * This allows the left part to be shared between references with different
+ * offsets as long as the rounded offsets are the same.
+ *
+ * The HPPA_RELOC_BR17 r_type also uses the above calculation and the right14
+ * bits, sign extened to fill the displacement, and converted to a word
+ * displacement by droping the low bits (after checking they are zero).
+ */
+
+/*
+ * For relocation types that use pairs the part of the relocated expression that
+ * is not stored in the instruction is stored in the r_address feild of the
+ * PAIR's entry.
+ *
+ * All low parts are stored as sign extened byte addressed values in the PAIR's
+ * r_address field as 32 bit values. This allows the HI21 not to have to know
+ * which type of low it is used with.
+ *
+ * The high parts are left justified 21 bit values zero filled to 32 bits and
+ * stored in the PAIR's r_address field.
+ */
+
+/*
+ * The instructions that use the non-RELOC_VANILLA r_types are and the r_types
+ * they use are as follows:
+ * instructions r_type
+ *
+ * LDIL,ADDIL HPPA_RELOC_HI21
+ * LDx, STx, LDO HPPA_RELOC_LO14
+ * BE, BLE HPPA_RELOC_BR17
+ * BL HPPA_RELOC_BL17
+ *
+ * For the HPPA_RELOC_JBSR the BL instruction must be targeted at a long branch
+ * stub that can be reached with 17 bits of signed word displacement. Also the
+ * stub must be in the same block as the BL instruction so that scattered
+ * loading done by the link editor will not move them apart. For example in
+ * assembly code:
+ * jbsr foo,%r2,L1 ; creates a bl inst with a HPPA_RELOC_JBSR
+ * ; relocation entry for the symbol foo and the
+ * ; instruction is targeted to L1
+ * ...
+ * L1: ldil L'foo,%r1 ; a HPPA_RELOC_HI21 entry for symbol foo
+ * ble,n R'foo(%sr4,%r1) ; a HPPA_RELOC_BR17 entry for symbol foo
+ */
+
+#endif /* HPPA_RELOC_INCLUDED */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/i860/reloc.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Relocation types used in the I860 implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * above and their r_type is RELOC_VANILLA. The rest of the relocation types
+ * are for instructions. Since they are for instructions the r_address field
+ * indicates the 32 bit instruction that the relocation is to be preformed on.
+ * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types
+ * except RELOC_SPLIT0 as discribed below.
+ */
+enum reloc_type_i860
+{
+ I860_RELOC_VANILLA, /* generic relocation as discribed above */
+
+ I860_RELOC_PAIR, /* Only follows a I860_RELOC_HIGH or a
+ * I860_RELOC_HIGHADJ and only the r_address has any
+ * meaning.
+ */
+ I860_RELOC_HIGH, /* The low 16 bits of the instruction contains the high
+ * 16 bits of the item being refered to. This
+ * relocation type must be followed by a I860_RELOC_PAIR
+ * relocation type. The low 16 bits of the item being
+ * refered to is stored in the r_address of the
+ * I860_RELOC_PAIR entry.
+ */
+ I860_RELOC_LOW0, /* For all of these the low 16 bits of the instruction*/
+ I860_RELOC_LOW1, /* (minus the low 0, 1, 2, 3, or 4 bits) contain the */
+ I860_RELOC_LOW2, /* low 16 bits of the item being refered to. The bits*/
+ I860_RELOC_LOW3, /* of the reference that are missing are 0 and the */
+ I860_RELOC_LOW4, /* bits in the instruction are part of the encoding of*/
+ /* instruction. The resulting low 16 bits of the item*/
+ /* being refered to is sign extended to 32 bits. */
+
+ I860_RELOC_SPLIT0, /* For all of these the bits 20-14 and bits 10-0 of */
+ I860_RELOC_SPLIT1, /* the instruction (minus the low 0, 1 or 2 bits) */
+ I860_RELOC_SPLIT2, /* contain the low 16 bits of the item to being */
+ /* refered to. The bits of the reference that are */
+ /* missing are 0 and the bits of the instruction are */
+ /* part of the encoding of the instruction. The */
+ /* resulting low 16 bits of the item being relocated */
+ /* is sign extened to 32 bits. A special case of the */
+ /* I860_RELOC_SPLIT0 is when r_pcrel is non-zero (for */
+ /* branch displacements). In this case the 16 bits */
+ /* from the instruction is a 32 bit word displacement.*/
+
+ I860_RELOC_HIGHADJ, /* Same as the RELOC_HIGH except the low 16 bits and the
+ * high 16 bits are added together with the low 16 bits
+ * sign extened first. This means if bit 15 of the low
+ * 16 bits is set the high 16 bits stored in the
+ * instruction will be adjusted.
+ */
+ I860_RELOC_BRADDR, /* The low 26 bits of the instruction is a 32 bit
+ * word displacement from the pc to the item to being
+ * refered to.
+ */
+ I860_RELOC_SECTDIFF /* a PAIR follows with subtract symbol value */
+};
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/loader.h
@@ -0,0 +1,1150 @@
+/*
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACHO_LOADER_H_
+#define _MACHO_LOADER_H_
+
+/*
+ * This file describes the format of mach object files.
+ */
+#include <stdint.h>
+
+/*
+ * <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
+ * and contains the constants for the possible values of these types.
+ */
+#include <mach/machine.h>
+
+/*
+ * <mach/vm_prot.h> is needed here for the vm_prot_t type and contains the
+ * constants that are or'ed together for the possible values of this type.
+ */
+#include <mach/vm_prot.h>
+
+/*
+ * <machine/thread_status.h> is expected to define the flavors of the thread
+ * states and the structures of those flavors for each machine.
+ */
+#include <mach/machine/thread_status.h>
+#include <architecture/byte_order.h>
+
+/*
+ * The 32-bit mach header appears at the very beginning of the object file for
+ * 32-bit architectures.
+ */
+struct mach_header {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+};
+
+/* Constant for the magic field of the mach_header (32-bit architectures) */
+#define MH_MAGIC 0xfeedface /* the mach magic number */
+#define MH_CIGAM 0xcefaedfe /* NXSwapInt(MH_MAGIC) */
+
+/*
+ * The 64-bit mach header appears at the very beginning of object files for
+ * 64-bit architectures.
+ */
+struct mach_header_64 {
+ uint32_t magic; /* mach magic number identifier */
+ cpu_type_t cputype; /* cpu specifier */
+ cpu_subtype_t cpusubtype; /* machine specifier */
+ uint32_t filetype; /* type of file */
+ uint32_t ncmds; /* number of load commands */
+ uint32_t sizeofcmds; /* the size of all the load commands */
+ uint32_t flags; /* flags */
+ uint32_t reserved; /* reserved */
+};
+
+/* Constant for the magic field of the mach_header_64 (64-bit architectures) */
+#define MH_MAGIC_64 0xfeedfacf /* the 64-bit mach magic number */
+#define MH_CIGAM_64 0xcffaedfe /* NXSwapInt(MH_MAGIC_64) */
+
+/*
+ * The layout of the file depends on the filetype. For all but the MH_OBJECT
+ * file type the segments are padded out and aligned on a segment alignment
+ * boundary for efficient demand pageing. The MH_EXECUTE, MH_FVMLIB, MH_DYLIB,
+ * MH_DYLINKER and MH_BUNDLE file types also have the headers included as part
+ * of their first segment.
+ *
+ * The file type MH_OBJECT is a compact format intended as output of the
+ * assembler and input (and possibly output) of the link editor (the .o
+ * format). All sections are in one unnamed segment with no segment padding.
+ * This format is used as an executable format when the file is so small the
+ * segment padding greatly increases its size.
+ *
+ * The file type MH_PRELOAD is an executable format intended for things that
+ * are not executed under the kernel (proms, stand alones, kernels, etc). The
+ * format can be executed under the kernel but may demand paged it and not
+ * preload it before execution.
+ *
+ * A core file is in MH_CORE format and can be any in an arbritray legal
+ * Mach-O file.
+ *
+ * Constants for the filetype field of the mach_header
+ */
+#define MH_OBJECT 0x1 /* relocatable object file */
+#define MH_EXECUTE 0x2 /* demand paged executable file */
+#define MH_FVMLIB 0x3 /* fixed VM shared library file */
+#define MH_CORE 0x4 /* core file */
+#define MH_PRELOAD 0x5 /* preloaded executable file */
+#define MH_DYLIB 0x6 /* dynamically bound shared library */
+#define MH_DYLINKER 0x7 /* dynamic link editor */
+#define MH_BUNDLE 0x8 /* dynamically bound bundle file */
+#define MH_DYLIB_STUB 0x9 /* shared library stub for static */
+ /* linking only, no section contents */
+#define MH_DSYM 0xa /* companion file with only debug */
+ /* sections */
+
+/* Constants for the flags field of the mach_header */
+#define MH_NOUNDEFS 0x1 /* the object file has no undefined
+ references */
+#define MH_INCRLINK 0x2 /* the object file is the output of an
+ incremental link against a base file
+ and can't be link edited again */
+#define MH_DYLDLINK 0x4 /* the object file is input for the
+ dynamic linker and can't be staticly
+ link edited again */
+#define MH_BINDATLOAD 0x8 /* the object file's undefined
+ references are bound by the dynamic
+ linker when loaded. */
+#define MH_PREBOUND 0x10 /* the file has its dynamic undefined
+ references prebound. */
+#define MH_SPLIT_SEGS 0x20 /* the file has its read-only and
+ read-write segments split */
+#define MH_LAZY_INIT 0x40 /* the shared library init routine is
+ to be run lazily via catching memory
+ faults to its writeable segments
+ (obsolete) */
+#define MH_TWOLEVEL 0x80 /* the image is using two-level name
+ space bindings */
+#define MH_FORCE_FLAT 0x100 /* the executable is forcing all images
+ to use flat name space bindings */
+#define MH_NOMULTIDEFS 0x200 /* this umbrella guarantees no multiple
+ defintions of symbols in its
+ sub-images so the two-level namespace
+ hints can always be used. */
+#define MH_NOFIXPREBINDING 0x400 /* do not have dyld notify the
+ prebinding agent about this
+ executable */
+#define MH_PREBINDABLE 0x800 /* the binary is not prebound but can
+ have its prebinding redone. only used
+ when MH_PREBOUND is not set. */
+#define MH_ALLMODSBOUND 0x1000 /* indicates that this binary binds to
+ all two-level namespace modules of
+ its dependent libraries. only used
+ when MH_PREBINDABLE and MH_TWOLEVEL
+ are both set. */
+#define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000/* safe to divide up the sections into
+ sub-sections via symbols for dead
+ code stripping */
+#define MH_CANONICAL 0x4000 /* the binary has been canonicalized
+ via the unprebind operation */
+#define MH_WEAK_DEFINES 0x8000 /* the final linked image contains
+ external weak symbols */
+#define MH_BINDS_TO_WEAK 0x10000 /* the final linked image uses
+ weak symbols */
+
+#define MH_ALLOW_STACK_EXECUTION 0x20000/* When this bit is set, all stacks
+ in the task will be given stack
+ execution privilege. Only used in
+ MH_EXECUTE filetypes. */
+#define MH_ROOT_SAFE 0x40000 /* When this bit is set, the binary
+ declares it is safe for use in
+ processes with uid zero */
+
+#define MH_SETUID_SAFE 0x80000 /* When this bit is set, the binary
+ declares it is safe for use in
+ processes when issetugid() is true */
+
+#define MH_NO_REEXPORTED_DYLIBS 0x100000 /* When this bit is set on a dylib,
+ the static linker does not need to
+ examine dependent dylibs to see
+ if any are re-exported */
+#define MH_PIE 0x200000 /* When this bit is set, the OS will
+ load the main executable at a
+ random address. Only used in
+ MH_EXECUTE filetypes. */
+
+/*
+ * 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
+ * load commands must have as their first two fields cmd and cmdsize. The cmd
+ * field is filled in with a constant for that command type. Each command type
+ * has a structure specifically for it. The cmdsize field is the size in bytes
+ * of the particular load command structure plus anything that follows it that
+ * is a part of the load command (i.e. section structures, strings, etc.). To
+ * advance to the next load command the cmdsize can be added to the offset or
+ * pointer of the current load command. The cmdsize for 32-bit architectures
+ * MUST be a multiple of 4 bytes and for 64-bit architectures MUST be a multiple
+ * of 8 bytes (these are forever the maximum alignment of any load commands).
+ * The padded bytes must be zero. All tables in the object file must also
+ * follow these rules so the file can be memory mapped. Otherwise the pointers
+ * to these tables will not work well or at all on some machines. With all
+ * padding zeroed like objects will compare byte for byte.
+ */
+struct load_command {
+ uint32_t cmd; /* type of load command */
+ uint32_t cmdsize; /* total size of command in bytes */
+};
+
+/*
+ * After MacOS X 10.1 when a new load command is added that is required to be
+ * understood by the dynamic linker for the image to execute properly the
+ * LC_REQ_DYLD bit will be or'ed into the load command constant. If the dynamic
+ * linker sees such a load command it it does not understand will issue a
+ * "unknown load command required for execution" error and refuse to use the
+ * image. Other load commands without this bit that are not understood will
+ * simply be ignored.
+ */
+#define LC_REQ_DYLD 0x80000000
+
+/* Constants for the cmd field of all load commands, the type */
+#define LC_SEGMENT 0x1 /* segment of this file to be mapped */
+#define LC_SYMTAB 0x2 /* link-edit stab symbol table info */
+#define LC_SYMSEG 0x3 /* link-edit gdb symbol table info (obsolete) */
+#define LC_THREAD 0x4 /* thread */
+#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */
+#define LC_LOADFVMLIB 0x6 /* load a specified fixed VM shared library */
+#define LC_IDFVMLIB 0x7 /* fixed VM shared library identification */
+#define LC_IDENT 0x8 /* object identification info (obsolete) */
+#define LC_FVMFILE 0x9 /* fixed VM file inclusion (internal use) */
+#define LC_PREPAGE 0xa /* prepage command (internal use) */
+#define LC_DYSYMTAB 0xb /* dynamic link-edit symbol table info */
+#define LC_LOAD_DYLIB 0xc /* load a dynamically linked shared library */
+#define LC_ID_DYLIB 0xd /* dynamically linked shared lib ident */
+#define LC_LOAD_DYLINKER 0xe /* load a dynamic linker */
+#define LC_ID_DYLINKER 0xf /* dynamic linker identification */
+#define LC_PREBOUND_DYLIB 0x10 /* modules prebound for a dynamically */
+ /* linked shared library */
+#define LC_ROUTINES 0x11 /* image routines */
+#define LC_SUB_FRAMEWORK 0x12 /* sub framework */
+#define LC_SUB_UMBRELLA 0x13 /* sub umbrella */
+#define LC_SUB_CLIENT 0x14 /* sub client */
+#define LC_SUB_LIBRARY 0x15 /* sub library */
+#define LC_TWOLEVEL_HINTS 0x16 /* two-level namespace lookup hints */
+#define LC_PREBIND_CKSUM 0x17 /* prebind checksum */
+
+/*
+ * load a dynamically linked shared library that is allowed to be missing
+ * (all symbols are weak imported).
+ */
+#define LC_LOAD_WEAK_DYLIB (0x18 | LC_REQ_DYLD)
+
+#define LC_SEGMENT_64 0x19 /* 64-bit segment of this file to be
+ mapped */
+#define LC_ROUTINES_64 0x1a /* 64-bit image routines */
+#define LC_UUID 0x1b /* the uuid */
+#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */
+#define LC_CODE_SIGNATURE 0x1d /* local of code signature */
+#define LC_SEGMENT_SPLIT_INFO 0x1e /* local of info to split segments */
+#define LC_REEXPORT_DYLIB (0x1f | LC_REQ_DYLD) /* load and re-export dylib */
+
+/*
+ * A variable length string in a load command is represented by an lc_str
+ * union. The strings are stored just after the load command structure and
+ * the offset is from the start of the load command structure. The size
+ * of the string is reflected in the cmdsize field of the load command.
+ * Once again any padded bytes to bring the cmdsize field to a multiple
+ * of 4 bytes must be zero.
+ */
+union lc_str {
+ uint32_t offset; /* offset to the string */
+#ifndef __LP64__
+ char *ptr; /* pointer to the string */
+#endif
+};
+
+/*
+ * The segment load command indicates that a part of this file is to be
+ * mapped into the task's address space. The size of this segment in memory,
+ * vmsize, maybe equal to or larger than the amount to map from this file,
+ * filesize. The file is mapped starting at fileoff to the beginning of
+ * the segment in memory, vmaddr. The rest of the memory of the segment,
+ * if any, is allocated zero fill on demand. The segment's maximum virtual
+ * memory protection and initial virtual memory protection are specified
+ * by the maxprot and initprot fields. If the segment has sections then the
+ * section structures directly follow the segment command and their size is
+ * reflected in cmdsize.
+ */
+struct segment_command { /* for 32-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT */
+ uint32_t cmdsize; /* includes sizeof section structs */
+ char segname[16]; /* segment name */
+ uint32_t vmaddr; /* memory address of this segment */
+ uint32_t vmsize; /* memory size of this segment */
+ uint32_t fileoff; /* file offset of this segment */
+ uint32_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+
+/*
+ * The 64-bit segment load command indicates that a part of this file is to be
+ * mapped into a 64-bit task's address space. If the 64-bit segment has
+ * sections then section_64 structures directly follow the 64-bit segment
+ * command and their size is reflected in cmdsize.
+ */
+struct segment_command_64 { /* for 64-bit architectures */
+ uint32_t cmd; /* LC_SEGMENT_64 */
+ uint32_t cmdsize; /* includes sizeof section_64 structs */
+ char segname[16]; /* segment name */
+ uint64_t vmaddr; /* memory address of this segment */
+ uint64_t vmsize; /* memory size of this segment */
+ uint64_t fileoff; /* file offset of this segment */
+ uint64_t filesize; /* amount to map from the file */
+ vm_prot_t maxprot; /* maximum VM protection */
+ vm_prot_t initprot; /* initial VM protection */
+ uint32_t nsects; /* number of sections in segment */
+ uint32_t flags; /* flags */
+};
+
+/* Constants for the flags field of the segment_command */
+#define SG_HIGHVM 0x1 /* the file contents for this segment is for
+ the high part of the VM space, the low part
+ is zero filled (for stacks in core files) */
+#define SG_FVMLIB 0x2 /* this segment is the VM that is allocated by
+ a fixed VM library, for overlap checking in
+ the link editor */
+#define SG_NORELOC 0x4 /* this segment has nothing that was relocated
+ in it and nothing relocated to it, that is
+ it maybe safely replaced without relocation*/
+#define SG_PROTECTED_VERSION_1 0x8 /* This segment is protected. If the
+ segment starts at file offset 0, the
+ first page of the segment is not
+ protected. All other pages of the
+ segment are protected. */
+
+/*
+ * A segment is made up of zero or more sections. Non-MH_OBJECT files have
+ * all of their segments with the proper sections in each, and padded to the
+ * specified segment alignment when produced by the link editor. The first
+ * segment of a MH_EXECUTE and MH_FVMLIB format file contains the mach_header
+ * and load commands of the object file before its first section. The zero
+ * fill sections are always last in their segment (in all formats). This
+ * allows the zeroed segment padding to be mapped into memory where zero fill
+ * sections might be. The gigabyte zero fill sections, those with the section
+ * type S_GB_ZEROFILL, can only be in a segment with sections of this type.
+ * These segments are then placed after all other segments.
+ *
+ * The MH_OBJECT format has all of its sections in one segment for
+ * compactness. There is no padding to a specified segment boundary and the
+ * mach_header and load commands are not part of the segment.
+ *
+ * Sections with the same section name, sectname, going into the same segment,
+ * segname, are combined by the link editor. The resulting section is aligned
+ * to the maximum alignment of the combined sections and is the new section's
+ * alignment. The combined sections are aligned to their original alignment in
+ * the combined section. Any padded bytes to get the specified alignment are
+ * zeroed.
+ *
+ * The format of the relocation entries referenced by the reloff and nreloc
+ * fields of the section structure for mach object files is described in the
+ * header file <reloc.h>.
+ */
+struct section { /* for 32-bit architectures */
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ uint32_t addr; /* memory address of this section */
+ uint32_t size; /* size in bytes of this section */
+ uint32_t offset; /* file offset of this section */
+ uint32_t align; /* section alignment (power of 2) */
+ uint32_t reloff; /* file offset of relocation entries */
+ uint32_t nreloc; /* number of relocation entries */
+ uint32_t flags; /* flags (section type and attributes)*/
+ uint32_t reserved1; /* reserved (for offset or index) */
+ uint32_t reserved2; /* reserved (for count or sizeof) */
+};
+
+struct section_64 { /* for 64-bit architectures */
+ char sectname[16]; /* name of this section */
+ char segname[16]; /* segment this section goes in */
+ uint64_t addr; /* memory address of this section */
+ uint64_t size; /* size in bytes of this section */
+ uint32_t offset; /* file offset of this section */
+ uint32_t align; /* section alignment (power of 2) */
+ uint32_t reloff; /* file offset of relocation entries */
+ uint32_t nreloc; /* number of relocation entries */
+ uint32_t flags; /* flags (section type and attributes)*/
+ uint32_t reserved1; /* reserved (for offset or index) */
+ uint32_t reserved2; /* reserved (for count or sizeof) */
+ uint32_t reserved3; /* reserved */
+};
+
+/*
+ * The flags field of a section structure is separated into two parts a section
+ * type and section attributes. The section types are mutually exclusive (it
+ * can only have one type) but the section attributes are not (it may have more
+ * than one attribute).
+ */
+#define SECTION_TYPE 0x000000ff /* 256 section types */
+#define SECTION_ATTRIBUTES 0xffffff00 /* 24 section attributes */
+
+/* Constants for the type of a section */
+#define S_REGULAR 0x0 /* regular section */
+#define S_ZEROFILL 0x1 /* zero fill on demand section */
+#define S_CSTRING_LITERALS 0x2 /* section with only literal C strings*/
+#define S_4BYTE_LITERALS 0x3 /* section with only 4 byte literals */
+#define S_8BYTE_LITERALS 0x4 /* section with only 8 byte literals */
+#define S_LITERAL_POINTERS 0x5 /* section with only pointers to */
+ /* literals */
+/*
+ * For the two types of symbol pointers sections and the symbol stubs section
+ * they have indirect symbol table entries. For each of the entries in the
+ * section the indirect symbol table entries, in corresponding order in the
+ * indirect symbol table, start at the index stored in the reserved1 field
+ * of the section structure. Since the indirect symbol table entries
+ * correspond to the entries in the section the number of indirect symbol table
+ * entries is inferred from the size of the section divided by the size of the
+ * entries in the section. For symbol pointers sections the size of the entries
+ * in the section is 4 bytes and for symbol stubs sections the byte size of the
+ * stubs is stored in the reserved2 field of the section structure.
+ */
+#define S_NON_LAZY_SYMBOL_POINTERS 0x6 /* section with only non-lazy
+ symbol pointers */
+#define S_LAZY_SYMBOL_POINTERS 0x7 /* section with only lazy symbol
+ pointers */
+#define S_SYMBOL_STUBS 0x8 /* section with only symbol
+ stubs, byte size of stub in
+ the reserved2 field */
+#define S_MOD_INIT_FUNC_POINTERS 0x9 /* section with only function
+ pointers for initialization*/
+#define S_MOD_TERM_FUNC_POINTERS 0xa /* section with only function
+ pointers for termination */
+#define S_COALESCED 0xb /* section contains symbols that
+ are to be coalesced */
+#define S_GB_ZEROFILL 0xc /* zero fill on demand section
+ (that can be larger than 4
+ gigabytes) */
+#define S_INTERPOSING 0xd /* section with only pairs of
+ function pointers for
+ interposing */
+#define S_16BYTE_LITERALS 0xe /* section with only 16 byte
+ literals */
+#define S_DTRACE_DOF 0xf /* section contains
+ DTrace Object Format */
+/*
+ * Constants for the section attributes part of the flags field of a section
+ * structure.
+ */
+#define SECTION_ATTRIBUTES_USR 0xff000000 /* User setable attributes */
+#define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section contains only true
+ machine instructions */
+#define S_ATTR_NO_TOC 0x40000000 /* section contains coalesced
+ symbols that are not to be
+ in a ranlib table of
+ contents */
+#define S_ATTR_STRIP_STATIC_SYMS 0x20000000 /* ok to strip static symbols
+ in this section in files
+ with the MH_DYLDLINK flag */
+#define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */
+#define S_ATTR_LIVE_SUPPORT 0x08000000 /* blocks are live if they
+ reference live blocks */
+#define S_ATTR_SELF_MODIFYING_CODE 0x04000000 /* Used with i386 code stubs
+ written on by dyld */
+/*
+ * If a segment contains any sections marked with S_ATTR_DEBUG then all
+ * sections in that segment must have this attribute. No section other than
+ * a section marked with this attribute may reference the contents of this
+ * section. A section with this attribute may contain no symbols and must have
+ * a section type S_REGULAR. The static linker will not copy section contents
+ * from sections with this attribute into its output file. These sections
+ * generally contain DWARF debugging info.
+ */
+#define S_ATTR_DEBUG 0x02000000 /* a debug section */
+#define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
+#define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
+ machine instructions */
+#define S_ATTR_EXT_RELOC 0x00000200 /* section has external
+ relocation entries */
+#define S_ATTR_LOC_RELOC 0x00000100 /* section has local
+ relocation entries */
+
+
+/*
+ * The names of segments and sections in them are mostly meaningless to the
+ * link-editor. But there are few things to support traditional UNIX
+ * executables that require the link-editor and assembler to use some names
+ * agreed upon by convention.
+ *
+ * The initial protection of the "__TEXT" segment has write protection turned
+ * off (not writeable).
+ *
+ * The link-editor will allocate common symbols at the end of the "__common"
+ * section in the "__DATA" segment. It will create the section and segment
+ * if needed.
+ */
+
+/* The currently known segment names and the section names in those segments */
+
+#define SEG_PAGEZERO "__PAGEZERO" /* the pagezero segment which has no */
+ /* protections and catches NULL */
+ /* references for MH_EXECUTE files */
+
+
+#define SEG_TEXT "__TEXT" /* the tradition UNIX text segment */
+#define SECT_TEXT "__text" /* the real text part of the text */
+ /* section no headers, and no padding */
+#define SECT_FVMLIB_INIT0 "__fvmlib_init0" /* the fvmlib initialization */
+ /* section */
+#define SECT_FVMLIB_INIT1 "__fvmlib_init1" /* the section following the */
+ /* fvmlib initialization */
+ /* section */
+
+#define SEG_DATA "__DATA" /* the tradition UNIX data segment */
+#define SECT_DATA "__data" /* the real initialized data section */
+ /* no padding, no bss overlap */
+#define SECT_BSS "__bss" /* the real uninitialized data section*/
+ /* no padding */
+#define SECT_COMMON "__common" /* the section common symbols are */
+ /* allocated in by the link editor */
+
+#define SEG_OBJC "__OBJC" /* objective-C runtime segment */
+#define SECT_OBJC_SYMBOLS "__symbol_table" /* symbol table */
+#define SECT_OBJC_MODULES "__module_info" /* module information */
+#define SECT_OBJC_STRINGS "__selector_strs" /* string table */
+#define SECT_OBJC_REFS "__selector_refs" /* string table */
+
+#define SEG_ICON "__ICON" /* the icon segment */
+#define SECT_ICON_HEADER "__header" /* the icon headers */
+#define SECT_ICON_TIFF "__tiff" /* the icons in tiff format */
+
+#define SEG_LINKEDIT "__LINKEDIT" /* the segment containing all structs */
+ /* created and maintained by the link */
+ /* editor. Created with -seglinkedit */
+ /* option to ld(1) for MH_EXECUTE and */
+ /* FVMLIB file types only */
+
+#define SEG_UNIXSTACK "__UNIXSTACK" /* the unix stack segment */
+
+#define SEG_IMPORT "__IMPORT" /* the segment for the self (dyld) */
+ /* modifing code stubs that has read, */
+ /* write and execute permissions */
+
+/*
+ * Fixed virtual memory shared libraries are identified by two things. The
+ * target pathname (the name of the library as found for execution), and the
+ * minor version number. The address of where the headers are loaded is in
+ * header_addr. (THIS IS OBSOLETE and no longer supported).
+ */
+struct fvmlib {
+ union lc_str name; /* library's target pathname */
+ uint32_t minor_version; /* library's minor version number */
+ uint32_t header_addr; /* library's header address */
+};
+
+/*
+ * A fixed virtual shared library (filetype == MH_FVMLIB in the mach header)
+ * contains a fvmlib_command (cmd == LC_IDFVMLIB) to identify the library.
+ * An object that uses a fixed virtual shared library also contains a
+ * fvmlib_command (cmd == LC_LOADFVMLIB) for each library it uses.
+ * (THIS IS OBSOLETE and no longer supported).
+ */
+struct fvmlib_command {
+ uint32_t cmd; /* LC_IDFVMLIB or LC_LOADFVMLIB */
+ uint32_t cmdsize; /* includes pathname string */
+ struct fvmlib fvmlib; /* the library identification */
+};
+
+/*
+ * Dynamicly linked shared libraries are identified by two things. The
+ * pathname (the name of the library as found for execution), and the
+ * compatibility version number. The pathname must match and the compatibility
+ * number in the user of the library must be greater than or equal to the
+ * library being used. The time stamp is used to record the time a library was
+ * built and copied into user so it can be use to determined if the library used
+ * at runtime is exactly the same as used to built the program.
+ */
+struct dylib {
+ union lc_str name; /* library's path name */
+ uint32_t timestamp; /* library's build time stamp */
+ uint32_t current_version; /* library's current version number */
+ uint32_t compatibility_version; /* library's compatibility vers number*/
+};
+
+/*
+ * A dynamically linked shared library (filetype == MH_DYLIB in the mach header)
+ * contains a dylib_command (cmd == LC_ID_DYLIB) to identify the library.
+ * An object that uses a dynamically linked shared library also contains a
+ * dylib_command (cmd == LC_LOAD_DYLIB, LC_LOAD_WEAK_DYLIB, or
+ * LC_REEXPORT_DYLIB) for each library it uses.
+ */
+struct dylib_command {
+ uint32_t cmd; /* LC_ID_DYLIB, LC_LOAD_{,WEAK_}DYLIB,
+ LC_REEXPORT_DYLIB */
+ uint32_t cmdsize; /* includes pathname string */
+ struct dylib dylib; /* the library identification */
+};
+
+/*
+ * A dynamically linked shared library may be a subframework of an umbrella
+ * framework. If so it will be linked with "-umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the umbrella framework. A subframework
+ * can only be linked against by its umbrella framework or other subframeworks
+ * that are part of the same umbrella framework. Otherwise the static link
+ * editor produces an error and states to link against the umbrella framework.
+ * The name of the umbrella framework for subframeworks is recorded in the
+ * following structure.
+ */
+struct sub_framework_command {
+ uint32_t cmd; /* LC_SUB_FRAMEWORK */
+ uint32_t cmdsize; /* includes umbrella string */
+ union lc_str umbrella; /* the umbrella framework name */
+};
+
+/*
+ * For dynamically linked shared libraries that are subframework of an umbrella
+ * framework they can allow clients other than the umbrella framework or other
+ * subframeworks in the same umbrella framework. To do this the subframework
+ * is built with "-allowable_client client_name" and an LC_SUB_CLIENT load
+ * command is created for each -allowable_client flag. The client_name is
+ * usually a framework name. It can also be a name used for bundles clients
+ * where the bundle is built with "-client_name client_name".
+ */
+struct sub_client_command {
+ uint32_t cmd; /* LC_SUB_CLIENT */
+ uint32_t cmdsize; /* includes client string */
+ union lc_str client; /* the client name */
+};
+
+/*
+ * A dynamically linked shared library may be a sub_umbrella of an umbrella
+ * framework. If so it will be linked with "-sub_umbrella umbrella_name" where
+ * Where "umbrella_name" is the name of the sub_umbrella framework. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * umbrella framework will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks to be implicited linked in. Any other
+ * dependent dynamic libraries will not be linked it when -twolevel_namespace
+ * is in effect. The primary library recorded by the static linker when
+ * resolving a symbol in these libraries will be the umbrella framework.
+ * Zero or more sub_umbrella frameworks may be use by an umbrella framework.
+ * The name of a sub_umbrella framework is recorded in the following structure.
+ */
+struct sub_umbrella_command {
+ uint32_t cmd; /* LC_SUB_UMBRELLA */
+ uint32_t cmdsize; /* includes sub_umbrella string */
+ union lc_str sub_umbrella; /* the sub_umbrella framework name */
+};
+
+/*
+ * A dynamically linked shared library may be a sub_library of another shared
+ * library. If so it will be linked with "-sub_library library_name" where
+ * Where "library_name" is the name of the sub_library shared library. When
+ * staticly linking when -twolevel_namespace is in effect a twolevel namespace
+ * shared library will only cause its subframeworks and those frameworks
+ * listed as sub_umbrella frameworks and libraries listed as sub_libraries to
+ * be implicited linked in. Any other dependent dynamic libraries will not be
+ * linked it when -twolevel_namespace is in effect. The primary library
+ * recorded by the static linker when resolving a symbol in these libraries
+ * will be the umbrella framework (or dynamic library). Zero or more sub_library
+ * shared libraries may be use by an umbrella framework or (or dynamic library).
+ * The name of a sub_library framework is recorded in the following structure.
+ * For example /usr/lib/libobjc_profile.A.dylib would be recorded as "libobjc".
+ */
+struct sub_library_command {
+ uint32_t cmd; /* LC_SUB_LIBRARY */
+ uint32_t cmdsize; /* includes sub_library string */
+ union lc_str sub_library; /* the sub_library name */
+};
+
+/*
+ * A program (filetype == MH_EXECUTE) that is
+ * prebound to its dynamic libraries has one of these for each library that
+ * the static linker used in prebinding. It contains a bit vector for the
+ * modules in the library. The bits indicate which modules are bound (1) and
+ * which are not (0) from the library. The bit for module 0 is the low bit
+ * of the first byte. So the bit for the Nth module is:
+ * (linked_modules[N/8] >> N%8) & 1
+ */
+struct prebound_dylib_command {
+ uint32_t cmd; /* LC_PREBOUND_DYLIB */
+ uint32_t cmdsize; /* includes strings */
+ union lc_str name; /* library's path name */
+ uint32_t nmodules; /* number of modules in library */
+ union lc_str linked_modules; /* bit vector of linked modules */
+};
+
+/*
+ * A program that uses a dynamic linker contains a dylinker_command to identify
+ * the name of the dynamic linker (LC_LOAD_DYLINKER). And a dynamic linker
+ * contains a dylinker_command to identify the dynamic linker (LC_ID_DYLINKER).
+ * A file can have at most one of these.
+ */
+struct dylinker_command {
+ uint32_t cmd; /* LC_ID_DYLINKER or LC_LOAD_DYLINKER */
+ uint32_t cmdsize; /* includes pathname string */
+ union lc_str name; /* dynamic linker's path name */
+};
+
+/*
+ * Thread commands contain machine-specific data structures suitable for
+ * use in the thread state primitives. The machine specific data structures
+ * follow the struct thread_command as follows.
+ * Each flavor of machine specific data structure is preceded by an unsigned
+ * long constant for the flavor of that data structure, an uint32_t
+ * that is the count of longs of the size of the state data structure and then
+ * the state data structure follows. This triple may be repeated for many
+ * flavors. The constants for the flavors, counts and state data structure
+ * definitions are expected to be in the header file <machine/thread_status.h>.
+ * These machine specific data structures sizes must be multiples of
+ * 4 bytes The cmdsize reflects the total size of the thread_command
+ * and all of the sizes of the constants for the flavors, counts and state
+ * data structures.
+ *
+ * For executable objects that are unix processes there will be one
+ * thread_command (cmd == LC_UNIXTHREAD) created for it by the link-editor.
+ * This is the same as a LC_THREAD, except that a stack is automatically
+ * created (based on the shell's limit for the stack size). Command arguments
+ * and environment variables are copied onto that stack.
+ */
+struct thread_command {
+ uint32_t cmd; /* LC_THREAD or LC_UNIXTHREAD */
+ uint32_t cmdsize; /* total size of this command */
+ /* uint32_t flavor flavor of thread state */
+ /* uint32_t count count of longs in thread state */
+ /* struct XXX_thread_state state thread state for this flavor */
+ /* ... */
+};
+
+/*
+ * The routines command contains the address of the dynamic shared library
+ * initialization routine and an index into the module table for the module
+ * that defines the routine. Before any modules are used from the library the
+ * dynamic linker fully binds the module that defines the initialization routine
+ * and then calls it. This gets called before any module initialization
+ * routines (used for C++ static constructors) in the library.
+ */
+struct routines_command { /* for 32-bit architectures */
+ uint32_t cmd; /* LC_ROUTINES */
+ uint32_t cmdsize; /* total size of this command */
+ uint32_t init_address; /* address of initialization routine */
+ uint32_t init_module; /* index into the module table that */
+ /* the init routine is defined in */
+ uint32_t reserved1;
+ uint32_t reserved2;
+ uint32_t reserved3;
+ uint32_t reserved4;
+ uint32_t reserved5;
+ uint32_t reserved6;
+};
+
+/*
+ * The 64-bit routines command. Same use as above.
+ */
+struct routines_command_64 { /* for 64-bit architectures */
+ uint32_t cmd; /* LC_ROUTINES_64 */
+ uint32_t cmdsize; /* total size of this command */
+ uint64_t init_address; /* address of initialization routine */
+ uint64_t init_module; /* index into the module table that */
+ /* the init routine is defined in */
+ uint64_t reserved1;
+ uint64_t reserved2;
+ uint64_t reserved3;
+ uint64_t reserved4;
+ uint64_t reserved5;
+ uint64_t reserved6;
+};
+
+/*
+ * The symtab_command contains the offsets and sizes of the link-edit 4.3BSD
+ * "stab" style symbol table information as described in the header files
+ * <nlist.h> and <stab.h>.
+ */
+struct symtab_command {
+ uint32_t cmd; /* LC_SYMTAB */
+ uint32_t cmdsize; /* sizeof(struct symtab_command) */
+ uint32_t symoff; /* symbol table offset */
+ uint32_t nsyms; /* number of symbol table entries */
+ uint32_t stroff; /* string table offset */
+ uint32_t strsize; /* string table size in bytes */
+};
+
+/*
+ * This is the second set of the symbolic information which is used to support
+ * the data structures for the dynamically link editor.
+ *
+ * The original set of symbolic information in the symtab_command which contains
+ * the symbol and string tables must also be present when this load command is
+ * present. When this load command is present the symbol table is organized
+ * into three groups of symbols:
+ * local symbols (static and debugging symbols) - grouped by module
+ * defined external symbols - grouped by module (sorted by name if not lib)
+ * undefined external symbols (sorted by name if MH_BINDATLOAD is not set,
+ * and in order the were seen by the static
+ * linker if MH_BINDATLOAD is set)
+ * In this load command there are offsets and counts to each of the three groups
+ * of symbols.
+ *
+ * This load command contains a the offsets and sizes of the following new
+ * symbolic information tables:
+ * table of contents
+ * module table
+ * reference symbol table
+ * indirect symbol table
+ * The first three tables above (the table of contents, module table and
+ * reference symbol table) are only present if the file is a dynamically linked
+ * shared library. For executable and object modules, which are files
+ * containing only one module, the information that would be in these three
+ * tables is determined as follows:
+ * table of contents - the defined external symbols are sorted by name
+ * module table - the file contains only one module so everything in the
+ * file is part of the module.
+ * reference symbol table - is the defined and undefined external symbols
+ *
+ * For dynamically linked shared library files this load command also contains
+ * offsets and sizes to the pool of relocation entries for all sections
+ * separated into two groups:
+ * external relocation entries
+ * local relocation entries
+ * For executable and object modules the relocation entries continue to hang
+ * off the section structures.
+ */
+struct dysymtab_command {
+ uint32_t cmd; /* LC_DYSYMTAB */
+ uint32_t cmdsize; /* sizeof(struct dysymtab_command) */
+
+ /*
+ * The symbols indicated by symoff and nsyms of the LC_SYMTAB load command
+ * are grouped into the following three groups:
+ * local symbols (further grouped by the module they are from)
+ * defined external symbols (further grouped by the module they are from)
+ * undefined symbols
+ *
+ * The local symbols are used only for debugging. The dynamic binding
+ * process may have to use them to indicate to the debugger the local
+ * symbols for a module that is being bound.
+ *
+ * The last two groups are used by the dynamic binding process to do the
+ * binding (indirectly through the module table and the reference symbol
+ * table when this is a dynamically linked shared library file).
+ */
+ uint32_t ilocalsym; /* index to local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextdefsym;/* index to externally defined symbols */
+ uint32_t nextdefsym;/* number of externally defined symbols */
+
+ uint32_t iundefsym; /* index to undefined symbols */
+ uint32_t nundefsym; /* number of undefined symbols */
+
+ /*
+ * For the for the dynamic binding process to find which module a symbol
+ * is defined in the table of contents is used (analogous to the ranlib
+ * structure in an archive) which maps defined external symbols to modules
+ * they are defined in. This exists only in a dynamically linked shared
+ * library file. For executable and object modules the defined external
+ * symbols are sorted by name and is use as the table of contents.
+ */
+ uint32_t tocoff; /* file offset to table of contents */
+ uint32_t ntoc; /* number of entries in table of contents */
+
+ /*
+ * To support dynamic binding of "modules" (whole object files) the symbol
+ * table must reflect the modules that the file was created from. This is
+ * done by having a module table that has indexes and counts into the merged
+ * tables for each module. The module structure that these two entries
+ * refer to is described below. This exists only in a dynamically linked
+ * shared library file. For executable and object modules the file only
+ * contains one module so everything in the file belongs to the module.
+ */
+ uint32_t modtaboff; /* file offset to module table */
+ uint32_t nmodtab; /* number of module table entries */
+
+ /*
+ * To support dynamic module binding the module structure for each module
+ * indicates the external references (defined and undefined) each module
+ * makes. For each module there is an offset and a count into the
+ * reference symbol table for the symbols that the module references.
+ * This exists only in a dynamically linked shared library file. For
+ * executable and object modules the defined external symbols and the
+ * undefined external symbols indicates the external references.
+ */
+ uint32_t extrefsymoff; /* offset to referenced symbol table */
+ uint32_t nextrefsyms; /* number of referenced symbol table entries */
+
+ /*
+ * The sections that contain "symbol pointers" and "routine stubs" have
+ * indexes and (implied counts based on the size of the section and fixed
+ * size of the entry) into the "indirect symbol" table for each pointer
+ * and stub. For every section of these two types the index into the
+ * indirect symbol table is stored in the section header in the field
+ * reserved1. An indirect symbol table entry is simply a 32bit index into
+ * the symbol table to the symbol that the pointer or stub is referring to.
+ * The indirect symbol table is ordered to match the entries in the section.
+ */
+ uint32_t indirectsymoff; /* file offset to the indirect symbol table */
+ uint32_t nindirectsyms; /* number of indirect symbol table entries */
+
+ /*
+ * To support relocating an individual module in a library file quickly the
+ * external relocation entries for each module in the library need to be
+ * accessed efficiently. Since the relocation entries can't be accessed
+ * through the section headers for a library file they are separated into
+ * groups of local and external entries further grouped by module. In this
+ * case the presents of this load command who's extreloff, nextrel,
+ * locreloff and nlocrel fields are non-zero indicates that the relocation
+ * entries of non-merged sections are not referenced through the section
+ * structures (and the reloff and nreloc fields in the section headers are
+ * set to zero).
+ *
+ * Since the relocation entries are not accessed through the section headers
+ * this requires the r_address field to be something other than a section
+ * offset to identify the item to be relocated. In this case r_address is
+ * set to the offset from the vmaddr of the first LC_SEGMENT command.
+ * For MH_SPLIT_SEGS images r_address is set to the the offset from the
+ * vmaddr of the first read-write LC_SEGMENT command.
+ *
+ * The relocation entries are grouped by module and the module table
+ * entries have indexes and counts into them for the group of external
+ * relocation entries for that the module.
+ *
+ * For sections that are merged across modules there must not be any
+ * remaining external relocation entries for them (for merged sections
+ * remaining relocation entries must be local).
+ */
+ uint32_t extreloff; /* offset to external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ /*
+ * All the local relocation entries are grouped together (they are not
+ * grouped by their module since they are only used if the object is moved
+ * from it staticly link edited address).
+ */
+ uint32_t locreloff; /* offset to local relocation entries */
+ uint32_t nlocrel; /* number of local relocation entries */
+
+};
+
+/*
+ * An indirect symbol table entry is simply a 32bit index into the symbol table
+ * to the symbol that the pointer or stub is refering to. Unless it is for a
+ * non-lazy symbol pointer section for a defined symbol which strip(1) as
+ * removed. In which case it has the value INDIRECT_SYMBOL_LOCAL. If the
+ * symbol was also absolute INDIRECT_SYMBOL_ABS is or'ed with that.
+ */
+#define INDIRECT_SYMBOL_LOCAL 0x80000000
+#define INDIRECT_SYMBOL_ABS 0x40000000
+
+
+/* a table of contents entry */
+struct dylib_table_of_contents {
+ uint32_t symbol_index; /* the defined external symbol
+ (index into the symbol table) */
+ uint32_t module_index; /* index into the module table this symbol
+ is defined in */
+};
+
+/* a module table entry */
+struct dylib_module {
+ uint32_t module_name; /* the module name (index into string table) */
+
+ uint32_t iextdefsym; /* index into externally defined symbols */
+ uint32_t nextdefsym; /* number of externally defined symbols */
+ uint32_t irefsym; /* index into reference symbol table */
+ uint32_t nrefsym; /* number of reference symbol table entries */
+ uint32_t ilocalsym; /* index into symbols for local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextrel; /* index into external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ uint32_t iinit_iterm; /* low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section */
+ uint32_t ninit_nterm; /* low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries */
+
+ uint32_t /* for this module address of the start of */
+ objc_module_info_addr; /* the (__OBJC,__module_info) section */
+ uint32_t /* for this module size of */
+ objc_module_info_size; /* the (__OBJC,__module_info) section */
+};
+
+/* a 64-bit module table entry */
+struct dylib_module_64 {
+ uint32_t module_name; /* the module name (index into string table) */
+
+ uint32_t iextdefsym; /* index into externally defined symbols */
+ uint32_t nextdefsym; /* number of externally defined symbols */
+ uint32_t irefsym; /* index into reference symbol table */
+ uint32_t nrefsym; /* number of reference symbol table entries */
+ uint32_t ilocalsym; /* index into symbols for local symbols */
+ uint32_t nlocalsym; /* number of local symbols */
+
+ uint32_t iextrel; /* index into external relocation entries */
+ uint32_t nextrel; /* number of external relocation entries */
+
+ uint32_t iinit_iterm; /* low 16 bits are the index into the init
+ section, high 16 bits are the index into
+ the term section */
+ uint32_t ninit_nterm; /* low 16 bits are the number of init section
+ entries, high 16 bits are the number of
+ term section entries */
+
+ uint32_t /* for this module size of */
+ objc_module_info_size; /* the (__OBJC,__module_info) section */
+ uint64_t /* for this module address of the start of */
+ objc_module_info_addr; /* the (__OBJC,__module_info) section */
+};
+
+/*
+ * The entries in the reference symbol table are used when loading the module
+ * (both by the static and dynamic link editors) and if the module is unloaded
+ * or replaced. Therefore all external symbols (defined and undefined) are
+ * listed in the module's reference table. The flags describe the type of
+ * reference that is being made. The constants for the flags are defined in
+ * <mach-o/nlist.h> as they are also used for symbol table entries.
+ */
+struct dylib_reference {
+ uint32_t isym:24, /* index into the symbol table */
+ flags:8; /* flags to indicate the type of reference */
+};
+
+/*
+ * The twolevel_hints_command contains the offset and number of hints in the
+ * two-level namespace lookup hints table.
+ */
+struct twolevel_hints_command {
+ uint32_t cmd; /* LC_TWOLEVEL_HINTS */
+ uint32_t cmdsize; /* sizeof(struct twolevel_hints_command) */
+ uint32_t offset; /* offset to the hint table */
+ uint32_t nhints; /* number of hints in the hint table */
+};
+
+/*
+ * The entries in the two-level namespace lookup hints table are twolevel_hint
+ * structs. These provide hints to the dynamic link editor where to start
+ * looking for an undefined symbol in a two-level namespace image. The
+ * isub_image field is an index into the sub-images (sub-frameworks and
+ * sub-umbrellas list) that made up the two-level image that the undefined
+ * symbol was found in when it was built by the static link editor. If
+ * isub-image is 0 the the symbol is expected to be defined in library and not
+ * in the sub-images. If isub-image is non-zero it is an index into the array
+ * of sub-images for the umbrella with the first index in the sub-images being
+ * 1. The array of sub-images is the ordered list of sub-images of the umbrella
+ * that would be searched for a symbol that has the umbrella recorded as its
+ * primary library. The table of contents index is an index into the
+ * library's table of contents. This is used as the starting point of the
+ * binary search or a directed linear search.
+ */
+struct twolevel_hint {
+ uint32_t
+ isub_image:8, /* index into the sub images */
+ itoc:24; /* index into the table of contents */
+};
+
+/*
+ * The prebind_cksum_command contains the value of the original check sum for
+ * prebound files or zero. When a prebound file is first created or modified
+ * for other than updating its prebinding information the value of the check sum
+ * is set to zero. When the file has it prebinding re-done and if the value of
+ * the check sum is zero the original check sum is calculated and stored in
+ * cksum field of this load command in the output file. If when the prebinding
+ * is re-done and the cksum field is non-zero it is left unchanged from the
+ * input file.
+ */
+struct prebind_cksum_command {
+ uint32_t cmd; /* LC_PREBIND_CKSUM */
+ uint32_t cmdsize; /* sizeof(struct prebind_cksum_command) */
+ uint32_t cksum; /* the check sum or zero */
+};
+
+/*
+ * The uuid load command contains a single 128-bit unique random number that
+ * identifies an object produced by the static link editor.
+ */
+struct uuid_command {
+ uint32_t cmd; /* LC_UUID */
+ uint32_t cmdsize; /* sizeof(struct uuid_command) */
+ uint8_t uuid[16]; /* the 128-bit uuid */
+};
+
+/*
+ * The rpath_command contains a path which at runtime should be added to
+ * the current run path used to find @rpath prefixed dylibs.
+ */
+struct rpath_command {
+ uint32_t cmd; /* LC_RPATH */
+ uint32_t cmdsize; /* includes string */
+ union lc_str path; /* path to add to run path */
+};
+
+/*
+ * The linkedit_data_command contains the offsets and sizes of a blob
+ * of data in the __LINKEDIT segment.
+ */
+struct linkedit_data_command {
+ uint32_t cmd; /* LC_CODE_SIGNATURE or LC_SEGMENT_SPLIT_INFO */
+ uint32_t cmdsize; /* sizeof(struct linkedit_data_command) */
+ uint32_t dataoff; /* file offset of data in __LINKEDIT segment */
+ uint32_t datasize; /* file size of data in __LINKEDIT segment */
+};
+
+/*
+ * The symseg_command contains the offset and size of the GNU style
+ * symbol table information as described in the header file <symseg.h>.
+ * The symbol roots of the symbol segments must also be aligned properly
+ * in the file. So the requirement of keeping the offsets aligned to a
+ * multiple of a 4 bytes translates to the length field of the symbol
+ * roots also being a multiple of a long. Also the padding must again be
+ * zeroed. (THIS IS OBSOLETE and no longer supported).
+ */
+struct symseg_command {
+ uint32_t cmd; /* LC_SYMSEG */
+ uint32_t cmdsize; /* sizeof(struct symseg_command) */
+ uint32_t offset; /* symbol segment offset */
+ uint32_t size; /* symbol segment size in bytes */
+};
+
+/*
+ * The ident_command contains a free format string table following the
+ * ident_command structure. The strings are null terminated and the size of
+ * the command is padded out with zero bytes to a multiple of 4 bytes/
+ * (THIS IS OBSOLETE and no longer supported).
+ */
+struct ident_command {
+ uint32_t cmd; /* LC_IDENT */
+ uint32_t cmdsize; /* strings that follow this command */
+};
+
+/*
+ * The fvmfile_command contains a reference to a file to be loaded at the
+ * specified virtual address. (Presently, this command is reserved for
+ * internal use. The kernel ignores this command when loading a program into
+ * memory).
+ */
+struct fvmfile_command {
+ uint32_t cmd; /* LC_FVMFILE */
+ uint32_t cmdsize; /* includes pathname string */
+ union lc_str name; /* files pathname */
+ uint32_t header_addr; /* files virtual address */
+};
+
+#endif /* _MACHO_LOADER_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/m68k/reloc.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* reloc.h - assemble for HP-PA */
+/* Defines machine specific relocation entries */
+
+#ifndef HPPA_RELOC_INCLUDED
+#define HPPA_RELOC_INCLUDED
+
+/*
+ * Relocation types used in the hppa implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * in <mach-o/reloc.h> and their r_type is HPPA_RELOC_VANILLA. The rest of the
+ * relocation types are for instructions. Since they are for instructions the
+ * r_address field indicates the 32 bit instruction that the relocation is to
+ * be preformed on. The field r_pcrel is set only for the HPPA_RELOC_BR17.
+ * And r_length is set to long for all non-RELOC_VANILLA r_types.
+ */
+enum reloc_type_hppa
+{
+ HPPA_RELOC_VANILLA, /* generic relocation as discribed in <mach-o/reloc.h>*/
+ HPPA_RELOC_PAIR, /* the second relocation entry of a pair */
+ HPPA_RELOC_HI21, /* a PAIR follows with the low part */
+ HPPA_RELOC_LO14, /* a PAIR follows with the high part */
+ HPPA_RELOC_BR17, /* 17 bit branch displacement (to a word address)
+ a PAIR follows with the high part */
+ HPPA_RELOC_BL17, /* a bl instruction (overlow causes an error) */
+ HPPA_RELOC_JBSR, /* a bl instruction that is targeted at a long branch
+ stub, a PAIR follows with the high part */
+ HPPA_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_HI21_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_LO14_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ HPPA_RELOC_PB_LA_PTR /* prebound lazy pointer */
+};
+
+/*
+ * For the HI and LO relocation types the two parts of the relocated expression
+ * (symbol + offset) are calculated as follows:
+ *
+ * rounded = round(offset, 0x2000);
+ * left21 = (symbol + rounded) & 0xfffff800;
+ * right14 = ((symbol + rounded) & 0x000007ff) + (offset - rounded);
+ *
+ * This allows the left part to be shared between references with different
+ * offsets as long as the rounded offsets are the same.
+ *
+ * The HPPA_RELOC_BR17 r_type also uses the above calculation and the right14
+ * bits, sign extened to fill the displacement, and converted to a word
+ * displacement by droping the low bits (after checking they are zero).
+ */
+
+/*
+ * For relocation types that use pairs the part of the relocated expression that
+ * is not stored in the instruction is stored in the r_address feild of the
+ * PAIR's entry.
+ *
+ * All low parts are stored as sign extened byte addressed values in the PAIR's
+ * r_address field as 32 bit values. This allows the HI21 not to have to know
+ * which type of low it is used with.
+ *
+ * The high parts are left justified 21 bit values zero filled to 32 bits and
+ * stored in the PAIR's r_address field.
+ */
+
+/*
+ * The instructions that use the non-RELOC_VANILLA r_types are and the r_types
+ * they use are as follows:
+ * instructions r_type
+ *
+ * LDIL,ADDIL HPPA_RELOC_HI21
+ * LDx, STx, LDO HPPA_RELOC_LO14
+ * BE, BLE HPPA_RELOC_BR17
+ * BL HPPA_RELOC_BL17
+ *
+ * For the HPPA_RELOC_JBSR the BL instruction must be targeted at a long branch
+ * stub that can be reached with 17 bits of signed word displacement. Also the
+ * stub must be in the same block as the BL instruction so that scattered
+ * loading done by the link editor will not move them apart. For example in
+ * assembly code:
+ * jbsr foo,%r2,L1 ; creates a bl inst with a HPPA_RELOC_JBSR
+ * ; relocation entry for the symbol foo and the
+ * ; instruction is targeted to L1
+ * ...
+ * L1: ldil L'foo,%r1 ; a HPPA_RELOC_HI21 entry for symbol foo
+ * ble,n R'foo(%sr4,%r1) ; a HPPA_RELOC_BR17 entry for symbol foo
+ */
+
+#endif /* HPPA_RELOC_INCLUDED */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/m88k/reloc.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Relocation types used in the m88k implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * above and their r_type is RELOC_VANILLA. The rest of the relocation types
+ * are for instructions. Since they are for instructions the r_address field
+ * indicates the 32 bit instruction that the relocation is to be preformed on.
+ * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types.
+ */
+enum reloc_type_m88k
+{
+ M88K_RELOC_VANILLA, /* generic relocation as discribed above */
+ M88K_RELOC_PAIR, /* the second relocation entry of a pair */
+ M88K_RELOC_PC16,
+ M88K_RELOC_PC26,
+ M88K_RELOC_HI16, /* a PAIR follows with the low half */
+ M88K_RELOC_LO16, /* a PAIR follows with the high half */
+ M88K_RELOC_SECTDIFF,/* a PAIR follows with subtract symbol value */
+ M88K_RELOC_PB_LA_PTR/* prebound lazy pointer */
+};
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/nlist.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACHO_NLIST_H_
+#define _MACHO_NLIST_H_
+/* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)nlist.h 8.2 (Berkeley) 1/21/94
+ */
+#include <stdint.h>
+
+/*
+ * Format of a symbol table entry of a Mach-O file for 32-bit architectures.
+ * Modified from the BSD format. The modifications from the original format
+ * were changing n_other (an unused field) to n_sect and the addition of the
+ * N_SECT type. These modifications are required to support symbols in a larger
+ * number of sections not just the three sections (text, data and bss) in a BSD
+ * file.
+ */
+struct nlist {
+ union {
+#ifndef __LP64__
+ char *n_name; /* for use when in-core */
+#endif
+ int32_t n_strx; /* index into the string table */
+ } n_un;
+ uint8_t n_type; /* type flag, see below */
+ uint8_t n_sect; /* section number or NO_SECT */
+ int16_t n_desc; /* see <mach-o/stab.h> */
+ uint32_t n_value; /* value of this symbol (or stab offset) */
+};
+
+/*
+ * This is the symbol table entry structure for 64-bit architectures.
+ */
+struct nlist_64 {
+ union {
+ uint32_t n_strx; /* index into the string table */
+ } n_un;
+ uint8_t n_type; /* type flag, see below */
+ uint8_t n_sect; /* section number or NO_SECT */
+ uint16_t n_desc; /* see <mach-o/stab.h> */
+ uint64_t n_value; /* value of this symbol (or stab offset) */
+};
+
+/*
+ * Symbols with a index into the string table of zero (n_un.n_strx == 0) are
+ * defined to have a null, "", name. Therefore all string indexes to non null
+ * names must not have a zero string index. This is bit historical information
+ * that has never been well documented.
+ */
+
+/*
+ * The n_type field really contains four fields:
+ * unsigned char N_STAB:3,
+ * N_PEXT:1,
+ * N_TYPE:3,
+ * N_EXT:1;
+ * which are used via the following masks.
+ */
+#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */
+#define N_PEXT 0x10 /* private external symbol bit */
+#define N_TYPE 0x0e /* mask for the type bits */
+#define N_EXT 0x01 /* external symbol bit, set for external symbols */
+
+/*
+ * Only symbolic debugging entries have some of the N_STAB bits set and if any
+ * of these bits are set then it is a symbolic debugging entry (a stab). In
+ * which case then the values of the n_type field (the entire field) are given
+ * in <mach-o/stab.h>
+ */
+
+/*
+ * Values for N_TYPE bits of the n_type field.
+ */
+#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */
+#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */
+#define N_SECT 0xe /* defined in section number n_sect */
+#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */
+#define N_INDR 0xa /* indirect */
+
+/*
+ * If the type is N_INDR then the symbol is defined to be the same as another
+ * symbol. In this case the n_value field is an index into the string table
+ * of the other symbol's name. When the other symbol is defined then they both
+ * take on the defined type and value.
+ */
+
+/*
+ * If the type is N_SECT then the n_sect field contains an ordinal of the
+ * section the symbol is defined in. The sections are numbered from 1 and
+ * refer to sections in order they appear in the load commands for the file
+ * they are in. This means the same ordinal may very well refer to different
+ * sections in different files.
+ *
+ * The n_value field for all symbol table entries (including N_STAB's) gets
+ * updated by the link editor based on the value of it's n_sect field and where
+ * the section n_sect references gets relocated. If the value of the n_sect
+ * field is NO_SECT then it's n_value field is not changed by the link editor.
+ */
+#define NO_SECT 0 /* symbol is not in any section */
+#define MAX_SECT 255 /* 1 thru 255 inclusive */
+
+/*
+ * Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
+ * who's values (n_value) are non-zero. In which case the value of the n_value
+ * field is the size (in bytes) of the common symbol. The n_sect field is set
+ * to NO_SECT. The alignment of a common symbol may be set as a power of 2
+ * between 2^1 and 2^15 as part of the n_desc field using the macros below. If
+ * the alignment is not set (a value of zero) then natural alignment based on
+ * the size is used.
+ */
+#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
+#define SET_COMM_ALIGN(n_desc,align) \
+ (n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
+
+/*
+ * To support the lazy binding of undefined symbols in the dynamic link-editor,
+ * the undefined symbols in the symbol table (the nlist structures) are marked
+ * with the indication if the undefined reference is a lazy reference or
+ * non-lazy reference. If both a non-lazy reference and a lazy reference is
+ * made to the same symbol the non-lazy reference takes precedence. A reference
+ * is lazy only when all references to that symbol are made through a symbol
+ * pointer in a lazy symbol pointer section.
+ *
+ * The implementation of marking nlist structures in the symbol table for
+ * undefined symbols will be to use some of the bits of the n_desc field as a
+ * reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
+ * of an nlist structure for an undefined symbol to determine the type of
+ * undefined reference (lazy or non-lazy).
+ *
+ * The constants for the REFERENCE FLAGS are propagated to the reference table
+ * in a shared library file. In that case the constant for a defined symbol,
+ * REFERENCE_FLAG_DEFINED, is also used.
+ */
+/* Reference type bits of the n_desc field of undefined symbols */
+#define REFERENCE_TYPE 0xf
+/* types of references */
+#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0
+#define REFERENCE_FLAG_UNDEFINED_LAZY 1
+#define REFERENCE_FLAG_DEFINED 2
+#define REFERENCE_FLAG_PRIVATE_DEFINED 3
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4
+#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5
+
+/*
+ * To simplify stripping of objects that use are used with the dynamic link
+ * editor, the static link editor marks the symbols defined an object that are
+ * referenced by a dynamicly bound object (dynamic shared libraries, bundles).
+ * With this marking strip knows not to strip these symbols.
+ */
+#define REFERENCED_DYNAMICALLY 0x0010
+
+/*
+ * For images created by the static link editor with the -twolevel_namespace
+ * option in effect the flags field of the mach header is marked with
+ * MH_TWOLEVEL. And the binding of the undefined references of the image are
+ * determined by the static link editor. Which library an undefined symbol is
+ * bound to is recorded by the static linker in the high 8 bits of the n_desc
+ * field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
+ * references the libraries listed in the Mach-O's LC_LOAD_DYLIB load commands
+ * in the order they appear in the headers. The library ordinals start from 1.
+ * For a dynamic library that is built as a two-level namespace image the
+ * undefined references from module defined in another use the same nlist struct
+ * an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
+ * defined symbols in all images they also must have the library ordinal set to
+ * SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
+ * image for references from plugins that refer to the executable that loads
+ * them.
+ *
+ * The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
+ * image that are looked up by the dynamic linker with flat namespace semantics.
+ * This ordinal was added as a feature in Mac OS X 10.3 by reducing the
+ * value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
+ * or binaries built with older tools to have 0xfe (254) dynamic libraries. In
+ * this case the ordinal value 0xfe (254) must be treated as a library ordinal
+ * for compatibility.
+ */
+#define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff)
+#define SET_LIBRARY_ORDINAL(n_desc,ordinal) \
+ (n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8))
+#define SELF_LIBRARY_ORDINAL 0x0
+#define MAX_LIBRARY_ORDINAL 0xfd
+#define DYNAMIC_LOOKUP_ORDINAL 0xfe
+#define EXECUTABLE_ORDINAL 0xff
+
+/*
+ * The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
+ * and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
+ */
+
+/*
+ * The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
+ * relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
+ * static link editor it is never to dead strip the symbol.
+ */
+#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */
+
+/*
+ * The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
+ * But is used in very rare cases by the dynamic link editor to mark an in
+ * memory symbol as discared and longer used for linking.
+ */
+#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */
+
+/*
+ * The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
+ * the undefined symbol is allowed to be missing and is to have the address of
+ * zero when missing.
+ */
+#define N_WEAK_REF 0x0040 /* symbol is weak referenced */
+
+/*
+ * The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
+ * linkers that the symbol definition is weak, allowing a non-weak symbol to
+ * also be used which causes the weak definition to be discared. Currently this
+ * is only supported for symbols in coalesed sections.
+ */
+#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */
+
+/*
+ * The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
+ * that the undefined symbol should be resolved using flat namespace searching.
+ */
+#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */
+
+#ifndef __STRICT_BSD__
+/*
+ * The function nlist(3) from the C library.
+ */
+extern int nlist (const char *filename, struct nlist *list);
+#endif /* __STRICT_BSD__ */
+
+#endif /* _MACHO_LIST_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/ppc/reloc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Relocation types used in the ppc implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * above and their r_type is RELOC_VANILLA. The rest of the relocation types
+ * are for instructions. Since they are for instructions the r_address field
+ * indicates the 32 bit instruction that the relocation is to be preformed on.
+ * The fields r_pcrel and r_length are ignored for non-RELOC_VANILLA r_types
+ * except for PPC_RELOC_BR14.
+ *
+ * For PPC_RELOC_BR14 if the r_length is the unused value 3, then the branch was
+ * statically predicted setting or clearing the Y-bit based on the sign of the
+ * displacement or the opcode. If this is the case the static linker must flip
+ * the value of the Y-bit if the sign of the displacement changes for non-branch
+ * always conditions.
+ */
+enum reloc_type_ppc
+{
+ PPC_RELOC_VANILLA, /* generic relocation as discribed above */
+ PPC_RELOC_PAIR, /* the second relocation entry of a pair */
+ PPC_RELOC_BR14, /* 14 bit branch displacement (to a word address) */
+ PPC_RELOC_BR24, /* 24 bit branch displacement (to a word address) */
+ PPC_RELOC_HI16, /* a PAIR follows with the low half */
+ PPC_RELOC_LO16, /* a PAIR follows with the high half */
+ PPC_RELOC_HA16, /* Same as the RELOC_HI16 except the low 16 bits and the
+ * high 16 bits are added together with the low 16 bits
+ * sign extened first. This means if bit 15 of the low
+ * 16 bits is set the high 16 bits stored in the
+ * instruction will be adjusted.
+ */
+ PPC_RELOC_LO14, /* Same as the LO16 except that the low 2 bits are not
+ * stored in the instruction and are always zero. This
+ * is used in double word load/store instructions.
+ */
+ PPC_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ PPC_RELOC_PB_LA_PTR,/* prebound lazy pointer */
+ PPC_RELOC_HI16_SECTDIFF, /* section difference forms of above. a PAIR */
+ PPC_RELOC_LO16_SECTDIFF, /* follows these with subtract symbol value */
+ PPC_RELOC_HA16_SECTDIFF,
+ PPC_RELOC_JBSR,
+ PPC_RELOC_LO14_SECTDIFF,
+ PPC_RELOC_LOCAL_SECTDIFF /* like PPC_RELOC_SECTDIFF, but the symbol
+ referenced was local. */
+};
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/ranlib.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* ranlib.h 4.1 83/05/03 */
+#ifndef _MACH_O_RANLIB_H_
+#define _MACH_O_RANLIB_H_
+
+#include <stdint.h>
+#include <sys/types.h> /* off_t */
+
+/*
+ * There are two known orders of table of contents for archives. The first is
+ * the order ranlib(1) originally produced and still produces without any
+ * options. This table of contents has the archive member name "__.SYMDEF"
+ * This order has the ranlib structures in the order the objects appear in the
+ * archive and the symbol names of those objects in the order of symbol table.
+ * The second know order is sorted by symbol name and is produced with the -s
+ * option to ranlib(1). This table of contents has the archive member name
+ * "__.SYMDEF SORTED" and many programs (notably the 1.0 version of ld(1) can't
+ * tell the difference between names because of the imbedded blank in the name
+ * and works with either table of contents). This second order is used by the
+ * post 1.0 link editor to produce faster linking. The original 1.0 version of
+ * ranlib(1) gets confused when it is run on a archive with the second type of
+ * table of contents because it and ar(1) which it uses use different ways to
+ * determined the member name (ar(1) treats all blanks in the name as
+ * significant and ranlib(1) only checks for the first one).
+ */
+#define SYMDEF "__.SYMDEF"
+#define SYMDEF_SORTED "__.SYMDEF SORTED"
+
+/*
+ * Structure of the __.SYMDEF table of contents for an archive.
+ * __.SYMDEF begins with a long giving the size in bytes of the ranlib
+ * structures which immediately follow, and then continues with a string
+ * table consisting of a long giving the number of bytes of strings which
+ * follow and then the strings themselves. The ran_strx fields index the
+ * string table whose first byte is numbered 0.
+ */
+struct ranlib {
+ union {
+ uint32_t ran_strx; /* string table index of */
+#ifndef __LP64__
+ char *ran_name; /* symbol defined by */
+#endif
+ } ran_un;
+ uint32_t ran_off; /* library member at this offset */
+};
+#endif /* _MACH_O_RANLIB_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/reloc.h
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* $NetBSD: exec.h,v 1.6 1994/10/27 04:16:05 cgd Exp $ */
+
+/*
+ * Copyright (c) 1993 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * 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.
+ */
+
+#ifndef _MACHO_RELOC_H_
+#define _MACHO_RELOC_H_
+#include <stdint.h>
+
+/*
+ * Format of a relocation entry of a Mach-O file. Modified from the 4.3BSD
+ * format. The modifications from the original format were changing the value
+ * of the r_symbolnum field for "local" (r_extern == 0) relocation entries.
+ * This modification is required to support symbols in an arbitrary number of
+ * sections not just the three sections (text, data and bss) in a 4.3BSD file.
+ * Also the last 4 bits have had the r_type tag added to them.
+ */
+struct relocation_info {
+ int32_t r_address; /* offset in the section to what is being
+ relocated */
+ uint32_t r_symbolnum:24, /* symbol index if r_extern == 1 or section
+ ordinal if r_extern == 0 */
+ r_pcrel:1, /* was relocated pc relative already */
+ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ r_extern:1, /* does not include value of sym referenced */
+ r_type:4; /* if not 0, machine specific relocation type */
+};
+#define R_ABS 0 /* absolute relocation type for Mach-O files */
+
+/*
+ * The r_address is not really the address as it's name indicates but an offset.
+ * In 4.3BSD a.out objects this offset is from the start of the "segment" for
+ * which relocation entry is for (text or data). For Mach-O object files it is
+ * also an offset but from the start of the "section" for which the relocation
+ * entry is for. See comments in <mach-o/loader.h> about the r_address feild
+ * in images for used with the dynamic linker.
+ *
+ * In 4.3BSD a.out objects if r_extern is zero then r_symbolnum is an ordinal
+ * for the segment the symbol being relocated is in. These ordinals are the
+ * symbol types N_TEXT, N_DATA, N_BSS or N_ABS. In Mach-O object files these
+ * ordinals refer to the sections in the object file in the order their section
+ * structures appear in the headers of the object file they are in. The first
+ * section has the ordinal 1, the second 2, and so on. This means that the
+ * same ordinal in two different object files could refer to two different
+ * sections. And further could have still different ordinals when combined
+ * by the link-editor. The value R_ABS is used for relocation entries for
+ * absolute symbols which need no further relocation.
+ */
+
+/*
+ * For RISC machines some of the references are split across two instructions
+ * and the instruction does not contain the complete value of the reference.
+ * In these cases a second, or paired relocation entry, follows each of these
+ * relocation entries, using a PAIR r_type, which contains the other part of the
+ * reference not contained in the instruction. This other part is stored in the
+ * pair's r_address field. The exact number of bits of the other part of the
+ * reference store in the r_address field is dependent on the particular
+ * relocation type for the particular architecture.
+ */
+
+/*
+ * To make scattered loading by the link editor work correctly "local"
+ * relocation entries can't be used when the item to be relocated is the value
+ * of a symbol plus an offset (where the resulting expresion is outside the
+ * block the link editor is moving, a blocks are divided at symbol addresses).
+ * In this case. where the item is a symbol value plus offset, the link editor
+ * needs to know more than just the section the symbol was defined. What is
+ * needed is the actual value of the symbol without the offset so it can do the
+ * relocation correctly based on where the value of the symbol got relocated to
+ * not the value of the expression (with the offset added to the symbol value).
+ * So for the NeXT 2.0 release no "local" relocation entries are ever used when
+ * there is a non-zero offset added to a symbol. The "external" and "local"
+ * relocation entries remain unchanged.
+ *
+ * The implemention is quite messy given the compatibility with the existing
+ * relocation entry format. The ASSUMPTION is that a section will never be
+ * bigger than 2**24 - 1 (0x00ffffff or 16,777,215) bytes. This assumption
+ * allows the r_address (which is really an offset) to fit in 24 bits and high
+ * bit of the r_address field in the relocation_info structure to indicate
+ * it is really a scattered_relocation_info structure. Since these are only
+ * used in places where "local" relocation entries are used and not where
+ * "external" relocation entries are used the r_extern field has been removed.
+ *
+ * For scattered loading to work on a RISC machine where some of the references
+ * are split across two instructions the link editor needs to be assured that
+ * each reference has a unique 32 bit reference (that more than one reference is
+ * NOT sharing the same high 16 bits for example) so it move each referenced
+ * item independent of each other. Some compilers guarantees this but the
+ * compilers don't so scattered loading can be done on those that do guarantee
+ * this.
+ */
+#if defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__)
+/*
+ * The reason for the ifdef's of __BIG_ENDIAN__ and __LITTLE_ENDIAN__ are that
+ * when stattered relocation entries were added the mistake of using a mask
+ * against a structure that is made up of bit fields was used. To make this
+ * design work this structure must be laid out in memory the same way so the
+ * mask can be applied can check the same bit each time (r_scattered).
+ */
+#endif /* defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__) */
+#define R_SCATTERED 0x80000000 /* mask to be applied to the r_address field
+ of a relocation_info structure to tell that
+ is is really a scattered_relocation_info
+ stucture */
+struct scattered_relocation_info {
+#ifdef __BIG_ENDIAN__
+ uint32_t r_scattered:1, /* 1=scattered, 0=non-scattered (see above) */
+ r_pcrel:1, /* was relocated pc relative already */
+ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ r_type:4, /* if not 0, machine specific relocation type */
+ r_address:24; /* offset in the section to what is being
+ relocated */
+ int32_t r_value; /* the value the item to be relocated is
+ refering to (without any offset added) */
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ uint32_t
+ r_address:24, /* offset in the section to what is being
+ relocated */
+ r_type:4, /* if not 0, machine specific relocation type */
+ r_length:2, /* 0=byte, 1=word, 2=long, 3=quad */
+ r_pcrel:1, /* was relocated pc relative already */
+ r_scattered:1; /* 1=scattered, 0=non-scattered (see above) */
+ int32_t r_value; /* the value the item to be relocated is
+ refering to (without any offset added) */
+#endif /* __LITTLE_ENDIAN__ */
+};
+
+/*
+ * Relocation types used in a generic implementation. Relocation entries for
+ * normal things use the generic relocation as discribed above and their r_type
+ * is GENERIC_RELOC_VANILLA (a value of zero).
+ *
+ * Another type of generic relocation, GENERIC_RELOC_SECTDIFF, is to support
+ * the difference of two symbols defined in different sections. That is the
+ * expression "symbol1 - symbol2 + constant" is a relocatable expression when
+ * both symbols are defined in some section. For this type of relocation the
+ * both relocations entries are scattered relocation entries. The value of
+ * symbol1 is stored in the first relocation entry's r_value field and the
+ * value of symbol2 is stored in the pair's r_value field.
+ *
+ * A special case for a prebound lazy pointer is needed to beable to set the
+ * value of the lazy pointer back to its non-prebound state. This is done
+ * using the GENERIC_RELOC_PB_LA_PTR r_type. This is a scattered relocation
+ * entry where the r_value feild is the value of the lazy pointer not prebound.
+ */
+enum reloc_type_generic
+{
+ GENERIC_RELOC_VANILLA, /* generic relocation as discribed above */
+ GENERIC_RELOC_PAIR, /* Only follows a GENERIC_RELOC_SECTDIFF */
+ GENERIC_RELOC_SECTDIFF,
+ GENERIC_RELOC_PB_LA_PTR, /* prebound lazy pointer */
+ GENERIC_RELOC_LOCAL_SECTDIFF
+};
+
+#endif /* _MACHO_RELOC_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/sparc/reloc.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* reloc.h - assemble for Sparc */
+/* Defines machine specific relocation entries */
+
+#ifndef SPARC_RELOC_INCLUDED
+#define SPARC_RELOC_INCLUDED
+
+/*
+ * Relocation types used in the sparc implementation. Relocation entries for
+ * things other than instructions use the same generic relocation as discribed
+ * in <mach-o/reloc.h> and their r_type is SPARC_RELOC_VANILLA. The rest of the
+ * relocation types are for instructions. Since they are for instructions the
+ * r_address field indicates the 32 bit instruction that the relocation is to
+ * be preformed on. The field r_pcrel is set only for the SPARC_RELOC_WDISP22
+ * and SPARC_RELOC_WDISP30. And r_length is set to long for all
+ * non-RELOC_VANILLA r_types.
+ */
+enum reloc_type_sparc
+{
+ SPARC_RELOC_VANILLA, /* vanilla relocation */
+ SPARC_RELOC_PAIR, /* the second relocation entry of a pair */
+ SPARC_RELOC_HI22, /* 22 high bits (sethi) (has pair) */
+ SPARC_RELOC_LO10, /* 10 low bits (has pair) */
+ SPARC_RELOC_WDISP22, /* 22 bit PC relative displacement */
+ SPARC_RELOC_WDISP30, /* 30 bit PC relative displacement */
+ SPARC_RELOC_SECTDIFF, /* a PAIR follows with subtract symbol value */
+ SPARC_RELOC_HI22_SECTDIFF,
+ SPARC_RELOC_LO10_SECTDIFF,
+ SPARC_RELOC_PB_LA_PTR /* prebound lazy pointer */
+};
+#endif /* SPARC_RELOC_INCLUDED */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/stab.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _MACHO_STAB_H_
+#define _MACHO_STAB_H_
+/* $NetBSD: stab.h,v 1.4 1994/10/26 00:56:25 cgd Exp $ */
+
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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.
+ *
+ * @(#)stab.h 5.2 (Berkeley) 4/4/91
+ */
+
+/*
+ * This file gives definitions supplementing <nlist.h> for permanent symbol
+ * table entries of Mach-O files. Modified from the BSD definitions. The
+ * modifications from the original definitions were changing what the values of
+ * what was the n_other field (an unused field) which is now the n_sect field.
+ * These modifications are required to support symbols in an arbitrary number of
+ * sections not just the three sections (text, data and bss) in a BSD file.
+ * The values of the defined constants have NOT been changed.
+ *
+ * These must have one of the N_STAB bits on. The n_value fields are subject
+ * to relocation according to the value of their n_sect field. So for types
+ * that refer to things in sections the n_sect field must be filled in with the
+ * proper section ordinal. For types that are not to have their n_value field
+ * relocatated the n_sect field must be NO_SECT.
+ */
+
+/*
+ * Symbolic debugger symbols. The comments give the conventional use for
+ *
+ * .stabs "n_name", n_type, n_sect, n_desc, n_value
+ *
+ * where n_type is the defined constant and not listed in the comment. Other
+ * fields not listed are zero. n_sect is the section ordinal the entry is
+ * refering to.
+ */
+#define N_GSYM 0x20 /* global symbol: name,,NO_SECT,type,0 */
+#define N_FNAME 0x22 /* procedure name (f77 kludge): name,,NO_SECT,0,0 */
+#define N_FUN 0x24 /* procedure: name,,n_sect,linenumber,address */
+#define N_STSYM 0x26 /* static symbol: name,,n_sect,type,address */
+#define N_LCSYM 0x28 /* .lcomm symbol: name,,n_sect,type,address */
+#define N_BNSYM 0x2e /* begin nsect sym: 0,,n_sect,0,address */
+#define N_OPT 0x3c /* emitted with gcc2_compiled and in gcc source */
+#define N_RSYM 0x40 /* register sym: name,,NO_SECT,type,register */
+#define N_SLINE 0x44 /* src line: 0,,n_sect,linenumber,address */
+#define N_ENSYM 0x4e /* end nsect sym: 0,,n_sect,0,address */
+#define N_SSYM 0x60 /* structure elt: name,,NO_SECT,type,struct_offset */
+#define N_SO 0x64 /* source file name: name,,n_sect,0,address */
+#define N_OSO 0x66 /* object file name: name,,0,0,st_mtime */
+#define N_LSYM 0x80 /* local sym: name,,NO_SECT,type,offset */
+#define N_BINCL 0x82 /* include file beginning: name,,NO_SECT,0,sum */
+#define N_SOL 0x84 /* #included file name: name,,n_sect,0,address */
+#define N_PARAMS 0x86 /* compiler parameters: name,,NO_SECT,0,0 */
+#define N_VERSION 0x88 /* compiler version: name,,NO_SECT,0,0 */
+#define N_OLEVEL 0x8A /* compiler -O level: name,,NO_SECT,0,0 */
+#define N_PSYM 0xa0 /* parameter: name,,NO_SECT,type,offset */
+#define N_EINCL 0xa2 /* include file end: name,,NO_SECT,0,0 */
+#define N_ENTRY 0xa4 /* alternate entry: name,,n_sect,linenumber,address */
+#define N_LBRAC 0xc0 /* left bracket: 0,,NO_SECT,nesting level,address */
+#define N_EXCL 0xc2 /* deleted include file: name,,NO_SECT,0,sum */
+#define N_RBRAC 0xe0 /* right bracket: 0,,NO_SECT,nesting level,address */
+#define N_BCOMM 0xe2 /* begin common: name,,NO_SECT,0,0 */
+#define N_ECOMM 0xe4 /* end common: name,,n_sect,0,0 */
+#define N_ECOML 0xe8 /* end common (local name): 0,,n_sect,0,address */
+#define N_LENG 0xfe /* second stab entry with length information */
+
+/*
+ * for the berkeley pascal compiler, pc(1):
+ */
+#define N_PC 0x30 /* global pascal symbol: name,,NO_SECT,subtype,line */
+
+#endif /* _MACHO_STAB_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach-o/x86_64/reloc.h
@@ -0,0 +1,174 @@
+/*
+ * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Relocations for x86_64 are a bit different than for other architectures in
+ * Mach-O: Scattered relocations are not used. Almost all relocations produced
+ * by the compiler are external relocations. An external relocation has the
+ * r_extern bit set to 1 and the r_symbolnum field contains the symbol table
+ * index of the target label.
+ *
+ * When the assembler is generating relocations, if the target label is a local
+ * label (begins with 'L'), then the previous non-local label in the same
+ * section is used as the target of the external relocation. An addend is used
+ * with the distance from that non-local label to the target label. Only when
+ * there is no previous non-local label in the section is an internal
+ * relocation used.
+ *
+ * The addend (i.e. the 4 in _foo+4) is encoded in the instruction (Mach-O does
+ * not have RELA relocations). For PC-relative relocations, the addend is
+ * stored directly in the instruction. This is different from other Mach-O
+ * architectures, which encode the addend minus the current section offset.
+ *
+ * The relocation types are:
+ *
+ * X86_64_RELOC_UNSIGNED // for absolute addresses
+ * X86_64_RELOC_SIGNED // for signed 32-bit displacement
+ * X86_64_RELOC_BRANCH // a CALL/JMP instruction with 32-bit displacement
+ * X86_64_RELOC_GOT_LOAD // a MOVQ load of a GOT entry
+ * X86_64_RELOC_GOT // other GOT references
+ * X86_64_RELOC_SUBTRACTOR // must be followed by a X86_64_RELOC_UNSIGNED
+ *
+ * The following are sample assembly instructions, followed by the relocation
+ * and section content they generate in an object file:
+ *
+ * call _foo
+ * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * E8 00 00 00 00
+ *
+ * call _foo+4
+ * r_type=X86_64_RELOC_BRANCH, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * E8 04 00 00 00
+ *
+ * movq _foo@GOTPCREL(%rip), %rax
+ * r_type=X86_64_RELOC_GOT_LOAD, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 48 8B 05 00 00 00 00
+ *
+ * pushq _foo@GOTPCREL(%rip)
+ * r_type=X86_64_RELOC_GOT, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * FF 35 00 00 00 00
+ *
+ * movl _foo(%rip), %eax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 8B 05 00 00 00 00
+ *
+ * movl _foo+4(%rip), %eax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * 8B 05 04 00 00 00
+ *
+ * movb $0x12, _foo(%rip)
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * C6 05 FF FF FF FF 12
+ *
+ * movl $0x12345678, _foo(%rip)
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_foo
+ * C7 05 FC FF FF FF 78 56 34 12
+ *
+ * .quad _foo
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00 00 00 00 00
+ *
+ * .quad _foo+4
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 04 00 00 00 00 00 00 00
+ *
+ * .quad _foo - _bar
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00 00 00 00 00
+ *
+ * .quad _foo - _bar + 4
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 04 00 00 00 00 00 00 00
+ *
+ * .long _foo - _bar
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_bar
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=2, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * 00 00 00 00
+ *
+ * lea L1(%rip), %rax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=1, r_pcrel=1, r_symbolnum=_prev
+ * 48 8d 05 12 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * lea L0(%rip), %rax
+ * r_type=X86_64_RELOC_SIGNED, r_length=2, r_extern=0, r_pcrel=1, r_symbolnum=3
+ * 48 8d 05 56 00 00 00
+ * // assumes L0 is in third section, has an address of 0x00000056 in .o
+ * // file, and there is no previous non-local label
+ *
+ * .quad L1
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * 12 00 00 00 00 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * .quad L0
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=0, r_pcrel=0, r_symbolnum=3
+ * 56 00 00 00 00 00 00 00
+ * // assumes L0 is in third section, has an address of 0x00000056 in .o
+ * // file, and there is no previous non-local label
+ *
+ * .quad _foo - .
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * EE FF FF FF FF FF FF FF
+ * // assumes _prev is the first non-local label 0x12 bytes before this
+ * // .quad
+ *
+ * .quad _foo - L1
+ * r_type=X86_64_RELOC_SUBTRACTOR, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_prev
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_extern=1, r_pcrel=0, r_symbolnum=_foo
+ * EE FF FF FF FF FF FF FF
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ * .quad L1 - _prev
+ * // No relocations. This is an assembly time constant.
+ * 12 00 00 00 00 00 00 00
+ * // assumes _prev is the first non-local label 0x12 bytes before L1
+ *
+ *
+ *
+ * In final linked images, there are only two valid relocation kinds:
+ *
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=1, r_symbolnum=sym_index
+ * This tells dyld to add the address of a symbol to a pointer sized (8-byte)
+ * piece of data (i.e on disk the 8-byte piece of data contains the addend). The
+ * r_symbolnum contains the index into the symbol table of the target symbol.
+ *
+ * r_type=X86_64_RELOC_UNSIGNED, r_length=3, r_pcrel=0, r_extern=0, r_symbolnum=0
+ * This tells dyld to adjust the pointer sized (8-byte) piece of data by the amount
+ * the containing image was loaded from its base address (e.g. slide).
+ *
+ */
+enum reloc_type_x86_64
+{
+ X86_64_RELOC_UNSIGNED, // for absolute addresses
+ X86_64_RELOC_SIGNED, // for signed 32-bit displacement
+ X86_64_RELOC_BRANCH, // a CALL/JMP instruction with 32-bit displacement
+ X86_64_RELOC_GOT_LOAD, // a MOVQ load of a GOT entry
+ X86_64_RELOC_GOT, // other GOT references
+ X86_64_RELOC_SUBTRACTOR, // must be followed by a X86_64_RELOC_UNSIGNED
+ X86_64_RELOC_SIGNED_1, // for signed 32-bit displacement with a -1 addend
+ X86_64_RELOC_SIGNED_2, // for signed 32-bit displacement with a -2 addend
+ X86_64_RELOC_SIGNED_4, // for signed 32-bit displacement with a -4 addend
+};
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/hppa/thread_status.h
@@ -0,0 +1,207 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/*
+ * @HP_COPYRIGHT@
+ */
+/*
+ * HISTORY
+ * Revision 1.1.1.1 1997/09/03 20:53:39 roland
+ * Initial checkin of SGS release 244
+ *
+ * Revision 1.4.3.2 1992/01/09 20:05:31 sharpe
+ * initial 1.1 vers from 1.0
+ * [1992/01/09 19:29:20 sharpe]
+ *
+ * Revision 1.4 1991/07/03 17:25:42 osfrcs
+ * 06/19/90 rand Add THREAD_STATE_FLAVOR_LIST to getstatus
+ * [91/06/21 17:29:52 brezak]
+ *
+ * Revision 1.3.2.2 91/06/21 18:05:17 brezak
+ * 06/19/90 rand Add THREAD_STATE_FLAVOR_LIST to getstatus
+ * [91/06/21 17:29:52 brezak]
+ *
+ * Revision 1.2.2.2 91/04/30 09:48:00 brezak
+ * rand 04/19/91 Add options to control reflection of assist/unalign exceptions
+ * [91/04/29 11:46:12 brezak]
+ *
+ * Revision 1.2 91/04/14 20:47:10 osfrcs
+ * Initial version.
+ * [91/03/30 09:32:42 brezak]
+ *
+ */
+
+#ifndef _HPPA_THREAD_STATE_
+#define _HPPA_THREAD_STATE_
+
+#include <mach/machine/boolean.h>
+
+
+#define HPPA_INTEGER_THREAD_STATE 1
+#define HPPA_FRAME_THREAD_STATE 2
+#define HPPA_FP_THREAD_STATE 3
+
+/*
+ * Flow control information that can
+ * be changed from user state (with
+ * some restrictions on psw).
+ */
+struct hp_pa_frame_thread_state {
+ unsigned long ts_pcsq_front; /* instruction address space front */
+ unsigned long ts_pcsq_back; /* instruction address space back */
+ unsigned long ts_pcoq_front; /* instruction offset space front */
+ unsigned long ts_pcoq_back; /* instruction offset space back */
+ unsigned long ts_psw; /* process status word */
+ unsigned long ts_unaligned_faults; /* number of unaligned data references READ-ONLY */
+ unsigned long ts_fault_address; /* address of failing page fault READ-ONLY */
+/*
+ * A step range is a range of address that
+ * will be executed with out generating a single
+ * step event. If both values are 0 no stepping
+ * will occur. Otherwise the program will run while:
+ *
+ * if (step_range_start <= step_range_stop)
+ * pcoq0 >= step_range_start && pcoq0 < step_range_stop
+ * if (step_range_start > step_range_stop)
+ * pcoq0 < step_range_stop && pcoq0 >= step_range_start
+ *
+ * notice that setting step_range_start and step_range_stop to the
+ * same non-zero value will execute only one instruction due to action
+ * of the pc queue. (Yes, nullified instructions count)
+ */
+ unsigned long ts_step_range_start;
+ unsigned long ts_step_range_stop;
+
+ /* Generate an exception when OS assists with an alignment fault */
+ boolean_t ts_alignment_trap_reflect;
+
+ /* Generate an exception when OS assists with an FP fault */
+ boolean_t ts_execution_trap_reflect;
+};
+
+/*
+ * Get rid of as soon as all users of frame_thread_state
+ * have been recompiled. XXX
+ */
+struct hp_pa_old_frame_thread_state {
+ unsigned long ts_pcsq_front; /* instruction address space front */
+ unsigned long ts_pcsq_back; /* instruction address space back */
+ unsigned long ts_pcoq_front; /* instruction offset space front */
+ unsigned long ts_pcoq_back; /* instruction offset space back */
+ unsigned long ts_psw; /* process status word */
+};
+
+/*
+ * The unsigned longeger state that may be changed by any
+ * process in user space.
+ */
+typedef struct hp_pa_integer_thread_state {
+ unsigned long ts_gr1; /* the user's general registers */
+ unsigned long ts_gr2;
+ unsigned long ts_gr3;
+ unsigned long ts_gr4;
+ unsigned long ts_gr5;
+ unsigned long ts_gr6;
+ unsigned long ts_gr7;
+ unsigned long ts_gr8;
+ unsigned long ts_gr9;
+ unsigned long ts_gr10;
+ unsigned long ts_gr11;
+ unsigned long ts_gr12;
+ unsigned long ts_gr13;
+ unsigned long ts_gr14;
+ unsigned long ts_gr15;
+ unsigned long ts_gr16;
+ unsigned long ts_gr17;
+ unsigned long ts_gr18;
+ unsigned long ts_gr19;
+ unsigned long ts_gr20;
+ unsigned long ts_gr21;
+ unsigned long ts_gr22;
+ unsigned long ts_gr23;
+ unsigned long ts_gr24;
+ unsigned long ts_gr25;
+ unsigned long ts_gr26;
+ unsigned long ts_gr27;
+ unsigned long ts_gr28;
+ unsigned long ts_gr29;
+ unsigned long ts_gr30;
+ unsigned long ts_gr31;
+ unsigned long ts_sr0; /* the user's space registgers */
+ unsigned long ts_sr1;
+ unsigned long ts_sr2;
+ unsigned long ts_sr3;
+ unsigned long ts_sar; /* the user's shift amount register */
+} hp_pa_integer_thread_state_t;
+
+/*
+ * The floating point state that may be changed by any
+ * process in user space.
+ */
+typedef struct hp_pa_fp_thread_state {
+ double ts_fp0; /* all of the execution unit registers */
+ double ts_fp1;
+ double ts_fp2;
+ double ts_fp3;
+ double ts_fp4;
+ double ts_fp5;
+ double ts_fp6;
+ double ts_fp7;
+ double ts_fp8;
+ double ts_fp9;
+ double ts_fp10;
+ double ts_fp11;
+ double ts_fp12;
+ double ts_fp13;
+ double ts_fp14;
+ double ts_fp15;
+ double ts_fp16;
+ double ts_fp17;
+ double ts_fp18;
+ double ts_fp19;
+ double ts_fp20;
+ double ts_fp21;
+ double ts_fp22;
+ double ts_fp23;
+ double ts_fp24;
+ double ts_fp25;
+ double ts_fp26;
+ double ts_fp27;
+ double ts_fp28;
+ double ts_fp29;
+ double ts_fp30;
+ double ts_fp31;
+} hp_pa_fp_thread_state_t;
+
+#define HPPA_INTEGER_THREAD_STATE_COUNT (sizeof(struct hp_pa_integer_thread_state) / sizeof(unsigned long))
+#define HPPA_FRAME_THREAD_STATE_COUNT (sizeof(struct hp_pa_frame_thread_state) / sizeof(unsigned long))
+#define HPPA_FP_THREAD_STATE_COUNT (sizeof(struct hp_pa_fp_thread_state) / sizeof(unsigned long))
+
+/* Get rid of as soon as all users of thread_frame_state have been recompiled XXX */
+#define HPPA_OLD_FRAME_THREAD_STATE_COUNT (sizeof(struct hp_pa_old_frame_thread_state) / sizeof(unsigned long))
+
+#endif /* _HPPA_THREAD_STATE_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/i860/thread_status.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/*
+ * Copyright (c) 1987, 1988 NeXT, Inc.
+ */
+
+#ifndef _I860_THREAD_STATE_
+#define _I860_THREAD_STATE_
+
+/*
+ * I860_thread_state_regs this is the structure that is exported
+ * to user threads for use in set/get
+ * status calls. This structure should
+ * never change.
+ */
+
+#define I860_THREAD_STATE_REGS (4) /* normal registers */
+
+struct i860_thread_state_regs {
+ int ireg[31]; /* core registers (incl stack pointer, but not r0) */
+ int freg[30]; /* FPU registers, except f0 and f1 */
+ int psr; /* user's processor status register */
+ int epsr; /* user's extended processor status register */
+ int db; /* user's data breakpoint register */
+ int pc; /* user's program counter */
+ int _padding_; /* not used */
+ /* Pipeline state for FPU */
+ double Mres3;
+ double Ares3;
+ double Mres2;
+ double Ares2;
+ double Mres1;
+ double Ares1;
+ double Ires1;
+ double Lres3m;
+ double Lres2m;
+ double Lres1m;
+ double KR;
+ double KI;
+ double T;
+ int Fsr3;
+ int Fsr2;
+ int Fsr1;
+ int Mergelo32;
+ int Mergehi32;
+};
+
+#define I860_THREAD_STATE_REGS_COUNT \
+ (sizeof (struct i860_thread_state_regs) / sizeof (int))
+
+#endif /* _I860_THREAD_STATE_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/m68k/thread_status.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/*
+ * Copyright (c) 1987, 1988 NeXT, Inc.
+ *
+ * HISTORY
+ * 15-May-91 Gregg Kellogg (gk) at NeXT
+ * Use m68k_saved_state instead of NeXT_saved_state.
+ * Use m68k_thread_state_regs NeXT_regs.
+ * Use m68k_thread_state_68882 NeXT_thread_state_68882.
+ * Use m68k_thread_state_user_reg NeXT_thread_state_user_reg.
+ * Moved m68k_saved_state and USER_REGS to pcb.h.
+ *
+ */
+
+#ifndef _MACH_M68K_THREAD_STATUS_
+#define _MACH_M68K_THREAD_STATUS_
+
+/*
+ * m68k_thread_state_regs this is the structure that is exported
+ * to user threads for use in set/get status
+ * calls. This structure should never
+ * change.
+ *
+ * m68k_thread_state_68882 this structure is exported to user threads
+ * to allow the to set/get 68882 floating
+ * pointer register state.
+ *
+ * m68k_saved_state this structure corresponds to the state
+ * of the user registers as saved on the
+ * stack upon kernel entry. This structure
+ * is used internally only. Since this
+ * structure may change from version to
+ * version, it is hidden from the user.
+ */
+
+#define M68K_THREAD_STATE_REGS (1) /* normal registers */
+#define M68K_THREAD_STATE_68882 (2) /* 68882 registers */
+#define M68K_THREAD_STATE_USER_REG (3) /* additional user register */
+
+#define M68K_THREAD_STATE_MAXFLAVOR (3)
+
+struct m68k_thread_state_regs {
+ int dreg[8]; /* data registers */
+ int areg[8]; /* address registers (incl stack pointer) */
+ short pad0; /* not used */
+ short sr; /* user's status register */
+ int pc; /* user's program counter */
+};
+
+#define M68K_THREAD_STATE_REGS_COUNT \
+ (sizeof (struct m68k_thread_state_regs) / sizeof (int))
+
+struct m68k_thread_state_68882 {
+ struct {
+ int fp[3]; /* 96-bit extended format */
+ } regs[8];
+ int cr; /* control */
+ int sr; /* status */
+ int iar; /* instruction address */
+ int state; /* execution state */
+};
+
+#define M68K_THREAD_STATE_68882_COUNT \
+ (sizeof (struct m68k_thread_state_68882) / sizeof (int))
+
+struct m68k_thread_state_user_reg {
+ int user_reg; /* user register (used by cthreads) */
+};
+
+#define M68K_THREAD_STATE_USER_REG_COUNT \
+ (sizeof (struct m68k_thread_state_user_reg) / sizeof (int))
+
+#endif /* _MACH_M68K_THREAD_STATUS_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/m88k/thread_status.h
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* Copyright (c) 1991 NeXT Computer, Inc. All rights reserved.
+ *
+ * File: mach/m88k/thread_status.h
+ * Author: Mike DeMoney, NeXT Computer, Inc.
+ *
+ * This include file defines the per-thread state
+ * for NeXT 88K-based products.
+ *
+ * HISTORY
+ * 23-Jan-91 Mike DeMoney (mike@next.com)
+ * Created.
+ *
+ * FIXME:
+ * All of these types should be pulled from architecture.
+ * Solve possible conflicting types problem for implementations
+ * by making user define an implementation (e.g. #define __M88110__)
+ * to get a implementation specific features.
+ *
+ * Put fp envelope stuff in mach/m88k/m88110_fpee.h.
+ */
+
+#ifndef _MACH_M88K_THREAD_STATE_
+#define _MACH_M88K_THREAD_STATE_
+
+#import <architecture/m88k/fp_regs.h>
+#import <architecture/m88k/reg_help.h>
+
+/**************************************************************************
+ * Data Typedefs used by thread_getstatus() and thread_setstatus() *
+ * NOTE: FP control and status regs described in <mach/m88k/fp_regs.h> *
+ **************************************************************************/
+
+#define M88K_THREAD_STATE_GRF (1) // general registers
+#define M88K_THREAD_STATE_XRF (2) // extended and fp registers
+#define M88K_THREAD_STATE_USER (3) // non-architectural user state
+#define M88110_THREAD_STATE_IMPL (4) // 88110 impl specific
+
+#define M88K_THREAD_STATE_MAXFLAVOR (M88110_THREAD_STATE_IMPL)
+
+/*
+ * m88k_thread_state_grf -- basic thread state for NeXT 88K-based products
+ */
+typedef struct _m88k_thread_state_grf {
+ unsigned r1; // rpc: return pc, caller-saved
+ unsigned r2; // a0: argument 0, caller-saved
+ unsigned r3; // a1
+ unsigned r4; // a2
+ unsigned r5; // a3
+ unsigned r6; // a4
+ unsigned r7; // a5
+ unsigned r8; // a6
+ unsigned r9; // a7
+ unsigned r10; // t0: temporary, caller-saved
+ unsigned r11; // t1
+ unsigned r12; // t2: struct return ptr,
+ unsigned r13; // t3
+ unsigned r14; // s0: saved, callee-saved
+ unsigned r15; // s1
+ unsigned r16; // s2
+ unsigned r17; // s3
+ unsigned r18; // s4
+ unsigned r19; // s5
+ unsigned r20; // s6
+ unsigned r21; // s7
+ unsigned r22; // s8
+ unsigned r23; // s9
+ unsigned r24; // s10
+ unsigned r25; // s11
+ unsigned r26; // t4
+ unsigned r27; // at: temp, used by asm macros
+ unsigned r28; // lk0: reserved for link editor
+ unsigned r29; // lk1
+ unsigned r30; // fp: frame ptr, callee-saved
+ unsigned r31; // sp: stack ptr, callee-saved
+ unsigned xip; // executing instruction pointer
+ unsigned xip_in_bd; // non-zero => xip in branch delay slot
+ /*
+ * nip is only valid if xip_in_bd is TRUE
+ */
+ unsigned nip; // next instruction pointer
+} m88k_thread_state_grf_t;
+
+#define M88K_THREAD_STATE_GRF_COUNT \
+ (sizeof(m88k_thread_state_grf_t)/sizeof(int))
+
+/*
+ * m88k_thread_state_xrf -- extended register file contents and floating point
+ * control registers for NeXT 88K-based products.
+ */
+typedef struct _m88k_thread_state_xrf {
+ m88k_xrf_t x1; // caller-saved
+ m88k_xrf_t x2;
+ m88k_xrf_t x3;
+ m88k_xrf_t x4;
+ m88k_xrf_t x5;
+ m88k_xrf_t x6;
+ m88k_xrf_t x7;
+ m88k_xrf_t x8;
+ m88k_xrf_t x9;
+ m88k_xrf_t x10;
+ m88k_xrf_t x11;
+ m88k_xrf_t x12;
+ m88k_xrf_t x13;
+ m88k_xrf_t x14;
+ m88k_xrf_t x15;
+ m88k_xrf_t x16;
+ m88k_xrf_t x17;
+ m88k_xrf_t x18;
+ m88k_xrf_t x19;
+ m88k_xrf_t x20;
+ m88k_xrf_t x21;
+ m88k_xrf_t x22; // callee-saved
+ m88k_xrf_t x23;
+ m88k_xrf_t x24;
+ m88k_xrf_t x25;
+ m88k_xrf_t x26;
+ m88k_xrf_t x27;
+ m88k_xrf_t x28;
+ m88k_xrf_t x29;
+ m88k_xrf_t x30; // reserved
+ m88k_xrf_t x31;
+ m88k_fpsr_t fpsr; // fp status, fcr62
+ m88k_fpcr_t fpcr; // fp control, fcr63
+} m88k_thread_state_xrf_t;
+
+#define M88K_THREAD_STATE_XRF_COUNT \
+ (sizeof(m88k_thread_state_xrf_t)/sizeof(int))
+
+typedef struct _m88k_thread_state_user {
+ int user; // user register (for cthreads)
+} m88k_thread_state_user_t;
+
+#define M88K_THREAD_STATE_USER_COUNT \
+ (sizeof(m88k_thread_state_user_t)/sizeof(int))
+
+/*
+ * Motorola 88110 specific state
+ * (Can't count on this being in all m88k implementations.)
+ */
+
+#define M88110_N_DATA_BP 2 // 88110 supports 2 data bp's
+
+/*
+ * Data Breakpoint Address Match Mask -- actually indicates don't
+ * care bits in addr
+ */
+typedef enum {
+ M88110_MATCH_BYTE = 0,
+ M88110_MATCH_SHORT = 0x1,
+ M88110_MATCH_WORD = 0x3,
+ M88110_MATCH_DOUBLE = 0x7,
+ M88110_MATCH_QUAD = 0xf,
+ M88110_MATCH_32 = 0x1f,
+ M88110_MATCH_64 = 0x3f,
+ M88110_MATCH_128 = 0x7f,
+ M88110_MATCH_256 = 0xff,
+ M88110_MATCH_512 = 0x1ff,
+ M88110_MATCH_1024 = 0x3ff,
+ M88110_MATCH_2048 = 0x7ff,
+ M88110_MATCH_4096 = 0xfff
+} m88110_match_t;
+
+/*
+ * Data Breakpoint Control Word
+ */
+typedef struct {
+ unsigned :BITS_WIDTH(31,29);
+ unsigned rw:BIT_WIDTH(28); // 1 => read access
+ unsigned rwm:BIT_WIDTH(27); // 0 => rw is don't care
+ unsigned :BITS_WIDTH(26,13);
+ m88110_match_t addr_match:BITS_WIDTH(12,1); // addr(12,1) don't cares
+ unsigned v:BIT_WIDTH(0);
+} m88110_bp_ctrl_t;
+
+/*
+ * A complete Data Breakpoint spec
+ */
+typedef struct {
+ unsigned addr; // data address
+ m88110_bp_ctrl_t ctrl;
+} m88110_data_bp_t;
+
+/*
+ * m88110_psr_t -- 88110 Processor Status Register
+ * System prohibits modification of supr, le, se, sgn_imd, sm and mxm_dis
+ * bits for user threads.
+ */
+typedef struct {
+ unsigned supr:BIT_WIDTH(31);
+ unsigned le:BIT_WIDTH(30); // little endian mode
+ unsigned se:BIT_WIDTH(29); // serial exec mode
+ unsigned c:BIT_WIDTH(28); // carry
+ unsigned :BIT_WIDTH(27);
+ unsigned sgn_imd:BIT_WIDTH(26); // signed immediates
+ unsigned sm:BIT_WIDTH(25); // serialize mem refs
+ unsigned :BIT_WIDTH(24);
+ unsigned trace:BIT_WIDTH(23);
+ unsigned :BITS_WIDTH(22,5);
+ unsigned sfu2dis:BIT_WIDTH(4); // gpu (sfu2) disable
+ unsigned sfu1dis:BIT_WIDTH(3); // fpu (sfu1) disable
+ unsigned mxm_dis:BIT_WIDTH(2); // misaligned dis
+ unsigned :BITS_WIDTH(1,0);
+} m88110_psr_t;
+
+/*
+ * Information for IEEE floating point user trap handlers
+ */
+typedef enum {
+ M88110_IRESULT_SIZE_NONE = 0, // no intermediate result
+ M88110_IRESULT_SIZE_SINGLE = 1, // single precision result
+ M88110_IRESULT_SIZE_DOUBLE = 2, // double precision result
+ M88110_IRESULT_SIZE_EXTENDED = 3 // double extended result
+} m88110_iresult_size_t;
+
+typedef struct {
+ unsigned :BITS_WIDTH(31,16); // unused
+ m88110_iresult_size_t iresult_size:BITS_WIDTH(15,14);
+ // size of iresult
+ unsigned :BITS_WIDTH(13,9); // unused
+ unsigned sfu1_disabled:BIT_WIDTH(8); // sfu disabled
+ unsigned int:BIT_WIDTH(7); // invalid int conv
+ unsigned unimp:BIT_WIDTH(6); // unimp ctrl reg
+ unsigned priv:BIT_WIDTH(5); // priv violation
+ unsigned efinv:BIT_WIDTH(4); // IEEE EFINV
+ unsigned efdvz:BIT_WIDTH(3); // IEEE EFDVZ
+ unsigned efunf:BIT_WIDTH(2); // IEEE EFUNF
+ unsigned efovf:BIT_WIDTH(1); // IEEE EFOVF
+ unsigned efinx:BIT_WIDTH(0); // IEEE EFINX
+} m88110_fp_trap_status_t;
+
+/*
+ * m88110_thread_state_impl -- 88110 implementation-specific
+ * control registers for NeXT 88K-based products.
+ */
+typedef struct _m88110_thread_state_impl {
+ m88110_data_bp_t data_bp[M88110_N_DATA_BP];
+
+ /*
+ * Certain of the 88110 psr bits may be modified
+ */
+ m88110_psr_t psr; // processor status
+ /*
+ * IEEE floating point user trap information. Read only.
+ * (Only valid immediately after an EXC_ARITHMETIC
+ * exception with code EXC_M88K_SFU1_EXCP. Trap
+ * handlers must determine operation, source and
+ * destination registers by fetching instruction at
+ * exip.)
+ */
+ m88k_xrf_t intermediate_result;
+ m88110_fp_trap_status_t fp_trap_status;
+} m88110_thread_state_impl_t;
+
+#define M88110_THREAD_STATE_IMPL_COUNT \
+ (sizeof(m88110_thread_state_impl_t)/sizeof(int))
+
+#endif /* _MACH_M88K_THREAD_STATE_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/machine.h
@@ -0,0 +1,383 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Mach Operating System
+ * Copyright (c) 1989 Carnegie-Mellon University
+ * Copyright (c) 1988 Carnegie-Mellon University
+ * Copyright (c) 1987 Carnegie-Mellon University
+ * All rights reserved. The CMU software License Agreement specifies
+ * the terms and conditions for use and redistribution.
+ */
+/*
+ * HISTORY
+ * Revision 1.1.1.1 1997/09/03 20:53:37 roland
+ * Initial checkin of SGS release 244
+ *
+ * 2 July 1992 Mac Gillon at NeXT
+ * Changed HPPA subtypes to follow our practice.
+ *
+ * 11 September 1992 David E. Bohman at NeXT
+ * Added CPU_SUBTYPE_486SX to the i386 family.
+ *
+ * 16 July 1992 David E. Bohman at NeXT
+ * Added CPU_SUBTYPE_586 to the i386 family.
+ *
+ * 17-Dec-91 Peter King (king) at NeXT
+ * Added support for the XXX_ALL subtypes. These are used to
+ * tag object files that can run on any implementation of a
+ * particular family.
+ *
+ * 1-Mar-90 John Seamons (jks) at NeXT
+ * Redefined cpu_type and cpu_subtype definitions to indicate processor
+ * architecture instead of product types for the MC680x0.
+ *
+ * Revision 2.15 89/10/11 14:39:56 dlb
+ * Removed should_exit - replaced by action thread.
+ * [89/01/25 dlb]
+ *
+ * Revision 2.14 89/07/14 17:21:39 rvb
+ * Added CPU types and subtypes for MC68030, MC68040, MC88000,
+ * HPPA, ARM and Sun4-SPARC.
+ * [89/07/13 mrt]
+ *
+ * Revision 2.12 89/05/30 10:38:58 rvb
+ * Add R2000 machine types.
+ * [89/05/30 08:28:53 rvb]
+ *
+ * Revision 2.11 89/04/18 16:43:32 mwyoung
+ * Use <machine/vm_types.h> rather than <vm/vm_param.h> to get
+ * VM types. Remove old history... none of it was insightful.
+ *
+ * The variable declarations should be moved elsewhere.
+ * [89/01/24 mwyoung]
+ *
+ */
+/*
+ * Machine independent machine abstraction.
+ * Copyright (C) 1986, Avadis Tevanian, Jr.
+ */
+
+#ifndef _MACH_MACHINE_H_
+#define _MACH_MACHINE_H_
+
+#import <mach/machine/vm_types.h>
+#import <mach/boolean.h>
+
+/*
+ * For each host, there is a maximum possible number of
+ * cpus that may be available in the system. This is the
+ * compile-time constant NCPUS, which is defined in cpus.h.
+ *
+ * In addition, there is a machine_slot specifier for each
+ * possible cpu in the system.
+ */
+
+struct machine_info {
+ int major_version; /* kernel major version id */
+ int minor_version; /* kernel minor version id */
+ int max_cpus; /* max number of cpus compiled */
+ int avail_cpus; /* number actually available */
+ vm_size_t memory_size; /* size of memory in bytes */
+};
+
+typedef struct machine_info *machine_info_t;
+typedef struct machine_info machine_info_data_t; /* bogus */
+
+typedef int cpu_type_t;
+typedef int cpu_subtype_t;
+typedef integer_t cpu_threadtype_t;
+
+#define CPU_STATE_MAX 3
+
+#define CPU_STATE_USER 0
+#define CPU_STATE_SYSTEM 1
+#define CPU_STATE_IDLE 2
+
+struct machine_slot {
+ boolean_t is_cpu; /* is there a cpu in this slot? */
+ cpu_type_t cpu_type; /* type of cpu */
+ cpu_subtype_t cpu_subtype; /* subtype of cpu */
+ volatile boolean_t running; /* is cpu running */
+ long cpu_ticks[CPU_STATE_MAX];
+ int clock_freq; /* clock interrupt frequency */
+};
+
+typedef struct machine_slot *machine_slot_t;
+typedef struct machine_slot machine_slot_data_t; /* bogus */
+
+#ifdef KERNEL
+extern struct machine_info machine_info;
+extern struct machine_slot machine_slot[];
+
+extern vm_offset_t interrupt_stack[];
+#endif /* KERNEL */
+
+/*
+ * Machine types known by all.
+ */
+
+#define CPU_TYPE_ANY ((cpu_type_t) -1)
+
+#define CPU_TYPE_VAX ((cpu_type_t) 1)
+#define CPU_TYPE_ROMP ((cpu_type_t) 2)
+#define CPU_TYPE_NS32032 ((cpu_type_t) 4)
+#define CPU_TYPE_NS32332 ((cpu_type_t) 5)
+#define CPU_TYPE_MC680x0 ((cpu_type_t) 6)
+#define CPU_TYPE_I386 ((cpu_type_t) 7)
+#define CPU_TYPE_X86_64 ((cpu_type_t) (CPU_TYPE_I386 | CPU_ARCH_ABI64))
+#define CPU_TYPE_MIPS ((cpu_type_t) 8)
+#define CPU_TYPE_NS32532 ((cpu_type_t) 9)
+#define CPU_TYPE_HPPA ((cpu_type_t) 11)
+#define CPU_TYPE_ARM ((cpu_type_t) 12)
+#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
+#define CPU_TYPE_SPARC ((cpu_type_t) 14)
+#define CPU_TYPE_I860 ((cpu_type_t) 15) // big-endian
+#define CPU_TYPE_I860_LITTLE ((cpu_type_t) 16) // little-endian
+#define CPU_TYPE_RS6000 ((cpu_type_t) 17)
+#define CPU_TYPE_MC98000 ((cpu_type_t) 18)
+#define CPU_TYPE_POWERPC ((cpu_type_t) 18)
+#define CPU_ARCH_ABI64 0x1000000
+#define CPU_TYPE_POWERPC64 ((cpu_type_t)(CPU_TYPE_POWERPC | CPU_ARCH_ABI64))
+#define CPU_TYPE_VEO ((cpu_type_t) 255)
+
+
+/*
+ * Machine subtypes (these are defined here, instead of in a machine
+ * dependent directory, so that any program can get all definitions
+ * regardless of where is it compiled).
+ */
+
+/*
+ * Capability bits used in the definition of cpu_subtype.
+ */
+#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */
+#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */
+
+
+/*
+ * Object files that are hand-crafted to run on any
+ * implementation of an architecture are tagged with
+ * CPU_SUBTYPE_MULTIPLE. This functions essentially the same as
+ * the "ALL" subtype of an architecture except that it allows us
+ * to easily find object files that may need to be modified
+ * whenever a new implementation of an architecture comes out.
+ *
+ * It is the responsibility of the implementor to make sure the
+ * software handles unsupported implementations elegantly.
+ */
+#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1)
+
+
+/*
+ * VAX subtypes (these do *not* necessary conform to the actual cpu
+ * ID assigned by DEC available via the SID register).
+ */
+
+#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6)
+#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7)
+#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8)
+#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9)
+#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10)
+#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11)
+#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12)
+
+/*
+ * ROMP subtypes.
+ */
+
+#define CPU_SUBTYPE_RT_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_RT_PC ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_RT_APC ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_RT_135 ((cpu_subtype_t) 3)
+
+/*
+ * 32032/32332/32532 subtypes.
+ */
+
+#define CPU_SUBTYPE_MMAX_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MMAX_DPC ((cpu_subtype_t) 1) /* 032 CPU */
+#define CPU_SUBTYPE_SQT ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_MMAX_APC_FPU ((cpu_subtype_t) 3) /* 32081 FPU */
+#define CPU_SUBTYPE_MMAX_APC_FPA ((cpu_subtype_t) 4) /* Weitek FPA */
+#define CPU_SUBTYPE_MMAX_XPC ((cpu_subtype_t) 5) /* 532 CPU */
+
+/*
+ * I386 subtypes.
+ */
+
+#define CPU_SUBTYPE_I386_ALL ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_X86_64_ALL CPU_SUBTYPE_I386_ALL
+#define CPU_SUBTYPE_386 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_486 ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_486SX ((cpu_subtype_t) 4 + 128)
+#define CPU_SUBTYPE_586 ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4))
+#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
+#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
+#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
+#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
+#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
+
+#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
+#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
+
+#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
+#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
+
+
+/*
+ * Mips subtypes.
+ */
+
+#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4)
+
+/*
+ * 680x0 subtypes
+ *
+ * The subtype definitions here are unusual for historical reasons.
+ * NeXT used to consider 68030 code as generic 68000 code. For
+ * backwards compatability:
+ *
+ * CPU_SUBTYPE_MC68030 symbol has been preserved for source code
+ * compatability.
+ *
+ * CPU_SUBTYPE_MC680x0_ALL has been defined to be the same
+ * subtype as CPU_SUBTYPE_MC68030 for binary comatability.
+ *
+ * CPU_SUBTYPE_MC68030_ONLY has been added to allow new object
+ * files to be tagged as containing 68030-specific instructions.
+ */
+
+#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */
+#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3)
+
+/*
+ * HPPA subtypes for Hewlett-Packard HP-PA family of
+ * risc processors. Port by NeXT to 700 series.
+ */
+
+#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */
+#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1)
+
+/*
+ * Acorn subtypes - Acorn Risc Machine port done by
+ * Olivetti System Software Laboratory
+ */
+
+#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_ARM_A500_ARCH ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_ARM_A500 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_ARM_A440 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_ARM_M4 ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_ARM_A680 ((cpu_subtype_t) 5)
+
+/*
+ * MC88000 subtypes
+ */
+#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MMAX_JPC ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2)
+
+/*
+ * MC98000 (PowerPC) subtypes
+ */
+#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1)
+
+/*
+ * I860 subtypes
+ */
+#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1)
+
+/*
+ * I860 subtypes for NeXT-internal backwards compatability.
+ * These constants will be going away. DO NOT USE THEM!!!
+ */
+#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1)
+
+/*
+ * I860_LITTLE subtypes
+ */
+#define CPU_SUBTYPE_I860_LITTLE_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_I860_LITTLE ((cpu_subtype_t) 1)
+
+/*
+ * RS6000 subtypes
+ */
+#define CPU_SUBTYPE_RS6000_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_RS6000 ((cpu_subtype_t) 1)
+
+/*
+ * Sun4 subtypes - port done at CMU
+ */
+#define CPU_SUBTYPE_SUN4_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_SUN4_260 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_SUN4_110 ((cpu_subtype_t) 2)
+
+#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0)
+
+/*
+ * PowerPC subtypes
+ */
+#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0)
+#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5)
+#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6)
+#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7)
+#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8)
+#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9)
+#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10)
+#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11)
+#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
+
+/*
+ * VEO subtypes
+ * Note: the CPU_SUBTYPE_VEO_ALL will likely change over time to be defined as
+ * one of the specific subtypes.
+ */
+#define CPU_SUBTYPE_VEO_1 ((cpu_subtype_t) 1)
+#define CPU_SUBTYPE_VEO_2 ((cpu_subtype_t) 2)
+#define CPU_SUBTYPE_VEO_3 ((cpu_subtype_t) 3)
+#define CPU_SUBTYPE_VEO_4 ((cpu_subtype_t) 4)
+#define CPU_SUBTYPE_VEO_ALL CPU_SUBTYPE_VEO_2
+
+#endif /* _MACH_MACHINE_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/mach/sparc/thread_status.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/*
+ * Copyright (c) 1994 by Sun Microsystems, Inc
+ */
+
+#ifndef _MACH_SPARC_THREAD_STATUS_H_
+#define _MACH_SPARC_THREAD_STATUS_H_
+
+#include <architecture/sparc/reg.h>
+
+/*
+ * sparc_thread_state_regs
+ * This is the structure that is exported
+ * to user threads for use in set/get status
+ * calls. This structure should never change.
+ * The "local" and "in" registers of the corresponding
+ * register window are saved in the stack frame pointed
+ * to by sp -> %o6.
+ *
+ * sparc_thread_state_fpu
+ * This is the structure that is exported
+ * to user threads for use in set/get FPU register
+ * status calls.
+ *
+ */
+
+#define SPARC_THREAD_STATE_REGS 1
+
+struct sparc_thread_state_regs {
+ struct regs regs;
+};
+
+#define SPARC_THREAD_STATE_REGS_COUNT \
+ (sizeof(struct sparc_thread_state_regs) / sizeof(int))
+
+/*
+ * Floating point unit registers
+ */
+
+#define SPARC_THREAD_STATE_FPU 2
+
+
+struct sparc_thread_state_fpu {
+ struct fpu fpu; /* floating point registers/status */
+};
+
+#define SPARC_THREAD_STATE_FPU_COUNT \
+ (sizeof(struct sparc_thread_state_fpu) / sizeof(int))
+
+#define SPARC_THREAD_STATE_FLAVOR_COUNT 2
+
+#define SPARC_THREAD_STATE_FLAVOR_LIST_COUNT \
+ ( SPARC_THREAD_STATE_FLAVOR_COUNT * \
+ (sizeof (struct thread_state_flavor) / sizeof(int)))
+
+#endif /* _MACH_SPARC_THREAD_STATUS_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/allocate.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+/* defined in allocate.c */
+
+__private_extern__ void *allocate(
+ unsigned long size);
+
+__private_extern__ void *reallocate(
+ void *,
+ unsigned long size);
+
+__private_extern__ char *savestr(
+ const char *s);
+
+__private_extern__ char *makestr(
+ const char *args, ...);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/arch.h
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef _STUFF_ARCH_H_
+#define _STUFF_ARCH_H_
+
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+/*
+ * This file contains the current known set of flags and constants for the
+ * known architectures.
+ */
+#include <mach/machine.h>
+#include <stuff/bytesex.h>
+
+/*
+ * The structure describing an architecture flag with the string of the flag
+ * name, and the cputype and cpusubtype.
+ */
+struct arch_flag {
+ char *name;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+};
+
+/*
+ * get_arch_from_flag() is passed a name of an architecture flag and returns
+ * zero if that flag is not known and non-zero if the flag is known.
+ * If the pointer to the arch_flag is not NULL it is filled in with the
+ * arch_flag struct that matches the name.
+ */
+__private_extern__ int get_arch_from_flag(
+ char *name,
+ struct arch_flag *arch_flag);
+
+/*
+ * get_arch_from_host() gets the architecture from the host this is running on
+ * and returns zero if the architecture is not known and zero if the
+ * architecture is known. If the parameters family_arch_flag and
+ * specific_arch_flag are not NULL they get fill in with the family
+ * architecture and specific architecure for the host. If the architecture
+ * is unknown and the parameters are not NULL then all fields are set to zero.
+ */
+__private_extern__ int get_arch_from_host(
+ struct arch_flag *family_arch_flag,
+ struct arch_flag *specific_arch_flag);
+
+/*
+ * get_arch_flags() returns a pointer to an array of all currently know
+ * architecture flags (terminated with an entry with all zeros).
+ */
+__private_extern__ const struct arch_flag *get_arch_flags(
+ void);
+
+/*
+ * arch_usage() is called when an unknown architecture flag is encountered.
+ * It prints the currently know architecture flags on stderr.
+ */
+__private_extern__ void arch_usage(
+ void);
+
+/*
+ * set_arch_flag_name() sets the name field of the specified arch_flag to
+ * match it's cputype and cpusubtype. The string is allocated via malloc by
+ * the routines in "allocate.h" and errors are handled by the routines in
+ * "error.h".
+ */
+__private_extern__ void set_arch_flag_name(
+ struct arch_flag *p);
+
+/*
+ * get_arch_name_from_types() returns the name of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns a pointer
+ * to the string "unknown".
+ */
+__private_extern__ const char *get_arch_name_from_types(
+ cpu_type_t cputype,
+ cpu_subtype_t cpusubtype);
+
+/*
+ * get_arch_family_from_cputype() returns the family architecture for the
+ * specified cputype if known. If unknown it returns NULL.
+ */
+__private_extern__ const struct arch_flag *get_arch_family_from_cputype(
+ cpu_type_t cputype);
+
+/*
+ * get_byte_sex_from_flag() returns the byte sex of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns
+ * UNKNOWN_BYTE_SEX. If the bytesex can be determined directly as in the case
+ * of reading a magic number from a file that should be done and this routine
+ * should not be used as it could be out of date.
+ */
+__private_extern__ enum byte_sex get_byte_sex_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * get_stack_direction_from_flag() returns the direction the stack grows as
+ * either positive (+1) or negative (-1) of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns 0.
+ */
+__private_extern__ long get_stack_direction_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * get_stack_addr_from_flag() returns the default starting address of the user
+ * stack.
+ */
+__private_extern__ uint64_t get_stack_addr_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * get_stack_size_from_flag() returns the default size of the userstack.
+ */
+__private_extern__ unsigned long get_stack_size_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * get_segalign_from_flag() returns the default segment alignment (page size).
+ */
+__private_extern__ unsigned long get_segalign_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * get_segprot_from_flag() returns the default segment protection.
+ */
+__private_extern__ vm_prot_t get_segprot_from_flag(
+ const struct arch_flag *flag);
+
+/*
+ * force_cpusubtype_ALL_for_cputype() takes a cputype and returns TRUE if for
+ * that cputype the cpusubtype should always be forced to the ALL cpusubtype,
+ * otherwise it returns FALSE.
+ */
+__private_extern__ enum bool force_cpusubtype_ALL_for_cputype(
+ cpu_type_t cputype);
+#endif /* _STUFF_ARCH_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/bool.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* bool.h */
+#ifndef ENUM_DYLD_BOOL
+#define ENUM_DYLD_BOOL
+
+#define _STDBOOL_H
+#undef bool
+
+#define DYLD_BOOL bool
+
+#undef FALSE
+#undef TRUE
+enum bool {
+ FALSE,
+ TRUE
+};
+
+#endif /* ENUM_DYLD_BOOL */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/breakout.h
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#import "stuff/ofile.h"
+
+/*
+ * This is used to build the table of contents of an archive. Each toc_entry
+ * Contains a pointer to a symbol name that is defined by a member of the
+ * archive. The member that defines this symbol is referenced by its index in
+ * the archive plus one. This is done so the negative value if the index can
+ * be used for marking then later to generate the ran_off field with the byte
+ * offset.
+ */
+struct toc_entry {
+ char *symbol_name;
+ long member_index;
+};
+
+/*
+ * The input files are broken out in to their object files and then placed in
+ * these structures. These structures are then used to edit the object files'
+ * symbol table. And then finally used to reassemble the object file for
+ * output.
+ */
+struct arch {
+ char *file_name; /* name of file this arch came from */
+ enum ofile_type type; /* The type of file for this architecture */
+ /* can be OFILE_ARCHIVE, OFILE_Mach_O or */
+ /* OFILE_UNKNOWN. */
+ struct fat_arch *fat_arch; /* If this came from fat file this is valid */
+ /* and not NULL (needed for the align value */
+ /* and to output a fat file if only one arch)*/
+ char *fat_arch_name; /* If this came from fat file this is valid */
+ /* and is tthe name of this architecture */
+ /* (used for error messages). */
+
+ /* if this is an archive: the members of this archive */
+ struct member *members; /* the members of the library for this arch */
+ unsigned long nmembers; /* the number of the above members */
+ /*
+ * The output table of contents (toc) for this arch in the library (this
+ * must be recreated, or at least the time of the toc member set, when
+ * the output is modified because modifiy time is shared by all libraries
+ * in the file).
+ */
+ unsigned long toc_size; /* total size of the toc including ar_hdr */
+ struct ar_hdr toc_ar_hdr; /* the archive header for this member */
+ enum bool toc_long_name;/* use the long name in the output */
+ char *toc_name; /* name of toc member */
+ unsigned long toc_name_size;/* size of name of toc member */
+ unsigned long ntocs; /* number of table of contents entries */
+ struct toc_entry
+ *toc_entries; /* the table of contents entries */
+ struct ranlib *toc_ranlibs; /* the ranlib structs */
+ char *toc_strings; /* strings of symbol names for toc entries */
+ unsigned long toc_strsize; /* number of bytes for the strings above */
+ unsigned long library_size; /* current working size and final output size */
+ /* for this arch when it's a library (used */
+ /* for creating the toc entries). */
+
+ /* if this is an object file: the object file */
+ struct object *object; /* the object file */
+
+ /* if this is an unknown file: the addr and size of the file */
+ char *unknown_addr;
+ unsigned long unknown_size;
+
+ /* don't update LC_ID_DYLIB timestamp */
+ enum bool dont_update_LC_ID_DYLIB_timestamp;
+};
+
+struct member {
+ enum ofile_type type; /* the type of this member can be OFILE_Mach_O*/
+ /* or OFILE_UNKNOWN */
+ struct ar_hdr *ar_hdr; /* the archive header for this member */
+ unsigned long offset; /* current working offset and final offset */
+ /* use in creating the table of contents */
+
+ /* the name of the member in the output */
+ char *member_name; /* the member name */
+ unsigned long member_name_size; /* the size of the member name */
+ enum bool member_long_name; /* use the extended format #1 for the
+ member name in the output */
+
+ /* if this member is an object file: the object file */
+ struct object *object; /* the object file */
+
+ /* if this member is an unknown file: the addr and size of the member */
+ char *unknown_addr;
+ unsigned long unknown_size;
+
+ /*
+ * If this member was created from a file then input_file_name is set else
+ * it is NULL and input_ar_hdr is set (these are recorded to allow
+ * warn_member() messages to be printed)
+ */
+ char *input_file_name;
+ struct ar_hdr *input_ar_hdr;
+};
+
+struct object {
+ char *object_addr; /* the address of the object file */
+ unsigned long object_size; /* the size of the object file on input */
+ enum byte_sex object_byte_sex; /* the byte sex of the object file */
+ struct mach_header *mh; /* the mach_header of 32-bit object file */
+ struct mach_header_64 *mh64; /* the mach_header of 64-bit object file */
+ /* these copied from the mach header above */
+ cpu_type_t mh_cputype; /* cpu specifier */
+ cpu_subtype_t mh_cpusubtype; /* machine specifier */
+ uint32_t mh_filetype; /* type of file */
+ struct load_command /* the start of the load commands */
+ *load_commands;
+ struct symtab_command *st; /* the symbol table command */
+ struct dysymtab_command *dyst; /* the dynamic symbol table command */
+ struct twolevel_hints_command /* the two-level namespace hints command */
+ *hints_cmd;
+ struct prebind_cksum_command *cs;/* the prebind check sum command */
+ struct segment_command
+ *seg_linkedit; /* the 32-bit link edit segment command */
+ struct segment_command_64
+ *seg_linkedit64; /* the 64-bit link edit segment command */
+ struct linkedit_data_command
+ *code_sig_cmd; /* the code signature load command, if any*/
+ struct linkedit_data_command
+ *split_info_cmd; /* the split info load command, if any*/
+ struct section **sections; /* array of 32-bit section structs */
+ struct section_64 **sections64; /* array of 64-bit section structs */
+
+ /*
+ * This is only used for redo_prebinding and is calculated by breakout()
+ * if the calculate_input_prebind_cksum parameter is TRUE and there is an
+ * LC_PREBIND_CKSUM load command that has a zero value for the cksum field
+ * (if so this will be value of the cksum field on output).
+ */
+ unsigned long calculated_input_prebind_cksum;
+
+ unsigned long input_sym_info_size;
+ unsigned long output_sym_info_size;
+
+ /*
+ * For 64-bit Mach-O files they may have an odd number of indirect symbol
+ * table entries so the next offset MAYBE or MAY NOT be rounded to a
+ * multiple of 8. input_indirectsym_pad contains the amount of padding in
+ * that was in the input.
+ */
+ unsigned long input_indirectsym_pad;
+
+ struct nlist *output_symbols;
+ struct nlist_64 *output_symbols64;
+ unsigned long output_nsymbols;
+ char *output_strings;
+ unsigned long output_strings_size;
+ char *output_code_sig_data;
+ unsigned long output_code_sig_data_size;
+ char *output_split_info_data;
+ unsigned long output_split_info_data_size;
+
+ unsigned long output_ilocalsym;
+ unsigned long output_nlocalsym;
+ unsigned long output_iextdefsym;
+ unsigned long output_nextdefsym;
+ unsigned long output_iundefsym;
+ unsigned long output_nundefsym;
+
+ struct twolevel_hint *output_hints;
+
+ struct relocation_info *output_loc_relocs;
+ struct relocation_info *output_ext_relocs;
+ uint32_t *output_indirect_symtab;
+
+ struct dylib_table_of_contents *output_tocs;
+ unsigned long output_ntoc;
+ struct dylib_module *output_mods;
+ struct dylib_module_64 *output_mods64;
+ unsigned long output_nmodtab;
+ struct dylib_reference *output_refs;
+ unsigned long output_nextrefsyms;
+};
+
+__private_extern__ struct ofile * breakout(
+ char *filename,
+ struct arch **archs,
+ unsigned long *narchs,
+ enum bool calculate_input_prebind_cksum);
+
+__private_extern__ struct ofile * breakout_mem(
+ void *membuf,
+ unsigned long length,
+ char *filename,
+ struct arch **archs,
+ unsigned long *narchs,
+ enum bool calculate_input_prebind_cksum);
+
+__private_extern__ void free_archs(
+ struct arch *archs,
+ unsigned long narchs);
+
+__private_extern__ void writeout(
+ struct arch *archs,
+ unsigned long narchs,
+ char *output,
+ unsigned short mode,
+ enum bool sort_toc,
+ enum bool commons_in_toc,
+ enum bool library_warnings,
+ unsigned long *throttle);
+
+__private_extern__ void writeout_to_mem(
+ struct arch *archs,
+ unsigned long narchs,
+ char *filename,
+ void **outputbuf,
+ unsigned long *length,
+ enum bool sort_toc,
+ enum bool commons_in_toc,
+ enum bool library_warning,
+ enum bool *seen_archive);
+
+__private_extern__ void checkout(
+ struct arch *archs,
+ unsigned long narchs);
+
+void warning_arch(
+ struct arch *arch,
+ struct member *member,
+ char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+ ;
+
+void error_arch(
+ struct arch *arch,
+ struct member *member,
+ char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+ ;
+
+void fatal_arch(
+ struct arch *arch,
+ struct member *member,
+ char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+ ;
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/bytesex.h
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* bytesex.h */
+#ifndef _STUFF_BYTESEX_H_
+#define _STUFF_BYTESEX_H_
+
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <mach/m68k/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/ppc/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/m88k/thread_status.h>
+#include <mach/i860/thread_status.h>
+#include <mach/i386/thread_status.h>
+#include <mach/hppa/thread_status.h>
+#include <mach/sparc/thread_status.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+#include <mach-o/ranlib.h>
+#include "stuff/bool.h"
+
+enum byte_sex {
+ UNKNOWN_BYTE_SEX,
+ BIG_ENDIAN_BYTE_SEX,
+ LITTLE_ENDIAN_BYTE_SEX
+};
+
+#define SWAP_SHORT(a) ( ((a & 0xff) << 8) | ((unsigned short)(a) >> 8) )
+
+#define SWAP_INT(a) ( ((a) << 24) | \
+ (((a) << 8) & 0x00ff0000) | \
+ (((a) >> 8) & 0x0000ff00) | \
+ ((unsigned int)(a) >> 24) )
+
+#ifndef __LP64__
+#define SWAP_LONG(a) ( ((a) << 24) | \
+ (((a) << 8) & 0x00ff0000) | \
+ (((a) >> 8) & 0x0000ff00) | \
+ ((unsigned long)(a) >> 24) )
+#endif
+
+__private_extern__ long long SWAP_LONG_LONG(
+ long long ll);
+
+__private_extern__ float SWAP_FLOAT(
+ float f);
+
+__private_extern__ double SWAP_DOUBLE(
+ double d);
+
+__private_extern__ enum byte_sex get_host_byte_sex(
+ void);
+
+__private_extern__ void swap_fat_header(
+ struct fat_header *fat_header,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_fat_arch(
+ struct fat_arch *fat_archs,
+ unsigned long nfat_arch,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_mach_header(
+ struct mach_header *mh,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_mach_header_64(
+ struct mach_header_64 *mh,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_load_command(
+ struct load_command *lc,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_segment_command(
+ struct segment_command *sg,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_segment_command_64(
+ struct segment_command_64 *sg,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_section(
+ struct section *s,
+ unsigned long nsects,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_section_64(
+ struct section_64 *s,
+ unsigned long nsects,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_symtab_command(
+ struct symtab_command *st,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dysymtab_command(
+ struct dysymtab_command *dyst,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_symseg_command(
+ struct symseg_command *ss,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_fvmlib_command(
+ struct fvmlib_command *fl,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylib_command(
+ struct dylib_command *dl,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_sub_framework_command(
+ struct sub_framework_command *sub,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_sub_umbrella_command(
+ struct sub_umbrella_command *usub,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_sub_library_command(
+ struct sub_library_command *lsub,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_sub_client_command(
+ struct sub_client_command *csub,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_prebound_dylib_command(
+ struct prebound_dylib_command *pbdylib,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylinker_command(
+ struct dylinker_command *dyld,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_fvmfile_command(
+ struct fvmfile_command *ff,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_thread_command(
+ struct thread_command *ut,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m68k_thread_state_regs(
+ struct m68k_thread_state_regs *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m68k_thread_state_68882(
+ struct m68k_thread_state_68882 *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m68k_thread_state_user_reg(
+ struct m68k_thread_state_user_reg *user_reg,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_ppc_thread_state_t(
+ ppc_thread_state_t *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_ppc_thread_state64_t(
+ ppc_thread_state64_t *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_ppc_float_state_t(
+ ppc_float_state_t *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_ppc_exception_state_t(
+ ppc_exception_state_t *state,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m88k_thread_state_grf_t(
+ m88k_thread_state_grf_t *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m88k_thread_state_xrf_t(
+ m88k_thread_state_xrf_t *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m88k_thread_state_user_t(
+ m88k_thread_state_user_t *user,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_m88110_thread_state_impl_t(
+ m88110_thread_state_impl_t *spu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_i860_thread_state_regs(
+ struct i860_thread_state_regs *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_i386_thread_state(
+ i386_thread_state_t *cpu,
+ enum byte_sex target_byte_sex);
+
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+__private_extern__ void swap_i386_float_state(
+ struct __darwin_i386_float_state *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_i386_exception_state(
+ i386_exception_state_t *exc,
+ enum byte_sex target_byte_sex);
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+__private_extern__ void swap_i386_thread_fpstate(
+ i386_thread_fpstate_t *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_i386_thread_exceptstate(
+ i386_thread_exceptstate_t *exc,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_i386_thread_cthreadstate(
+ i386_thread_cthreadstate_t *user,
+ enum byte_sex target_byte_sex);
+#endif /* i386_THREAD_STATE == -1 */
+
+#ifdef x86_THREAD_STATE64
+__private_extern__ void swap_x86_thread_state64(
+ x86_thread_state64_t *cpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_x86_float_state64(
+ x86_float_state64_t *fpu,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_x86_state_hdr(
+ struct x86_state_hdr *hdr,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_x86_exception_state64(
+ x86_exception_state64_t *exc,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_x86_debug_state32(
+ x86_debug_state32_t *debug,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_x86_debug_state64(
+ x86_debug_state64_t *debug,
+ enum byte_sex target_byte_sex);
+#endif /* x86_THREAD_STATE64 */
+
+__private_extern__ void swap_hppa_integer_thread_state(
+ struct hp_pa_integer_thread_state *regs,
+ enum byte_sex target_byte_order);
+
+__private_extern__ void swap_hppa_frame_thread_state(
+ struct hp_pa_frame_thread_state *frame,
+ enum byte_sex target_byte_order);
+
+__private_extern__ void swap_hppa_fp_thread_state(
+ struct hp_pa_fp_thread_state *fp,
+ enum byte_sex target_byte_order);
+
+__private_extern__ void swap_sparc_thread_state_regs(
+ struct sparc_thread_state_regs *cpu,
+ enum byte_sex target_byte_order);
+
+__private_extern__ void swap_sparc_thread_state_fpu(
+ struct sparc_thread_state_fpu *fpu,
+ enum byte_sex target_byte_order);
+
+__private_extern__ void swap_ident_command(
+ struct ident_command *id_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_routines_command(
+ struct routines_command *r_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_routines_command_64(
+ struct routines_command_64 *r_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_twolevel_hints_command(
+ struct twolevel_hints_command *hints_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_prebind_cksum_command(
+ struct prebind_cksum_command *cksum_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_uuid_command(
+ struct uuid_command *uuid_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_linkedit_data_command(
+ struct linkedit_data_command *ld,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_rpath_command(
+ struct rpath_command *rpath_cmd,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_nlist(
+ struct nlist *symbols,
+ unsigned long nsymbols,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_nlist_64(
+ struct nlist_64 *symbols,
+ unsigned long nsymbols,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_ranlib(
+ struct ranlib *ranlibs,
+ unsigned long nranlibs,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_relocation_info(
+ struct relocation_info *relocs,
+ unsigned long nrelocs,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_indirect_symbols(
+ uint32_t *indirect_symbols,
+ uint32_t nindirect_symbols,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylib_reference(
+ struct dylib_reference *refs,
+ unsigned long nrefs,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylib_module(
+ struct dylib_module *mods,
+ unsigned long nmods,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylib_module_64(
+ struct dylib_module_64 *mods,
+ unsigned long nmods,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_dylib_table_of_contents(
+ struct dylib_table_of_contents *tocs,
+ unsigned long ntocs,
+ enum byte_sex target_byte_sex);
+
+__private_extern__ void swap_twolevel_hint(
+ struct twolevel_hint *hints,
+ unsigned long nhints,
+ enum byte_sex target_byte_sex);
+
+/*
+ * swap_object_headers() swaps the object file headers from the host byte sex
+ * into the non-host byte sex. It returns TRUE if it can and did swap the
+ * headers else returns FALSE and does not touch the headers and prints an error
+ * using the error() routine.
+ */
+__private_extern__ enum bool swap_object_headers(
+ void *mach_header, /* either a mach_header or a mach_header_64 */
+ struct load_command *load_commands);
+
+/*
+ * get_toc_byte_sex() guesses the byte sex of the table of contents of the
+ * library mapped in at the address, addr, of size, size based on the first
+ * object file's bytesex. If it can't figure it out, because the library has
+ * no object file members or is malformed it will return UNKNOWN_BYTE_SEX.
+ */
+__private_extern__ enum byte_sex get_toc_byte_sex(
+ char *addr,
+ unsigned long size);
+
+#endif /* _STUFF_BYTESEX_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/crc32.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+__private_extern__ unsigned long crc32(
+ const void *buf,
+ unsigned int len);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/errors.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#import "mach/mach.h"
+
+/* user defined (imported) */
+__private_extern__ char *progname;
+
+/* defined in errors.c */
+/* number of detected calls to error() */
+__private_extern__ unsigned long errors;
+
+__private_extern__ void warning(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void error(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void error_with_arch(
+ const char *arch_name,
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+__private_extern__ void system_error(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void fatal(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void system_fatal(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void my_mach_error(
+ kern_return_t r,
+ char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+__private_extern__ void mach_fatal(
+ kern_return_t r,
+ char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/ofile.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/* ofile.h */
+#ifndef _STUFF_OFILE_H_
+#define _STUFF_OFILE_H_
+
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#import <ar.h>
+#ifndef AR_EFMT1
+#define AR_EFMT1 "#1/" /* extended format #1 */
+#endif
+#import <mach-o/loader.h>
+#ifdef OFI
+#import <mach-o/dyld.h>
+#endif
+#import "stuff/bytesex.h"
+#import "stuff/bool.h"
+#import "stuff/arch.h"
+
+enum ofile_type {
+ OFILE_UNKNOWN,
+ OFILE_FAT,
+ OFILE_ARCHIVE,
+ OFILE_Mach_O
+};
+
+/*
+ * The structure used by ofile_*() routines for object files.
+ */
+struct ofile {
+ char *file_name; /* pointer to name malloc'ed by ofile_map */
+ char *file_addr; /* pointer to vm_allocate'ed memory */
+ unsigned long file_size; /* size of vm_allocate'ed memory */
+ enum ofile_type file_type; /* type of the file */
+
+ struct fat_header *fat_header; /* If a fat file these are filled in and */
+ struct fat_arch *fat_archs; /* if needed converted to host byte sex */
+
+ /* If this is a fat file then these are valid and filled in */
+ unsigned long narch; /* the current architecture */
+ enum ofile_type arch_type; /* the type of file for this arch. */
+ struct arch_flag arch_flag; /* the arch_flag for this arch, the name */
+ /* field is pointing at space malloc'ed */
+ /* by ofile_map. */
+
+ /* If this structure is currently referencing an archive member or an object
+ file that is an archive member these are valid and filled in. */
+ unsigned long member_offset; /* logical offset to the member starting */
+ char *member_addr; /* pointer to the member contents */
+ unsigned long member_size; /* actual size of the member (not rounded)*/
+ struct ar_hdr *member_ar_hdr; /* pointer to the ar_hdr for this member */
+ char *member_name; /* name of this member */
+ unsigned long member_name_size; /* size of the member name */
+ enum ofile_type member_type; /* the type of file for this member */
+ cpu_type_t archive_cputype; /* if the archive contains objects then */
+ cpu_subtype_t /* these two fields reflect the object */
+ archive_cpusubtype; /* at are in the archive. */
+
+ /* If this structure is currently referencing a dynamic library module
+ these are valid and filled in. */
+ struct dylib_module *modtab; /* the 32-bit module table */
+ struct dylib_module_64 *modtab64;/* the 64-bit module table */
+ unsigned long nmodtab; /* the number of module table entries */
+ struct dylib_module /* pointer to the 32-bit dylib_module for */
+ *dylib_module; /* this module. */
+ struct dylib_module_64 /* pointer to the 64-bit dylib_module for */
+ *dylib_module64; /* this module. */
+ char *dylib_module_name; /* the name of the module */
+
+ /* If this structure is currently referencing an object file these are
+ valid and filled in. The mach_header and load commands have been
+ converted to the host byte sex if needed */
+ enum bool headers_swapped; /* true if the headers have already been
+ swapped to host byte sex */
+ char *object_addr; /* the address of the object file */
+ unsigned long object_size; /* the size of the object file */
+ enum byte_sex object_byte_sex; /* the byte sex of the object file */
+ struct mach_header *mh; /* the mach_header of 32-bit object file */
+ struct mach_header_64 *mh64; /* the mach_header of 64-bit object file */
+ struct load_command /* the start of the load commands */
+ *load_commands;
+ /* these copied from the mach header above */
+ cpu_type_t mh_cputype; /* cpu specifier */
+ cpu_subtype_t mh_cpusubtype; /* machine specifier */
+ uint32_t mh_filetype; /* type of file */
+};
+
+__private_extern__ void ofile_process(
+ char *name,
+ struct arch_flag *arch_flags,
+ unsigned long narch_flags,
+ enum bool all_archs,
+ enum bool process_non_objects,
+ enum bool dylib_flat,
+ enum bool use_member_syntax,
+ void (*processor)(struct ofile *ofile, char *arch_name, void *cookie),
+ void *cookie);
+#ifdef OFI
+__private_extern__ NSObjectFileImageReturnCode ofile_map(
+#else
+__private_extern__ enum bool ofile_map(
+#endif
+ const char *file_name,
+ const struct arch_flag *arch_flag, /* can be NULL */
+ const char *object_name, /* can be NULL */
+ struct ofile *ofile,
+ enum bool archives_with_fat_objects);
+#ifdef OFI
+__private_extern__ NSObjectFileImageReturnCode ofile_map_from_memory(
+#else
+__private_extern__ enum bool ofile_map_from_memory(
+#endif
+ char *addr,
+ unsigned long size,
+ const char *file_name,
+ const struct arch_flag *arch_flag, /* can be NULL */
+ const char *object_name, /* can be NULL */
+ struct ofile *ofile,
+ enum bool archives_with_fat_objects);
+__private_extern__ void ofile_unmap(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_first_arch(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_next_arch(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_first_member(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_next_member(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_specific_member(
+ const char *object_name,
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_first_module(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_next_module(
+ struct ofile *ofile);
+__private_extern__ enum bool ofile_specific_module(
+ const char *module_name,
+ struct ofile *ofile);
+__private_extern__ void ofile_print(
+ struct ofile *ofile);
+__private_extern__ unsigned long size_ar_name(
+ const struct ar_hdr *ar_hdr);
+__private_extern__ long ofile_get_word(
+ uint64_t addr,
+ uint32_t *word,
+ void *get_word_data /* struct ofile *ofile */);
+__private_extern__ void archive_error(
+ struct ofile *ofile,
+ const char *format, ...)
+#ifndef __MWERKS__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+__private_extern__ void archive_member_error(
+ struct ofile *ofile,
+ const char *format, ...)
+#ifndef __MWERKS__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+__private_extern__ void Mach_O_error(
+ struct ofile *ofile,
+ const char *format, ...)
+#ifndef __MWERKS__
+ __attribute__ ((format (printf, 2, 3)))
+#endif
+ ;
+
+#endif /* _STUFF_OFILE_H_ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/openstep_mach.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+#ifdef __OPENSTEP__
+/*
+ * This file is used to allow cctools to be compiled for Openstep now that
+ * the code has been changed to use Mach 3.0 names (which work for MacOS X and
+ * Rhapsody but not for Openstep).
+ */
+#define mach_task_self task_self
+#define mach_task_self_ task_self_
+#define mach_host_self host_self
+#define mach_thread_self thread_self
+#define mach_port_allocate port_allocate
+#define mach_port_deallocate port_deallocate
+#define mach_port_names port_names
+#endif /* __OPENSTEP__ */
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/print.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#import <stdarg.h>
+
+__private_extern__ void print(
+ const char *format, ...)
+#ifdef __GNUC__
+ __attribute__ ((format (printf, 1, 2)))
+#endif
+ ;
+__private_extern__ void vprint(
+ const char *format, va_list ap);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/reloc.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+#import <mach/machine.h>
+#import "stuff/bool.h"
+
+__private_extern__ unsigned long reloc_pair_r_type(
+ cpu_type_t cputype);
+__private_extern__ enum bool reloc_has_pair(
+ cpu_type_t cputype,
+ unsigned long r_type);
+__private_extern__ enum bool reloc_is_sectdiff(
+ cpu_type_t cputype,
+ unsigned long r_type);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/round.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+#if defined(__MWERKS__) && !defined(__private_extern__)
+#define __private_extern__ __declspec(private_extern)
+#endif
+
+/*
+ * round() rounds v to a multiple of r.
+ */
+__private_extern__ unsigned long round(
+ unsigned long v,
+ unsigned long r);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/symbol_list.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <mach-o/nlist.h>
+#include <stuff/bool.h>
+
+/*
+ * Data structures to perform selective stripping of symbol table entries.
+ */
+struct symbol_list {
+ char *name; /* name of the global symbol */
+ void *sym; /* pointer to the nlist structure for this symbol */
+ enum bool seen; /* set if the symbol is seen in the input file */
+};
+
+__private_extern__ void setup_symbol_list(
+ char *file,
+ struct symbol_list **list,
+ unsigned long *size);
+
+__private_extern__ int symbol_list_bsearch(
+ const char *name,
+ const struct symbol_list *sym);
new file mode 100644
--- /dev/null
+++ b/striptease/include/stuff/unix_standard_mode.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include "stuff/bool.h"
+
+__private_extern__ enum bool get_unix_standard_mode(
+ void);
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/allocate.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <mach/mach.h>
+
+#include "stuff/allocate.h"
+#include "stuff/errors.h"
+/*
+ * allocate() is just a wrapper around malloc that prints an error message and
+ * exits if the malloc fails.
+ */
+__private_extern__
+void *
+allocate(
+unsigned long size)
+{
+ void *p;
+
+ if(size == 0)
+ return(NULL);
+ if((p = malloc(size)) == NULL)
+ system_fatal("virtual memory exhausted (malloc failed)");
+ return(p);
+}
+
+/*
+ * reallocate() is just a wrapper around realloc that prints and error message
+ * and exits if the realloc fails.
+ */
+__private_extern__
+void *
+reallocate(
+void *p,
+unsigned long size)
+{
+ if(p == NULL)
+ return(allocate(size));
+ if((p = realloc(p, size)) == NULL)
+ system_fatal("virtual memory exhausted (realloc failed)");
+ return(p);
+}
+
+/*
+ * savestr() malloc's space for the string passed to it, copys the string into
+ * the space and returns a pointer to that space.
+ */
+__private_extern__
+char *
+savestr(
+const char *s)
+{
+ long len;
+ char *r;
+
+ len = strlen(s) + 1;
+ r = (char *)allocate(len);
+ strcpy(r, s);
+ return(r);
+}
+
+/*
+ * Makestr() creates a string that is the concatenation of a variable number of
+ * strings. It is pass a variable number of pointers to strings and the last
+ * pointer is NULL. It returns the pointer to the string it created. The
+ * storage for the string is malloc()'ed can be free()'ed when nolonger needed.
+ */
+__private_extern__
+char *
+makestr(
+const char *args,
+...)
+{
+ va_list ap;
+ char *s, *p;
+ long size;
+
+ size = 0;
+ if(args != NULL){
+ size += strlen(args);
+ va_start(ap, args);
+ p = (char *)va_arg(ap, char *);
+ while(p != NULL){
+ size += strlen(p);
+ p = (char *)va_arg(ap, char *);
+ }
+ }
+ s = allocate(size + 1);
+ *s = '\0';
+
+ if(args != NULL){
+ (void)strcat(s, args);
+ va_start(ap, args);
+ p = (char *)va_arg(ap, char *);
+ while(p != NULL){
+ (void)strcat(s, p);
+ p = (char *)va_arg(ap, char *);
+ }
+ va_end(ap);
+ }
+ return(s);
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/arch.c
@@ -0,0 +1,342 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include "stdio.h"
+#endif /* !defined(RLD) */
+#include "stdlib.h"
+#include "string.h"
+#include <mach/mach.h>
+#include "stuff/openstep_mach.h"
+#include "stuff/arch.h"
+#include "stuff/allocate.h"
+
+/*
+ * The array of all currently know architecture flags (terminated with an entry
+ * with all zeros). Pointer to this returned with get_arch_flags().
+ */
+#ifdef __DYNAMIC__
+static struct arch_flag arch_flags[] = {
+#else
+static const struct arch_flag arch_flags[] = {
+#endif
+ { "any", CPU_TYPE_ANY, CPU_SUBTYPE_MULTIPLE },
+ { "little", CPU_TYPE_ANY, CPU_SUBTYPE_LITTLE_ENDIAN },
+ { "big", CPU_TYPE_ANY, CPU_SUBTYPE_BIG_ENDIAN },
+
+/* 64-bit Mach-O architectures */
+
+ /* architecture families */
+ { "ppc64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_ALL },
+ { "x86_64", CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL },
+ /* specific architecture implementations */
+ { "ppc970-64", CPU_TYPE_POWERPC64, CPU_SUBTYPE_POWERPC_970 },
+
+/* 32-bit Mach-O architectures */
+
+ /* architecture families */
+ { "ppc", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_ALL },
+ { "i386", CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL },
+ { "m68k", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC680x0_ALL },
+ { "hppa", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_ALL },
+ { "sparc", CPU_TYPE_SPARC, CPU_SUBTYPE_SPARC_ALL },
+ { "m88k", CPU_TYPE_MC88000, CPU_SUBTYPE_MC88000_ALL },
+ { "i860", CPU_TYPE_I860, CPU_SUBTYPE_I860_ALL },
+ { "veo", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_ALL },
+ /* specific architecture implementations */
+ { "ppc601", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_601 },
+ { "ppc603", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603 },
+ { "ppc603e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_603e },
+ { "ppc603ev",CPU_TYPE_POWERPC,CPU_SUBTYPE_POWERPC_603ev },
+ { "ppc604", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604 },
+ { "ppc604e",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_604e },
+ { "ppc750", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_750 },
+ { "ppc7400",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7400 },
+ { "ppc7450",CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_7450 },
+ { "ppc970", CPU_TYPE_POWERPC, CPU_SUBTYPE_POWERPC_970 },
+ { "i486", CPU_TYPE_I386, CPU_SUBTYPE_486 },
+ { "i486SX", CPU_TYPE_I386, CPU_SUBTYPE_486SX },
+ { "pentium",CPU_TYPE_I386, CPU_SUBTYPE_PENT }, /* same as i586 */
+ { "i586", CPU_TYPE_I386, CPU_SUBTYPE_586 },
+ { "pentpro", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO }, /* same as i686 */
+ { "i686", CPU_TYPE_I386, CPU_SUBTYPE_PENTPRO },
+ { "pentIIm3",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M3 },
+ { "pentIIm5",CPU_TYPE_I386, CPU_SUBTYPE_PENTII_M5 },
+ { "pentium4",CPU_TYPE_I386, CPU_SUBTYPE_PENTIUM_4 },
+ { "m68030", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68030_ONLY },
+ { "m68040", CPU_TYPE_MC680x0, CPU_SUBTYPE_MC68040 },
+ { "hppa7100LC", CPU_TYPE_HPPA, CPU_SUBTYPE_HPPA_7100LC },
+ { "veo1", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_1 },
+ { "veo2", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_2 },
+ { "veo3", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_3 },
+ { "veo4", CPU_TYPE_VEO, CPU_SUBTYPE_VEO_4 },
+ { NULL, 0, 0 }
+};
+
+#ifndef RLD
+/*
+ * get_arch_from_flag() is passed a name of an architecture flag and returns
+ * zero if that flag is not known and non-zero if the flag is known.
+ * If the pointer to the arch_flag is not NULL it is filled in with the
+ * arch_flag struct that matches the name.
+ */
+__private_extern__
+int
+get_arch_from_flag(
+char *name,
+struct arch_flag *arch_flag)
+{
+ unsigned long i;
+
+ for(i = 0; arch_flags[i].name != NULL; i++){
+ if(strcmp(arch_flags[i].name, name) == 0){
+ if(arch_flag != NULL)
+ *arch_flag = arch_flags[i];
+ return(1);
+ }
+ }
+ if(arch_flag != NULL)
+ memset(arch_flag, '\0', sizeof(struct arch_flag));
+ return(0);
+}
+
+/*
+ * get_arch_flags() returns a pointer to an array of all currently know
+ * architecture flags (terminated with an entry with all zeros).
+ */
+__private_extern__
+const struct arch_flag *
+get_arch_flags(
+void)
+{
+ return(arch_flags);
+}
+#endif /* !defined(RLD) */
+
+/*
+ * get_arch_name_from_types() returns the name of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns a pointer
+ * to the an allocated string "cputype X cpusubtype Y" where X and Y are decimal
+ * values.
+ */
+__private_extern__
+const char *
+get_arch_name_from_types(
+cpu_type_t cputype,
+cpu_subtype_t cpusubtype)
+{
+ unsigned long i;
+ char *p;
+
+ for(i = 0; arch_flags[i].name != NULL; i++){
+ if(arch_flags[i].cputype == cputype &&
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (cpusubtype & ~CPU_SUBTYPE_MASK))
+ return(arch_flags[i].name);
+ }
+#ifndef RLD
+ p = savestr("cputype 1234567890 cpusubtype 1234567890");
+ if(p != NULL)
+ sprintf(p, "cputype %u cpusubtype %u", cputype,
+ cpusubtype & ~CPU_SUBTYPE_MASK);
+#else
+ /* there is no sprintf() in the rld kernel API's */
+ p = savestr("cputype ?? cpusubtype ??");
+#endif
+ return(p);
+}
+
+/*
+ * get_arch_family_from_cputype() returns the family architecture for the
+ * specified cputype if known. If unknown it returns NULL.
+ */
+__private_extern__
+const struct arch_flag *
+get_arch_family_from_cputype(
+cpu_type_t cputype)
+{
+ unsigned long i;
+
+ for(i = 0; arch_flags[i].name != NULL; i++){
+ if(arch_flags[i].cputype == cputype)
+ return(arch_flags + i);
+ }
+ return(NULL);
+}
+
+/*
+ * get_byte_sex_from_flag() returns the byte sex of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns
+ * UNKNOWN_BYTE_SEX. If the bytesex can be determined directly as in the case
+ * of reading a magic number from a file that should be done and this routine
+ * should not be used as it could be out of date.
+ */
+__private_extern__
+enum byte_sex
+get_byte_sex_from_flag(
+const struct arch_flag *flag)
+{
+ if(flag->cputype == CPU_TYPE_MC680x0 ||
+ flag->cputype == CPU_TYPE_MC88000 ||
+ flag->cputype == CPU_TYPE_POWERPC ||
+ flag->cputype == CPU_TYPE_POWERPC64 ||
+ flag->cputype == CPU_TYPE_HPPA ||
+ flag->cputype == CPU_TYPE_SPARC ||
+ flag->cputype == CPU_TYPE_I860 ||
+ flag->cputype == CPU_TYPE_VEO)
+ return BIG_ENDIAN_BYTE_SEX;
+ else if(flag->cputype == CPU_TYPE_I386)
+ return LITTLE_ENDIAN_BYTE_SEX;
+ else
+ return UNKNOWN_BYTE_SEX;
+}
+
+#ifndef RLD
+/*
+ * get_stack_direction_from_flag() returns the direction the stack grows as
+ * either positive (+1) or negative (-1) of the architecture for the
+ * specified cputype and cpusubtype if known. If unknown it returns 0.
+ */
+__private_extern__
+long
+get_stack_direction_from_flag(
+const struct arch_flag *flag)
+{
+ if(flag->cputype == CPU_TYPE_MC680x0 ||
+ flag->cputype == CPU_TYPE_MC88000 ||
+ flag->cputype == CPU_TYPE_POWERPC ||
+ flag->cputype == CPU_TYPE_I386 ||
+ flag->cputype == CPU_TYPE_SPARC ||
+ flag->cputype == CPU_TYPE_I860 ||
+ flag->cputype == CPU_TYPE_VEO)
+ return(-1);
+ else if(flag->cputype == CPU_TYPE_HPPA)
+ return(+1);
+ else
+ return(0);
+}
+
+/*
+ * get_stack_addr_from_flag() returns the default starting address of the user
+ * stack. This should be in the header file <bsd/XXX/vmparam.h> as USRSTACK.
+ * Since some architectures have come and gone and come back and because you
+ * can't include all of these headers in one source the constants have been
+ * copied here.
+ */
+__private_extern__
+uint64_t
+get_stack_addr_from_flag(
+const struct arch_flag *flag)
+{
+ switch(flag->cputype){
+ case CPU_TYPE_MC680x0:
+ return(0x04000000);
+ case CPU_TYPE_MC88000:
+ return(0xffffe000);
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_VEO:
+ return(0xc0000000);
+ case CPU_TYPE_I386:
+ return(0xc0000000);
+ case CPU_TYPE_SPARC:
+ return(0xf0000000);
+ case CPU_TYPE_I860:
+ return(0);
+ case CPU_TYPE_HPPA:
+ return(0xc0000000-0x04000000);
+ case CPU_TYPE_POWERPC64:
+ return(0x7ffff00000000LL);
+ case CPU_TYPE_X86_64:
+ return(0x7fff5fc00000LL);
+ default:
+ return(0);
+ }
+}
+
+/*
+ * get_stack_size_from_flag() returns the default size of the userstack. This
+ * should be in the header file <bsd/XXX/vmparam.h> as MAXSSIZ. Since some
+ * architectures have come and gone and come back, you can't include all of
+ * these headers in one source and some of the constants covered the whole
+ * address space the common value of 64meg was chosen.
+ */
+__private_extern__
+unsigned long
+get_stack_size_from_flag(
+const struct arch_flag *flag)
+{
+#ifdef __MWERKS__
+ const struct arch_flag *dummy;
+ dummy = flag;
+#endif
+
+ return(64*1024*1024);
+}
+#endif /* !defined(RLD) */
+
+/*
+ * get_segalign_from_flag() returns the default segment alignment (page size).
+ */
+__private_extern__
+unsigned long
+get_segalign_from_flag(
+const struct arch_flag *flag)
+{
+ if(flag->cputype == CPU_TYPE_POWERPC ||
+ flag->cputype == CPU_TYPE_POWERPC64 ||
+ flag->cputype == CPU_TYPE_VEO ||
+ flag->cputype == CPU_TYPE_I386 ||
+ flag->cputype == CPU_TYPE_X86_64)
+ return(0x1000); /* 4K */
+ else
+ return(0x2000); /* 8K */
+}
+
+/*
+ * get_segprot_from_flag() returns the default segment protection.
+ */
+__private_extern__
+vm_prot_t
+get_segprot_from_flag(
+const struct arch_flag *flag)
+{
+ if(flag->cputype == CPU_TYPE_I386)
+ return(VM_PROT_READ | VM_PROT_WRITE);
+ else
+ return(VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE);
+}
+
+/*
+ * force_cpusubtype_ALL_for_cputype() takes a cputype and returns TRUE if for
+ * that cputype the cpusubtype should always be forced to the ALL cpusubtype,
+ * otherwise it returns FALSE.
+ */
+__private_extern__
+enum bool
+force_cpusubtype_ALL_for_cputype(
+cpu_type_t cputype)
+{
+ if(cputype == CPU_TYPE_I386)
+ return(TRUE);
+ else
+ return(FALSE);
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/arch_usage.c
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <mach/mach.h> /* first to get rid of pre-comp warning */
+#include <stdio.h>
+#include "stuff/arch.h"
+#include "stuff/errors.h"
+
+/*
+ * arch_usage() is called when an unknown architecture flag is encountered.
+ * It prints the currently know architecture flags on stderr.
+ */
+__private_extern__
+void
+arch_usage(void)
+{
+ unsigned long i;
+ const struct arch_flag *arch_flags;
+
+ arch_flags = get_arch_flags();
+ fprintf(stderr, "%s: known architecture flags are:", progname);
+ for(i = 0; arch_flags[i].name != NULL; i++){
+ fprintf(stderr, " %s", arch_flags[i].name);
+ }
+ fprintf(stderr, "\n");
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/breakout.c
@@ -0,0 +1,477 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "stuff/ofile.h"
+#include "stuff/breakout.h"
+#include "stuff/allocate.h"
+#include "stuff/errors.h"
+#include "stuff/round.h"
+#include "stuff/crc32.h"
+
+static void breakout_internal(
+ char *filename,
+ struct arch **archs,
+ unsigned long *narchs,
+ enum bool calculate_input_prebind_cksum,
+ struct ofile *ofile);
+static void breakout_loop_through_archive(
+ char *filename,
+ struct arch *arch,
+ struct ofile *ofile);
+static void cksum_object(
+ struct arch *arch,
+ enum bool calculate_input_prebind_cksum);
+static struct arch *new_arch(
+ struct arch **archs,
+ unsigned long *narchs);
+static struct member *new_member(
+ struct arch *arch);
+
+__private_extern__
+struct ofile *
+breakout_mem(
+void *membuf,
+unsigned long length,
+char *filename,
+struct arch **archs,
+unsigned long *narchs,
+enum bool calculate_input_prebind_cksum)
+{
+ struct ofile *ofile;
+ unsigned long previous_errors;
+
+ *archs = NULL;
+ *narchs = 0;
+ ofile = allocate(sizeof(struct ofile));
+
+ /*
+ * If the file_name is NULL, we will use a dummy file name so
+ * that error reporting, etc. works.
+ */
+ if(filename == NULL)
+ filename = "(broken out from memory)";
+
+ /*
+ * Rely on the ofile_*() routines to do all the checking and only
+ * return valid ofiles files broken out.
+ */
+ if(ofile_map_from_memory((char *)membuf, length, filename, NULL, NULL,
+ ofile, FALSE) == FALSE){
+ free(ofile);
+ return(NULL);
+ }
+
+ previous_errors = errors;
+ breakout_internal(filename, archs, narchs,
+ calculate_input_prebind_cksum, ofile);
+ errors += previous_errors;
+ if(errors != 0){
+ free(ofile);
+ return(NULL);
+ }
+ return(ofile);
+}
+
+__private_extern__
+struct ofile *
+breakout(
+char *filename,
+struct arch **archs,
+unsigned long *narchs,
+enum bool calculate_input_prebind_cksum)
+{
+ struct ofile *ofile;
+ unsigned long previous_errors;
+
+ *archs = NULL;
+ *narchs = 0;
+ ofile = allocate(sizeof(struct ofile));
+ /*
+ * Rely on the ofile_*() routines to do all the checking and only
+ * return valid ofiles files broken out.
+ */
+ if(ofile_map(filename, NULL, NULL, ofile, FALSE) == FALSE){
+ free(ofile);
+ return(NULL);
+ }
+
+ previous_errors = errors;
+ breakout_internal(filename, archs, narchs,
+ calculate_input_prebind_cksum, ofile);
+ errors += previous_errors;
+ if(errors != 0){
+ free(ofile);
+ return(NULL);
+ }
+ return(ofile);
+}
+
+static
+void
+breakout_internal(
+char *filename,
+struct arch **archs,
+unsigned long *narchs,
+enum bool calculate_input_prebind_cksum,
+struct ofile *ofile)
+{
+ struct arch *arch;
+
+ errors = 0;
+ if(ofile->file_type == OFILE_FAT && errors == 0){
+ /* loop through the fat architectures (can't have zero archs) */
+ (void)ofile_first_arch(ofile);
+ do{
+ if(errors != 0)
+ break;
+ arch = new_arch(archs, narchs);
+ arch->file_name = savestr(filename);
+ arch->type = ofile->arch_type;
+ arch->fat_arch = ofile->fat_archs + ofile->narch;
+ arch->fat_arch_name = savestr(ofile->arch_flag.name);
+
+ if(ofile->arch_type == OFILE_ARCHIVE){
+ breakout_loop_through_archive(filename, arch, ofile);
+ }
+ else if(ofile->arch_type == OFILE_Mach_O){
+ arch->object = allocate(sizeof(struct object));
+ memset(arch->object, '\0', sizeof(struct object));
+ arch->object->object_addr = ofile->object_addr;
+ arch->object->object_size = ofile->object_size;
+ arch->object->object_byte_sex = ofile->object_byte_sex;
+ arch->object->mh64 = ofile->mh64;
+ arch->object->mh = ofile->mh;
+ arch->object->mh_filetype = ofile->mh_filetype;
+ arch->object->mh_cputype = ofile->mh_cputype;
+ arch->object->mh_cpusubtype = ofile->mh_cpusubtype;
+ arch->object->load_commands = ofile->load_commands;
+ cksum_object(arch, calculate_input_prebind_cksum);
+ }
+ else{ /* ofile->arch_type == OFILE_UNKNOWN */
+ arch->unknown_addr = ofile->file_addr +
+ arch->fat_arch->offset;
+ arch->unknown_size = arch->fat_arch->size;
+ }
+ }while(ofile_next_arch(ofile) == TRUE);
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE && errors == 0){
+ arch = new_arch(archs, narchs);
+ arch->file_name = savestr(filename);
+ arch->type = ofile->file_type;
+
+ breakout_loop_through_archive(filename, arch, ofile);
+ }
+ else if(ofile->file_type == OFILE_Mach_O && errors == 0){
+ arch = new_arch(archs, narchs);
+ arch->file_name = savestr(filename);
+ arch->type = ofile->file_type;
+ arch->object = allocate(sizeof(struct object));
+ memset(arch->object, '\0', sizeof(struct object));
+ arch->object->object_addr = ofile->object_addr;
+ arch->object->object_size = ofile->object_size;
+ arch->object->object_byte_sex = ofile->object_byte_sex;
+ arch->object->mh64 = ofile->mh64;
+ arch->object->mh = ofile->mh;
+ arch->object->mh_filetype = ofile->mh_filetype;
+ arch->object->mh_cputype = ofile->mh_cputype;
+ arch->object->mh_cpusubtype = ofile->mh_cpusubtype;
+ arch->object->load_commands = ofile->load_commands;
+ cksum_object(arch, calculate_input_prebind_cksum);
+ }
+ else if(errors == 0){ /* ofile->file_type == OFILE_UNKNOWN */
+ arch = new_arch(archs, narchs);
+ arch->file_name = savestr(filename);
+ arch->type = ofile->file_type;
+ arch->unknown_addr = ofile->file_addr;
+ arch->unknown_size = ofile->file_size;
+ }
+ if(errors != 0){
+ free_archs(*archs, *narchs);
+ *archs = NULL;
+ *narchs = 0;
+ }
+}
+
+static
+void
+breakout_loop_through_archive(
+char *filename,
+struct arch *arch,
+struct ofile *ofile)
+{
+ struct member *member;
+ enum bool flag;
+ struct ar_hdr *ar_hdr;
+ unsigned long size, ar_name_size;
+ char ar_name_buf[sizeof(ofile->member_ar_hdr->ar_name) + 1];
+ char ar_size_buf[sizeof(ofile->member_ar_hdr->ar_size) + 1];
+
+ /* loop through archive (can be empty) */
+ if((flag = ofile_first_member(ofile)) == TRUE && errors == 0){
+ /*
+ * If the first member is a table of contents then skip
+ * it as it is always rebuilt (so to get the time to
+ * match the modtime so it won't appear out of date).
+ * Also force it to be a long name so members can be 8 byte
+ * aligned.
+ */
+ if(ofile->member_ar_hdr != NULL &&
+ strncmp(ofile->member_name, SYMDEF,
+ sizeof(SYMDEF) - 1) == 0){
+ arch->toc_long_name = TRUE;
+ flag = ofile_next_member(ofile);
+ }
+ while(flag == TRUE && errors == 0){
+ member = new_member(arch);
+ member->type = ofile->member_type;
+ member->member_name = ofile->member_name;
+ /*
+ * Determine the size this member will have in the library which
+ * includes the padding as a result of rounding the size of the
+ * member. To get all members on an 8 byte boundary (so that
+ * mapping in object files can be used directly) the size of the
+ * member is CHANGED to reflect this padding. In the UNIX
+ * definition of archives the size of the member is never
+ * changed but the offset to the next member is defined to be
+ * the offset of the previous member plus the size of the
+ * previous member rounded to 2. So to get 8 byte boundaries
+ * without breaking the UNIX definition of archives the size is
+ * changed here. As with the UNIX ar(1) program the padded
+ * bytes will be set to the character '\n'.
+ */
+ if(ofile->mh != NULL || ofile->mh64 != NULL)
+ size = round(ofile->object_size, 8);
+ else
+ size = round(ofile->member_size, 8);
+ /*
+ * We will force the use of long names so we can make sure the
+ * size of the name and the size of struct ar_hdr are rounded to
+ * 8 bytes. And that rounded size is what will be in the
+ * ar_name with the AR_EFMT1 string. To avoid growing the size
+ * of names first trim the name size before rounding up.
+ */
+ member->member_long_name = TRUE;
+ for(ar_name_size = ofile->member_name_size;
+ ar_name_size > 1 ;
+ ar_name_size--){
+ if(ofile->member_name[ar_name_size - 1] != '\0')
+ break;
+ }
+ member->member_name_size = ar_name_size;
+ ar_name_size = round(ar_name_size, 8) +
+ (round(sizeof(struct ar_hdr), 8) -
+ sizeof(struct ar_hdr));
+ size += ar_name_size;
+ /*
+ * Now with the output sizes of the long member name and rounded
+ * size of the member the offset to this member can be set and
+ * then left incremented for the next member's offset.
+ */
+ member->offset = arch->library_size;
+ arch->library_size += sizeof(struct ar_hdr) + size;
+ /*
+ * Since we are rounding the member size and forcing a the use
+ * of a long name make a new ar_hdr with this information.
+ * Note the code in writeout() will do the padding with '\n'
+ * characters as needed.
+ */
+ ar_hdr = allocate(sizeof(struct ar_hdr));
+ *ar_hdr = *(ofile->member_ar_hdr);
+ sprintf(ar_name_buf, "%s%-*lu", AR_EFMT1,
+ (int)(sizeof(ar_hdr->ar_name) -
+ (sizeof(AR_EFMT1) - 1)), ar_name_size);
+ memcpy(ar_hdr->ar_name, ar_name_buf,
+ sizeof(ar_hdr->ar_name));
+ sprintf(ar_size_buf, "%-*ld",
+ (int)sizeof(ar_hdr->ar_size), size);
+ memcpy(ar_hdr->ar_size, ar_size_buf,
+ sizeof(ar_hdr->ar_size));
+
+ member->ar_hdr = ar_hdr;
+ member->input_ar_hdr = ofile->member_ar_hdr;
+ member->input_file_name = filename;
+
+ if(ofile->member_type == OFILE_Mach_O){
+ member->object = allocate(sizeof(struct object));
+ memset(member->object, '\0', sizeof(struct object));
+ member->object->object_addr = ofile->object_addr;
+ member->object->object_size = ofile->object_size;
+ member->object->object_byte_sex = ofile->object_byte_sex;
+ member->object->mh64 = ofile->mh64;
+ member->object->mh = ofile->mh;
+ member->object->mh_filetype = ofile->mh_filetype;
+ member->object->mh_cputype = ofile->mh_cputype;
+ member->object->mh_cpusubtype = ofile->mh_cpusubtype;
+ member->object->load_commands = ofile->load_commands;
+ }
+ else{ /* ofile->member_type == OFILE_UNKNOWN */
+ member->unknown_addr = ofile->member_addr;
+ member->unknown_size = ofile->member_size;
+ }
+ flag = ofile_next_member(ofile);
+ }
+ }
+}
+
+/*
+ * cksum_object() is called to set the pointer to the LC_PREBIND_CKSUM load
+ * command in the object struct for the specified arch. If the parameter
+ * calculate_input_prebind_cksum is TRUE then calculate the value
+ * of the check sum for the input object if needed, set that into the
+ * the calculated_input_prebind_cksum field of the object struct for the
+ * specified arch. This is needed for prebound files where the original
+ * checksum (or zero) is recorded in the LC_PREBIND_CKSUM load command.
+ * Only redo_prebinding operations sets the value of the cksum field to
+ * non-zero and only if previously zero. All other operations will set this
+ * field to zero indicating a new original prebound file.
+ */
+static
+void
+cksum_object(
+struct arch *arch,
+enum bool calculate_input_prebind_cksum)
+{
+ unsigned long i, buf_size, ncmds;
+ struct load_command *lc;
+ enum byte_sex host_byte_sex;
+ char *buf;
+
+ arch->object->cs = NULL;
+ lc = arch->object->load_commands;
+ if(arch->object->mh != NULL)
+ ncmds = arch->object->mh->ncmds;
+ else
+ ncmds = arch->object->mh64->ncmds;
+ for(i = 0;
+ i < ncmds && arch->object->cs == NULL;
+ i++){
+ if(lc->cmd == LC_PREBIND_CKSUM)
+ arch->object->cs = (struct prebind_cksum_command *)lc;
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+
+ /*
+ * If we don't want to calculate the input check sum, or there is no
+ * LC_PREBIND_CKSUM load command or there is one and the check sum is
+ * not zero then return.
+ */
+ if(calculate_input_prebind_cksum == FALSE ||
+ arch->object->cs == NULL ||
+ arch->object->cs->cksum != 0)
+ return;
+
+
+ host_byte_sex = get_host_byte_sex();
+ buf_size = 0;
+ buf = NULL;
+ if(arch->object->object_byte_sex != host_byte_sex){
+ if(arch->object->mh != NULL){
+ buf_size = sizeof(struct mach_header) +
+ arch->object->mh->sizeofcmds;
+ buf = allocate(buf_size);
+ memcpy(buf, arch->object->mh, buf_size);
+ if(swap_object_headers(arch->object->mh,
+ arch->object->load_commands) == FALSE)
+ return;
+ }
+ else{
+ buf_size = sizeof(struct mach_header_64) +
+ arch->object->mh64->sizeofcmds;
+ buf = allocate(buf_size);
+ memcpy(buf, arch->object->mh64, buf_size);
+ if(swap_object_headers(arch->object->mh64,
+ arch->object->load_commands) == FALSE)
+ return;
+ }
+ }
+
+ arch->object->calculated_input_prebind_cksum =
+ crc32(arch->object->object_addr, arch->object->object_size);
+
+ if(arch->object->object_byte_sex != host_byte_sex){
+ if(arch->object->mh != NULL)
+ memcpy(arch->object->mh, buf, buf_size);
+ else
+ memcpy(arch->object->mh64, buf, buf_size);
+ free(buf);
+ }
+}
+
+__private_extern__
+void
+free_archs(
+struct arch *archs,
+unsigned long narchs)
+{
+ unsigned long i, j;
+
+ for(i = 0; i < narchs; i++){
+ if(archs[i].type == OFILE_ARCHIVE){
+ for(j = 0; j < archs[i].nmembers; j++){
+ if(archs[i].members[j].type == OFILE_Mach_O)
+ free(archs[i].members[j].object);
+ }
+ if(archs[i].nmembers > 0 && archs[i].members != NULL)
+ free(archs[i].members);
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ free(archs[i].object);
+ }
+ }
+ if(narchs > 0 && archs != NULL)
+ free(archs);
+}
+
+static
+struct arch *
+new_arch(
+struct arch **archs,
+unsigned long *narchs)
+{
+ struct arch *arch;
+
+ *archs = reallocate(*archs, (*narchs + 1) * sizeof(struct arch));
+ arch = *archs + *narchs;
+ *narchs = *narchs + 1;
+ memset(arch, '\0', sizeof(struct arch));
+ return(arch);
+}
+
+static
+struct member *
+new_member(
+struct arch *arch)
+{
+ struct member *member;
+
+ arch->members = reallocate(arch->members,
+ (arch->nmembers + 1) * sizeof(struct member));
+ member = arch->members + arch->nmembers;
+ arch->nmembers++;
+ memset(member, '\0', sizeof(struct member));
+ return(member);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/bytesex.c
@@ -0,0 +1,2765 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
+ */
+/* byte_sex.c */
+
+#define __cr cr
+#define __ctr ctr
+#define __dar dar
+#define __dsisr dsisr
+#define __exception exception
+#define __fpregs fpregs
+#define __fpscr fpscr
+#define __fpscr_pad fpscr_pad
+#define __lr lr
+#define __mq mq
+#define __pad0 pad0
+#define __pad1 pad1
+#define __r0 r0
+#define __r1 r1
+#define __r10 r10
+#define __r11 r11
+#define __r12 r12
+#define __r13 r13
+#define __r14 r14
+#define __r15 r15
+#define __r16 r16
+#define __r17 r17
+#define __r18 r18
+#define __r19 r19
+#define __r2 r2
+#define __r20 r20
+#define __r21 r21
+#define __r22 r22
+#define __r23 r23
+#define __r24 r24
+#define __r25 r25
+#define __r26 r26
+#define __r27 r27
+#define __r28 r28
+#define __r29 r29
+#define __r3 r3
+#define __r30 r30
+#define __r31 r31
+#define __r4 r4
+#define __r5 r5
+#define __r6 r6
+#define __r7 r7
+#define __r8 r8
+#define __r9 r9
+#define __srr0 srr0
+#define __srr1 srr1
+#define __vrsave vrsave
+#define __xer xer
+
+#define __darwin_i386_exception_state i386_exception_state
+#define __darwin_i386_float_state i386_float_state
+#define __darwin_i386_thread_state i386_thread_state
+#define __busy busy
+#define __c0 c0
+#define __c1 c1
+#define __c2 c2
+#define __c3 c3
+#define __cs cs
+#define __darwin_fp_control fp_control
+#define __darwin_fp_status fp_status
+#define __darwin_mmst_reg mmst_reg
+#define __darwin_xmm_reg xmm_reg
+#define __denorm denorm
+#define __ds ds
+#define __eax eax
+#define __ebp ebp
+#define __ebx ebx
+#define __ecx ecx
+#define __edi edi
+#define __edx edx
+#define __eflags eflags
+#define __eip eip
+#define __err err
+#define __errsumm errsumm
+#define __es es
+#define __esi esi
+#define __esp esp
+#define __faultvaddr faultvaddr
+#define __fpu_cs fpu_cs
+#define __fpu_dp fpu_dp
+#define __fpu_ds fpu_ds
+#define __fpu_fcw fpu_fcw
+#define __fpu_fop fpu_fop
+#define __fpu_fsw fpu_fsw
+#define __fpu_ftw fpu_ftw
+#define __fpu_ip fpu_ip
+#define __fpu_mxcsr fpu_mxcsr
+#define __fpu_mxcsrmask fpu_mxcsrmask
+#define __fpu_reserved fpu_reserved
+#define __fpu_reserved1 fpu_reserved1
+#define __fpu_rsrv1 fpu_rsrv1
+#define __fpu_rsrv2 fpu_rsrv2
+#define __fpu_rsrv3 fpu_rsrv3
+#define __fpu_rsrv4 fpu_rsrv4
+#define __fpu_stmm0 fpu_stmm0
+#define __fpu_stmm1 fpu_stmm1
+#define __fpu_stmm2 fpu_stmm2
+#define __fpu_stmm3 fpu_stmm3
+#define __fpu_stmm4 fpu_stmm4
+#define __fpu_stmm5 fpu_stmm5
+#define __fpu_stmm6 fpu_stmm6
+#define __fpu_stmm7 fpu_stmm7
+#define __fpu_xmm0 fpu_xmm0
+#define __fpu_xmm1 fpu_xmm1
+#define __fpu_xmm2 fpu_xmm2
+#define __fpu_xmm3 fpu_xmm3
+#define __fpu_xmm4 fpu_xmm4
+#define __fpu_xmm5 fpu_xmm5
+#define __fpu_xmm6 fpu_xmm6
+#define __fpu_xmm7 fpu_xmm7
+#define __fs fs
+#define __gs gs
+#define __invalid invalid
+#define __mmst_reg mmst_reg
+#define __mmst_rsrv mmst_rsrv
+#define __ovrfl ovrfl
+#define __pc pc
+#define __precis precis
+#define __rc rc
+#define __ss ss
+#define __stkflt stkflt
+#define __tos tos
+#define __trapno trapno
+#define __undfl undfl
+#define __xmm_reg xmm_reg
+#define __zdiv zdiv
+
+#define __rax rax
+#define __rbx rbx
+#define __rcx rcx
+#define __rdx rdx
+#define __rdi rdi
+#define __rsi rsi
+#define __rbp rbp
+#define __rsp rsp
+#define __r8 r8
+#define __r9 r9
+#define __r10 r10
+#define __r11 r11
+#define __r12 r12
+#define __r13 r13
+#define __r14 r14
+#define __r15 r15
+#define __rip rip
+#define __rflags rflags
+
+#define __dr0 dr0
+#define __dr1 dr1
+#define __dr2 dr2
+#define __dr3 dr3
+#define __dr4 dr4
+#define __dr5 dr5
+#define __dr6 dr6
+#define __dr7 dr7
+
+#include <string.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <mach/m68k/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/ppc/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/m88k/thread_status.h>
+#include <mach/i860/thread_status.h>
+#include <mach/i386/thread_status.h>
+#include <mach/hppa/thread_status.h>
+#include <mach/sparc/thread_status.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+#include <mach-o/ranlib.h>
+#include "stuff/bool.h"
+#include "stuff/bytesex.h"
+
+__private_extern__
+long long
+SWAP_LONG_LONG(
+long long ll)
+{
+ union {
+ char c[8];
+ long long ll;
+ } in, out;
+ in.ll = ll;
+ out.c[0] = in.c[7];
+ out.c[1] = in.c[6];
+ out.c[2] = in.c[5];
+ out.c[3] = in.c[4];
+ out.c[4] = in.c[3];
+ out.c[5] = in.c[2];
+ out.c[6] = in.c[1];
+ out.c[7] = in.c[0];
+ return(out.ll);
+}
+
+__private_extern__
+double
+SWAP_DOUBLE(
+double d)
+{
+ union {
+ char c[8];
+ double d;
+ } in, out;
+ in.d = d;
+ out.c[0] = in.c[7];
+ out.c[1] = in.c[6];
+ out.c[2] = in.c[5];
+ out.c[3] = in.c[4];
+ out.c[4] = in.c[3];
+ out.c[5] = in.c[2];
+ out.c[6] = in.c[1];
+ out.c[7] = in.c[0];
+ return(out.d);
+}
+
+__private_extern__
+float
+SWAP_FLOAT(
+float f)
+{
+ union {
+ char c[7];
+ float f;
+ } in, out;
+ in.f = f;
+ out.c[0] = in.c[3];
+ out.c[1] = in.c[2];
+ out.c[2] = in.c[1];
+ out.c[3] = in.c[0];
+ return(out.f);
+}
+
+/*
+ * get_host_byte_sex() returns the enum constant for the byte sex of the host
+ * it is running on.
+ */
+__private_extern__
+enum byte_sex
+get_host_byte_sex(
+void)
+{
+ uint32_t s;
+
+ s = (BIG_ENDIAN_BYTE_SEX << 24) | LITTLE_ENDIAN_BYTE_SEX;
+ return((enum byte_sex)*((char *)&s));
+}
+
+__private_extern__
+void
+swap_fat_header(
+struct fat_header *fat_header,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ fat_header->magic = SWAP_INT(fat_header->magic);
+ fat_header->nfat_arch = SWAP_INT(fat_header->nfat_arch);
+}
+
+__private_extern__
+void
+swap_fat_arch(
+struct fat_arch *fat_archs,
+unsigned long nfat_arch,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nfat_arch; i++){
+ fat_archs[i].cputype = SWAP_INT(fat_archs[i].cputype);
+ fat_archs[i].cpusubtype = SWAP_INT(fat_archs[i].cpusubtype);
+ fat_archs[i].offset = SWAP_INT(fat_archs[i].offset);
+ fat_archs[i].size = SWAP_INT(fat_archs[i].size);
+ fat_archs[i].align = SWAP_INT(fat_archs[i].align);
+ }
+}
+
+__private_extern__
+void
+swap_mach_header(
+struct mach_header *mh,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ mh->magic = SWAP_INT(mh->magic);
+ mh->cputype = SWAP_INT(mh->cputype);
+ mh->cpusubtype = SWAP_INT(mh->cpusubtype);
+ mh->filetype = SWAP_INT(mh->filetype);
+ mh->ncmds = SWAP_INT(mh->ncmds);
+ mh->sizeofcmds = SWAP_INT(mh->sizeofcmds);
+ mh->flags = SWAP_INT(mh->flags);
+}
+
+__private_extern__
+void
+swap_mach_header_64(
+struct mach_header_64 *mh,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ mh->magic = SWAP_INT(mh->magic);
+ mh->cputype = SWAP_INT(mh->cputype);
+ mh->cpusubtype = SWAP_INT(mh->cpusubtype);
+ mh->filetype = SWAP_INT(mh->filetype);
+ mh->ncmds = SWAP_INT(mh->ncmds);
+ mh->sizeofcmds = SWAP_INT(mh->sizeofcmds);
+ mh->flags = SWAP_INT(mh->flags);
+ mh->reserved = SWAP_INT(mh->reserved);
+}
+
+__private_extern__
+void
+swap_load_command(
+struct load_command *lc,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ lc->cmd = SWAP_INT(lc->cmd);
+ lc->cmdsize = SWAP_INT(lc->cmdsize);
+}
+
+__private_extern__
+void
+swap_segment_command(
+struct segment_command *sg,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ /* segname[16] */
+ sg->cmd = SWAP_INT(sg->cmd);
+ sg->cmdsize = SWAP_INT(sg->cmdsize);
+ sg->vmaddr = SWAP_INT(sg->vmaddr);
+ sg->vmsize = SWAP_INT(sg->vmsize);
+ sg->fileoff = SWAP_INT(sg->fileoff);
+ sg->filesize = SWAP_INT(sg->filesize);
+ sg->maxprot = SWAP_INT(sg->maxprot);
+ sg->initprot = SWAP_INT(sg->initprot);
+ sg->nsects = SWAP_INT(sg->nsects);
+ sg->flags = SWAP_INT(sg->flags);
+}
+
+__private_extern__
+void
+swap_segment_command_64(
+struct segment_command_64 *sg,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ /* segname[16] */
+ sg->cmd = SWAP_INT(sg->cmd);
+ sg->cmdsize = SWAP_INT(sg->cmdsize);
+ sg->vmaddr = SWAP_LONG_LONG(sg->vmaddr);
+ sg->vmsize = SWAP_LONG_LONG(sg->vmsize);
+ sg->fileoff = SWAP_LONG_LONG(sg->fileoff);
+ sg->filesize = SWAP_LONG_LONG(sg->filesize);
+ sg->maxprot = SWAP_INT(sg->maxprot);
+ sg->initprot = SWAP_INT(sg->initprot);
+ sg->nsects = SWAP_INT(sg->nsects);
+ sg->flags = SWAP_INT(sg->flags);
+}
+
+__private_extern__
+void
+swap_section(
+struct section *s,
+unsigned long nsects,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nsects; i++){
+ /* sectname[16] */
+ /* segname[16] */
+ s[i].addr = SWAP_INT(s[i].addr);
+ s[i].size = SWAP_INT(s[i].size);
+ s[i].offset = SWAP_INT(s[i].offset);
+ s[i].align = SWAP_INT(s[i].align);
+ s[i].reloff = SWAP_INT(s[i].reloff);
+ s[i].nreloc = SWAP_INT(s[i].nreloc);
+ s[i].flags = SWAP_INT(s[i].flags);
+ s[i].reserved1 = SWAP_INT(s[i].reserved1);
+ s[i].reserved2 = SWAP_INT(s[i].reserved2);
+ }
+}
+
+__private_extern__
+void
+swap_section_64(
+struct section_64 *s,
+unsigned long nsects,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nsects; i++){
+ /* sectname[16] */
+ /* segname[16] */
+ s[i].addr = SWAP_LONG_LONG(s[i].addr);
+ s[i].size = SWAP_LONG_LONG(s[i].size);
+ s[i].offset = SWAP_INT(s[i].offset);
+ s[i].align = SWAP_INT(s[i].align);
+ s[i].reloff = SWAP_INT(s[i].reloff);
+ s[i].nreloc = SWAP_INT(s[i].nreloc);
+ s[i].flags = SWAP_INT(s[i].flags);
+ s[i].reserved1 = SWAP_INT(s[i].reserved1);
+ s[i].reserved2 = SWAP_INT(s[i].reserved2);
+ }
+}
+
+__private_extern__
+void
+swap_symtab_command(
+struct symtab_command *st,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ st->cmd = SWAP_INT(st->cmd);
+ st->cmdsize = SWAP_INT(st->cmdsize);
+ st->symoff = SWAP_INT(st->symoff);
+ st->nsyms = SWAP_INT(st->nsyms);
+ st->stroff = SWAP_INT(st->stroff);
+ st->strsize = SWAP_INT(st->strsize);
+}
+
+__private_extern__
+void
+swap_dysymtab_command(
+struct dysymtab_command *dyst,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ dyst->cmd = SWAP_INT(dyst->cmd);
+ dyst->cmdsize = SWAP_INT(dyst->cmdsize);
+ dyst->ilocalsym = SWAP_INT(dyst->ilocalsym);
+ dyst->nlocalsym = SWAP_INT(dyst->nlocalsym);
+ dyst->iextdefsym = SWAP_INT(dyst->iextdefsym);
+ dyst->nextdefsym = SWAP_INT(dyst->nextdefsym);
+ dyst->iundefsym = SWAP_INT(dyst->iundefsym);
+ dyst->nundefsym = SWAP_INT(dyst->nundefsym);
+ dyst->tocoff = SWAP_INT(dyst->tocoff);
+ dyst->ntoc = SWAP_INT(dyst->ntoc);
+ dyst->modtaboff = SWAP_INT(dyst->modtaboff);
+ dyst->nmodtab = SWAP_INT(dyst->nmodtab);
+ dyst->extrefsymoff = SWAP_INT(dyst->extrefsymoff);
+ dyst->nextrefsyms = SWAP_INT(dyst->nextrefsyms);
+ dyst->indirectsymoff = SWAP_INT(dyst->indirectsymoff);
+ dyst->nindirectsyms = SWAP_INT(dyst->nindirectsyms);
+ dyst->extreloff = SWAP_INT(dyst->extreloff);
+ dyst->nextrel = SWAP_INT(dyst->nextrel);
+ dyst->locreloff = SWAP_INT(dyst->locreloff);
+ dyst->nlocrel = SWAP_INT(dyst->nlocrel);
+}
+
+__private_extern__
+void
+swap_symseg_command(
+struct symseg_command *ss,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ ss->cmd = SWAP_INT(ss->cmd);
+ ss->cmdsize = SWAP_INT(ss->cmdsize);
+ ss->offset = SWAP_INT(ss->offset);
+ ss->size = SWAP_INT(ss->size);
+}
+
+__private_extern__
+void
+swap_fvmlib_command(
+struct fvmlib_command *fl,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ fl->cmd = SWAP_INT(fl->cmd);
+ fl->cmdsize = SWAP_INT(fl->cmdsize);
+ fl->fvmlib.name.offset = SWAP_INT(fl->fvmlib.name.offset);
+ fl->fvmlib.minor_version = SWAP_INT(fl->fvmlib.minor_version);
+ fl->fvmlib.header_addr = SWAP_INT(fl->fvmlib.header_addr);
+}
+
+__private_extern__
+void
+swap_dylib_command(
+struct dylib_command *dl,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ dl->cmd = SWAP_INT(dl->cmd);
+ dl->cmdsize = SWAP_INT(dl->cmdsize);
+ dl->dylib.name.offset = SWAP_INT(dl->dylib.name.offset);
+ dl->dylib.timestamp = SWAP_INT(dl->dylib.timestamp);
+ dl->dylib.current_version = SWAP_INT(dl->dylib.current_version);
+ dl->dylib.compatibility_version =
+ SWAP_INT(dl->dylib.compatibility_version);
+}
+
+__private_extern__
+void
+swap_sub_framework_command(
+struct sub_framework_command *sub,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ sub->cmd = SWAP_INT(sub->cmd);
+ sub->cmdsize = SWAP_INT(sub->cmdsize);
+ sub->umbrella.offset = SWAP_INT(sub->umbrella.offset);
+}
+
+__private_extern__
+void
+swap_sub_umbrella_command(
+struct sub_umbrella_command *usub,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ usub->cmd = SWAP_INT(usub->cmd);
+ usub->cmdsize = SWAP_INT(usub->cmdsize);
+ usub->sub_umbrella.offset = SWAP_INT(usub->sub_umbrella.offset);
+}
+
+__private_extern__
+void
+swap_sub_library_command(
+struct sub_library_command *lsub,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ lsub->cmd = SWAP_INT(lsub->cmd);
+ lsub->cmdsize = SWAP_INT(lsub->cmdsize);
+ lsub->sub_library.offset = SWAP_INT(lsub->sub_library.offset);
+}
+
+__private_extern__
+void
+swap_sub_client_command(
+struct sub_client_command *csub,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ csub->cmd = SWAP_INT(csub->cmd);
+ csub->cmdsize = SWAP_INT(csub->cmdsize);
+ csub->client.offset = SWAP_INT(csub->client.offset);
+}
+
+__private_extern__
+void
+swap_prebound_dylib_command(
+struct prebound_dylib_command *pbdylib,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ pbdylib->cmd = SWAP_INT(pbdylib->cmd);
+ pbdylib->cmdsize = SWAP_INT(pbdylib->cmdsize);
+ pbdylib->name.offset = SWAP_INT(pbdylib->name.offset);
+ pbdylib->nmodules = SWAP_INT(pbdylib->nmodules);
+ pbdylib->linked_modules.offset =
+ SWAP_INT(pbdylib->linked_modules.offset);
+}
+
+__private_extern__
+void
+swap_dylinker_command(
+struct dylinker_command *dyld,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ dyld->cmd = SWAP_INT(dyld->cmd);
+ dyld->cmdsize = SWAP_INT(dyld->cmdsize);
+ dyld->name.offset = SWAP_INT(dyld->name.offset);
+}
+
+__private_extern__
+void
+swap_fvmfile_command(
+struct fvmfile_command *ff,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ ff->cmd = SWAP_INT(ff->cmd);
+ ff->cmdsize = SWAP_INT(ff->cmdsize);
+ ff->name.offset = SWAP_INT(ff->name.offset);
+ ff->header_addr = SWAP_INT(ff->header_addr);
+}
+
+
+__private_extern__
+void
+swap_thread_command(
+struct thread_command *ut,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ ut->cmd = SWAP_INT(ut->cmd);
+ ut->cmdsize = SWAP_INT(ut->cmdsize);
+}
+
+__private_extern__
+void
+swap_m68k_thread_state_regs(
+struct m68k_thread_state_regs *cpu,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < 8; i++)
+ cpu->dreg[i] = SWAP_INT(cpu->dreg[i]);
+ for(i = 0; i < 8; i++)
+ cpu->areg[i] = SWAP_INT(cpu->areg[i]);
+ cpu->pad0 = SWAP_SHORT(cpu->pad0);
+ cpu->sr = SWAP_SHORT(cpu->sr);
+ cpu->pc = SWAP_INT(cpu->pc);
+}
+
+__private_extern__
+void
+swap_m68k_thread_state_68882(
+struct m68k_thread_state_68882 *fpu,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i, tmp;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < 8; i++){
+ tmp = SWAP_INT(fpu->regs[i].fp[0]);
+ fpu->regs[i].fp[1] = SWAP_INT(fpu->regs[i].fp[1]);
+ fpu->regs[i].fp[0] = SWAP_INT(fpu->regs[i].fp[2]);
+ fpu->regs[i].fp[2] = tmp;
+ }
+ fpu->cr = SWAP_INT(fpu->cr);
+ fpu->sr = SWAP_INT(fpu->sr);
+ fpu->iar = SWAP_INT(fpu->iar);
+ fpu->state = SWAP_INT(fpu->state);
+}
+
+__private_extern__
+void
+swap_m68k_thread_state_user_reg(
+struct m68k_thread_state_user_reg *user_reg,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ user_reg->user_reg = SWAP_INT(user_reg->user_reg);
+}
+
+__private_extern__
+void
+swap_ppc_thread_state_t(
+ppc_thread_state_t *cpu,
+enum byte_sex target_byte_sex)
+{
+ cpu->srr0 = SWAP_INT(cpu->srr0);
+ cpu->srr1 = SWAP_INT(cpu->srr1);
+ cpu->r0 = SWAP_INT(cpu->r0);
+ cpu->r1 = SWAP_INT(cpu->r1);
+ cpu->r2 = SWAP_INT(cpu->r2);
+ cpu->r3 = SWAP_INT(cpu->r3);
+ cpu->r4 = SWAP_INT(cpu->r4);
+ cpu->r5 = SWAP_INT(cpu->r5);
+ cpu->r6 = SWAP_INT(cpu->r6);
+ cpu->r7 = SWAP_INT(cpu->r7);
+ cpu->r8 = SWAP_INT(cpu->r8);
+ cpu->r9 = SWAP_INT(cpu->r9);
+ cpu->r10 = SWAP_INT(cpu->r10);
+ cpu->r11 = SWAP_INT(cpu->r11);
+ cpu->r12 = SWAP_INT(cpu->r12);
+ cpu->r13 = SWAP_INT(cpu->r13);
+ cpu->r14 = SWAP_INT(cpu->r14);
+ cpu->r15 = SWAP_INT(cpu->r15);
+ cpu->r16 = SWAP_INT(cpu->r16);
+ cpu->r17 = SWAP_INT(cpu->r17);
+ cpu->r18 = SWAP_INT(cpu->r18);
+ cpu->r19 = SWAP_INT(cpu->r19);
+ cpu->r20 = SWAP_INT(cpu->r20);
+ cpu->r21 = SWAP_INT(cpu->r21);
+ cpu->r22 = SWAP_INT(cpu->r22);
+ cpu->r23 = SWAP_INT(cpu->r23);
+ cpu->r24 = SWAP_INT(cpu->r24);
+ cpu->r25 = SWAP_INT(cpu->r25);
+ cpu->r26 = SWAP_INT(cpu->r26);
+ cpu->r27 = SWAP_INT(cpu->r27);
+ cpu->r28 = SWAP_INT(cpu->r28);
+ cpu->r29 = SWAP_INT(cpu->r29);
+ cpu->r30 = SWAP_INT(cpu->r30);
+ cpu->r31 = SWAP_INT(cpu->r31);
+ cpu->cr = SWAP_INT(cpu->cr);
+ cpu->xer = SWAP_INT(cpu->xer);
+ cpu->lr = SWAP_INT(cpu->lr);
+ cpu->ctr = SWAP_INT(cpu->ctr);
+ cpu->mq = SWAP_INT(cpu->mq);
+ cpu->vrsave = SWAP_INT(cpu->vrsave);
+}
+
+__private_extern__
+void
+swap_ppc_thread_state64_t(
+ppc_thread_state64_t *cpu,
+enum byte_sex target_byte_sex)
+{
+ cpu->srr0 = SWAP_LONG_LONG(cpu->srr0);
+ cpu->srr1 = SWAP_LONG_LONG(cpu->srr1);
+ cpu->r0 = SWAP_LONG_LONG(cpu->r0);
+ cpu->r1 = SWAP_LONG_LONG(cpu->r1);
+ cpu->r2 = SWAP_LONG_LONG(cpu->r2);
+ cpu->r3 = SWAP_LONG_LONG(cpu->r3);
+ cpu->r4 = SWAP_LONG_LONG(cpu->r4);
+ cpu->r5 = SWAP_LONG_LONG(cpu->r5);
+ cpu->r6 = SWAP_LONG_LONG(cpu->r6);
+ cpu->r7 = SWAP_LONG_LONG(cpu->r7);
+ cpu->r8 = SWAP_LONG_LONG(cpu->r8);
+ cpu->r9 = SWAP_LONG_LONG(cpu->r9);
+ cpu->r10 = SWAP_LONG_LONG(cpu->r10);
+ cpu->r11 = SWAP_LONG_LONG(cpu->r11);
+ cpu->r12 = SWAP_LONG_LONG(cpu->r12);
+ cpu->r13 = SWAP_LONG_LONG(cpu->r13);
+ cpu->r14 = SWAP_LONG_LONG(cpu->r14);
+ cpu->r15 = SWAP_LONG_LONG(cpu->r15);
+ cpu->r16 = SWAP_LONG_LONG(cpu->r16);
+ cpu->r17 = SWAP_LONG_LONG(cpu->r17);
+ cpu->r18 = SWAP_LONG_LONG(cpu->r18);
+ cpu->r19 = SWAP_LONG_LONG(cpu->r19);
+ cpu->r20 = SWAP_LONG_LONG(cpu->r20);
+ cpu->r21 = SWAP_LONG_LONG(cpu->r21);
+ cpu->r22 = SWAP_LONG_LONG(cpu->r22);
+ cpu->r23 = SWAP_LONG_LONG(cpu->r23);
+ cpu->r24 = SWAP_LONG_LONG(cpu->r24);
+ cpu->r25 = SWAP_LONG_LONG(cpu->r25);
+ cpu->r26 = SWAP_LONG_LONG(cpu->r26);
+ cpu->r27 = SWAP_LONG_LONG(cpu->r27);
+ cpu->r28 = SWAP_LONG_LONG(cpu->r28);
+ cpu->r29 = SWAP_LONG_LONG(cpu->r29);
+ cpu->r30 = SWAP_LONG_LONG(cpu->r30);
+ cpu->r31 = SWAP_LONG_LONG(cpu->r31);
+ cpu->cr = SWAP_INT(cpu->cr);
+ cpu->xer = SWAP_LONG_LONG(cpu->xer);
+ cpu->lr = SWAP_LONG_LONG(cpu->lr);
+ cpu->ctr = SWAP_LONG_LONG(cpu->ctr);
+ cpu->vrsave = SWAP_INT(cpu->vrsave);
+}
+
+__private_extern__
+void
+swap_ppc_float_state_t(
+ppc_float_state_t *fpu,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < 32; i++)
+ fpu->fpregs[i] = SWAP_DOUBLE(fpu->fpregs[i]);
+
+ fpu->fpscr_pad = SWAP_INT(fpu->fpscr_pad);
+ fpu->fpscr = SWAP_INT(fpu->fpscr);
+}
+
+__private_extern__
+void
+swap_ppc_exception_state_t(
+ppc_exception_state_t *state,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ state->dar = SWAP_INT(state->dar);
+ state->dsisr = SWAP_INT(state->dsisr);
+ state->exception = SWAP_INT(state->exception);
+ state->pad0 = SWAP_INT(state->pad0);
+
+ for(i = 0; i < 4; i++)
+ state->pad1[i] = SWAP_INT(state->pad1[i]);
+}
+
+__private_extern__
+void
+swap_m88k_thread_state_grf_t(
+m88k_thread_state_grf_t *cpu,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ cpu->r1 = SWAP_INT(cpu->r1);
+ cpu->r2 = SWAP_INT(cpu->r2);
+ cpu->r3 = SWAP_INT(cpu->r3);
+ cpu->r4 = SWAP_INT(cpu->r4);
+ cpu->r5 = SWAP_INT(cpu->r5);
+ cpu->r6 = SWAP_INT(cpu->r6);
+ cpu->r7 = SWAP_INT(cpu->r7);
+ cpu->r8 = SWAP_INT(cpu->r8);
+ cpu->r9 = SWAP_INT(cpu->r9);
+ cpu->r10 = SWAP_INT(cpu->r10);
+ cpu->r11 = SWAP_INT(cpu->r11);
+ cpu->r12 = SWAP_INT(cpu->r12);
+ cpu->r13 = SWAP_INT(cpu->r13);
+ cpu->r14 = SWAP_INT(cpu->r14);
+ cpu->r15 = SWAP_INT(cpu->r15);
+ cpu->r16 = SWAP_INT(cpu->r16);
+ cpu->r17 = SWAP_INT(cpu->r17);
+ cpu->r18 = SWAP_INT(cpu->r18);
+ cpu->r19 = SWAP_INT(cpu->r19);
+ cpu->r20 = SWAP_INT(cpu->r20);
+ cpu->r21 = SWAP_INT(cpu->r21);
+ cpu->r22 = SWAP_INT(cpu->r22);
+ cpu->r23 = SWAP_INT(cpu->r23);
+ cpu->r24 = SWAP_INT(cpu->r24);
+ cpu->r25 = SWAP_INT(cpu->r25);
+ cpu->r26 = SWAP_INT(cpu->r26);
+ cpu->r27 = SWAP_INT(cpu->r27);
+ cpu->r28 = SWAP_INT(cpu->r28);
+ cpu->r29 = SWAP_INT(cpu->r29);
+ cpu->r30 = SWAP_INT(cpu->r30);
+ cpu->r31 = SWAP_INT(cpu->r31);
+ cpu->xip = SWAP_INT(cpu->xip);
+ cpu->xip_in_bd = SWAP_INT(cpu->xip_in_bd);
+ cpu->nip = SWAP_INT(cpu->nip);
+}
+
+__private_extern__
+void
+swap_m88k_thread_state_xrf_t(
+m88k_thread_state_xrf_t *fpu,
+enum byte_sex target_byte_sex)
+{
+ enum byte_sex host_byte_sex;
+
+ struct swapped_m88k_fpsr {
+ union {
+ struct {
+ unsigned afinx:BIT_WIDTH(0);
+ unsigned afovf:BIT_WIDTH(1);
+ unsigned afunf:BIT_WIDTH(2);
+ unsigned afdvz:BIT_WIDTH(3);
+ unsigned afinv:BIT_WIDTH(4);
+ unsigned :BITS_WIDTH(15,5);
+ unsigned xmod:BIT_WIDTH(16);
+ unsigned :BITS_WIDTH(31,17);
+ } fields;
+ uint32_t word;
+ } u;
+ } ssr;
+ struct swapped_m88k_fpcr {
+ union {
+ struct {
+ unsigned efinx:BIT_WIDTH(0);
+ unsigned efovf:BIT_WIDTH(1);
+ unsigned efunf:BIT_WIDTH(2);
+ unsigned efdvz:BIT_WIDTH(3);
+ unsigned efinv:BIT_WIDTH(4);
+ unsigned :BITS_WIDTH(13,5);
+ m88k_fpcr_rm_t rm:BITS_WIDTH(15,14);
+ unsigned :BITS_WIDTH(31,16);
+ } fields;
+ uint32_t word;
+ } u;
+ } scr;
+
+ host_byte_sex = get_host_byte_sex();
+
+ fpu->x1.x[0] = SWAP_INT(fpu->x1.x[0]);
+ fpu->x1.x[1] = SWAP_INT(fpu->x1.x[1]);
+ fpu->x1.x[2] = SWAP_INT(fpu->x1.x[2]);
+ fpu->x1.x[3] = SWAP_INT(fpu->x1.x[3]);
+ fpu->x2.x[0] = SWAP_INT(fpu->x2.x[0]);
+ fpu->x2.x[1] = SWAP_INT(fpu->x2.x[1]);
+ fpu->x2.x[2] = SWAP_INT(fpu->x2.x[2]);
+ fpu->x2.x[3] = SWAP_INT(fpu->x2.x[3]);
+ fpu->x3.x[0] = SWAP_INT(fpu->x3.x[0]);
+ fpu->x3.x[1] = SWAP_INT(fpu->x3.x[1]);
+ fpu->x3.x[2] = SWAP_INT(fpu->x3.x[2]);
+ fpu->x3.x[3] = SWAP_INT(fpu->x3.x[3]);
+ fpu->x4.x[0] = SWAP_INT(fpu->x4.x[0]);
+ fpu->x4.x[1] = SWAP_INT(fpu->x4.x[1]);
+ fpu->x4.x[2] = SWAP_INT(fpu->x4.x[2]);
+ fpu->x4.x[3] = SWAP_INT(fpu->x4.x[3]);
+ fpu->x5.x[0] = SWAP_INT(fpu->x5.x[0]);
+ fpu->x5.x[1] = SWAP_INT(fpu->x5.x[1]);
+ fpu->x5.x[2] = SWAP_INT(fpu->x5.x[2]);
+ fpu->x5.x[3] = SWAP_INT(fpu->x5.x[3]);
+ fpu->x6.x[0] = SWAP_INT(fpu->x6.x[0]);
+ fpu->x6.x[1] = SWAP_INT(fpu->x6.x[1]);
+ fpu->x6.x[2] = SWAP_INT(fpu->x6.x[2]);
+ fpu->x6.x[3] = SWAP_INT(fpu->x6.x[3]);
+ fpu->x7.x[0] = SWAP_INT(fpu->x7.x[0]);
+ fpu->x7.x[1] = SWAP_INT(fpu->x7.x[1]);
+ fpu->x7.x[2] = SWAP_INT(fpu->x7.x[2]);
+ fpu->x7.x[3] = SWAP_INT(fpu->x7.x[3]);
+ fpu->x8.x[0] = SWAP_INT(fpu->x8.x[0]);
+ fpu->x8.x[1] = SWAP_INT(fpu->x8.x[1]);
+ fpu->x8.x[2] = SWAP_INT(fpu->x8.x[2]);
+ fpu->x8.x[3] = SWAP_INT(fpu->x8.x[3]);
+ fpu->x9.x[0] = SWAP_INT(fpu->x9.x[0]);
+ fpu->x9.x[1] = SWAP_INT(fpu->x9.x[1]);
+ fpu->x9.x[2] = SWAP_INT(fpu->x9.x[2]);
+ fpu->x9.x[3] = SWAP_INT(fpu->x9.x[3]);
+ fpu->x10.x[0] = SWAP_INT(fpu->x10.x[0]);
+ fpu->x10.x[1] = SWAP_INT(fpu->x10.x[1]);
+ fpu->x10.x[2] = SWAP_INT(fpu->x10.x[2]);
+ fpu->x10.x[3] = SWAP_INT(fpu->x10.x[3]);
+ fpu->x11.x[0] = SWAP_INT(fpu->x11.x[0]);
+ fpu->x11.x[1] = SWAP_INT(fpu->x11.x[1]);
+ fpu->x11.x[2] = SWAP_INT(fpu->x11.x[2]);
+ fpu->x11.x[3] = SWAP_INT(fpu->x11.x[3]);
+ fpu->x12.x[0] = SWAP_INT(fpu->x12.x[0]);
+ fpu->x12.x[1] = SWAP_INT(fpu->x12.x[1]);
+ fpu->x12.x[2] = SWAP_INT(fpu->x12.x[2]);
+ fpu->x12.x[3] = SWAP_INT(fpu->x12.x[3]);
+ fpu->x13.x[0] = SWAP_INT(fpu->x13.x[0]);
+ fpu->x13.x[1] = SWAP_INT(fpu->x13.x[1]);
+ fpu->x13.x[2] = SWAP_INT(fpu->x13.x[2]);
+ fpu->x13.x[3] = SWAP_INT(fpu->x13.x[3]);
+ fpu->x14.x[0] = SWAP_INT(fpu->x14.x[0]);
+ fpu->x14.x[1] = SWAP_INT(fpu->x14.x[1]);
+ fpu->x14.x[2] = SWAP_INT(fpu->x14.x[2]);
+ fpu->x14.x[3] = SWAP_INT(fpu->x14.x[3]);
+ fpu->x15.x[0] = SWAP_INT(fpu->x15.x[0]);
+ fpu->x15.x[1] = SWAP_INT(fpu->x15.x[1]);
+ fpu->x15.x[2] = SWAP_INT(fpu->x15.x[2]);
+ fpu->x15.x[3] = SWAP_INT(fpu->x15.x[3]);
+ fpu->x16.x[0] = SWAP_INT(fpu->x16.x[0]);
+ fpu->x16.x[1] = SWAP_INT(fpu->x16.x[1]);
+ fpu->x16.x[2] = SWAP_INT(fpu->x16.x[2]);
+ fpu->x16.x[3] = SWAP_INT(fpu->x16.x[3]);
+ fpu->x17.x[0] = SWAP_INT(fpu->x17.x[0]);
+ fpu->x17.x[1] = SWAP_INT(fpu->x17.x[1]);
+ fpu->x17.x[2] = SWAP_INT(fpu->x17.x[2]);
+ fpu->x17.x[3] = SWAP_INT(fpu->x17.x[3]);
+ fpu->x18.x[0] = SWAP_INT(fpu->x18.x[0]);
+ fpu->x18.x[1] = SWAP_INT(fpu->x18.x[1]);
+ fpu->x18.x[2] = SWAP_INT(fpu->x18.x[2]);
+ fpu->x18.x[3] = SWAP_INT(fpu->x18.x[3]);
+ fpu->x19.x[0] = SWAP_INT(fpu->x19.x[0]);
+ fpu->x19.x[1] = SWAP_INT(fpu->x19.x[1]);
+ fpu->x19.x[2] = SWAP_INT(fpu->x19.x[2]);
+ fpu->x19.x[3] = SWAP_INT(fpu->x19.x[3]);
+ fpu->x20.x[0] = SWAP_INT(fpu->x20.x[0]);
+ fpu->x20.x[1] = SWAP_INT(fpu->x20.x[1]);
+ fpu->x20.x[2] = SWAP_INT(fpu->x20.x[2]);
+ fpu->x20.x[3] = SWAP_INT(fpu->x20.x[3]);
+ fpu->x21.x[0] = SWAP_INT(fpu->x21.x[0]);
+ fpu->x21.x[1] = SWAP_INT(fpu->x21.x[1]);
+ fpu->x21.x[2] = SWAP_INT(fpu->x21.x[2]);
+ fpu->x21.x[3] = SWAP_INT(fpu->x21.x[3]);
+ fpu->x22.x[0] = SWAP_INT(fpu->x22.x[0]);
+ fpu->x22.x[1] = SWAP_INT(fpu->x22.x[1]);
+ fpu->x22.x[2] = SWAP_INT(fpu->x22.x[2]);
+ fpu->x22.x[3] = SWAP_INT(fpu->x22.x[3]);
+ fpu->x23.x[0] = SWAP_INT(fpu->x23.x[0]);
+ fpu->x23.x[1] = SWAP_INT(fpu->x23.x[1]);
+ fpu->x23.x[2] = SWAP_INT(fpu->x23.x[2]);
+ fpu->x23.x[3] = SWAP_INT(fpu->x23.x[3]);
+ fpu->x24.x[0] = SWAP_INT(fpu->x24.x[0]);
+ fpu->x24.x[1] = SWAP_INT(fpu->x24.x[1]);
+ fpu->x24.x[2] = SWAP_INT(fpu->x24.x[2]);
+ fpu->x24.x[3] = SWAP_INT(fpu->x24.x[3]);
+ fpu->x25.x[0] = SWAP_INT(fpu->x25.x[0]);
+ fpu->x25.x[1] = SWAP_INT(fpu->x25.x[1]);
+ fpu->x25.x[2] = SWAP_INT(fpu->x25.x[2]);
+ fpu->x25.x[3] = SWAP_INT(fpu->x25.x[3]);
+ fpu->x26.x[0] = SWAP_INT(fpu->x26.x[0]);
+ fpu->x26.x[1] = SWAP_INT(fpu->x26.x[1]);
+ fpu->x26.x[2] = SWAP_INT(fpu->x26.x[2]);
+ fpu->x26.x[3] = SWAP_INT(fpu->x26.x[3]);
+ fpu->x27.x[0] = SWAP_INT(fpu->x27.x[0]);
+ fpu->x27.x[1] = SWAP_INT(fpu->x27.x[1]);
+ fpu->x27.x[2] = SWAP_INT(fpu->x27.x[2]);
+ fpu->x27.x[3] = SWAP_INT(fpu->x27.x[3]);
+ fpu->x28.x[0] = SWAP_INT(fpu->x28.x[0]);
+ fpu->x28.x[1] = SWAP_INT(fpu->x28.x[1]);
+ fpu->x28.x[2] = SWAP_INT(fpu->x28.x[2]);
+ fpu->x28.x[3] = SWAP_INT(fpu->x28.x[3]);
+ fpu->x29.x[0] = SWAP_INT(fpu->x29.x[0]);
+ fpu->x29.x[1] = SWAP_INT(fpu->x29.x[1]);
+ fpu->x29.x[2] = SWAP_INT(fpu->x29.x[2]);
+ fpu->x29.x[3] = SWAP_INT(fpu->x29.x[3]);
+ fpu->x30.x[0] = SWAP_INT(fpu->x30.x[0]);
+ fpu->x30.x[1] = SWAP_INT(fpu->x30.x[1]);
+ fpu->x30.x[2] = SWAP_INT(fpu->x30.x[2]);
+ fpu->x30.x[3] = SWAP_INT(fpu->x30.x[3]);
+ fpu->x31.x[0] = SWAP_INT(fpu->x31.x[0]);
+ fpu->x31.x[1] = SWAP_INT(fpu->x31.x[1]);
+ fpu->x31.x[2] = SWAP_INT(fpu->x31.x[2]);
+ fpu->x31.x[3] = SWAP_INT(fpu->x31.x[3]);
+
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&ssr, &(fpu->fpsr), sizeof(struct swapped_m88k_fpsr));
+ ssr.u.word = SWAP_INT(ssr.u.word);
+ fpu->fpsr.afinx = ssr.u.fields.afinx;
+ fpu->fpsr.afovf = ssr.u.fields.afovf;
+ fpu->fpsr.afunf = ssr.u.fields.afunf;
+ fpu->fpsr.afdvz = ssr.u.fields.afdvz;
+ fpu->fpsr.afinv = ssr.u.fields.afinv;
+ fpu->fpsr.xmod = ssr.u.fields.xmod;
+
+ memcpy(&scr, &(fpu->fpcr), sizeof(struct swapped_m88k_fpcr));
+ scr.u.word = SWAP_INT(scr.u.word);
+ fpu->fpcr.efinx = scr.u.fields.efinx;
+ fpu->fpcr.efovf = scr.u.fields.efovf;
+ fpu->fpcr.efunf = scr.u.fields.efunf;
+ fpu->fpcr.efdvz = scr.u.fields.efdvz;
+ fpu->fpcr.efinv = scr.u.fields.efinv;
+ fpu->fpcr.rm = scr.u.fields.rm;
+ }
+ else{
+ ssr.u.fields.afinx = fpu->fpsr.afinx;
+ ssr.u.fields.afovf = fpu->fpsr.afovf;
+ ssr.u.fields.afunf = fpu->fpsr.afunf;
+ ssr.u.fields.afdvz = fpu->fpsr.afdvz;
+ ssr.u.fields.afinv = fpu->fpsr.afinv;
+ ssr.u.fields.xmod = fpu->fpsr.xmod;
+ ssr.u.word = SWAP_INT(ssr.u.word);
+ memcpy(&(fpu->fpsr), &ssr, sizeof(struct swapped_m88k_fpsr));
+
+ scr.u.fields.efinx = fpu->fpcr.efinx;
+ scr.u.fields.efovf = fpu->fpcr.efovf;
+ scr.u.fields.efunf = fpu->fpcr.efunf;
+ scr.u.fields.efdvz = fpu->fpcr.efdvz;
+ scr.u.fields.efinv = fpu->fpcr.efinv;
+ scr.u.fields.rm = fpu->fpcr.rm;
+ scr.u.word = SWAP_INT(scr.u.word);
+ memcpy(&(fpu->fpcr), &scr, sizeof(struct swapped_m88k_fpcr));
+ }
+}
+
+__private_extern__
+void
+swap_m88k_thread_state_user_t(
+m88k_thread_state_user_t *user,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ user->user = SWAP_INT(user->user);
+}
+
+__private_extern__
+void
+swap_m88110_thread_state_impl_t(
+m88110_thread_state_impl_t *spu,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+ enum byte_sex host_byte_sex;
+
+ struct swapped_m88110_bp_ctrl {
+ union {
+ struct {
+ unsigned v:BIT_WIDTH(0);
+ m88110_match_t addr_match:BITS_WIDTH(12,1);
+ unsigned :BITS_WIDTH(26,13);
+ unsigned rwm:BIT_WIDTH(27);
+ unsigned rw:BIT_WIDTH(28);
+ unsigned :BITS_WIDTH(31,29);
+ } fields;
+ uint32_t word;
+ } u;
+ } sbpc;
+
+ struct swap_m88110_psr {
+ union {
+ struct {
+ unsigned :BITS_WIDTH(1,0);
+ unsigned mxm_dis:BIT_WIDTH(2);
+ unsigned sfu1dis:BIT_WIDTH(3);
+ unsigned :BITS_WIDTH(22,4);
+ unsigned trace:BIT_WIDTH(23);
+ unsigned :BIT_WIDTH(24);
+ unsigned sm:BIT_WIDTH(25);
+ unsigned sgn_imd:BIT_WIDTH(26);
+ unsigned :BIT_WIDTH(27);
+ unsigned c:BIT_WIDTH(28);
+ unsigned se:BIT_WIDTH(29);
+ unsigned le:BIT_WIDTH(30);
+ unsigned supr:BIT_WIDTH(31);
+ } fields;
+ uint32_t word;
+ } u;
+ } spsr;
+
+ struct swapped_m88110_fp_trap_status {
+ union {
+ struct {
+ unsigned efinx:BIT_WIDTH(0);
+ unsigned efovf:BIT_WIDTH(1);
+ unsigned efunf:BIT_WIDTH(2);
+ unsigned efdvz:BIT_WIDTH(3);
+ unsigned efinv:BIT_WIDTH(4);
+ unsigned priv:BIT_WIDTH(5);
+ unsigned unimp:BIT_WIDTH(6);
+ unsigned int:BIT_WIDTH(7);
+ unsigned sfu1_disabled:BIT_WIDTH(8);
+ unsigned :BITS_WIDTH(13,9);
+ m88110_iresult_size_t iresult_size:BITS_WIDTH(15,14);
+ unsigned :BITS_WIDTH(31,16);
+ } fields;
+ uint32_t word;
+ } u;
+ } sfps;
+
+ host_byte_sex = get_host_byte_sex();
+
+ if(target_byte_sex == host_byte_sex){
+ for(i = 0; i < M88110_N_DATA_BP; i++){
+ spu->data_bp[i].addr = SWAP_INT(spu->data_bp[i].addr);
+ memcpy(&sbpc, &(spu->data_bp[i].ctrl),
+ sizeof(struct swapped_m88110_bp_ctrl));
+ sbpc.u.word = SWAP_INT(sbpc.u.word);
+ spu->data_bp[i].ctrl.v = sbpc.u.fields.v;
+ spu->data_bp[i].ctrl.addr_match = sbpc.u.fields.addr_match;
+ spu->data_bp[i].ctrl.rwm = sbpc.u.fields.rwm;
+ spu->data_bp[i].ctrl.rw = sbpc.u.fields.rw;
+ }
+
+ memcpy(&spsr, &(spu->psr), sizeof(struct swap_m88110_psr));
+ spsr.u.word = SWAP_INT(spsr.u.word);
+ spu->psr.mxm_dis = spsr.u.fields.mxm_dis;
+ spu->psr.sfu1dis = spsr.u.fields.sfu1dis;
+ spu->psr.trace = spsr.u.fields.trace;
+ spu->psr.sm = spsr.u.fields.sm;
+ spu->psr.sgn_imd = spsr.u.fields.sgn_imd;
+ spu->psr.c = spsr.u.fields.c;
+ spu->psr.se = spsr.u.fields.se;
+ spu->psr.le = spsr.u.fields.le;
+ spu->psr.supr = spsr.u.fields.supr;
+
+ memcpy(&sfps, &(spu->fp_trap_status),
+ sizeof(struct swapped_m88110_fp_trap_status));
+ sfps.u.word = SWAP_INT(sfps.u.word);
+ spu->fp_trap_status.efinx = sfps.u.fields.efinx;
+ spu->fp_trap_status.efovf = sfps.u.fields.efovf;
+ spu->fp_trap_status.efunf = sfps.u.fields.efunf;
+ spu->fp_trap_status.efdvz = sfps.u.fields.efdvz;
+ spu->fp_trap_status.efinv = sfps.u.fields.efinv;
+ spu->fp_trap_status.priv = sfps.u.fields.priv;
+ spu->fp_trap_status.unimp = sfps.u.fields.unimp;
+ spu->fp_trap_status.sfu1_disabled = sfps.u.fields.sfu1_disabled;
+ spu->fp_trap_status.iresult_size = sfps.u.fields.iresult_size;
+ }
+ else{
+ for(i = 0; i < M88110_N_DATA_BP; i++){
+ spu->data_bp[i].addr = SWAP_INT(spu->data_bp[i].addr);
+ sbpc.u.fields.v = spu->data_bp[i].ctrl.v;
+ sbpc.u.fields.addr_match = spu->data_bp[i].ctrl.addr_match;
+ sbpc.u.fields.rwm = spu->data_bp[i].ctrl.rwm;
+ sbpc.u.fields.rw = spu->data_bp[i].ctrl.rw;
+ sbpc.u.word = SWAP_INT(sbpc.u.word);
+ memcpy(&(spu->data_bp[i].ctrl), &sbpc,
+ sizeof(struct swapped_m88110_bp_ctrl));
+ }
+
+ spsr.u.fields.mxm_dis = spu->psr.mxm_dis;
+ spsr.u.fields.sfu1dis = spu->psr.sfu1dis;
+ spsr.u.fields.trace = spu->psr.trace;
+ spsr.u.fields.sm = spu->psr.sm;
+ spsr.u.fields.sgn_imd = spu->psr.sgn_imd;
+ spsr.u.fields.c = spu->psr.c;
+ spsr.u.fields.se = spu->psr.se;
+ spsr.u.fields.le = spu->psr.le;
+ spsr.u.fields.supr = spu->psr.supr;
+ spsr.u.word = SWAP_INT(spsr.u.word);
+ memcpy(&(spu->psr), &spsr, sizeof(struct swap_m88110_psr));
+
+ sfps.u.fields.efinx = spu->fp_trap_status.efinx;
+ sfps.u.fields.efovf = spu->fp_trap_status.efovf;
+ sfps.u.fields.efunf = spu->fp_trap_status.efunf;
+ sfps.u.fields.efdvz = spu->fp_trap_status.efdvz;
+ sfps.u.fields.efinv = spu->fp_trap_status.efinv;
+ sfps.u.fields.priv = spu->fp_trap_status.priv;
+ sfps.u.fields.unimp = spu->fp_trap_status.unimp;
+ sfps.u.fields.sfu1_disabled = spu->fp_trap_status.sfu1_disabled;
+ sfps.u.fields.iresult_size = spu->fp_trap_status.iresult_size;
+ sfps.u.word = SWAP_INT(sfps.u.word);
+ memcpy(&(spu->fp_trap_status), &sfps,
+ sizeof(struct swapped_m88110_fp_trap_status));
+ }
+ spu->intermediate_result.x[0] =
+ SWAP_INT(spu->intermediate_result.x[0]);
+ spu->intermediate_result.x[1] =
+ SWAP_INT(spu->intermediate_result.x[1]);
+ spu->intermediate_result.x[2] =
+ SWAP_INT(spu->intermediate_result.x[2]);
+ spu->intermediate_result.x[3] =
+ SWAP_INT(spu->intermediate_result.x[3]);
+}
+
+__private_extern__
+void
+swap_i860_thread_state_regs(
+struct i860_thread_state_regs *cpu,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < 31; i++)
+ cpu->ireg[i] = SWAP_INT(cpu->ireg[i]);
+ for(i = 0; i < 30; i++)
+ cpu->freg[i] = SWAP_INT(cpu->freg[i]);
+ cpu->psr = SWAP_INT(cpu->psr);
+ cpu->epsr = SWAP_INT(cpu->epsr);
+ cpu->db = SWAP_INT(cpu->db);
+ cpu->pc = SWAP_INT(cpu->pc);
+ cpu->_padding_ = SWAP_INT(cpu->_padding_);
+ cpu->Mres3 = SWAP_DOUBLE(cpu->Mres3);
+ cpu->Ares3 = SWAP_DOUBLE(cpu->Ares3);
+ cpu->Mres2 = SWAP_DOUBLE(cpu->Mres2);
+ cpu->Ares2 = SWAP_DOUBLE(cpu->Ares2);
+ cpu->Mres1 = SWAP_DOUBLE(cpu->Mres1);
+ cpu->Ares1 = SWAP_DOUBLE(cpu->Ares1);
+ cpu->Ires1 = SWAP_DOUBLE(cpu->Ires1);
+ cpu->Lres3m = SWAP_DOUBLE(cpu->Lres3m);
+ cpu->Lres2m = SWAP_DOUBLE(cpu->Lres2m);
+ cpu->Lres1m = SWAP_DOUBLE(cpu->Lres1m);
+ cpu->KR = SWAP_DOUBLE(cpu->KR);
+ cpu->KI = SWAP_DOUBLE(cpu->KI);
+ cpu->T = SWAP_DOUBLE(cpu->T);
+ cpu->Fsr3 = SWAP_INT(cpu->Fsr3);
+ cpu->Fsr2 = SWAP_INT(cpu->Fsr2);
+ cpu->Fsr1 = SWAP_INT(cpu->Fsr1);
+ cpu->Mergelo32 = SWAP_INT(cpu->Mergelo32);
+ cpu->Mergehi32 = SWAP_INT(cpu->Mergehi32);
+}
+
+__private_extern__
+void
+swap_i386_thread_state(
+i386_thread_state_t *cpu,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ cpu->eax = SWAP_INT(cpu->eax);
+ cpu->ebx = SWAP_INT(cpu->ebx);
+ cpu->ecx = SWAP_INT(cpu->ecx);
+ cpu->edx = SWAP_INT(cpu->edx);
+ cpu->edi = SWAP_INT(cpu->edi);
+ cpu->esi = SWAP_INT(cpu->esi);
+ cpu->ebp = SWAP_INT(cpu->ebp);
+ cpu->esp = SWAP_INT(cpu->esp);
+ cpu->ss = SWAP_INT(cpu->ss);
+ cpu->eflags = SWAP_INT(cpu->eflags);
+ cpu->eip = SWAP_INT(cpu->eip);
+ cpu->cs = SWAP_INT(cpu->cs);
+ cpu->ds = SWAP_INT(cpu->ds);
+ cpu->es = SWAP_INT(cpu->es);
+ cpu->fs = SWAP_INT(cpu->fs);
+ cpu->gs = SWAP_INT(cpu->gs);
+}
+
+#ifdef x86_THREAD_STATE64
+__private_extern__
+void
+swap_x86_thread_state64(
+x86_thread_state64_t *cpu,
+enum byte_sex target_byte_sex)
+{
+ cpu->rax = SWAP_LONG_LONG(cpu->rax);
+ cpu->rbx = SWAP_LONG_LONG(cpu->rbx);
+ cpu->rcx = SWAP_LONG_LONG(cpu->rcx);
+ cpu->rdx = SWAP_LONG_LONG(cpu->rdx);
+ cpu->rdi = SWAP_LONG_LONG(cpu->rdi);
+ cpu->rsi = SWAP_LONG_LONG(cpu->rsi);
+ cpu->rbp = SWAP_LONG_LONG(cpu->rbp);
+ cpu->rsp = SWAP_LONG_LONG(cpu->rsp);
+ cpu->rflags = SWAP_LONG_LONG(cpu->rflags);
+ cpu->rip = SWAP_LONG_LONG(cpu->rip);
+ cpu->r8 = SWAP_LONG_LONG(cpu->r8);
+ cpu->r9 = SWAP_LONG_LONG(cpu->r9);
+ cpu->r10 = SWAP_LONG_LONG(cpu->r10);
+ cpu->r11 = SWAP_LONG_LONG(cpu->r11);
+ cpu->r12 = SWAP_LONG_LONG(cpu->r12);
+ cpu->r13 = SWAP_LONG_LONG(cpu->r13);
+ cpu->r14 = SWAP_LONG_LONG(cpu->r14);
+ cpu->r15 = SWAP_LONG_LONG(cpu->r15);
+ cpu->cs = SWAP_LONG_LONG(cpu->cs);
+ cpu->fs = SWAP_LONG_LONG(cpu->fs);
+ cpu->gs = SWAP_LONG_LONG(cpu->gs);
+}
+#endif /* x86_THREAD_STATE64 */
+
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+__private_extern__
+void
+swap_i386_float_state(
+struct i386_float_state *fpu,
+enum byte_sex target_byte_sex)
+{
+#ifndef i386_EXCEPTION_STATE_COUNT
+ /* this routine does nothing as their are currently no non-byte fields */
+#else /* defined(i386_EXCEPTION_STATE_COUNT) */
+ struct swapped_fp_control {
+ union {
+ struct {
+ unsigned short
+ :3,
+ /*inf*/ :1,
+ rc :2,
+ pc :2,
+ :2,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfpc;
+
+ struct swapped_fp_status {
+ union {
+ struct {
+ unsigned short
+ busy :1,
+ c3 :1,
+ tos :3,
+ c2 :1,
+ c1 :1,
+ c0 :1,
+ errsumm :1,
+ stkflt :1,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfps;
+
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ fpu->fpu_reserved[0] = SWAP_INT(fpu->fpu_reserved[0]);
+ fpu->fpu_reserved[1] = SWAP_INT(fpu->fpu_reserved[1]);
+
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sfpc, &(fpu->fpu_fcw),
+ sizeof(struct swapped_fp_control));
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ fpu->fpu_fcw.rc = sfpc.u.fields.rc;
+ fpu->fpu_fcw.pc = sfpc.u.fields.pc;
+ fpu->fpu_fcw.precis = sfpc.u.fields.precis;
+ fpu->fpu_fcw.undfl = sfpc.u.fields.undfl;
+ fpu->fpu_fcw.ovrfl = sfpc.u.fields.ovrfl;
+ fpu->fpu_fcw.zdiv = sfpc.u.fields.zdiv;
+ fpu->fpu_fcw.denorm = sfpc.u.fields.denorm;
+ fpu->fpu_fcw.invalid = sfpc.u.fields.invalid;
+
+ memcpy(&sfps, &(fpu->fpu_fsw),
+ sizeof(struct swapped_fp_status));
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ fpu->fpu_fsw.busy = sfps.u.fields.busy;
+ fpu->fpu_fsw.c3 = sfps.u.fields.c3;
+ fpu->fpu_fsw.tos = sfps.u.fields.tos;
+ fpu->fpu_fsw.c2 = sfps.u.fields.c2;
+ fpu->fpu_fsw.c1 = sfps.u.fields.c1;
+ fpu->fpu_fsw.c0 = sfps.u.fields.c0;
+ fpu->fpu_fsw.errsumm = sfps.u.fields.errsumm;
+ fpu->fpu_fsw.stkflt = sfps.u.fields.stkflt;
+ fpu->fpu_fsw.precis = sfps.u.fields.precis;
+ fpu->fpu_fsw.undfl = sfps.u.fields.undfl;
+ fpu->fpu_fsw.ovrfl = sfps.u.fields.ovrfl;
+ fpu->fpu_fsw.zdiv = sfps.u.fields.zdiv;
+ fpu->fpu_fsw.denorm = sfps.u.fields.denorm;
+ fpu->fpu_fsw.invalid = sfps.u.fields.invalid;
+ }
+ else{
+ sfpc.u.fields.rc = fpu->fpu_fcw.rc;
+ sfpc.u.fields.pc = fpu->fpu_fcw.pc;
+ sfpc.u.fields.precis = fpu->fpu_fcw.precis;
+ sfpc.u.fields.undfl = fpu->fpu_fcw.undfl;
+ sfpc.u.fields.ovrfl = fpu->fpu_fcw.ovrfl;
+ sfpc.u.fields.zdiv = fpu->fpu_fcw.zdiv;
+ sfpc.u.fields.denorm = fpu->fpu_fcw.denorm;
+ sfpc.u.fields.invalid = fpu->fpu_fcw.invalid;
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ memcpy(&(fpu->fpu_fcw), &sfpc,
+ sizeof(struct swapped_fp_control));
+
+ sfps.u.fields.busy = fpu->fpu_fsw.busy;
+ sfps.u.fields.c3 = fpu->fpu_fsw.c3;
+ sfps.u.fields.tos = fpu->fpu_fsw.tos;
+ sfps.u.fields.c2 = fpu->fpu_fsw.c2;
+ sfps.u.fields.c1 = fpu->fpu_fsw.c1;
+ sfps.u.fields.c0 = fpu->fpu_fsw.c0;
+ sfps.u.fields.errsumm = fpu->fpu_fsw.errsumm;
+ sfps.u.fields.stkflt = fpu->fpu_fsw.stkflt;
+ sfps.u.fields.precis = fpu->fpu_fsw.precis;
+ sfps.u.fields.undfl = fpu->fpu_fsw.undfl;
+ sfps.u.fields.ovrfl = fpu->fpu_fsw.ovrfl;
+ sfps.u.fields.zdiv = fpu->fpu_fsw.zdiv;
+ sfps.u.fields.denorm = fpu->fpu_fsw.denorm;
+ sfps.u.fields.invalid = fpu->fpu_fsw.invalid;
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ memcpy(&(fpu->fpu_fsw), &sfps,
+ sizeof(struct swapped_fp_status));
+ }
+ fpu->fpu_fop = SWAP_SHORT(fpu->fpu_fop);
+ fpu->fpu_ip = SWAP_INT(fpu->fpu_ip);
+ fpu->fpu_cs = SWAP_SHORT(fpu->fpu_cs);
+ fpu->fpu_rsrv2 = SWAP_SHORT(fpu->fpu_rsrv2);
+ fpu->fpu_dp = SWAP_INT(fpu->fpu_dp);
+ fpu->fpu_ds = SWAP_SHORT(fpu->fpu_ds);
+ fpu->fpu_rsrv3 = SWAP_SHORT(fpu->fpu_rsrv3);
+ fpu->fpu_mxcsr = SWAP_INT(fpu->fpu_mxcsr);
+ fpu->fpu_mxcsrmask = SWAP_INT(fpu->fpu_mxcsrmask);
+ fpu->fpu_reserved1 = SWAP_INT(fpu->fpu_reserved1);
+
+#endif /* defined(i386_EXCEPTION_STATE_COUNT) */
+}
+
+__private_extern__
+void
+swap_i386_exception_state(
+i386_exception_state_t *exc,
+enum byte_sex target_byte_sex)
+{
+ exc->trapno = SWAP_INT(exc->trapno);
+ exc->err = SWAP_INT(exc->err);
+ exc->faultvaddr = SWAP_INT(exc->faultvaddr);
+}
+
+#ifdef x86_THREAD_STATE64
+
+__private_extern__
+void
+swap_x86_float_state64(
+x86_float_state64_t *fpu,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_fp_control {
+ union {
+ struct {
+ unsigned short
+ :3,
+ /*inf*/ :1,
+ rc :2,
+ pc :2,
+ :2,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfpc;
+
+ struct swapped_fp_status {
+ union {
+ struct {
+ unsigned short
+ busy :1,
+ c3 :1,
+ tos :3,
+ c2 :1,
+ c1 :1,
+ c0 :1,
+ errsumm :1,
+ stkflt :1,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfps;
+
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ fpu->fpu_reserved[0] = SWAP_INT(fpu->fpu_reserved[0]);
+ fpu->fpu_reserved[1] = SWAP_INT(fpu->fpu_reserved[1]);
+
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sfpc, &(fpu->fpu_fcw),
+ sizeof(struct swapped_fp_control));
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ fpu->fpu_fcw.rc = sfpc.u.fields.rc;
+ fpu->fpu_fcw.pc = sfpc.u.fields.pc;
+ fpu->fpu_fcw.precis = sfpc.u.fields.precis;
+ fpu->fpu_fcw.undfl = sfpc.u.fields.undfl;
+ fpu->fpu_fcw.ovrfl = sfpc.u.fields.ovrfl;
+ fpu->fpu_fcw.zdiv = sfpc.u.fields.zdiv;
+ fpu->fpu_fcw.denorm = sfpc.u.fields.denorm;
+ fpu->fpu_fcw.invalid = sfpc.u.fields.invalid;
+
+ memcpy(&sfps, &(fpu->fpu_fsw),
+ sizeof(struct swapped_fp_status));
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ fpu->fpu_fsw.busy = sfps.u.fields.busy;
+ fpu->fpu_fsw.c3 = sfps.u.fields.c3;
+ fpu->fpu_fsw.tos = sfps.u.fields.tos;
+ fpu->fpu_fsw.c2 = sfps.u.fields.c2;
+ fpu->fpu_fsw.c1 = sfps.u.fields.c1;
+ fpu->fpu_fsw.c0 = sfps.u.fields.c0;
+ fpu->fpu_fsw.errsumm = sfps.u.fields.errsumm;
+ fpu->fpu_fsw.stkflt = sfps.u.fields.stkflt;
+ fpu->fpu_fsw.precis = sfps.u.fields.precis;
+ fpu->fpu_fsw.undfl = sfps.u.fields.undfl;
+ fpu->fpu_fsw.ovrfl = sfps.u.fields.ovrfl;
+ fpu->fpu_fsw.zdiv = sfps.u.fields.zdiv;
+ fpu->fpu_fsw.denorm = sfps.u.fields.denorm;
+ fpu->fpu_fsw.invalid = sfps.u.fields.invalid;
+ }
+ else{
+ sfpc.u.fields.rc = fpu->fpu_fcw.rc;
+ sfpc.u.fields.pc = fpu->fpu_fcw.pc;
+ sfpc.u.fields.precis = fpu->fpu_fcw.precis;
+ sfpc.u.fields.undfl = fpu->fpu_fcw.undfl;
+ sfpc.u.fields.ovrfl = fpu->fpu_fcw.ovrfl;
+ sfpc.u.fields.zdiv = fpu->fpu_fcw.zdiv;
+ sfpc.u.fields.denorm = fpu->fpu_fcw.denorm;
+ sfpc.u.fields.invalid = fpu->fpu_fcw.invalid;
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ memcpy(&(fpu->fpu_fcw), &sfpc,
+ sizeof(struct swapped_fp_control));
+
+ sfps.u.fields.busy = fpu->fpu_fsw.busy;
+ sfps.u.fields.c3 = fpu->fpu_fsw.c3;
+ sfps.u.fields.tos = fpu->fpu_fsw.tos;
+ sfps.u.fields.c2 = fpu->fpu_fsw.c2;
+ sfps.u.fields.c1 = fpu->fpu_fsw.c1;
+ sfps.u.fields.c0 = fpu->fpu_fsw.c0;
+ sfps.u.fields.errsumm = fpu->fpu_fsw.errsumm;
+ sfps.u.fields.stkflt = fpu->fpu_fsw.stkflt;
+ sfps.u.fields.precis = fpu->fpu_fsw.precis;
+ sfps.u.fields.undfl = fpu->fpu_fsw.undfl;
+ sfps.u.fields.ovrfl = fpu->fpu_fsw.ovrfl;
+ sfps.u.fields.zdiv = fpu->fpu_fsw.zdiv;
+ sfps.u.fields.denorm = fpu->fpu_fsw.denorm;
+ sfps.u.fields.invalid = fpu->fpu_fsw.invalid;
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ memcpy(&(fpu->fpu_fsw), &sfps,
+ sizeof(struct swapped_fp_status));
+ }
+ fpu->fpu_fop = SWAP_SHORT(fpu->fpu_fop);
+ fpu->fpu_ip = SWAP_INT(fpu->fpu_ip);
+ fpu->fpu_cs = SWAP_SHORT(fpu->fpu_cs);
+ fpu->fpu_rsrv2 = SWAP_SHORT(fpu->fpu_rsrv2);
+ fpu->fpu_dp = SWAP_INT(fpu->fpu_dp);
+ fpu->fpu_ds = SWAP_SHORT(fpu->fpu_ds);
+ fpu->fpu_rsrv3 = SWAP_SHORT(fpu->fpu_rsrv3);
+ fpu->fpu_mxcsr = SWAP_INT(fpu->fpu_mxcsr);
+ fpu->fpu_mxcsrmask = SWAP_INT(fpu->fpu_mxcsrmask);
+ fpu->fpu_reserved1 = SWAP_INT(fpu->fpu_reserved1);
+}
+
+__private_extern__
+void
+swap_x86_exception_state64(
+x86_exception_state64_t *exc,
+enum byte_sex target_byte_sex)
+{
+ exc->trapno = SWAP_INT(exc->trapno);
+ exc->err = SWAP_INT(exc->err);
+ exc->faultvaddr = SWAP_LONG_LONG(exc->faultvaddr);
+}
+
+__private_extern__
+void
+swap_x86_debug_state32(
+x86_debug_state32_t *debug,
+enum byte_sex target_byte_sex)
+{
+ debug->dr0 = SWAP_INT(debug->dr0);
+ debug->dr1 = SWAP_INT(debug->dr1);
+ debug->dr2 = SWAP_INT(debug->dr2);
+ debug->dr3 = SWAP_INT(debug->dr3);
+ debug->dr4 = SWAP_INT(debug->dr4);
+ debug->dr5 = SWAP_INT(debug->dr5);
+ debug->dr6 = SWAP_INT(debug->dr6);
+ debug->dr7 = SWAP_INT(debug->dr7);
+}
+
+__private_extern__
+void
+swap_x86_debug_state64(
+x86_debug_state64_t *debug,
+enum byte_sex target_byte_sex)
+{
+ debug->dr0 = SWAP_LONG_LONG(debug->dr0);
+ debug->dr1 = SWAP_LONG_LONG(debug->dr1);
+ debug->dr2 = SWAP_LONG_LONG(debug->dr2);
+ debug->dr3 = SWAP_LONG_LONG(debug->dr3);
+ debug->dr4 = SWAP_LONG_LONG(debug->dr4);
+ debug->dr5 = SWAP_LONG_LONG(debug->dr5);
+ debug->dr6 = SWAP_LONG_LONG(debug->dr6);
+ debug->dr7 = SWAP_LONG_LONG(debug->dr7);
+}
+
+__private_extern__
+void
+swap_x86_state_hdr(
+struct x86_state_hdr *hdr,
+enum byte_sex target_byte_sex)
+{
+ hdr->flavor = SWAP_INT(hdr->flavor);
+ hdr->count = SWAP_INT(hdr->count);
+}
+#endif /* x86_THREAD_STATE64 */
+
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+__private_extern__
+void
+swap_i386_thread_fpstate(
+i386_thread_fpstate_t *fpu,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_fp_control {
+ union {
+ struct {
+ unsigned short
+ :3,
+ /*inf*/ :1,
+ rc :2,
+ pc :2,
+ :2,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfpc;
+
+ struct swapped_fp_status {
+ union {
+ struct {
+ unsigned short
+ busy :1,
+ c3 :1,
+ tos :3,
+ c2 :1,
+ c1 :1,
+ c0 :1,
+ errsumm :1,
+ stkflt :1,
+ precis :1,
+ undfl :1,
+ ovrfl :1,
+ zdiv :1,
+ denorm :1,
+ invalid :1;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfps;
+
+ struct swapped_fp_tag {
+ union {
+ struct {
+ unsigned short
+ tag7 :2,
+ tag6 :2,
+ tag5 :2,
+ tag4 :2,
+ tag3 :2,
+ tag2 :2,
+ tag1 :2,
+ tag0 :2;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfpt;
+
+ struct swapped_fp_data_reg {
+ unsigned short mant;
+ unsigned short mant1 :16,
+ mant2 :16,
+ mant3 :16;
+ union {
+ struct {
+ unsigned short sign :1,
+ exp :15;
+ } fields;
+ unsigned short half;
+ } u;
+ } sfpd;
+
+ struct swapped_sel {
+ union {
+ struct {
+ unsigned short
+ index :13,
+ ti :1,
+ rpl :2;
+ } fields;
+ unsigned short half;
+ } u;
+ } ss;
+
+ enum byte_sex host_byte_sex;
+ unsigned long i;
+
+ host_byte_sex = get_host_byte_sex();
+
+ fpu->environ.ip = SWAP_INT(fpu->environ.ip);
+ fpu->environ.opcode = SWAP_SHORT(fpu->environ.opcode);
+ fpu->environ.dp = SWAP_INT(fpu->environ.dp);
+
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sfpc, &(fpu->environ.control),
+ sizeof(struct swapped_fp_control));
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ fpu->environ.control.rc = sfpc.u.fields.rc;
+ fpu->environ.control.pc = sfpc.u.fields.pc;
+ fpu->environ.control.precis = sfpc.u.fields.precis;
+ fpu->environ.control.undfl = sfpc.u.fields.undfl;
+ fpu->environ.control.ovrfl = sfpc.u.fields.ovrfl;
+ fpu->environ.control.zdiv = sfpc.u.fields.zdiv;
+ fpu->environ.control.denorm = sfpc.u.fields.denorm;
+ fpu->environ.control.invalid = sfpc.u.fields.invalid;
+
+ memcpy(&sfps, &(fpu->environ.status),
+ sizeof(struct swapped_fp_status));
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ fpu->environ.status.busy = sfps.u.fields.busy;
+ fpu->environ.status.c3 = sfps.u.fields.c3;
+ fpu->environ.status.tos = sfps.u.fields.tos;
+ fpu->environ.status.c2 = sfps.u.fields.c2;
+ fpu->environ.status.c1 = sfps.u.fields.c1;
+ fpu->environ.status.c0 = sfps.u.fields.c0;
+ fpu->environ.status.errsumm = sfps.u.fields.errsumm;
+ fpu->environ.status.stkflt = sfps.u.fields.stkflt;
+ fpu->environ.status.precis = sfps.u.fields.precis;
+ fpu->environ.status.undfl = sfps.u.fields.undfl;
+ fpu->environ.status.ovrfl = sfps.u.fields.ovrfl;
+ fpu->environ.status.zdiv = sfps.u.fields.zdiv;
+ fpu->environ.status.denorm = sfps.u.fields.denorm;
+ fpu->environ.status.invalid = sfps.u.fields.invalid;
+
+ memcpy(&sfpt, &(fpu->environ.tag),
+ sizeof(struct swapped_fp_tag));
+ sfpt.u.half = SWAP_SHORT(sfpt.u.half);
+ fpu->environ.tag.tag7 = sfpt.u.fields.tag7;
+ fpu->environ.tag.tag6 = sfpt.u.fields.tag6;
+ fpu->environ.tag.tag5 = sfpt.u.fields.tag5;
+ fpu->environ.tag.tag4 = sfpt.u.fields.tag4;
+ fpu->environ.tag.tag3 = sfpt.u.fields.tag3;
+ fpu->environ.tag.tag2 = sfpt.u.fields.tag2;
+ fpu->environ.tag.tag1 = sfpt.u.fields.tag1;
+ fpu->environ.tag.tag0 = sfpt.u.fields.tag0;
+
+ memcpy(&ss, &(fpu->environ.cs),
+ sizeof(struct swapped_sel));
+ ss.u.half = SWAP_SHORT(ss.u.half);
+ fpu->environ.cs.index = ss.u.fields.index;
+ fpu->environ.cs.ti = ss.u.fields.ti;
+ fpu->environ.cs.rpl = ss.u.fields.rpl;
+
+ memcpy(&ss, &(fpu->environ.ds),
+ sizeof(struct swapped_sel));
+ ss.u.half = SWAP_SHORT(ss.u.half);
+ fpu->environ.ds.index = ss.u.fields.index;
+ fpu->environ.ds.ti = ss.u.fields.ti;
+ fpu->environ.ds.rpl = ss.u.fields.rpl;
+
+ for(i = 0; i < 8; i++){
+ memcpy(&sfpd, &(fpu->stack.ST[i]),
+ sizeof(struct swapped_fp_data_reg));
+ fpu->stack.ST[i].mant = SWAP_SHORT(sfpd.mant);
+ fpu->stack.ST[i].mant1 = SWAP_SHORT(sfpd.mant1);
+ fpu->stack.ST[i].mant2 = SWAP_SHORT(sfpd.mant2);
+ fpu->stack.ST[i].mant3 = SWAP_SHORT(sfpd.mant3);
+ sfpd.u.half = SWAP_SHORT(sfpd.u.half);
+ fpu->stack.ST[i].exp = sfpd.u.fields.exp;
+ fpu->stack.ST[i].sign = sfpd.u.fields.sign;
+ }
+ }
+ else{
+ sfpc.u.fields.rc = fpu->environ.control.rc;
+ sfpc.u.fields.pc = fpu->environ.control.pc;
+ sfpc.u.fields.precis = fpu->environ.control.precis;
+ sfpc.u.fields.undfl = fpu->environ.control.undfl;
+ sfpc.u.fields.ovrfl = fpu->environ.control.ovrfl;
+ sfpc.u.fields.zdiv = fpu->environ.control.zdiv;
+ sfpc.u.fields.denorm = fpu->environ.control.denorm;
+ sfpc.u.fields.invalid = fpu->environ.control.invalid;
+ sfpc.u.half = SWAP_SHORT(sfpc.u.half);
+ memcpy(&(fpu->environ.control), &sfpc,
+ sizeof(struct swapped_fp_control));
+
+ sfps.u.fields.busy = fpu->environ.status.busy;
+ sfps.u.fields.c3 = fpu->environ.status.c3;
+ sfps.u.fields.tos = fpu->environ.status.tos;
+ sfps.u.fields.c2 = fpu->environ.status.c2;
+ sfps.u.fields.c1 = fpu->environ.status.c1;
+ sfps.u.fields.c0 = fpu->environ.status.c0;
+ sfps.u.fields.errsumm = fpu->environ.status.errsumm;
+ sfps.u.fields.stkflt = fpu->environ.status.stkflt;
+ sfps.u.fields.precis = fpu->environ.status.precis;
+ sfps.u.fields.undfl = fpu->environ.status.undfl;
+ sfps.u.fields.ovrfl = fpu->environ.status.ovrfl;
+ sfps.u.fields.zdiv = fpu->environ.status.zdiv;
+ sfps.u.fields.denorm = fpu->environ.status.denorm;
+ sfps.u.fields.invalid = fpu->environ.status.invalid;
+ sfps.u.half = SWAP_SHORT(sfps.u.half);
+ memcpy(&(fpu->environ.status), &sfps,
+ sizeof(struct swapped_fp_status));
+
+ sfpt.u.fields.tag7 = fpu->environ.tag.tag7;
+ sfpt.u.fields.tag6 = fpu->environ.tag.tag6;
+ sfpt.u.fields.tag5 = fpu->environ.tag.tag5;
+ sfpt.u.fields.tag4 = fpu->environ.tag.tag4;
+ sfpt.u.fields.tag3 = fpu->environ.tag.tag3;
+ sfpt.u.fields.tag2 = fpu->environ.tag.tag2;
+ sfpt.u.fields.tag1 = fpu->environ.tag.tag1;
+ sfpt.u.fields.tag0 = fpu->environ.tag.tag0;
+ sfpt.u.half = SWAP_SHORT(sfpt.u.half);
+ memcpy(&(fpu->environ.tag), &sfpt,
+ sizeof(struct swapped_fp_tag));
+
+ ss.u.fields.index = fpu->environ.cs.index;
+ ss.u.fields.ti = fpu->environ.cs.ti;
+ ss.u.fields.rpl = fpu->environ.cs.rpl;
+ ss.u.half = SWAP_SHORT(ss.u.half);
+ memcpy(&(fpu->environ.cs), &ss,
+ sizeof(struct swapped_sel));
+
+ ss.u.fields.index = fpu->environ.ds.index;
+ ss.u.fields.ti = fpu->environ.ds.ti;
+ ss.u.fields.rpl = fpu->environ.ds.rpl;
+ ss.u.half = SWAP_SHORT(ss.u.half);
+ memcpy(&(fpu->environ.cs), &ss,
+ sizeof(struct swapped_sel));
+
+ for(i = 0; i < 8; i++){
+ sfpd.mant = SWAP_SHORT(fpu->stack.ST[i].mant);
+ sfpd.mant1 = SWAP_SHORT(fpu->stack.ST[i].mant1);
+ sfpd.mant2 = SWAP_SHORT(fpu->stack.ST[i].mant2);
+ sfpd.mant3 = SWAP_SHORT(fpu->stack.ST[i].mant3);
+ sfpd.u.fields.exp = fpu->stack.ST[i].exp;
+ sfpd.u.fields.sign = fpu->stack.ST[i].sign;
+ sfpd.u.half = SWAP_SHORT(sfpd.u.half);
+ memcpy(&(fpu->stack.ST[i]), &sfpd,
+ sizeof(struct swapped_fp_data_reg));
+ }
+ }
+}
+
+__private_extern__
+void
+swap_i386_thread_exceptstate(
+i386_thread_exceptstate_t *exc,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_err_code {
+ union {
+ struct err_code_normal {
+ unsigned int :16,
+ index :13,
+ tbl :2,
+ ext :1;
+ } normal;
+ struct err_code_pgfault {
+ unsigned int :29,
+ user :1,
+ wrtflt :1,
+ prot :1;
+ } pgfault;
+ uint32_t word;
+ } u;
+ } sec;
+ uint32_t word;
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ exc->trapno = SWAP_INT(exc->trapno);
+ if(exc->trapno == 14){
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sec, &(exc->err), sizeof(struct swapped_err_code));
+ sec.u.word = SWAP_INT(sec.u.word);
+ exc->err.pgfault.user = sec.u.pgfault.user;
+ exc->err.pgfault.wrtflt = sec.u.pgfault.wrtflt;
+ exc->err.pgfault.prot = sec.u.pgfault.prot;
+ }
+ else{
+ sec.u.pgfault.prot = exc->err.pgfault.prot;
+ sec.u.pgfault.wrtflt = exc->err.pgfault.wrtflt;
+ sec.u.pgfault.user = exc->err.pgfault.user;
+ sec.u.word = SWAP_INT(sec.u.word);
+ memcpy(&(exc->err), &sec, sizeof(struct swapped_err_code));
+ }
+ }
+ else{
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sec, &(exc->err), sizeof(struct swapped_err_code));
+ sec.u.word = SWAP_INT(sec.u.word);
+ word = sec.u.normal.index;
+ exc->err.normal.index = SWAP_INT(word);
+ exc->err.normal.tbl = sec.u.normal.tbl;
+ exc->err.normal.ext = sec.u.normal.ext;
+ }
+ else{
+ sec.u.normal.ext = exc->err.normal.ext;
+ sec.u.normal.tbl = exc->err.normal.tbl;
+ word = exc->err.normal.index;
+ sec.u.normal.index = SWAP_INT(word);
+ sec.u.word = SWAP_INT(sec.u.word);
+ memcpy(&(exc->err), &sec, sizeof(struct swapped_err_code));
+ }
+ }
+}
+
+__private_extern__
+void
+swap_i386_thread_cthreadstate(
+i386_thread_cthreadstate_t *user,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ user->self = SWAP_INT(user->self);
+}
+#endif /* i386_THREAD_STATE == -1 */
+
+__private_extern__
+void
+swap_hppa_integer_thread_state(
+struct hp_pa_integer_thread_state *regs,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ regs->ts_gr1 = SWAP_INT(regs->ts_gr1);
+ regs->ts_gr2 = SWAP_INT(regs->ts_gr2);
+ regs->ts_gr3 = SWAP_INT(regs->ts_gr3);
+ regs->ts_gr4 = SWAP_INT(regs->ts_gr4);
+ regs->ts_gr5 = SWAP_INT(regs->ts_gr5);
+ regs->ts_gr6 = SWAP_INT(regs->ts_gr6);
+ regs->ts_gr7 = SWAP_INT(regs->ts_gr7);
+ regs->ts_gr8 = SWAP_INT(regs->ts_gr8);
+ regs->ts_gr9 = SWAP_INT(regs->ts_gr9);
+ regs->ts_gr10 = SWAP_INT(regs->ts_gr10);
+ regs->ts_gr11 = SWAP_INT(regs->ts_gr11);
+ regs->ts_gr12 = SWAP_INT(regs->ts_gr12);
+ regs->ts_gr13 = SWAP_INT(regs->ts_gr13);
+ regs->ts_gr14 = SWAP_INT(regs->ts_gr14);
+ regs->ts_gr15 = SWAP_INT(regs->ts_gr15);
+ regs->ts_gr16 = SWAP_INT(regs->ts_gr16);
+ regs->ts_gr17 = SWAP_INT(regs->ts_gr17);
+ regs->ts_gr18 = SWAP_INT(regs->ts_gr18);
+ regs->ts_gr19 = SWAP_INT(regs->ts_gr19);
+ regs->ts_gr20 = SWAP_INT(regs->ts_gr20);
+ regs->ts_gr21 = SWAP_INT(regs->ts_gr21);
+ regs->ts_gr22 = SWAP_INT(regs->ts_gr22);
+ regs->ts_gr23 = SWAP_INT(regs->ts_gr23);
+ regs->ts_gr24 = SWAP_INT(regs->ts_gr24);
+ regs->ts_gr25 = SWAP_INT(regs->ts_gr25);
+ regs->ts_gr26 = SWAP_INT(regs->ts_gr26);
+ regs->ts_gr27 = SWAP_INT(regs->ts_gr27);
+ regs->ts_gr28 = SWAP_INT(regs->ts_gr28);
+ regs->ts_gr29 = SWAP_INT(regs->ts_gr29);
+ regs->ts_gr30 = SWAP_INT(regs->ts_gr30);
+ regs->ts_gr31 = SWAP_INT(regs->ts_gr31);
+ regs->ts_sr0 = SWAP_INT(regs->ts_sr0);
+ regs->ts_sr1 = SWAP_INT(regs->ts_sr1);
+ regs->ts_sr2 = SWAP_INT(regs->ts_sr2);
+ regs->ts_sr3 = SWAP_INT(regs->ts_sr3);
+ regs->ts_sar = SWAP_INT(regs->ts_sar);
+}
+
+__private_extern__
+void swap_hppa_frame_thread_state(
+struct hp_pa_frame_thread_state *frame,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ frame->ts_pcsq_front = SWAP_INT(frame->ts_pcsq_front);
+ frame->ts_pcsq_back = SWAP_INT(frame->ts_pcsq_back);
+ frame->ts_pcoq_front = SWAP_INT(frame->ts_pcoq_front);
+ frame->ts_pcoq_back = SWAP_INT(frame->ts_pcoq_back);
+ frame->ts_psw = SWAP_INT(frame->ts_psw);
+ frame->ts_unaligned_faults = SWAP_INT(frame->ts_unaligned_faults);
+ frame->ts_fault_address = SWAP_INT(frame->ts_fault_address);
+ frame->ts_step_range_start = SWAP_INT(frame->ts_step_range_start);
+ frame->ts_step_range_stop = SWAP_INT(frame->ts_step_range_stop);
+}
+
+__private_extern__
+void swap_hppa_fp_thread_state(
+struct hp_pa_fp_thread_state *fp,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ fp->ts_fp0 = SWAP_DOUBLE(fp->ts_fp0);
+ fp->ts_fp1 = SWAP_DOUBLE(fp->ts_fp1);
+ fp->ts_fp2 = SWAP_DOUBLE(fp->ts_fp2);
+ fp->ts_fp3 = SWAP_DOUBLE(fp->ts_fp3);
+ fp->ts_fp4 = SWAP_DOUBLE(fp->ts_fp4);
+ fp->ts_fp5 = SWAP_DOUBLE(fp->ts_fp5);
+ fp->ts_fp6 = SWAP_DOUBLE(fp->ts_fp6);
+ fp->ts_fp7 = SWAP_DOUBLE(fp->ts_fp7);
+ fp->ts_fp8 = SWAP_DOUBLE(fp->ts_fp8);
+ fp->ts_fp9 = SWAP_DOUBLE(fp->ts_fp9);
+ fp->ts_fp10 = SWAP_DOUBLE(fp->ts_fp10);
+ fp->ts_fp11 = SWAP_DOUBLE(fp->ts_fp11);
+ fp->ts_fp12 = SWAP_DOUBLE(fp->ts_fp12);
+ fp->ts_fp13 = SWAP_DOUBLE(fp->ts_fp13);
+ fp->ts_fp14 = SWAP_DOUBLE(fp->ts_fp14);
+ fp->ts_fp15 = SWAP_DOUBLE(fp->ts_fp15);
+ fp->ts_fp16 = SWAP_DOUBLE(fp->ts_fp16);
+ fp->ts_fp17 = SWAP_DOUBLE(fp->ts_fp17);
+ fp->ts_fp18 = SWAP_DOUBLE(fp->ts_fp18);
+ fp->ts_fp19 = SWAP_DOUBLE(fp->ts_fp19);
+ fp->ts_fp20 = SWAP_DOUBLE(fp->ts_fp20);
+ fp->ts_fp21 = SWAP_DOUBLE(fp->ts_fp21);
+ fp->ts_fp22 = SWAP_DOUBLE(fp->ts_fp22);
+ fp->ts_fp23 = SWAP_DOUBLE(fp->ts_fp23);
+ fp->ts_fp24 = SWAP_DOUBLE(fp->ts_fp24);
+ fp->ts_fp25 = SWAP_DOUBLE(fp->ts_fp25);
+ fp->ts_fp26 = SWAP_DOUBLE(fp->ts_fp26);
+ fp->ts_fp27 = SWAP_DOUBLE(fp->ts_fp27);
+ fp->ts_fp28 = SWAP_DOUBLE(fp->ts_fp28);
+ fp->ts_fp29 = SWAP_DOUBLE(fp->ts_fp29);
+ fp->ts_fp30 = SWAP_DOUBLE(fp->ts_fp30);
+ fp->ts_fp31 = SWAP_DOUBLE(fp->ts_fp31);
+}
+
+__private_extern__
+void
+swap_sparc_thread_state_regs(
+struct sparc_thread_state_regs *cpu,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_psr {
+ union {
+ struct {
+ unsigned int
+ cwp:BITS_WIDTH(4,0),
+ et:BIT_WIDTH(5),
+ ps:BIT_WIDTH(6),
+ s:BIT_WIDTH(7),
+ pil:BITS_WIDTH(11,8),
+ ef:BIT_WIDTH(12),
+ ec:BIT_WIDTH(13),
+ reserved:BITS_WIDTH(19,14),
+ icc:BITS_WIDTH(23,20),
+ ver:BITS_WIDTH(27,24),
+ impl:BITS_WIDTH(31,28);
+ } fields;
+ unsigned int word;
+ } u;
+ } spsr;
+ struct p_status *pr_status;
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ cpu->regs.r_pc = SWAP_INT(cpu->regs.r_pc);
+ cpu->regs.r_npc = SWAP_INT(cpu->regs.r_npc);
+ cpu->regs.r_y = SWAP_INT(cpu->regs.r_y);
+ cpu->regs.r_g1 = SWAP_INT(cpu->regs.r_g1);
+ cpu->regs.r_g2 = SWAP_INT(cpu->regs.r_g2);
+ cpu->regs.r_g3 = SWAP_INT(cpu->regs.r_g3);
+ cpu->regs.r_g4 = SWAP_INT(cpu->regs.r_g4);
+ cpu->regs.r_g5 = SWAP_INT(cpu->regs.r_g5);
+ cpu->regs.r_g6 = SWAP_INT(cpu->regs.r_g6);
+ cpu->regs.r_g7 = SWAP_INT(cpu->regs.r_g7);
+ cpu->regs.r_o0 = SWAP_INT(cpu->regs.r_o0);
+ cpu->regs.r_o1 = SWAP_INT(cpu->regs.r_o1);
+ cpu->regs.r_o2 = SWAP_INT(cpu->regs.r_o2);
+ cpu->regs.r_o3 = SWAP_INT(cpu->regs.r_o3);
+ cpu->regs.r_o4 = SWAP_INT(cpu->regs.r_o4);
+ cpu->regs.r_o5 = SWAP_INT(cpu->regs.r_o5);
+ cpu->regs.r_o6 = SWAP_INT(cpu->regs.r_o6);
+ cpu->regs.r_o7 = SWAP_INT(cpu->regs.r_o7);
+
+ pr_status = (struct p_status *) &(cpu->regs.r_psr);
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&spsr, &(cpu->regs.r_psr), sizeof(struct swapped_psr));
+ spsr.u.word = SWAP_INT(spsr.u.word);
+ pr_status->PSRREG.psr_bits.cwp = spsr.u.fields.cwp;
+ pr_status->PSRREG.psr_bits.ps = spsr.u.fields.ps;
+ pr_status->PSRREG.psr_bits.s = spsr.u.fields.s;
+ pr_status->PSRREG.psr_bits.pil = spsr.u.fields.pil;
+ pr_status->PSRREG.psr_bits.ef = spsr.u.fields.ef;
+ pr_status->PSRREG.psr_bits.ec = spsr.u.fields.ec;
+ pr_status->PSRREG.psr_bits.reserved = spsr.u.fields.reserved;
+ pr_status->PSRREG.psr_bits.icc = spsr.u.fields.icc;
+ pr_status->PSRREG.psr_bits.et = spsr.u.fields.ver;
+ pr_status->PSRREG.psr_bits.impl = spsr.u.fields.impl;
+ }
+ else{
+ spsr.u.fields.cwp = pr_status->PSRREG.psr_bits.cwp;
+ spsr.u.fields.ps = pr_status->PSRREG.psr_bits.ps;
+ spsr.u.fields.s = pr_status->PSRREG.psr_bits.s;
+ spsr.u.fields.pil = pr_status->PSRREG.psr_bits.pil;
+ spsr.u.fields.ef = pr_status->PSRREG.psr_bits.ef;
+ spsr.u.fields.ec = pr_status->PSRREG.psr_bits.ec;
+ spsr.u.fields.reserved = pr_status->PSRREG.psr_bits.reserved;
+ spsr.u.fields.icc = pr_status->PSRREG.psr_bits.icc;
+ spsr.u.fields.ver = pr_status->PSRREG.psr_bits.et;
+ spsr.u.fields.impl = pr_status->PSRREG.psr_bits.impl;
+ spsr.u.word = SWAP_INT(spsr.u.word);
+ memcpy(&(cpu->regs.r_psr), &spsr, sizeof(struct swapped_psr));
+ }
+}
+
+__private_extern__
+void
+swap_sparc_thread_state_fpu(
+struct sparc_thread_state_fpu *fpu,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_fsr {
+ union {
+ struct {
+ unsigned int
+ cexc:BITS_WIDTH(4,0),
+ aexc:BITS_WIDTH(9,5),
+ fcc:BITS_WIDTH(11,10),
+ pr:BIT_WIDTH(12),
+ qne:BIT_WIDTH(13),
+ ftt:BITS_WIDTH(16,14),
+ res:BITS_WIDTH(22,17),
+ tem:BITS_WIDTH(27,23),
+ rp:BITS_WIDTH(29,28),
+ rd:BITS_WIDTH(31,30);
+ } fields;
+ unsigned int word;
+ } u;
+ } sfsr;
+ unsigned long i;
+ struct f_status *fpu_status;
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+
+ /* floating point registers */
+ for(i = 0; i < 16; i++) /* 16 doubles */
+ fpu->fpu.fpu_fr.Fpu_dregs[i] =
+ SWAP_DOUBLE(fpu->fpu.fpu_fr.Fpu_dregs[i]);
+
+ fpu->fpu.Fpu_q[0].FQu.whole = SWAP_DOUBLE(fpu->fpu.Fpu_q[0].FQu.whole);
+ fpu->fpu.Fpu_q[1].FQu.whole = SWAP_DOUBLE(fpu->fpu.Fpu_q[1].FQu.whole);
+ fpu->fpu.Fpu_flags = SWAP_INT(fpu->fpu.Fpu_flags);
+ fpu->fpu.Fpu_extra = SWAP_INT(fpu->fpu.Fpu_extra);
+ fpu->fpu.Fpu_qcnt = SWAP_INT(fpu->fpu.Fpu_qcnt);
+
+ fpu_status = (struct f_status *) &(fpu->fpu.Fpu_fsr);
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sfsr, &(fpu->fpu.Fpu_fsr), sizeof(unsigned int));
+ sfsr.u.word = SWAP_INT(sfsr.u.word);
+ fpu_status->FPUREG.Fpu_fsr_bits.rd = sfsr.u.fields.rd;
+ fpu_status->FPUREG.Fpu_fsr_bits.rp = sfsr.u.fields.rp;
+ fpu_status->FPUREG.Fpu_fsr_bits.tem = sfsr.u.fields.tem;
+ fpu_status->FPUREG.Fpu_fsr_bits.res = sfsr.u.fields.res;
+ fpu_status->FPUREG.Fpu_fsr_bits.ftt = sfsr.u.fields.ftt;
+ fpu_status->FPUREG.Fpu_fsr_bits.qne = sfsr.u.fields.qne;
+ fpu_status->FPUREG.Fpu_fsr_bits.pr = sfsr.u.fields.pr;
+ fpu_status->FPUREG.Fpu_fsr_bits.fcc = sfsr.u.fields.fcc;
+ fpu_status->FPUREG.Fpu_fsr_bits.aexc = sfsr.u.fields.aexc;
+ fpu_status->FPUREG.Fpu_fsr_bits.cexc = sfsr.u.fields.cexc;
+ }
+ else{
+ sfsr.u.fields.rd = fpu_status->FPUREG.Fpu_fsr_bits.rd;
+ sfsr.u.fields.rp = fpu_status->FPUREG.Fpu_fsr_bits.rp;
+ sfsr.u.fields.tem = fpu_status->FPUREG.Fpu_fsr_bits.tem;
+ sfsr.u.fields.res = fpu_status->FPUREG.Fpu_fsr_bits.res;
+ sfsr.u.fields.ftt = fpu_status->FPUREG.Fpu_fsr_bits.ftt;
+ sfsr.u.fields.qne = fpu_status->FPUREG.Fpu_fsr_bits.qne;
+ sfsr.u.fields.pr = fpu_status->FPUREG.Fpu_fsr_bits.pr;
+ sfsr.u.fields.fcc = fpu_status->FPUREG.Fpu_fsr_bits.fcc;
+ sfsr.u.fields.aexc = fpu_status->FPUREG.Fpu_fsr_bits.aexc;
+ sfsr.u.fields.cexc = fpu_status->FPUREG.Fpu_fsr_bits.cexc;
+ sfsr.u.word = SWAP_INT(sfsr.u.word);
+ memcpy(&(fpu->fpu.Fpu_fsr), &sfsr, sizeof(struct swapped_fsr));
+ }
+}
+
+__private_extern__
+void
+swap_ident_command(
+struct ident_command *id_cmd,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ id_cmd->cmd = SWAP_INT(id_cmd->cmd);
+ id_cmd->cmdsize = SWAP_INT(id_cmd->cmdsize);
+}
+
+__private_extern__
+void
+swap_routines_command(
+struct routines_command *r_cmd,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ r_cmd->cmd = SWAP_INT(r_cmd->cmd);
+ r_cmd->cmdsize = SWAP_INT(r_cmd->cmdsize);
+ r_cmd->init_address = SWAP_INT(r_cmd->init_address);
+ r_cmd->init_module = SWAP_INT(r_cmd->init_module);
+ r_cmd->reserved1 = SWAP_INT(r_cmd->reserved1);
+ r_cmd->reserved2 = SWAP_INT(r_cmd->reserved2);
+ r_cmd->reserved3 = SWAP_INT(r_cmd->reserved3);
+ r_cmd->reserved4 = SWAP_INT(r_cmd->reserved4);
+ r_cmd->reserved5 = SWAP_INT(r_cmd->reserved5);
+ r_cmd->reserved6 = SWAP_INT(r_cmd->reserved6);
+}
+
+__private_extern__
+void
+swap_routines_command_64(
+struct routines_command_64 *r_cmd,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ r_cmd->cmd = SWAP_INT(r_cmd->cmd);
+ r_cmd->cmdsize = SWAP_INT(r_cmd->cmdsize);
+ r_cmd->init_address = SWAP_LONG_LONG(r_cmd->init_address);
+ r_cmd->init_module = SWAP_LONG_LONG(r_cmd->init_module);
+ r_cmd->reserved1 = SWAP_LONG_LONG(r_cmd->reserved1);
+ r_cmd->reserved2 = SWAP_LONG_LONG(r_cmd->reserved2);
+ r_cmd->reserved3 = SWAP_LONG_LONG(r_cmd->reserved3);
+ r_cmd->reserved4 = SWAP_LONG_LONG(r_cmd->reserved4);
+ r_cmd->reserved5 = SWAP_LONG_LONG(r_cmd->reserved5);
+ r_cmd->reserved6 = SWAP_LONG_LONG(r_cmd->reserved6);
+}
+
+__private_extern__
+void
+swap_twolevel_hints_command(
+struct twolevel_hints_command *hints_cmd,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ hints_cmd->cmd = SWAP_INT(hints_cmd->cmd);
+ hints_cmd->cmdsize = SWAP_INT(hints_cmd->cmdsize);
+ hints_cmd->offset = SWAP_INT(hints_cmd->offset);
+ hints_cmd->nhints = SWAP_INT(hints_cmd->nhints);
+}
+
+__private_extern__
+void
+swap_twolevel_hint(
+struct twolevel_hint *hints,
+unsigned long nhints,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_twolevel_hint {
+ union {
+ struct {
+ uint32_t
+ itoc:24,
+ isub_image:8;
+ } fields;
+ uint32_t word;
+ } u;
+ } shint;
+
+ unsigned long i;
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ for(i = 0; i < nhints; i++){
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&shint, hints + i, sizeof(struct swapped_twolevel_hint));
+ shint.u.word = SWAP_INT(shint.u.word);
+ hints[i].itoc = shint.u.fields.itoc;
+ hints[i].isub_image = shint.u.fields.isub_image;
+ }
+ else{
+ shint.u.fields.isub_image = hints[i].isub_image;
+ shint.u.fields.itoc = hints[i].itoc;
+ shint.u.word = SWAP_INT(shint.u.word);
+ memcpy(hints + i, &shint, sizeof(struct swapped_twolevel_hint));
+ }
+ }
+}
+
+__private_extern__
+void
+swap_prebind_cksum_command(
+struct prebind_cksum_command *cksum_cmd,
+enum byte_sex target_byte_sex)
+{
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+ cksum_cmd->cmd = SWAP_INT(cksum_cmd->cmd);
+ cksum_cmd->cmdsize = SWAP_INT(cksum_cmd->cmdsize);
+ cksum_cmd->cksum = SWAP_INT(cksum_cmd->cksum);
+}
+
+__private_extern__
+void
+swap_uuid_command(
+struct uuid_command *uuid_cmd,
+enum byte_sex target_byte_sex)
+{
+ uuid_cmd->cmd = SWAP_INT(uuid_cmd->cmd);
+ uuid_cmd->cmdsize = SWAP_INT(uuid_cmd->cmdsize);
+}
+
+__private_extern__
+void
+swap_linkedit_data_command(
+struct linkedit_data_command *ld,
+enum byte_sex target_byte_sex)
+{
+ ld->cmd = SWAP_INT(ld->cmd);
+ ld->cmdsize = SWAP_INT(ld->cmdsize);
+ ld->dataoff = SWAP_INT(ld->dataoff);
+ ld->datasize = SWAP_INT(ld->datasize);
+}
+
+__private_extern__
+void swap_rpath_command(
+struct rpath_command *rpath_cmd,
+enum byte_sex target_byte_sex)
+{
+ rpath_cmd->cmd = SWAP_INT(rpath_cmd->cmd);
+ rpath_cmd->cmdsize = SWAP_INT(rpath_cmd->cmdsize);
+ rpath_cmd->path.offset = SWAP_INT(rpath_cmd->path.offset);
+}
+
+__private_extern__
+void
+swap_nlist(
+struct nlist *symbols,
+unsigned long nsymbols,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nsymbols; i++){
+ symbols[i].n_un.n_strx = SWAP_INT(symbols[i].n_un.n_strx);
+ /* n_type */
+ /* n_sect */
+ symbols[i].n_desc = SWAP_SHORT(symbols[i].n_desc);
+ symbols[i].n_value = SWAP_INT(symbols[i].n_value);
+ }
+}
+
+__private_extern__
+void
+swap_nlist_64(
+struct nlist_64 *symbols,
+unsigned long nsymbols,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nsymbols; i++){
+ symbols[i].n_un.n_strx = SWAP_INT(symbols[i].n_un.n_strx);
+ /* n_type */
+ /* n_sect */
+ symbols[i].n_desc = SWAP_SHORT(symbols[i].n_desc);
+ symbols[i].n_value = SWAP_LONG_LONG(symbols[i].n_value);
+ }
+}
+
+__private_extern__
+void
+swap_ranlib(
+struct ranlib *ranlibs,
+unsigned long nranlibs,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nranlibs; i++){
+ ranlibs[i].ran_un.ran_strx = SWAP_INT(ranlibs[i].ran_un.ran_strx);
+ ranlibs[i].ran_off = SWAP_INT(ranlibs[i].ran_off);
+ }
+}
+
+__private_extern__
+void
+swap_relocation_info(
+struct relocation_info *relocs,
+unsigned long nrelocs,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+ enum byte_sex host_byte_sex;
+ enum bool to_host_byte_sex, scattered;
+
+ struct swapped_relocation_info {
+ long r_address;
+ union {
+ struct {
+ unsigned int
+ r_type:4,
+ r_extern:1,
+ r_length:2,
+ r_pcrel:1,
+ r_symbolnum:24;
+ } fields;
+ uint32_t word;
+ } u;
+ } sr;
+
+ struct swapped_scattered_relocation_info {
+ uint32_t word;
+ long r_value;
+ } *ssr;
+
+ host_byte_sex = get_host_byte_sex();
+ to_host_byte_sex = (enum bool)(target_byte_sex == host_byte_sex);
+
+ for(i = 0; i < nrelocs; i++){
+ if(to_host_byte_sex)
+ scattered = (enum bool)(
+ (SWAP_INT(relocs[i].r_address) & R_SCATTERED) != 0);
+ else
+ scattered = (enum bool)
+ (((relocs[i].r_address) & R_SCATTERED) != 0);
+ if(scattered == FALSE){
+ if(to_host_byte_sex){
+ memcpy(&sr, relocs + i, sizeof(struct relocation_info));
+ sr.r_address = SWAP_INT(sr.r_address);
+ sr.u.word = SWAP_INT(sr.u.word);
+ relocs[i].r_address = sr.r_address;
+ relocs[i].r_symbolnum = sr.u.fields.r_symbolnum;
+ relocs[i].r_pcrel = sr.u.fields.r_pcrel;
+ relocs[i].r_length = sr.u.fields.r_length;
+ relocs[i].r_extern = sr.u.fields.r_extern;
+ relocs[i].r_type = sr.u.fields.r_type;
+ }
+ else{
+ sr.r_address = relocs[i].r_address;
+ sr.u.fields.r_symbolnum = relocs[i].r_symbolnum;
+ sr.u.fields.r_length = relocs[i].r_length;
+ sr.u.fields.r_pcrel = relocs[i].r_pcrel;
+ sr.u.fields.r_extern = relocs[i].r_extern;
+ sr.u.fields.r_type = relocs[i].r_type;
+ sr.r_address = SWAP_INT(sr.r_address);
+ sr.u.word = SWAP_INT(sr.u.word);
+ memcpy(relocs + i, &sr, sizeof(struct relocation_info));
+ }
+ }
+ else{
+ ssr = (struct swapped_scattered_relocation_info *)(relocs + i);
+ ssr->word = SWAP_INT(ssr->word);
+ ssr->r_value = SWAP_INT(ssr->r_value);
+ }
+ }
+}
+
+__private_extern__
+void
+swap_indirect_symbols(
+uint32_t *indirect_symbols,
+uint32_t nindirect_symbols,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nindirect_symbols; i++)
+ indirect_symbols[i] = SWAP_INT(indirect_symbols[i]);
+}
+
+__private_extern__
+void
+swap_dylib_reference(
+struct dylib_reference *refs,
+unsigned long nrefs,
+enum byte_sex target_byte_sex)
+{
+ struct swapped_dylib_reference {
+ union {
+ struct {
+ uint32_t
+ flags:8,
+ isym:24;
+ } fields;
+ uint32_t word;
+ } u;
+ } sref;
+
+ unsigned long i;
+ enum byte_sex host_byte_sex;
+
+ host_byte_sex = get_host_byte_sex();
+
+ for(i = 0; i < nrefs; i++){
+ if(target_byte_sex == host_byte_sex){
+ memcpy(&sref, refs + i, sizeof(struct swapped_dylib_reference));
+ sref.u.word = SWAP_INT(sref.u.word);
+ refs[i].flags = sref.u.fields.flags;
+ refs[i].isym = sref.u.fields.isym;
+ }
+ else{
+ sref.u.fields.isym = refs[i].isym;
+ sref.u.fields.flags = refs[i].flags;
+ sref.u.word = SWAP_INT(sref.u.word);
+ memcpy(refs + i, &sref, sizeof(struct swapped_dylib_reference));
+ }
+ }
+
+}
+
+__private_extern__
+void
+swap_dylib_module(
+struct dylib_module *mods,
+unsigned long nmods,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nmods; i++){
+ mods[i].module_name = SWAP_INT(mods[i].module_name);
+ mods[i].iextdefsym = SWAP_INT(mods[i].iextdefsym);
+ mods[i].nextdefsym = SWAP_INT(mods[i].nextdefsym);
+ mods[i].irefsym = SWAP_INT(mods[i].irefsym);
+ mods[i].nrefsym = SWAP_INT(mods[i].nrefsym);
+ mods[i].ilocalsym = SWAP_INT(mods[i].ilocalsym);
+ mods[i].nlocalsym = SWAP_INT(mods[i].nlocalsym);
+ mods[i].iextrel = SWAP_INT(mods[i].iextrel);
+ mods[i].nextrel = SWAP_INT(mods[i].nextrel);
+ mods[i].iinit_iterm = SWAP_INT(mods[i].iinit_iterm);
+ mods[i].ninit_nterm = SWAP_INT(mods[i].ninit_nterm);
+ mods[i].objc_module_info_addr =
+ SWAP_INT(mods[i].objc_module_info_addr);
+ mods[i].objc_module_info_size =
+ SWAP_INT(mods[i].objc_module_info_size);
+ }
+}
+
+__private_extern__
+void
+swap_dylib_module_64(
+struct dylib_module_64 *mods,
+unsigned long nmods,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < nmods; i++){
+ mods[i].module_name = SWAP_INT(mods[i].module_name);
+ mods[i].iextdefsym = SWAP_INT(mods[i].iextdefsym);
+ mods[i].nextdefsym = SWAP_INT(mods[i].nextdefsym);
+ mods[i].irefsym = SWAP_INT(mods[i].irefsym);
+ mods[i].nrefsym = SWAP_INT(mods[i].nrefsym);
+ mods[i].ilocalsym = SWAP_INT(mods[i].ilocalsym);
+ mods[i].nlocalsym = SWAP_INT(mods[i].nlocalsym);
+ mods[i].iextrel = SWAP_INT(mods[i].iextrel);
+ mods[i].nextrel = SWAP_INT(mods[i].nextrel);
+ mods[i].iinit_iterm = SWAP_INT(mods[i].iinit_iterm);
+ mods[i].ninit_nterm = SWAP_INT(mods[i].ninit_nterm);
+ mods[i].objc_module_info_addr =
+ SWAP_LONG_LONG(mods[i].objc_module_info_addr);
+ mods[i].objc_module_info_size =
+ SWAP_LONG_LONG(mods[i].objc_module_info_size);
+ }
+}
+
+__private_extern__
+void
+swap_dylib_table_of_contents(
+struct dylib_table_of_contents *tocs,
+unsigned long ntocs,
+enum byte_sex target_byte_sex)
+{
+ unsigned long i;
+#ifdef __MWERKS__
+ enum byte_sex dummy;
+ dummy = target_byte_sex;
+#endif
+
+ for(i = 0; i < ntocs; i++){
+ tocs[i].symbol_index = SWAP_INT(tocs[i].symbol_index);
+ tocs[i].module_index = SWAP_INT(tocs[i].module_index);
+ }
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/checkout.c
@@ -0,0 +1,583 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdio.h>
+#include <string.h>
+#include "stuff/ofile.h"
+#include "stuff/breakout.h"
+#include "stuff/round.h"
+
+static void check_object(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+
+static void symbol_string_at_end(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+
+static void dyld_order(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+
+static void order_error(
+ struct arch *arch,
+ struct member *member,
+ char *reason);
+
+__private_extern__
+void
+checkout(
+struct arch *archs,
+unsigned long narchs)
+{
+ unsigned long i, j;
+
+ for(i = 0; i < narchs; i++){
+ if(archs[i].type == OFILE_ARCHIVE){
+ for(j = 0; j < archs[i].nmembers; j++){
+ if(archs[i].members[j].type == OFILE_Mach_O){
+ check_object(archs + i, archs[i].members + j,
+ archs[i].members[j].object);
+ }
+ }
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ check_object(archs + i, NULL, archs[i].object);
+ }
+ }
+}
+
+static
+void
+check_object(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ unsigned long i, ncmds, flags;
+ struct load_command *lc;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct dylib_command *dl_id;
+
+ /*
+ * Set up the symtab load command field and link edit segment feilds in
+ * the object structure.
+ */
+ object->st = NULL;
+ object->dyst = NULL;
+ object->hints_cmd = NULL;
+ object->seg_linkedit = NULL;
+ object->seg_linkedit64 = NULL;
+ object->code_sig_cmd = NULL;
+ dl_id = NULL;
+ lc = object->load_commands;
+ if(object->mh != NULL){
+ ncmds = object->mh->ncmds;
+ flags = object->mh->flags;
+ }
+ else{
+ ncmds = object->mh64->ncmds;
+ flags = object->mh64->flags;
+ }
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SYMTAB){
+ if(object->st != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_SYMTAB load command): ");
+ object->st = (struct symtab_command *)lc;
+ }
+ else if(lc->cmd == LC_DYSYMTAB){
+ if(object->dyst != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_DYSYMTAB load command): ");
+ object->dyst = (struct dysymtab_command *)lc;
+ }
+ else if(lc->cmd == LC_TWOLEVEL_HINTS){
+ if(object->hints_cmd != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_TWOLEVEL_HINTS load command): ");
+ object->hints_cmd = (struct twolevel_hints_command *)lc;
+ }
+ else if(lc->cmd == LC_CODE_SIGNATURE){
+ if(object->code_sig_cmd != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_CODE_SIGNATURE load command): ");
+ object->code_sig_cmd = (struct linkedit_data_command *)lc;
+ }
+ else if(lc->cmd == LC_SEGMENT_SPLIT_INFO){
+ if(object->split_info_cmd != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_SEGMENT_SPLIT_INFO load command): ");
+ object->split_info_cmd = (struct linkedit_data_command *)lc;
+ }
+ else if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ if(strcmp(sg->segname, SEG_LINKEDIT) == 0){
+ if(object->seg_linkedit != NULL)
+ fatal_arch(arch, member, "malformed file (more than "
+ "one " SEG_LINKEDIT "segment): ");
+ object->seg_linkedit = sg;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ if(strcmp(sg64->segname, SEG_LINKEDIT) == 0){
+ if(object->seg_linkedit64 != NULL)
+ fatal_arch(arch, member, "malformed file (more than "
+ "one " SEG_LINKEDIT "segment): ");
+ object->seg_linkedit64 = sg64;
+ }
+ }
+ else if(lc->cmd == LC_ID_DYLIB){
+ if(dl_id != NULL)
+ fatal_arch(arch, member, "malformed file (more than one "
+ "LC_ID_DYLIB load command): ");
+ dl_id = (struct dylib_command *)lc;
+ if(dl_id->dylib.name.offset >= dl_id->cmdsize)
+ fatal_arch(arch, member, "malformed file (name.offset of "
+ "load command %lu extends past the end of the load "
+ "command): ", i);
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if((object->mh_filetype == MH_DYLIB ||
+ (object->mh_filetype == MH_DYLIB_STUB && ncmds > 0)) &&
+ dl_id == NULL)
+ fatal_arch(arch, member, "malformed file (no LC_ID_DYLIB load "
+ "command in %s file): ", object->mh_filetype == MH_DYLIB ?
+ "MH_DYLIB" : "MH_DYLIB_STUB");
+ if(object->hints_cmd != NULL){
+ if(object->dyst == NULL && object->hints_cmd->nhints != 0)
+ fatal_arch(arch, member, "malformed file (LC_TWOLEVEL_HINTS "
+ "load command present without an LC_DYSYMTAB load command):");
+ if(object->hints_cmd->nhints != 0 &&
+ object->hints_cmd->nhints != object->dyst->nundefsym)
+ fatal_arch(arch, member, "malformed file (LC_TWOLEVEL_HINTS "
+ "load command's nhints does not match LC_DYSYMTAB load "
+ "command's nundefsym):");
+ }
+
+ /*
+ * For objects without a dynamic symbol table check to see that the
+ * string table is at the end of the file and that the symbol table is
+ * just before it.
+ */
+ if(object->dyst == NULL){
+ symbol_string_at_end(arch, member, object);
+ }
+ else{
+ /*
+ * This file has a dynamic symbol table command. We handle three
+ * cases, a dynamic shared library, a file for the dynamic linker,
+ * and a relocatable object file. Since it has a dynamic symbol
+ * table command it could have an indirect symbol table.
+ */
+ if(object->mh_filetype == MH_DYLIB /* ||
+ object->mh_filetype == MH_DYLIB_STUB */ ){
+ /*
+ * This is a dynamic shared library.
+ * The order of the symbolic info is:
+ * local relocation entries
+ * symbol table
+ * local symbols
+ * defined external symbols
+ * undefined symbols
+ * two-level namespace hints
+ * external relocation entries
+ * indirect symbol table
+ * table of contents
+ * module table
+ * reference table
+ * string table
+ * strings for external symbols
+ * strings for local symbols
+ * code signature data (16 byte aligned)
+ */
+ dyld_order(arch, member, object);
+ }
+ else if(flags & MH_DYLDLINK){
+ /*
+ * This is a file for the dynamic linker (output of ld(1) with
+ * -output_for_dyld . That is the relocation entries are split
+ * into local and external and hanging off the dysymtab not off
+ * the sections.
+ * The order of the symbolic info is:
+ * local relocation entries
+ * symbol table
+ * local symbols (in order as appeared in stabs)
+ * defined external symbols (sorted by name)
+ * undefined symbols (sorted by name)
+ * external relocation entries
+ * indirect symbol table
+ * string table
+ * strings for external symbols
+ * strings for local symbols
+ * code signature data (16 byte aligned)
+ */
+ dyld_order(arch, member, object);
+ }
+ else{
+ /*
+ * This is a relocatable object file either the output of the
+ * assembler or output of ld(1) with -r. For the output of
+ * the assembler:
+ * The order of the symbolic info is:
+ * relocation entries (by section)
+ * indirect symbol table
+ * symbol table
+ * local symbols (in order as appeared in stabs)
+ * defined external symbols (sorted by name)
+ * undefined symbols (sorted by name)
+ * string table
+ * strings for external symbols
+ * strings for local symbols
+ * With this order the symbol table can be replaced and the
+ * relocation entries and the indirect symbol table entries
+ * can be updated in the file and not moved.
+ * For the output of ld -r:
+ * The order of the symbolic info is:
+ * relocation entries (by section)
+ * symbol table
+ * local symbols (in order as appeared in stabs)
+ * defined external symbols (sorted by name)
+ * undefined symbols (sorted by name)
+ * indirect symbol table
+ * string table
+ * strings for external symbols
+ * strings for local symbols
+ */
+ symbol_string_at_end(arch, member, object);
+ }
+ }
+}
+
+static
+void
+dyld_order(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ unsigned long offset, rounded_offset, isym;
+
+ if(object->mh != NULL){
+ if(object->seg_linkedit == NULL)
+ fatal_arch(arch, member, "malformed file (no " SEG_LINKEDIT
+ " segment): ");
+ if(object->seg_linkedit->filesize != 0 &&
+ object->seg_linkedit->fileoff +
+ object->seg_linkedit->filesize != object->object_size)
+ fatal_arch(arch, member, "the " SEG_LINKEDIT " segment "
+ "does not cover the end of the file (can't "
+ "be processed) in: ");
+
+ offset = object->seg_linkedit->fileoff;
+ }
+ else{
+ if(object->seg_linkedit64 == NULL)
+ fatal_arch(arch, member, "malformed file (no " SEG_LINKEDIT
+ " segment): ");
+ if(object->seg_linkedit64->filesize != 0 &&
+ object->seg_linkedit64->fileoff +
+ object->seg_linkedit64->filesize != object->object_size)
+ fatal_arch(arch, member, "the " SEG_LINKEDIT " segment "
+ "does not cover the end of the file (can't "
+ "be processed) in: ");
+
+ offset = object->seg_linkedit64->fileoff;
+ }
+ if(object->dyst->nlocrel != 0){
+ if(object->dyst->locreloff != offset)
+ order_error(arch, member, "local relocation entries "
+ "out of place");
+ offset += object->dyst->nlocrel *
+ sizeof(struct relocation_info);
+ }
+ if(object->split_info_cmd != NULL){
+ if(object->split_info_cmd->dataoff != offset)
+ order_error(arch, member, "split info data out of place");
+ offset += object->split_info_cmd->datasize;
+ }
+ if(object->st->nsyms != 0){
+ if(object->st->symoff != offset)
+ order_error(arch, member, "symbol table out of place");
+ if(object->mh != NULL)
+ offset += object->st->nsyms * sizeof(struct nlist);
+ else
+ offset += object->st->nsyms * sizeof(struct nlist_64);
+ }
+ isym = 0;
+ if(object->dyst->nlocalsym != 0){
+ if(object->dyst->ilocalsym != isym)
+ order_error(arch, member, "local symbols out of place");
+ isym += object->dyst->nlocalsym;
+ }
+ if(object->dyst->nextdefsym != 0){
+ if(object->dyst->iextdefsym != isym)
+ order_error(arch, member, "externally defined symbols out of "
+ "place");
+ isym += object->dyst->nextdefsym;
+ }
+ if(object->dyst->nundefsym != 0){
+ if(object->dyst->iundefsym != isym)
+ order_error(arch, member, "undefined symbols out of place");
+ isym += object->dyst->nundefsym;
+ }
+ if(object->hints_cmd != NULL && object->hints_cmd->nhints != 0){
+ if(object->hints_cmd->offset != offset)
+ order_error(arch, member, "hints table out of place");
+ offset += object->hints_cmd->nhints * sizeof(struct twolevel_hint);
+ }
+ if(object->dyst->nextrel != 0){
+ if(object->dyst->extreloff != offset)
+ order_error(arch, member, "external relocation entries"
+ " out of place");
+ offset += object->dyst->nextrel *
+ sizeof(struct relocation_info);
+ }
+ if(object->dyst->nindirectsyms != 0){
+ if(object->dyst->indirectsymoff != offset)
+ order_error(arch, member, "indirect symbol table "
+ "out of place");
+ offset += object->dyst->nindirectsyms *
+ sizeof(uint32_t);
+ }
+
+ /*
+ * If this is a 64-bit Mach-O file and has an odd number of indirect
+ * symbol table entries the next offset MAYBE rounded to a multiple of
+ * 8 or MAY NOT BE. This should done to keep all the tables aligned but
+ * was not done for 64-bit Mach-O in Mac OS X 10.4.
+ */
+ object->input_indirectsym_pad = 0;
+ if(object->mh64 != NULL &&
+ (object->dyst->nindirectsyms % 2) != 0){
+ rounded_offset = round(offset, 8);
+ }
+ else{
+ rounded_offset = offset;
+ }
+
+ if(object->dyst->ntoc != 0){
+ if(object->dyst->tocoff != offset &&
+ object->dyst->tocoff != rounded_offset)
+ order_error(arch, member, "table of contents out of place");
+ if(object->dyst->tocoff == offset){
+ offset += object->dyst->ntoc *
+ sizeof(struct dylib_table_of_contents);
+ rounded_offset = offset;
+ }
+ else if(object->dyst->tocoff == rounded_offset){
+ object->input_indirectsym_pad = rounded_offset - offset;
+ rounded_offset += object->dyst->ntoc *
+ sizeof(struct dylib_table_of_contents);
+ offset = rounded_offset;
+ }
+ }
+ if(object->dyst->nmodtab != 0){
+ if(object->dyst->modtaboff != offset &&
+ object->dyst->modtaboff != rounded_offset)
+ order_error(arch, member, "module table out of place");
+ if(object->mh != NULL){
+ offset += object->dyst->nmodtab *
+ sizeof(struct dylib_module);
+ rounded_offset = offset;
+ }
+ else{
+ if(object->dyst->modtaboff == offset){
+ offset += object->dyst->nmodtab *
+ sizeof(struct dylib_module_64);
+ rounded_offset = offset;
+ }
+ else if(object->dyst->modtaboff == rounded_offset){
+ object->input_indirectsym_pad = rounded_offset - offset;
+ rounded_offset += object->dyst->nmodtab *
+ sizeof(struct dylib_module_64);
+ offset = rounded_offset;
+ }
+ }
+ }
+ if(object->dyst->nextrefsyms != 0){
+ if(object->dyst->extrefsymoff != offset &&
+ object->dyst->extrefsymoff != rounded_offset)
+ order_error(arch, member, "reference table out of place");
+ if(object->dyst->extrefsymoff == offset){
+ offset += object->dyst->nextrefsyms *
+ sizeof(struct dylib_reference);
+ rounded_offset = offset;
+ }
+ else if(object->dyst->extrefsymoff == rounded_offset){
+ object->input_indirectsym_pad = rounded_offset - offset;
+ rounded_offset += object->dyst->nextrefsyms *
+ sizeof(struct dylib_reference);
+ offset = rounded_offset;
+ }
+ }
+ if(object->st->strsize != 0){
+ if(object->st->stroff != offset &&
+ object->st->stroff != rounded_offset)
+ order_error(arch, member, "string table out of place");
+ if(object->st->stroff == offset){
+ offset += object->st->strsize;
+ rounded_offset = offset;
+ }
+ else if(object->st->stroff == rounded_offset){
+ object->input_indirectsym_pad = rounded_offset - offset;
+ rounded_offset += object->st->strsize;
+ offset = rounded_offset;
+ }
+ }
+ if(object->code_sig_cmd != NULL){
+ rounded_offset = round(rounded_offset, 16);
+ if(object->code_sig_cmd->dataoff != rounded_offset)
+ order_error(arch, member, "code signature data out of place");
+ rounded_offset += object->code_sig_cmd->datasize;
+ offset = rounded_offset;
+ }
+ if(offset != object->object_size &&
+ rounded_offset != object->object_size)
+ order_error(arch, member, "link edit information does not fill the "
+ SEG_LINKEDIT " segment");
+}
+
+static
+void
+order_error(
+struct arch *arch,
+struct member *member,
+char *reason)
+{
+ fatal_arch(arch, member, "file not in an order that can be processed "
+ "(%s): ", reason);
+}
+
+static
+void
+symbol_string_at_end(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ unsigned long end, strend, rounded_strend;
+ unsigned long indirectend, rounded_indirectend;
+
+ if(object->st != NULL && object->st->nsyms != 0){
+ end = object->object_size;
+ if(object->st->strsize != 0){
+ strend = object->st->stroff + object->st->strsize;
+ /*
+ * Since archive member sizes are now rounded to 8 bytes the
+ * string table may not be exactly at the end of the
+ * object_size due to rounding.
+ */
+ rounded_strend = round(strend, 8);
+ if(strend != end && rounded_strend != end)
+ fatal_arch(arch, member, "string table not at the end "
+ "of the file (can't be processed) in file: ");
+ /*
+ * To make the code work that assumes the end of string table is
+ * 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.
+ */
+ if(rounded_strend != strend)
+ object->object_size = strend;
+ end = object->st->stroff;
+ }
+ if(object->dyst != NULL &&
+ object->dyst->nindirectsyms != 0 &&
+ object->st->nsyms != 0 &&
+ object->dyst->indirectsymoff > object->st->symoff){
+
+ indirectend = object->dyst->indirectsymoff +
+ object->dyst->nindirectsyms * sizeof(uint32_t);
+
+ /*
+ * If this is a 64-bit Mach-O file and has an odd number of indirect
+ * symbol table entries the next offset MAYBE rounded to a multiple of
+ * 8 or MAY NOT BE. This should done to keep all the tables aligned but
+ * was not done for 64-bit Mach-O in Mac OS X 10.4.
+ */
+ if(object->mh64 != NULL &&
+ (object->dyst->nindirectsyms % 2) != 0){
+ rounded_indirectend = round(indirectend, 8);
+ }
+ else{
+ rounded_indirectend = indirectend;
+ }
+
+ if(indirectend != end && rounded_indirectend != end){
+ fatal_arch(arch, member, "indirect symbol table does not "
+ "directly preceed the string table (can't be "
+ "processed) in file: ");
+ }
+ object->input_indirectsym_pad = end - indirectend;
+ end = object->dyst->indirectsymoff;
+ if(object->mh != NULL){
+ if(object->st->symoff +
+ object->st->nsyms * sizeof(struct nlist) != end)
+ fatal_arch(arch, member, "symbol table does not "
+ "directly preceed the indirect symbol table (can't "
+ "be processed) in file: ");
+ }
+ else{
+ if(object->st->symoff +
+ object->st->nsyms * sizeof(struct nlist_64) != end)
+ fatal_arch(arch, member, "symbol table does not "
+ "directly preceed the indirect symbol table (can't "
+ "be processed) in file: ");
+ }
+ }
+ else{
+ if(object->mh != NULL){
+ if(object->st->symoff +
+ object->st->nsyms * sizeof(struct nlist) != end)
+ fatal_arch(arch, member, "symbol table and string "
+ "table not at the end of the file (can't be "
+ "processed) in file: ");
+ }
+ else{
+ if(object->st->symoff +
+ object->st->nsyms * sizeof(struct nlist_64) != end)
+ fatal_arch(arch, member, "symbol table and string "
+ "table not at the end of the file (can't be "
+ "processed) in file: ");
+ }
+ }
+ if(object->seg_linkedit != NULL &&
+ (object->seg_linkedit->flags & SG_FVMLIB) != SG_FVMLIB &&
+ object->seg_linkedit->filesize != 0){
+ if(object->seg_linkedit->fileoff +
+ object->seg_linkedit->filesize != object->object_size)
+ fatal_arch(arch, member, "the " SEG_LINKEDIT " segment "
+ "does not cover the symbol and string table (can't "
+ "be processed) in file: ");
+ }
+ }
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/crc32.c
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James W. Williams of NASA Goddard Space Flight Center.
+ *
+ * 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. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``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 REGENTS OR CONTRIBUTORS 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 <sys/types.h>
+
+static const u_int32_t crctab[] = {
+ 0x0,
+ 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
+ 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6,
+ 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
+ 0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9, 0x5f15adac,
+ 0x5bd4b01b, 0x569796c2, 0x52568b75, 0x6a1936c8, 0x6ed82b7f,
+ 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 0x709f7b7a,
+ 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
+ 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58,
+ 0xbaea46ef, 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033,
+ 0xa4ad16ea, 0xa06c0b5d, 0xd4326d90, 0xd0f37027, 0xddb056fe,
+ 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
+ 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 0xe13ef6f4,
+ 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0,
+ 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5,
+ 0x2ac12072, 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
+ 0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca, 0x7897ab07,
+ 0x7c56b6b0, 0x71159069, 0x75d48dde, 0x6b93dddb, 0x6f52c06c,
+ 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1,
+ 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
+ 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b,
+ 0xbb60adfc, 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698,
+ 0x832f1041, 0x87ee0df6, 0x99a95df3, 0x9d684044, 0x902b669d,
+ 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
+ 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 0xc6bcf05f,
+ 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34,
+ 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80,
+ 0x644fc637, 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
+ 0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f, 0x5c007b8a,
+ 0x58c1663d, 0x558240e4, 0x51435d53, 0x251d3b9e, 0x21dc2629,
+ 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 0x3f9b762c,
+ 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
+ 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e,
+ 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65,
+ 0xeba91bbc, 0xef68060b, 0xd727bbb6, 0xd3e6a601, 0xdea580d8,
+ 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
+ 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 0xae3afba2,
+ 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71,
+ 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74,
+ 0x857130c3, 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
+ 0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c, 0x7b827d21,
+ 0x7f436096, 0x7200464f, 0x76c15bf8, 0x68860bfd, 0x6c47164a,
+ 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 0x18197087,
+ 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
+ 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d,
+ 0x2056cd3a, 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce,
+ 0xcc2b1d17, 0xc8ea00a0, 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb,
+ 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
+ 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 0x89b8fd09,
+ 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662,
+ 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf,
+ 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
+};
+
+#define COMPUTE(var, ch) (var) = (var) << 8 ^ crctab[(var) >> 24 ^ (ch)]
+
+__private_extern__
+unsigned long
+crc32(
+const void *buf,
+unsigned int len)
+{
+
+ register const u_char *p;
+ register int nr;
+ register u_int32_t crc;
+
+ crc = 0;
+ for (nr = len, p = buf; nr--; ++p) {
+ COMPUTE(crc, *p);
+ }
+
+ for (; len != 0; len >>= 8) {
+ COMPUTE(crc, len & 0xff);
+ }
+
+ return(~crc);
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/errors.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "stuff/errors.h"
+
+__private_extern__ unsigned long errors = 0; /* number of calls to error() */
+
+/*
+ * Just print the message in the standard format without setting an error.
+ */
+__private_extern__
+void
+warning(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+/*
+ * Print the error message and return to the caller after setting the error
+ * indication.
+ */
+__private_extern__
+void
+error(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ errors++;
+}
+
+/*
+ * Print the error message, the architecture if not NULL and return to the
+ * caller after setting the error indication.
+ */
+__private_extern__
+void
+error_with_arch(
+const char *arch_name,
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ if(arch_name != NULL)
+ fprintf(stderr, "for architecture: %s ", arch_name);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ errors++;
+}
+
+/*
+ * Print the error message along with the system error message and return to
+ * the caller after setting the error indication.
+ */
+__private_extern__
+void
+system_error(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, " (%s)\n", strerror(errno));
+ va_end(ap);
+ errors++;
+}
+
+/*
+ * Print the error message along with the mach error string.
+ */
+__private_extern__
+void
+my_mach_error(
+kern_return_t r,
+char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, " (%s)\n", mach_error_string(r));
+ va_end(ap);
+ errors++;
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/fatal_arch.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include "stuff/breakout.h"
+#include "stuff/errors.h"
+
+/*
+ * Print the warning message and the input file.
+ */
+__private_extern__
+void
+warning_arch(
+struct arch *arch,
+struct member *member,
+char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if(member != NULL){
+ fprintf(stderr, "%s(%.*s)", arch->file_name,
+ (int)member->member_name_size, member->member_name);
+ }
+ else
+ fprintf(stderr, "%s", arch->file_name);
+ if(arch->fat_arch_name != NULL)
+ fprintf(stderr, " (for architecture %s)\n", arch->fat_arch_name);
+ else
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+
+/*
+ * Print the error message the input file and increment the error count
+ */
+__private_extern__
+void
+error_arch(
+struct arch *arch,
+struct member *member,
+char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if(member != NULL){
+ fprintf(stderr, "%s(%.*s)", arch->file_name,
+ (int)member->member_name_size, member->member_name);
+ }
+ else
+ fprintf(stderr, "%s", arch->file_name);
+ if(arch->fat_arch_name != NULL)
+ fprintf(stderr, " (for architecture %s)\n", arch->fat_arch_name);
+ else
+ fprintf(stderr, "\n");
+ va_end(ap);
+ errors++;
+}
+
+/*
+ * Print the fatal error message the input file and exit non-zero.
+ */
+__private_extern__
+void
+fatal_arch(
+struct arch *arch,
+struct member *member,
+char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+ if(member != NULL){
+ fprintf(stderr, "%s(%.*s)", arch->file_name,
+ (int)member->member_name_size, member->member_name);
+ }
+ else
+ fprintf(stderr, "%s", arch->file_name);
+ if(arch->fat_arch_name != NULL)
+ fprintf(stderr, " (for architecture %s)\n", arch->fat_arch_name);
+ else
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(EXIT_FAILURE);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/fatals.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <mach/mach.h>
+#include <mach/mach_error.h>
+
+#include "stuff/errors.h"
+
+/*
+ * Print the fatal error message and exit.
+ */
+__private_extern__
+void
+fatal(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(1);
+}
+
+/*
+ * Print the fatal error message along with the system error message and exit.
+ */
+__private_extern__
+void
+system_fatal(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, " (%s)\n", strerror(errno));
+ va_end(ap);
+ exit(1);
+}
+
+/*
+ * Print the fatal error message along with the mach error string and exit.
+ */
+__private_extern__
+void
+mach_fatal(
+kern_return_t r,
+char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ fprintf(stderr, "%s: ", progname);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, " (%s)\n", mach_error_string(r));
+ va_end(ap);
+ exit(1);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/get_arch_from_host.c
@@ -0,0 +1,403 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include "stdio.h"
+#include "stdlib.h"
+#include "string.h"
+#include <mach/mach.h>
+#include "stuff/openstep_mach.h"
+#include "stuff/arch.h"
+#include "stuff/allocate.h"
+
+/*
+ * get_arch_from_host() gets the architecture from the host this is running on
+ * and returns zero if the architecture is not known and zero if the
+ * architecture is known. If the parameters family_arch_flag and
+ * specific_arch_flag are not NULL they get fill in with the family
+ * architecture and specific architecure for the host. If the architecture
+ * is unknown and the parameters are not NULL then all fields are set to zero.
+ */
+__private_extern__
+int
+get_arch_from_host(
+struct arch_flag *family_arch_flag,
+struct arch_flag *specific_arch_flag)
+{
+ struct host_basic_info host_basic_info;
+ unsigned int count;
+ kern_return_t r;
+ mach_port_t my_mach_host_self;
+
+ if(family_arch_flag != NULL)
+ memset(family_arch_flag, '\0', sizeof(struct arch_flag));
+ if(specific_arch_flag != NULL)
+ memset(specific_arch_flag, '\0', sizeof(struct arch_flag));
+
+ count = HOST_BASIC_INFO_COUNT;
+ my_mach_host_self = mach_host_self();
+ if((r = host_info(my_mach_host_self, HOST_BASIC_INFO,
+ (host_info_t)(&host_basic_info),
+ &count)) != KERN_SUCCESS){
+ mach_port_deallocate(mach_task_self(), my_mach_host_self);
+ return(0);
+ }
+ mach_port_deallocate(mach_task_self(), my_mach_host_self);
+
+ if(family_arch_flag != NULL){
+ family_arch_flag->cputype = host_basic_info.cpu_type;
+ }
+ if(specific_arch_flag != NULL){
+ specific_arch_flag->cputype = host_basic_info.cpu_type;
+ specific_arch_flag->cpusubtype = host_basic_info.cpu_subtype;
+ }
+ switch(host_basic_info.cpu_type){
+ case CPU_TYPE_MC680x0:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_MC680x0_ALL:
+ case CPU_SUBTYPE_MC68030_ONLY:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "m68k";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL;
+ }
+ if(specific_arch_flag != NULL){
+ specific_arch_flag->name = "m68030";
+ /*
+ * There is a "bug" in the kernel for compatiblity that on
+ * an 030 machine host_info() returns cpusubtype
+ * CPU_SUBTYPE_MC680x0_ALL and not CPU_SUBTYPE_MC68030_ONLY.
+ */
+ specific_arch_flag->cpusubtype = CPU_SUBTYPE_MC68030_ONLY;
+ }
+ return(1);
+ case CPU_SUBTYPE_MC68040:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "m68k";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "m68040";
+ return(1);
+ }
+ break;
+ case CPU_TYPE_POWERPC:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_POWERPC_ALL:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_601:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc601";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_603:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc603";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_603e:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc603e";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_603ev:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc603ev";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_604:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc604";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_604e:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc604e";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_750:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc750";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_7400:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc7400";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_7450:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc7450";
+ return(1);
+ case CPU_SUBTYPE_POWERPC_970:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "ppc970";
+ return(1);
+ default:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "ppc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL;
+ }
+ if(specific_arch_flag != NULL){
+ specific_arch_flag->name =
+ savestr("PowerPC cpusubtype 1234567890");
+ if(specific_arch_flag->name != NULL)
+ sprintf(specific_arch_flag->name,
+ "PowerPC cpusubtype %u",
+ host_basic_info.cpu_subtype);
+ }
+ return(1);
+ }
+ break;
+ case CPU_TYPE_VEO:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_VEO_1:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "veo";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "veo1";
+ return(1);
+ case CPU_SUBTYPE_VEO_2:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "veo";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "veo2";
+ return(1);
+ case CPU_SUBTYPE_VEO_3:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "veo";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "veo3";
+ return(1);
+ case CPU_SUBTYPE_VEO_4:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "veo";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "veo4";
+ return(1);
+ default:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "veo";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL;
+ }
+ if(specific_arch_flag != NULL){
+ specific_arch_flag->name =
+ savestr("VEO cpusubtype 1234567890");
+ sprintf(specific_arch_flag->name,
+ "VEO cpusubtype %u",
+ host_basic_info.cpu_subtype);
+ }
+ return(1);
+ }
+ break;
+ case CPU_TYPE_MC88000:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_MC88000_ALL:
+ case CPU_SUBTYPE_MC88110:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "m88k";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_MC88000_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "m88k";
+ return(1);
+ }
+ break;
+ case CPU_TYPE_I386:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_I386_ALL:
+ /* case CPU_SUBTYPE_386: same value as above */
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "i386";
+ return(1);
+ case CPU_SUBTYPE_486:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "i486";
+ return(1);
+ case CPU_SUBTYPE_486SX:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "i486SX";
+ return(1);
+ case CPU_SUBTYPE_PENT: /* same as CPU_SUBTYPE_586 */
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "pentium";
+ return(1);
+ case CPU_SUBTYPE_PENTPRO:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "pentpro";
+ return(1);
+ case CPU_SUBTYPE_PENTII_M3:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "pentIIm3";
+ return(1);
+ case CPU_SUBTYPE_PENTII_M5:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "pentIIm5";
+ return(1);
+ case CPU_SUBTYPE_PENTIUM_4:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "pentium4";
+ return(1);
+ default:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i386";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL;
+ }
+ if(specific_arch_flag != NULL){
+ specific_arch_flag->name =
+ savestr("Intel family 12 model 12345678");
+ if(specific_arch_flag->name != NULL)
+ sprintf(specific_arch_flag->name,
+ "Intel family %u model %u",
+ CPU_SUBTYPE_INTEL_FAMILY(host_basic_info.cpu_subtype),
+ CPU_SUBTYPE_INTEL_MODEL(host_basic_info.cpu_subtype));
+ }
+ return(1);
+ }
+ break;
+ case CPU_TYPE_I860:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_I860_ALL:
+ case CPU_SUBTYPE_I860_860:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "i860";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_I860_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "i860";
+ return(1);
+ }
+ break;
+ case CPU_TYPE_HPPA:
+ switch(host_basic_info.cpu_subtype){
+ case CPU_SUBTYPE_HPPA_ALL:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "hppa";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "hppa";
+ return(1);
+ case CPU_SUBTYPE_HPPA_7100LC:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "hppa";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "hppa7100LC";
+ return(1);
+
+ }
+ break;
+ case CPU_TYPE_SPARC:
+ switch(host_basic_info.cpu_subtype){
+ case /*CPU_SUBTYPE_SPARC_ALL*/0:
+ if(family_arch_flag != NULL){
+ family_arch_flag->name = "sparc";
+ family_arch_flag->cpusubtype = CPU_SUBTYPE_SPARC_ALL;
+ }
+ if(specific_arch_flag != NULL)
+ specific_arch_flag->name = "sparc";
+ return(1);
+ }
+ break;
+ }
+ return(0);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/ofile.c
@@ -0,0 +1,4770 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#define __darwin_i386_exception_state i386_exception_state
+#define __darwin_i386_float_state i386_float_state
+#define __darwin_i386_thread_state i386_thread_state
+
+#ifndef RLD
+#ifdef SHLIB
+#include "shlib.h"
+#endif
+#include <libc.h>
+#include <mach/mach.h>
+#include "stuff/openstep_mach.h"
+#include <stddef.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <ar.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#import <mach/m68k/thread_status.h>
+#import <mach/ppc/thread_status.h>
+#import <mach/m88k/thread_status.h>
+#import <mach/i860/thread_status.h>
+#import <mach/i386/thread_status.h>
+#import <mach/sparc/thread_status.h>
+#include <mach-o/nlist.h>
+#include <mach-o/reloc.h>
+#include "stuff/bool.h"
+#ifdef OFI
+#include <mach-o/dyld.h>
+#endif
+#include "stuff/bytesex.h"
+#include "stuff/arch.h"
+#include "stuff/round.h"
+#include "stuff/errors.h"
+#include "stuff/allocate.h"
+#include "stuff/ofile.h"
+#include "stuff/print.h"
+
+#ifdef OTOOL
+#undef ALIGNMENT_CHECKS
+#include "otool.h"
+#include "ofile_print.h"
+static enum bool otool_first_ofile_map = TRUE;
+#else /* !define(OTOOL) */
+#if (!defined(m68k) && !defined(__i386__) && !defined(__ppc__))
+#define ALIGNMENT_CHECKS_ARCHIVE_64_BIT
+static enum bool archive_64_bit_align_warning = FALSE;
+#endif /* (!defined(m68k) && !defined(__i386__)) && !defined(__ppc__) */
+#endif /* OTOOL */
+
+/* <mach/loader.h> */
+/* The maximum section alignment allowed to be specified, as a power of two */
+#define MAXSECTALIGN 15 /* 2**15 or 0x8000 */
+
+enum check_type {
+ CHECK_BAD,
+ CHECK_GOOD
+};
+static enum bool ofile_specific_arch(
+ struct ofile *ofile,
+ unsigned long narch);
+static enum check_type check_fat(
+ struct ofile *ofile);
+static enum check_type check_fat_object_in_archive(
+ struct ofile *ofile);
+static enum check_type check_archive(
+ struct ofile *ofile,
+ enum bool archives_with_fat_objects);
+static enum check_type check_extend_format_1(
+ struct ofile *ofile,
+ struct ar_hdr *ar_hdr,
+ unsigned long size_left,
+ unsigned long *member_name_size);
+static enum check_type check_Mach_O(
+ struct ofile *ofile);
+static void swap_back_Mach_O(
+ struct ofile *ofile);
+static enum check_type check_dylib_module(
+ struct ofile *ofile,
+ struct symtab_command *st,
+ struct dysymtab_command *dyst,
+ char *strings,
+ unsigned long module_index);
+
+#ifndef OTOOL
+#if defined(ALIGNMENT_CHECKS) || defined(ALIGNMENT_CHECKS_ARCHIVE_64_BIT)
+static
+void
+temporary_archive_member_warning(
+struct ofile *ofile,
+const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(ofile->file_type == OFILE_FAT){
+ print("%s: for architecture %s archive member: %s(%.*s) ",
+ progname, ofile->arch_flag.name, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ else{
+ print("%s: archive member: %s(%.*s) ", progname, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ vprint(format, ap);
+ print("\n");
+ va_end(ap);
+}
+#endif /* defined(ALIGNMENT_CHECKS) */
+#endif /* !defined(OTOOL) */
+
+#ifndef OFI
+/*
+ * ofile_process() processes the specified file name can calls the routine
+ * processor on the ofiles in it. arch_flags is an array of architectures
+ * containing narch_flags which are the only architectures to process if
+ * narch_flags is non-zero. If all_archs is TRUE then all architectures of
+ * the specified file are processed. The specified file name can be of the
+ * form "archive(member)" which is taken to mean that member in that archive
+ * (or that module of a dynamic library if dylib_flat is not FALSE).
+ * For each ofile that is to be processed the routine processor is called with
+ * the corresponding ofile struct, the arch_name pass to it is either NULL or
+ * an architecture name (when it should be printed or show by processor) and
+ * cookie is the same value as passed to ofile_process.
+ */
+__private_extern__
+void
+ofile_process(
+char *name,
+struct arch_flag *arch_flags,
+unsigned long narch_flags,
+enum bool all_archs,
+enum bool process_non_objects,
+enum bool dylib_flat,
+enum bool use_member_syntax,
+void (*processor)(struct ofile *ofile, char *arch_name, void *cookie),
+void *cookie)
+{
+ char *member_name, *p, *arch_name;
+ unsigned long len, i;
+ struct ofile ofile;
+ enum bool flag, hostflag, arch_found, family;
+ struct arch_flag host_arch_flag;
+ const struct arch_flag *family_arch_flag;
+
+ /*
+ * If use_member_syntax is TRUE look for a name of the form
+ * "archive(member)" which is to mean a member in that archive (the
+ * member name must be at least one character long to be recognized as
+ * this form).
+ */
+ member_name = NULL;
+ if(use_member_syntax == TRUE){
+ len = strlen(name);
+ if(len >= 4 && name[len-1] == ')'){
+ p = strrchr(name, '(');
+ if(p != NULL && p != name){
+ member_name = p+1;
+ *p = '\0';
+ name[len-1] = '\0';
+ }
+ }
+ }
+
+#ifdef OTOOL
+ otool_first_ofile_map = TRUE;
+#endif /* OTOOL */
+ if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
+ return;
+#ifdef OTOOL
+ otool_first_ofile_map = FALSE;
+#endif /* OTOOL */
+
+ if(ofile.file_type == OFILE_FAT){
+ /*
+ * This is a fat file so see if a list of architecture is
+ * specified and process only those.
+ */
+ if(all_archs == FALSE && narch_flags != 0){
+
+ family = FALSE;
+ if(narch_flags == 1){
+ family_arch_flag =
+ get_arch_family_from_cputype(arch_flags[0].cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[0].cpusubtype & ~CPU_SUBTYPE_MASK));
+ }
+
+ for(i = 0; i < narch_flags; i++){
+ if(ofile_first_arch(&ofile) == FALSE)
+ return;
+ arch_found = FALSE;
+ if(narch_flags != 1)
+ arch_name = ofile.arch_flag.name;
+ else
+ arch_name = NULL;
+ do{
+ if(ofile.arch_flag.cputype ==
+ arch_flags[i].cputype &&
+ ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ if(ofile.arch_type == OFILE_ARCHIVE){
+ if(member_name != NULL){
+ if(ofile_specific_member(member_name,
+ &ofile) == TRUE){
+ processor(&ofile, arch_name, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }
+ else{
+ /* loop through archive */
+#ifdef OTOOL
+ printf("Archive : %s", ofile.file_name);
+ if(arch_name != NULL)
+ printf(" (architecture %s)",
+ arch_name);
+ printf("\n");
+#endif /* OTOOL */
+ if(ofile_first_member(&ofile) == TRUE){
+ flag = FALSE;
+ do{
+ if(process_non_objects == TRUE ||
+ ofile.member_type ==
+ OFILE_Mach_O){
+ processor(&ofile, arch_name,
+ cookie);
+ if(ofile.headers_swapped ==TRUE)
+ swap_back_Mach_O(&ofile);
+ flag = TRUE;
+ }
+ }while(ofile_next_member(&ofile) ==
+ TRUE);
+ if(flag == FALSE){
+ error("for architecture: %s "
+ "archive: %s contains no "
+ "members that are object "
+ "files", ofile.arch_flag.name,
+ ofile.file_name);
+ }
+ }
+ else{
+ error("for architecture: %s archive: "
+ "%s contains no members",
+ ofile.arch_flag.name,
+ ofile.file_name);
+ }
+ }
+ }
+ else if(process_non_objects == TRUE ||
+ ofile.arch_type == OFILE_Mach_O){
+ if(ofile.arch_type == OFILE_Mach_O &&
+ (ofile.mh_filetype == MH_DYLIB ||
+ ofile.mh_filetype == MH_DYLIB_STUB)){
+ if(dylib_flat == TRUE){
+ processor(&ofile, arch_name, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ else{
+ if(member_name != NULL){
+ if(ofile_specific_module(
+ member_name, &ofile) == TRUE){
+ processor(&ofile, arch_name,
+ cookie);
+ if(ofile.headers_swapped ==TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }
+ else{
+ /*loop through the dynamic library*/
+ if(ofile_first_module(&ofile)){
+ do{
+ processor(&ofile, arch_name,
+ cookie);
+ }while(ofile_next_module(
+ &ofile));
+ }
+ else{
+ processor(&ofile, arch_name,
+ cookie);
+ }
+ }
+ }
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ else{
+ if(member_name != NULL)
+ error("for architecture: %s file: %s "
+ "is not an archive and thus does "
+ "not contain member: %s",
+ ofile.arch_flag.name,
+ ofile.file_name,
+ member_name);
+ else{
+ processor(&ofile, arch_name, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }
+ }
+ else if(ofile.arch_type == OFILE_UNKNOWN){
+ error("for architecture: %s file: %s is "
+ "not an object file",
+ ofile.arch_flag.name,ofile.file_name);
+ }
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ break;
+ }
+ else{
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }while(ofile_next_arch(&ofile) == TRUE);
+ if(arch_found == FALSE)
+ error("file: %s does not contain architecture: %s",
+ ofile.file_name, arch_flags[i].name);
+ }
+ return;
+ }
+
+ /*
+ * This is a fat file and no architectures has been specified
+ * so if it contains the host architecture process only that
+ * architecture but if not process all architectures
+ * specified.
+ */
+ if(all_archs == FALSE){
+ (void)get_arch_from_host(&host_arch_flag, NULL);
+ hostflag = FALSE;
+
+ family = FALSE;
+ family_arch_flag =
+ get_arch_family_from_cputype(host_arch_flag.cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK));
+
+ ofile_unmap(&ofile);
+ if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
+ return;
+ if(ofile_first_arch(&ofile) == FALSE)
+ return;
+ do{
+ if(ofile.arch_flag.cputype ==
+ host_arch_flag.cputype &&
+ ((ofile.arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ hostflag = TRUE;
+ if(ofile.arch_type == OFILE_ARCHIVE){
+ if(member_name != NULL){
+ if(ofile_specific_member(member_name,
+ &ofile) == TRUE){
+ processor(&ofile, NULL, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }
+ else{
+ /* loop through archive */
+#ifdef OTOOL
+ printf("Archive : %s\n", ofile.file_name);
+#endif /* OTOOL */
+ if(ofile_first_member(&ofile) == TRUE){
+ flag = FALSE;
+ do{
+ if(process_non_objects == TRUE ||
+ ofile.member_type == OFILE_Mach_O){
+ processor(&ofile, NULL, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ flag = TRUE;
+ }
+ }while(ofile_next_member(&ofile) ==
+ TRUE);
+ if(flag == FALSE){
+ error("archive: %s contains no "
+ "members that are object "
+ "files", ofile.file_name);
+ }
+ }
+ else{
+ error("archive: %s contains no "
+ "members", ofile.file_name);
+ }
+ }
+ }
+ else if(process_non_objects == TRUE ||
+ ofile.arch_type == OFILE_Mach_O){
+ if(ofile.arch_type == OFILE_Mach_O &&
+ (ofile.mh_filetype == MH_DYLIB ||
+ ofile.mh_filetype == MH_DYLIB_STUB)){
+ if(dylib_flat == TRUE){
+ processor(&ofile, NULL, cookie);
+ }
+ else{
+ if(member_name != NULL){
+ if(ofile_specific_module(member_name,
+ &ofile) == TRUE)
+ processor(&ofile, NULL, cookie);
+ }
+ else{
+ /* loop through the dynamic library */
+ if(ofile_first_module(&ofile) == TRUE){
+ do{
+ processor(&ofile, NULL, cookie);
+ }while(ofile_next_module(&ofile));
+ }
+ else{
+ processor(&ofile, NULL, cookie);
+ }
+ }
+ }
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ else{
+ if(member_name != NULL)
+ error("for architecture: %s file: %s is "
+ "not an archive and thus does not "
+ "contain member: %s",
+ ofile.arch_flag.name, ofile.file_name,
+ member_name);
+ else{
+ processor(&ofile, NULL, cookie);
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }
+ }
+ else if(ofile.arch_type == OFILE_UNKNOWN){
+ error("file: %s is not an object file",
+ ofile.file_name);
+ }
+ }
+ else{
+ if(ofile.headers_swapped == TRUE)
+ swap_back_Mach_O(&ofile);
+ }
+ }while(hostflag == FALSE && ofile_next_arch(&ofile) == TRUE);
+ if(hostflag == TRUE)
+ return;
+ }
+
+ /*
+ * Either all architectures have been specified or none have
+ * been specified and it does not contain the host architecture
+ * so do all the architectures in the fat file
+ */
+ ofile_unmap(&ofile);
+ if(ofile_map(name, NULL, NULL, &ofile, FALSE) == FALSE)
+ return;
+ if(ofile_first_arch(&ofile) == FALSE)
+ return;
+ do{
+ if(ofile.arch_type == OFILE_ARCHIVE){
+ if(member_name != NULL){
+ if(ofile_specific_member(member_name, &ofile) == TRUE)
+ processor(&ofile, ofile.arch_flag.name, cookie);
+ }
+ else{
+ /* loop through archive */
+#ifdef OTOOL
+ printf("Archive : %s (architecture %s)\n",
+ ofile.file_name, ofile.arch_flag.name);
+#endif /* OTOOL */
+ if(ofile_first_member(&ofile) == TRUE){
+ flag = FALSE;
+ do{
+ if(process_non_objects == TRUE ||
+ ofile.member_type == OFILE_Mach_O){
+ processor(&ofile, ofile.arch_flag.name,
+ cookie);
+ flag = TRUE;
+ }
+ }while(ofile_next_member(&ofile) == TRUE);
+ if(flag == FALSE){
+ error("for architecture: %s archive: %s "
+ "contains no members that are object "
+ "files", ofile.arch_flag.name,
+ ofile.file_name);
+ }
+ }
+ else{
+ error("for architecture: %s archive: %s "
+ "contains no members",
+ ofile.arch_flag.name, ofile.file_name);
+ }
+ }
+ }
+ else if(process_non_objects == TRUE ||
+ ofile.arch_type == OFILE_Mach_O){
+ if(ofile.arch_type == OFILE_Mach_O &&
+ (ofile.mh_filetype == MH_DYLIB ||
+ ofile.mh_filetype == MH_DYLIB_STUB)){
+ if(dylib_flat == TRUE){
+ processor(&ofile, ofile.arch_flag.name, cookie);
+ }
+ else{
+ if(member_name != NULL){
+ if(ofile_specific_module(member_name, &ofile)
+ == TRUE)
+ processor(&ofile, ofile.arch_flag.name,
+ cookie);
+ }
+ else{
+ /* loop through the dynamic library */
+ if(ofile_first_module(&ofile) == TRUE){
+ do{
+ processor(&ofile, ofile.arch_flag.name,
+ cookie);
+ }while(ofile_next_module(&ofile) == TRUE);
+ }
+ else{
+ processor(&ofile, ofile.arch_flag.name,
+ cookie);
+ }
+ }
+ }
+ }
+ else{
+ if(member_name != NULL)
+ error("for architecture: %s file: %s is not an "
+ "archive and thus does not contain member: "
+ "%s", ofile.arch_flag.name, ofile.file_name,
+ member_name);
+ else
+ processor(&ofile, ofile.arch_flag.name, cookie);
+ }
+ }
+ else if(ofile.arch_type == OFILE_UNKNOWN){
+ error("for architecture: %s file: %s is not an "
+ "object file", ofile.arch_flag.name,
+ ofile.file_name);
+ }
+ }while(ofile_next_arch(&ofile) == TRUE);
+ }
+ else if(ofile.file_type == OFILE_ARCHIVE){
+ if(narch_flags != 0){
+ arch_found = FALSE;
+ for(i = 0; i < narch_flags; i++){
+ family = FALSE;
+ if(narch_flags == 1){
+ family_arch_flag =
+ get_arch_family_from_cputype(arch_flags[0].cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype &
+ ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[0].cpusubtype &
+ ~CPU_SUBTYPE_MASK));
+ }
+ if(ofile.archive_cputype == arch_flags[i].cputype &&
+ ((ofile.archive_cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ else{
+ error("file: %s does not contain architecture: %s",
+ ofile.file_name, arch_flags[i].name);
+ }
+ }
+ if(arch_found == FALSE)
+ return;
+ }
+ if(member_name != NULL){
+ if(ofile_specific_member(member_name, &ofile) == TRUE)
+ processor(&ofile, NULL, cookie);
+ }
+ else{
+ /* loop through archive */
+#ifdef OTOOL
+ printf("Archive : %s\n", ofile.file_name);
+#endif /* OTOOL */
+ if(ofile_first_member(&ofile) == TRUE){
+ flag = FALSE;
+ do{
+ if(process_non_objects == TRUE ||
+ ofile.member_type == OFILE_Mach_O){
+ processor(&ofile, NULL, cookie);
+ flag = TRUE;
+ }
+ }while(ofile_next_member(&ofile) == TRUE);
+ if(flag == FALSE){
+ error("archive: %s contains no members that are "
+ "object files", ofile.file_name);
+ }
+ }
+ else{
+ error("archive: %s contains no members",
+ ofile.file_name);
+ }
+ }
+ }
+ else if(ofile.file_type == OFILE_Mach_O){
+ if(narch_flags != 0){
+ arch_found = FALSE;
+ for(i = 0; i < narch_flags; i++){
+ family = FALSE;
+ if(narch_flags == 1){
+ family_arch_flag =
+ get_arch_family_from_cputype(arch_flags[0].cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype &
+ ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[0].cpusubtype &
+ ~CPU_SUBTYPE_MASK));
+ }
+#ifdef OTOOL
+ if(ofile.mh != NULL){
+ if(ofile.mh->magic == MH_MAGIC &&
+ ofile.mh->cputype == arch_flags[i].cputype &&
+ ((ofile.mh->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ if(ofile.mh->magic == SWAP_INT(MH_MAGIC) &&
+ (cpu_type_t)SWAP_INT(ofile.mh->cputype) ==
+ arch_flags[i].cputype &&
+ ((cpu_subtype_t)SWAP_INT(ofile.mh->cpusubtype &
+ ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype &
+ ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ }
+ else if(ofile.mh64 != NULL){
+ if(ofile.mh64->magic == MH_MAGIC_64 &&
+ ofile.mh64->cputype == arch_flags[i].cputype &&
+ ((ofile.mh64->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ if(ofile.mh64->magic == SWAP_INT(MH_MAGIC_64) &&
+ (cpu_type_t)SWAP_INT(ofile.mh64->cputype) ==
+ arch_flags[i].cputype &&
+ ((cpu_subtype_t)SWAP_INT((ofile.mh64->cpusubtype &
+ ~CPU_SUBTYPE_MASK)) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ }
+ else
+#endif /* OTOOL */
+ if(ofile.mh_cputype == arch_flags[i].cputype &&
+ ((ofile.mh_cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[i].cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_found = TRUE;
+ }
+ else{
+ error("file: %s does not contain architecture: %s",
+ ofile.file_name, arch_flags[i].name);
+ }
+ }
+ if(arch_found == FALSE)
+ return;
+ }
+ if(ofile.mh_filetype == MH_DYLIB ||
+ ofile.mh_filetype == MH_DYLIB_STUB){
+ if(dylib_flat == TRUE){
+ processor(&ofile, NULL, cookie);
+ }
+ else{
+ if(member_name != NULL){
+ if(ofile_specific_module(member_name, &ofile) == TRUE)
+ processor(&ofile, NULL, cookie);
+ }
+ else{
+ /* loop through the dynamic library */
+ if(ofile_first_module(&ofile) == TRUE){
+ do{
+ processor(&ofile, NULL, cookie);
+ }while(ofile_next_module(&ofile) == TRUE);
+ }
+ else{
+ processor(&ofile, NULL, cookie);
+ }
+ }
+ }
+ }
+ else{
+ if(member_name != NULL)
+ error("file: %s is not an archive and thus does not contain"
+ " member: %s", ofile.file_name, member_name);
+ else
+ processor(&ofile, NULL, cookie);
+ }
+ }
+ else{
+ if(process_non_objects == TRUE)
+ processor(&ofile, NULL, cookie);
+ else if(member_name != NULL)
+ error("file: %s(%s) is not an object file", name,
+ member_name);
+ else
+ error("file: %s is not an object file", name);
+ }
+}
+#endif /* !defined(OFI) */
+
+/*
+ * ofile_map maps in the object file specified by file_name, arch_flag and
+ * object_name and fills in the ofile struct pointed to by ofile for it.
+ * When arch_flag and object_name are both NULL, the file is just set up into
+ * ofile (if the file can be opened and mapped in, if not this call fails
+ * are error routnes are called). If arch_flag is not NULL and object_file is
+ * NULL, then the file must be a Mach-O file or a fat file with the architecture
+ * specified in the arch_flag, if not this call fails and error routines are
+ * called. When arch_flag and object_name are both not NULL, then the file must
+ * be an archive or a fat file containing archives for the specified architec-
+ * ture and contain an archive member object file with the name object_name,
+ * otherwise this call fails and error routines are called. If arch_flag is
+ * NULL and object_file is not NULL, then the file name must be an archive (not
+ * a fat file containing archives) and contain an archive member object file
+ * with the name object_name, otherwise this call fails and calls error
+ * routines. If this call suceeds then it returns non-zero and the ofile
+ * structure pointed to by ofile is filled in. If this call fails it returns 0
+ * and calls error routines to print error messages and clears the
+ * ofile structure pointed to by ofile.
+ */
+__private_extern__
+#ifdef OFI
+NSObjectFileImageReturnCode
+#else
+enum bool
+#endif
+ofile_map(
+const char *file_name,
+const struct arch_flag *arch_flag, /* can be NULL */
+const char *object_name, /* can be NULL */
+struct ofile *ofile,
+enum bool archives_with_fat_objects)
+{
+ int fd;
+ struct stat stat_buf;
+ unsigned long size, magic;
+ char *addr;
+
+ magic = 0; /* to shut up the compiler warning message */
+ memset(ofile, '\0', sizeof(struct ofile));
+
+ /* Open the file and map it in */
+ if((fd = open(file_name, O_RDONLY)) == -1){
+#ifdef OFI
+ return(NSObjectFileImageAccess);
+#else
+ system_error("can't open file: %s", file_name);
+ return(FALSE);
+#endif
+ }
+ if(fstat(fd, &stat_buf) == -1){
+ close(fd);
+#ifdef OFI
+ return(NSObjectFileImageAccess);
+#else
+ system_error("can't stat file: %s", file_name);
+ return(FALSE);
+#endif
+ }
+ size = stat_buf.st_size;
+
+ addr = NULL;
+ if(size != 0){
+ addr = mmap(0, size, PROT_READ|PROT_WRITE, MAP_FILE|MAP_PRIVATE, fd,
+ 0);
+ if((intptr_t)addr == -1){
+ system_error("can't map file: %s", file_name);
+ close(fd);
+ return(FALSE);
+ }
+ }
+ close(fd);
+#ifdef OTOOL
+ if(otool_first_ofile_map && Wflag)
+ printf("Modification time = %ld\n", (long int)stat_buf.st_mtime);
+#endif /* OTOOL */
+
+ return(ofile_map_from_memory(addr, size, file_name, arch_flag,
+ object_name, ofile, archives_with_fat_objects));
+}
+
+/*
+ * ofile_map_from_memory() is the guts of ofile_map() but with an interface
+ * to pass the address and size of the file already mapped in.
+ */
+__private_extern__
+#ifdef OFI
+NSObjectFileImageReturnCode
+#else
+enum bool
+#endif
+ofile_map_from_memory(
+char *addr,
+unsigned long size,
+const char *file_name,
+const struct arch_flag *arch_flag, /* can be NULL */
+const char *object_name, /* can be NULL */
+struct ofile *ofile,
+enum bool archives_with_fat_objects)
+{
+ unsigned long i;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+ struct arch_flag host_arch_flag;
+ enum bool family;
+ const struct arch_flag *family_arch_flag;
+ uint64_t big_size;
+#ifdef OTOOL
+ uint32_t small_nfat_arch;
+#endif /* OTOOL */
+
+ /* fill in the start of the ofile structure */
+ ofile->file_name = savestr(file_name);
+ if(ofile->file_name == NULL)
+ return(FALSE);
+ ofile->file_addr = addr;
+ ofile->file_size = size;
+
+ /* Try to figure out what kind of file this is */
+
+ if(size >= sizeof(uint32_t)){
+ magic = *((uint32_t *)addr);
+ }
+ host_byte_sex = get_host_byte_sex();
+
+ /* see if this file is a fat file (always in big endian byte sex) */
+#ifdef __BIG_ENDIAN__
+ if(size >= sizeof(struct fat_header) && magic == FAT_MAGIC)
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ if(size >= sizeof(struct fat_header) && SWAP_INT(magic) == FAT_MAGIC)
+#endif /* __LITTLE_ENDIAN__ */
+ {
+ ofile->file_type = OFILE_FAT;
+ ofile->fat_header = (struct fat_header *)addr;
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_header(ofile->fat_header, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+#ifdef OTOOL
+ if(otool_first_ofile_map && fflag)
+ printf("Fat headers\n");
+#endif /* OTOOL */
+ big_size = ofile->fat_header->nfat_arch;
+ big_size *= sizeof(struct fat_arch);
+ big_size += sizeof(struct fat_header);
+ if(big_size > size){
+#ifdef OTOOL
+ error("fat file: %s truncated or malformed (fat_arch structs "
+ "would extend past the end of the file)", file_name);
+ ofile->fat_archs = allocate(size - sizeof(struct fat_header));
+ memset(ofile->fat_archs, '\0',
+ size - sizeof(struct fat_header));
+ memcpy(ofile->fat_archs,
+ addr + sizeof(struct fat_header),
+ size - sizeof(struct fat_header));
+ small_nfat_arch = (size - sizeof(struct fat_header)) /
+ sizeof(struct fat_arch);
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_arch(ofile->fat_archs, small_nfat_arch,
+ host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(otool_first_ofile_map && fflag)
+ print_fat_headers(ofile->fat_header, ofile->fat_archs,
+ size, vflag);
+ free(ofile->fat_archs);
+ ofile_unmap(ofile);
+ return(FALSE);
+#else /* !defined(OTOOL) */
+ goto unknown;
+#endif /* OTOOL */
+ }
+ ofile->fat_archs = (struct fat_arch *)(addr +
+ sizeof(struct fat_header));
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_arch(ofile->fat_archs, ofile->fat_header->nfat_arch,
+ host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+#ifdef OTOOL
+ if(otool_first_ofile_map && fflag)
+ print_fat_headers(ofile->fat_header, ofile->fat_archs,
+ size, vflag);
+#endif /* OTOOL */
+ if(check_fat(ofile) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+ /*
+ * Now that the fat file is mapped fill in the ofile to the level
+ * the caller wants based on the arch_flag and object_name passed.
+ * If the caller did not specify an arch_flag or an object_name
+ * then everything the caller wants is done.
+ */
+ if(arch_flag == NULL && object_name == NULL)
+ goto success;
+ if(arch_flag == NULL){
+ if(get_arch_from_host(&host_arch_flag, NULL) == 0){
+ error("can't determine the host architecture (specify an "
+ "arch_flag or fix get_arch_from_host() )");
+ goto cleanup;
+ }
+ ofile->arch_flag.name = savestr(host_arch_flag.name);
+ if(ofile->arch_flag.name == NULL)
+ goto cleanup;
+ ofile->arch_flag.cputype = host_arch_flag.cputype;
+ ofile->arch_flag.cpusubtype = host_arch_flag.cpusubtype;
+ }
+ else{
+ ofile->arch_flag.name = savestr(arch_flag->name);
+ if(ofile->arch_flag.name == NULL)
+ goto cleanup;
+ ofile->arch_flag.cputype = arch_flag->cputype;
+ ofile->arch_flag.cpusubtype = arch_flag->cpusubtype;
+ }
+
+ ofile->narch = ULONG_MAX;
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ if(ofile->fat_archs[i].cputype ==
+ ofile->arch_flag.cputype &&
+ (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK)){
+ ofile->narch = i;
+ break;
+ }
+ }
+ if(ofile->narch == ULONG_MAX){
+ family = FALSE;
+ family_arch_flag =
+ get_arch_family_from_cputype(ofile->arch_flag.cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK));
+ ofile->narch = ULONG_MAX;
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ if(ofile->fat_archs[i].cputype ==
+ ofile->arch_flag.cputype &&
+ (family == TRUE ||
+ (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (ofile->arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK))){
+ ofile->arch_flag.cpusubtype =
+ ofile->fat_archs[i].cpusubtype;
+ ofile->narch = i;
+ break;
+ }
+ }
+ }
+ if(ofile->narch == ULONG_MAX){
+#ifdef OFI
+ ofile_unmap(ofile);
+ return(NSObjectFileImageArch);
+#else
+ error("fat file: %s does not contain architecture %s",
+ ofile->file_name, arch_flag->name);
+ ofile_unmap(ofile);
+ return(FALSE);
+#endif
+ }
+ /* Now determine the file type for this specific architecture */
+ size = ofile->fat_archs[i].size;
+ addr = addr + ofile->fat_archs[i].offset;
+ if(size >= sizeof(struct mach_header))
+ memcpy(&magic, addr, sizeof(uint32_t));
+ /* see if this file is a 32-bit Mach-O file */
+ if(size >= sizeof(struct mach_header) &&
+ (magic == MH_MAGIC ||
+ magic == SWAP_INT(MH_MAGIC))){
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->fat_archs[i].offset % 4 != 0){
+ error("fat file: %s architecture %s malformed for a 32-bit "
+ "object file (offset is not a multiple of 4)",
+ ofile->file_name, arch_flag->name);
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->arch_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+ if(object_name != NULL){
+ error("fat file: %s architecture %s is not an archive "
+ "(object_name to ofile_map() can't be specified to "
+ "be other than NULL)", ofile->file_name,
+ arch_flag->name);
+ goto cleanup;
+ }
+ }
+ /* see if this file is a 64-bit Mach-O file */
+ else if(size >= sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 ||
+ magic == SWAP_INT(MH_MAGIC_64))){
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->fat_archs[i].offset % 8 != 0){
+ error("fat file: %s architecture %s malformed for a 64-bit "
+ "object file (offset is not a multiple of 8)",
+ ofile->file_name, arch_flag->name);
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->arch_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+ if(object_name != NULL){
+ error("fat file: %s architecture %s is not an archive "
+ "(object_name to ofile_map() can't be specified to "
+ "be other than NULL)", ofile->file_name,
+ arch_flag->name);
+ goto cleanup;
+ }
+ }
+ /* see if this file is an archive file */
+ else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
+ ofile->arch_type = OFILE_ARCHIVE;
+ if(check_archive(ofile, FALSE) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageInappropriateFile);
+#else
+ return(FALSE);
+#endif
+ }
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->archive_cputype != 0 &&
+ ofile->fat_archs[i].offset % sizeof(uint32_t) != 0){
+ error("fat file: %s architecture %s malformed archive that "
+ "contains object files (offset to archive is not a "
+ "multiple of sizeof(uint32_t))",
+ ofile->file_name, arch_flag->name);
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageInappropriateFile);
+#else
+ return(FALSE);
+#endif
+ }
+#endif /* ALIGNMENT_CHECKS */
+ if(object_name != NULL){
+ if(ofile_specific_member(object_name, ofile) == FALSE)
+ goto cleanup;
+ }
+ }
+ /* this file type is now known to be unknown to this program */
+ else{
+ ofile->file_type = OFILE_UNKNOWN;
+ if(object_name != NULL){
+ error("fat file: %s architecture %s is not an archive "
+ "(object_name to ofile_map() can't be specified to "
+ "be other than NULL)", ofile->file_name,
+ arch_flag->name);
+ goto cleanup;
+ }
+ }
+ }
+ /* see if this file is a 32-bit Mach-O file */
+ else if(size >= sizeof(struct mach_header) &&
+ (magic == MH_MAGIC ||
+ magic == SWAP_INT(MH_MAGIC))){
+ ofile->file_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+ if(object_name != NULL){
+ error("file: %s is not an archive (object_name to ofile_map() "
+ "can't be specified to be other than NULL)",
+ ofile->file_name);
+ goto cleanup;
+ }
+ if(arch_flag != NULL){
+ if(arch_flag->cputype != ofile->mh_cputype &&
+ (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
+ (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
+#ifdef OFI
+ ofile_unmap(ofile);
+ return(NSObjectFileImageArch);
+#else
+ error("object file: %s does not match specified arch_flag: "
+ "%s passed to ofile_map()", ofile->file_name,
+ arch_flag->name);
+ ofile_unmap(ofile);
+ return(FALSE);
+#endif
+ goto cleanup;
+ }
+ }
+ }
+ /* see if this file is a 64-bit Mach-O file */
+ else if(size >= sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 ||
+ magic == SWAP_INT(MH_MAGIC_64))){
+ ofile->file_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex = host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD){
+ ofile_unmap(ofile);
+#ifdef OFI
+ return(NSObjectFileImageFormat);
+#else
+ return(FALSE);
+#endif
+ }
+ if(object_name != NULL){
+ error("file: %s is not an archive (object_name to ofile_map() "
+ "can't be specified to be other than NULL)",
+ ofile->file_name);
+ goto cleanup;
+ }
+ if(arch_flag != NULL){
+ if(arch_flag->cputype != ofile->mh_cputype &&
+ (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
+ (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
+#ifdef OFI
+ ofile_unmap(ofile);
+ return(NSObjectFileImageArch);
+#else
+ error("object file: %s does not match specified arch_flag: "
+ "%s passed to ofile_map()", ofile->file_name,
+ arch_flag->name);
+ ofile_unmap(ofile);
+ return(FALSE);
+#endif
+ goto cleanup;
+ }
+ }
+ }
+ /* see if this file is an archive file */
+ else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
+ ofile->file_type = OFILE_ARCHIVE;
+ if(check_archive(ofile, archives_with_fat_objects) == CHECK_BAD)
+ goto cleanup;
+ if(object_name != NULL){
+ if(ofile_specific_member(object_name, ofile) == FALSE)
+ goto cleanup;
+ if(arch_flag != NULL){
+ if(arch_flag->cputype != ofile->mh_cputype &&
+ (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
+ (ofile->mh_cpusubtype & ~CPU_SUBTYPE_MASK)){
+ error("object file: %s(%.*s) does not match specified "
+ "arch_flag: %s passed to ofile_map()",
+ ofile->file_name, (int)ofile->member_name_size,
+ ofile->member_name, arch_flag->name);
+ goto cleanup;
+ }
+ }
+ }
+ else{
+ if(arch_flag != NULL){
+ if(arch_flag->cputype != ofile->archive_cputype &&
+ (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) !=
+ (ofile->archive_cpusubtype & ~CPU_SUBTYPE_MASK)){
+ error("archive file: %s objects do not match specified "
+ "arch_flag: %s passed to ofile_map()",
+ ofile->file_name, arch_flag->name);
+ goto cleanup;
+ }
+ }
+ }
+ }
+ /* this file type is now known to be unknown to this program */
+ else{
+#ifndef OTOOL
+unknown:
+#endif
+ ofile->file_type = OFILE_UNKNOWN;
+ if(arch_flag != NULL){
+#ifdef OFI
+ ofile_unmap(ofile);
+ return(NSObjectFileImageInappropriateFile);
+#else
+ error("file: %s is unknown type (arch_flag to ofile_map() "
+ "can't be specified to be other than NULL)",
+ ofile->file_name);
+ ofile_unmap(ofile);
+ return(FALSE);
+#endif
+ }
+ if(object_name != NULL){
+ error("file: %s is not an archive (object_name to ofile_map() "
+ "can't be specified to be other than NULL)",
+ ofile->file_name);
+ goto cleanup;
+ }
+ }
+success:
+ return(TRUE);
+
+cleanup:
+ ofile_unmap(ofile);
+ return(FALSE);
+}
+
+/*
+ * ofile_unmap() deallocates the memory associated with the specified ofile
+ * struct.
+ */
+__private_extern__
+void
+ofile_unmap(
+struct ofile *ofile)
+{
+ kern_return_t r;
+
+ if(ofile->file_addr != NULL){
+ if((r = vm_deallocate(mach_task_self(),
+ (vm_address_t)ofile->file_addr,
+ (vm_size_t)ofile->file_size)) != KERN_SUCCESS){
+ my_mach_error(r, "Can't vm_deallocate mapped memory for file: "
+ "%s", ofile->file_name);
+ }
+ }
+ if(ofile->file_name != NULL)
+ free(ofile->file_name);
+ if(ofile->arch_flag.name != NULL)
+ free(ofile->arch_flag.name);
+ memset(ofile, '\0', sizeof(struct ofile));
+}
+
+/*
+ * ofile_first_arch() sets up the ofile struct for a fat file to the first arch
+ * in it.
+ */
+__private_extern__
+enum bool
+ofile_first_arch(
+struct ofile *ofile)
+{
+ if(ofile->file_type == OFILE_FAT ||
+ (ofile->file_type == OFILE_ARCHIVE &&
+ ofile->member_type == OFILE_FAT) )
+ return(ofile_specific_arch(ofile, 0));
+ else{
+ error("ofile_first_arch() called and file type of: %s is not a fat "
+ "file\n", ofile->file_name);
+ return(FALSE);
+ }
+}
+
+/*
+ * ofile_next_arch() sets up the ofile struct for a fat file to the next arch
+ * in it.
+ */
+__private_extern__
+enum bool
+ofile_next_arch(
+struct ofile *ofile)
+{
+ if(ofile->file_type == OFILE_FAT ||
+ (ofile->file_type == OFILE_ARCHIVE &&
+ ofile->member_type == OFILE_FAT) ){
+ if(ofile->narch + 1 < ofile->fat_header->nfat_arch)
+ return(ofile_specific_arch(ofile, ofile->narch + 1));
+ else
+ return(FALSE);
+ }
+ else{
+ error("ofile_next_arch() called and file type of: %s is not a fat "
+ "file\n", ofile->file_name);
+ return(FALSE);
+ }
+}
+
+/*
+ * ofile_specific_arch() sets up the ofile struct for the fat file for the
+ * specified narch.
+ */
+static
+enum bool
+ofile_specific_arch(
+struct ofile *ofile,
+unsigned long narch)
+{
+ char *addr;
+ unsigned long size;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+
+ ofile->narch = narch;
+ ofile->arch_type = OFILE_UNKNOWN;
+ if(ofile->arch_flag.name != NULL)
+ free(ofile->arch_flag.name);
+ ofile->arch_flag.name = NULL;
+ ofile->arch_flag.cputype = 0;
+ ofile->arch_flag.cpusubtype = 0;
+ ofile->archive_cputype = 0;
+ ofile->archive_cpusubtype = 0;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+
+ ofile->arch_flag.cputype = ofile->fat_archs[ofile->narch].cputype;
+ ofile->arch_flag.cpusubtype = ofile->fat_archs[ofile->narch].cpusubtype;
+ set_arch_flag_name(&(ofile->arch_flag));
+
+
+ /* Now determine the file type for this specific architecture */
+ if(ofile->file_type == OFILE_FAT){
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_type = OFILE_UNKNOWN;
+
+ size = ofile->fat_archs[ofile->narch].size;
+ addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
+ }
+ else{
+ if(ofile->file_type != OFILE_ARCHIVE ||
+ ofile->member_type != OFILE_FAT){
+ error("internal error. ofile_specific_arch() called but file "
+ "is not a fat file or an archive with a fat member ");
+ }
+ size = ofile->fat_archs[ofile->narch].size;
+ addr = ofile->file_addr +
+ ofile->member_offset +
+ ofile->fat_archs[ofile->narch].offset;
+ }
+
+#ifdef OTOOL
+ if(addr - ofile->file_addr > (ptrdiff_t)ofile->file_size){
+ error("fat file: %s offset to architecture %s extends past end "
+ "of file", ofile->file_name, ofile->arch_flag.name);
+ return(FALSE);
+ }
+ if(addr + size > ofile->file_addr + ofile->file_size)
+ size = (ofile->file_addr + ofile->file_size) - addr;
+#endif /* OTOOL */
+
+ if(size >= sizeof(struct mach_header))
+ memcpy(&magic, addr, sizeof(uint32_t));
+ /* see if this file is a 32-bit Mach-O file */
+ if(size >= sizeof(struct mach_header) &&
+ (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->fat_archs[ofile->narch].offset % 4 != 0){
+ if(ofile->file_type == OFILE_ARCHIVE){
+ error("fat file: %s(%.*s) architecture %s malformed for a "
+ "32-bit object file (offset is not a multiple of 4)",
+ ofile->file_name, (int)ofile->member_name_size,
+ ofile->member_name, ofile->arch_flag.name);
+ }
+ else
+ error("fat file: %s architecture %s malformed for a 32-bit "
+ "object file (offset is not a multiple of 4)",
+ ofile->file_name, ofile->arch_flag.name);
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->arch_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ host_byte_sex = get_host_byte_sex();
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ /* see if this file is a 64-bit Mach-O file */
+ else if(size >= sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->fat_archs[ofile->narch].offset % 8 != 0){
+ if(ofile->file_type == OFILE_ARCHIVE){
+ error("fat file: %s(%.*s) architecture %s malformed for an "
+ "object file (offset is not a multiple of 8)",
+ ofile->file_name, (int)ofile->member_name_size,
+ ofile->member_name, ofile->arch_flag.name);
+ }
+ else
+ error("fat file: %s architecture %s malformed for a 64-bit "
+ "object file (offset is not a multiple of 8",
+ ofile->file_name, ofile->arch_flag.name);
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->arch_type = OFILE_Mach_O;
+ ofile->object_addr = addr;
+ ofile->object_size = size;
+ host_byte_sex = get_host_byte_sex();
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)addr;
+ ofile->load_commands = (struct load_command *)(addr +
+ sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ /* see if this file is an archive file */
+ else if(size >= SARMAG && strncmp(addr, ARMAG, SARMAG) == 0){
+ ofile->arch_type = OFILE_ARCHIVE;
+ if(check_archive(ofile, FALSE) == CHECK_BAD)
+ goto cleanup;
+#ifdef ALIGNMENT_CHECKS
+ if(ofile->archive_cputype != 0 &&
+ ofile->fat_archs[ofile->narch].offset %
+ sizeof(uint32_t) != 0){
+ error("fat file: %s architecture %s malformed archive that "
+ "contains object files (offset to archive is not a "
+ "multiple of sizeof(uint32_t))",
+ ofile->file_name, ofile->arch_flag.name);
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ }
+ /*
+ * This type for this architecture is now known to be unknown to this
+ * program.
+ */
+ else{
+ ofile->arch_type = OFILE_UNKNOWN;
+ }
+ return(TRUE);
+cleanup:
+ ofile->narch = 0;;
+ ofile->arch_type = OFILE_UNKNOWN;
+ if(ofile->arch_flag.name != NULL)
+ free(ofile->arch_flag.name);
+ ofile->arch_flag.name = NULL;
+ ofile->arch_flag.cputype = 0;
+ ofile->arch_flag.cpusubtype = 0;
+ if(ofile->file_type != OFILE_ARCHIVE){
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_type = OFILE_UNKNOWN;
+ }
+ ofile->archive_cputype = 0;
+ ofile->archive_cpusubtype = 0;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+ return(FALSE);
+}
+
+/*
+ * ofile_first_member() set up the ofile structure (the member_* fields and
+ * the object file fields if the first member is an object file) for the first
+ * member.
+ */
+__private_extern__
+enum bool
+ofile_first_member(
+struct ofile *ofile)
+{
+ char *addr;
+ unsigned long size, offset;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+ struct ar_hdr *ar_hdr;
+ unsigned long ar_name_size;
+
+ /* These fields are to be filled in by this routine, clear them first */
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+
+ /*
+ * Get the address and size of the archive.
+ */
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_ARCHIVE){
+ error("ofile_first_member() called on fat file: %s with a "
+ "non-archive architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
+ size = ofile->fat_archs[ofile->narch].size;
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE){
+ addr = ofile->file_addr;
+ size = ofile->file_size;
+ }
+ else{
+ error("ofile_first_member() called and file type of %s is "
+ "OFILE_UNKNOWN\n", ofile->file_name);
+ return(FALSE);
+ }
+#ifdef OTOOL
+ if((addr + SARMAG) - ofile->file_addr > (ptrdiff_t)ofile->file_size){
+ archive_error(ofile, "offset to first member extends past the end "
+ "of the file");
+ return(FALSE);
+ }
+ if(addr + size > ofile->file_addr + ofile->file_size)
+ size = (ofile->file_addr + ofile->file_size) - addr;
+#endif /* OTOOL */
+ if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
+ archive_error(ofile, "internal error. ofile_first_member() "
+ "called but file does not have an archive magic "
+ "string");
+ return(FALSE);
+ }
+
+ offset = SARMAG;
+ if(offset != size && offset + sizeof(struct ar_hdr) > size){
+ archive_error(ofile, "truncated or malformed (archive header of "
+ "first member extends past the end of the file)");
+ return(FALSE);
+ }
+
+ /* check for empty archive */
+ if(size == offset)
+ return(FALSE);
+
+ /* now we know there is a first member so set it up */
+ ar_hdr = (struct ar_hdr *)(addr + offset);
+ offset += sizeof(struct ar_hdr);
+ ofile->member_offset = offset;
+ ofile->member_addr = addr + offset;
+ ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
+ ofile->member_ar_hdr = ar_hdr;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->member_name = ar_hdr->ar_name;
+ if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
+ ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
+ ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,
+ NULL, 10);
+ ofile->member_name_size = ar_name_size;
+ ofile->member_offset += ar_name_size;
+ ofile->member_addr += ar_name_size;
+ ofile->member_size -= ar_name_size;
+ }
+ else{
+ ofile->member_name_size = size_ar_name(ar_hdr);
+ ar_name_size = 0;
+ }
+
+ host_byte_sex = get_host_byte_sex();
+
+ if(ofile->member_size > sizeof(uint32_t)){
+ memcpy(&magic, ofile->member_addr, sizeof(uint32_t));
+#ifdef __BIG_ENDIAN__
+ if(magic == FAT_MAGIC)
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ if(magic == SWAP_INT(FAT_MAGIC))
+#endif /* __LITTLE_ENDIAN__ */
+ {
+ ofile->member_type = OFILE_FAT;
+ ofile->fat_header =
+ (struct fat_header *)(ofile->member_addr);
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_header(ofile->fat_header, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(sizeof(struct fat_header) +
+ ofile->fat_header->nfat_arch *
+ sizeof(struct fat_arch) > ofile->member_size){
+ archive_member_error(ofile, "fat file truncated or "
+ "malformed (fat_arch structs would extend past "
+ "the end of the archive member)");
+ goto fatcleanup;
+ }
+ ofile->fat_archs = (struct fat_arch *)
+ (ofile->member_addr + sizeof(struct fat_header));
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_arch(ofile->fat_archs,
+ ofile->fat_header->nfat_arch, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(check_fat_object_in_archive(ofile) == FALSE)
+ goto fatcleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header) &&
+ (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
+#ifdef ALIGNMENT_CHECKS
+ if((offset + ar_name_size) % 4 != 0){
+ archive_member_error(ofile, "offset in archive not a "
+ "multiple of 4 (must be since member is a 32-bit "
+ "object file)");
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)(ofile->object_addr);
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr + sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64))){
+#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
+ if(archive_64_bit_align_warning == FALSE &&
+ (offset + ar_name_size) % 8 != 0){
+ temporary_archive_member_warning(ofile, "offset in archive "
+ "not a multiple of 8 (must be since member is an "
+ "64-bit object file)");
+ archive_64_bit_align_warning = TRUE;
+ /* goto cleanup; */
+ }
+#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)(ofile->object_addr);
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr + sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ }
+ return(TRUE);
+
+fatcleanup:
+ ofile->fat_header = NULL;
+ ofile->fat_archs = NULL;
+cleanup:
+ ofile->member_offset = 0;
+ ofile->member_addr = 0;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+ return(FALSE);
+}
+
+/*
+ * ofile_next_member() set up the ofile structure (the member_* fields and
+ * the object file fields if the next member is an object file) for the next
+ * member.
+ */
+__private_extern__
+enum bool
+ofile_next_member(
+struct ofile *ofile)
+{
+ char *addr;
+ unsigned long size, offset;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+ struct ar_hdr *ar_hdr;
+ unsigned long ar_name_size;
+
+ /*
+ * Get the address and size of the archive.
+ */
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_ARCHIVE){
+ error("ofile_next_member() called on fat file: %s with a "
+ "non-archive architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
+ size = ofile->fat_archs[ofile->narch].size;
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE){
+ addr = ofile->file_addr;
+ size = ofile->file_size;
+ }
+ else{
+ error("ofile_next_member() called and file type of %s is "
+ "OFILE_UNKNOWN\n", ofile->file_name);
+ return(FALSE);
+ }
+ if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
+ archive_error(ofile, "internal error. ofile_next_member() "
+ "called but file does not have an archive magic "
+ "string");
+ return(FALSE);
+ }
+ if(ofile->member_ar_hdr == NULL){
+ archive_error(ofile, "internal error. ofile_next_member() called "
+ "but the ofile struct does not have an archive "
+ "member selected");
+ return(FALSE);
+ }
+
+ /* figure out the offset to the next member */
+ offset = ofile->member_offset + round(ofile->member_size,sizeof(short));
+#ifdef OTOOL
+ if((addr - ofile->file_addr) + offset > ofile->file_size){
+ archive_error(ofile, "offset to next member extends past the end "
+ "of the file");
+ return(FALSE);
+ }
+#endif /* OTOOL */
+ /* if now at the end of the file then no more members */
+ if(offset == size)
+ goto cleanup;
+ if(offset > size){
+ archive_error(ofile, "truncated or malformed (archive header of "
+ "next member extends past the end of the file)");
+ return(FALSE);
+ }
+
+ /* now we know there is a next member so set it up */
+ ar_hdr = (struct ar_hdr *)(addr + offset);
+ offset += sizeof(struct ar_hdr);
+ ofile->member_offset = offset;
+ ofile->member_addr = addr + offset;
+ ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
+ ofile->member_ar_hdr = ar_hdr;
+ ofile->member_name = ar_hdr->ar_name;
+ if(strncmp(ofile->member_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
+ ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
+ ar_name_size = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,
+ NULL, 10);
+ ofile->member_name_size = ar_name_size;
+ ofile->member_offset += ar_name_size;
+ ofile->member_addr += ar_name_size;
+ ofile->member_size -= ar_name_size;
+ }
+ else{
+ ofile->member_name_size = size_ar_name(ar_hdr);
+ ar_name_size = 0;
+ }
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+
+ host_byte_sex = get_host_byte_sex();
+
+ if(ofile->member_size > sizeof(uint32_t)){
+ memcpy(&magic, ofile->member_addr, sizeof(uint32_t));
+#ifdef __BIG_ENDIAN__
+ if(magic == FAT_MAGIC)
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ if(magic == SWAP_INT(FAT_MAGIC))
+#endif /* __LITTLE_ENDIAN__ */
+ {
+ ofile->member_type = OFILE_FAT;
+ ofile->fat_header = (struct fat_header *)(ofile->member_addr);
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_header(ofile->fat_header, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(sizeof(struct fat_header) +
+ ofile->fat_header->nfat_arch *
+ sizeof(struct fat_arch) > ofile->member_size){
+ archive_member_error(ofile, "fat file truncated or "
+ "malformed (fat_arch structs would extend past "
+ "the end of the archive member)");
+ goto cleanup;
+ }
+ ofile->fat_archs = (struct fat_arch *)(ofile->member_addr +
+ sizeof(struct fat_header));
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_arch(ofile->fat_archs,
+ ofile->fat_header->nfat_arch, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(check_fat_object_in_archive(ofile) == FALSE)
+ goto cleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header) &&
+ (magic == MH_MAGIC ||
+ magic == SWAP_INT(MH_MAGIC))){
+#ifdef ALIGNMENT_CHECKS
+ if((offset + ar_name_size) % 4 != 0){
+ archive_member_error(ofile, "offset in archive not "
+ "a multiple of 4 (must be since member is an 32-bit "
+ "object file)");
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)ofile->object_addr;
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr + sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 ||
+ magic == SWAP_INT(MH_MAGIC_64))){
+#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
+ if(archive_64_bit_align_warning == FALSE &&
+ (offset + ar_name_size) % 8 != 0){
+ temporary_archive_member_warning(ofile, "offset in archive "
+ "not a multiple of 8 (must be since member is an "
+ "64-bit object file)");
+ archive_64_bit_align_warning = TRUE;
+ /* goto cleanup; */
+ }
+#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)ofile->object_addr;
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr + sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ }
+ return(TRUE);
+
+cleanup:
+ if(ofile->member_type == OFILE_FAT){
+ ofile->fat_header = NULL;
+ ofile->fat_archs = NULL;
+ }
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+ return(FALSE);
+}
+
+/*
+ * ofile_specific_member() set up the ofile structure (the member_* fields and
+ * the object file fields if the member is an object file) for the specified
+ * member member_name.
+ */
+__private_extern__
+enum bool
+ofile_specific_member(
+const char *member_name,
+struct ofile *ofile)
+{
+ long i;
+ char *addr;
+ unsigned long size, offset;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+ char *ar_name;
+ unsigned long ar_name_size;
+ struct ar_hdr *ar_hdr;
+
+ /* These fields are to be filled in by this routine, clear them first */
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+
+ /*
+ * Get the address and size of the archive.
+ */
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_ARCHIVE){
+ error("ofile_specific_member() called on fat file: %s with a "
+ "non-archive architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
+ size = ofile->fat_archs[ofile->narch].size;
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE){
+ addr = ofile->file_addr;
+ size = ofile->file_size;
+ }
+ else{
+ error("ofile_specific_member() called and file type of %s is "
+ "OFILE_UNKNOWN\n", ofile->file_name);
+ return(FALSE);
+ }
+ if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
+ archive_error(ofile, "internal error. ofile_specific_member() "
+ "called but file does not have an archive magic "
+ "string");
+ return(FALSE);
+ }
+
+ offset = SARMAG;
+ if(offset != size && offset + sizeof(struct ar_hdr) > size){
+ archive_error(ofile, "truncated or malformed (archive header of "
+ "first member extends past the end of the file)");
+ return(FALSE);
+ }
+ while(size > offset){
+ ar_hdr = (struct ar_hdr *)(addr + offset);
+ offset += sizeof(struct ar_hdr);
+ if(strncmp(ar_hdr->ar_name, AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
+#ifdef OTOOL
+ if(check_extend_format_1(ofile, ar_hdr, size - offset,
+ &ar_name_size) == CHECK_BAD){
+ i = size_ar_name(ar_hdr);
+ ar_name = ar_hdr->ar_name;
+ ar_name_size = 0;
+ }
+ else
+#endif /* OTOOL */
+ {
+ i = strtoul(ar_hdr->ar_name + sizeof(AR_EFMT1) - 1,NULL,10);
+ ar_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
+ ar_name_size = i;
+ }
+ }
+ else{
+ i = size_ar_name(ar_hdr);
+ ar_name = ar_hdr->ar_name;
+ ar_name_size = 0;
+ }
+ if(i > 0 && strncmp(ar_name, member_name, i) == 0){
+
+ ofile->member_name = ar_name;
+ ofile->member_name_size = i;
+ ofile->member_offset = offset + ar_name_size;
+ ofile->member_addr = addr + offset + ar_name_size;
+ ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10) -
+ ar_name_size;
+ ofile->member_ar_hdr = ar_hdr;
+ ofile->member_type = OFILE_UNKNOWN;
+
+ host_byte_sex = get_host_byte_sex();
+
+ if(ofile->member_size > sizeof(uint32_t)){
+ memcpy(&magic, addr + offset + ar_name_size,
+ sizeof(uint32_t));
+#ifdef __BIG_ENDIAN__
+ if(magic == FAT_MAGIC)
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ if(magic == SWAP_INT(FAT_MAGIC))
+#endif /* __LITTLE_ENDIAN__ */
+ {
+ ofile->member_type = OFILE_FAT;
+ ofile->fat_header =
+ (struct fat_header *)(addr + offset + ar_name_size);
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_header(ofile->fat_header, host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(sizeof(struct fat_header) +
+ ofile->fat_header->nfat_arch *
+ sizeof(struct fat_arch) > ofile->member_size){
+ archive_member_error(ofile, "fat file truncated or "
+ "malformed (fat_arch structs would extend "
+ "past the end of the archive member)");
+ goto fatcleanup;
+ }
+ ofile->fat_archs =
+ (struct fat_arch *)(addr + offset + ar_name_size +
+ sizeof(struct fat_header));
+#ifdef __LITTLE_ENDIAN__
+ swap_fat_arch(ofile->fat_archs,
+ ofile->fat_header->nfat_arch,
+ host_byte_sex);
+#endif /* __LITTLE_ENDIAN__ */
+ if(check_fat_object_in_archive(ofile) == FALSE)
+ goto fatcleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header) &&
+ (magic == MH_MAGIC ||
+ magic == SWAP_INT(MH_MAGIC))){
+#ifdef ALIGNMENT_CHECKS
+ if((offset + ar_name_size) % 4 != 0){
+ archive_member_error(ofile, "offset in archive not "
+ "a multiple of 4) (must be since member is a "
+ "32-bit object file)");
+ goto cleanup;
+ }
+#endif /* ALIGNMENT_CHECKS */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh = (struct mach_header *)ofile->object_addr;
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr + sizeof(struct mach_header));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ else if(size - (offset + ar_name_size) >=
+ sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 ||
+ magic == SWAP_INT(MH_MAGIC_64))){
+#ifdef ALIGNMENT_CHECKS_ARCHIVE_64_BIT
+ if(archive_64_bit_align_warning == FALSE &&
+ (offset + ar_name_size) % 8 != 0){
+ temporary_archive_member_warning(ofile, "offset in "
+ "archive not a multiple of 8) (must be since "
+ "member is a 64-bit object file)");
+ archive_64_bit_align_warning = TRUE;
+ /* goto cleanup; */
+ }
+#endif /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
+ ofile->member_type = OFILE_Mach_O;
+ ofile->object_addr = ofile->member_addr;
+ ofile->object_size = ofile->member_size;
+ if(magic == MH_MAGIC_64)
+ ofile->object_byte_sex = host_byte_sex;
+ else
+ ofile->object_byte_sex =
+ host_byte_sex == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ ofile->mh64 = (struct mach_header_64 *)
+ ofile->object_addr;
+ ofile->load_commands = (struct load_command *)
+ (ofile->object_addr +sizeof(struct mach_header_64));
+ if(check_Mach_O(ofile) == CHECK_BAD)
+ goto cleanup;
+ }
+ }
+ return(TRUE);
+ }
+ offset += round(strtoul(ar_hdr->ar_size, NULL, 10),
+ sizeof(short));
+ }
+ archive_error(ofile, "does not contain a member named: %s",
+ member_name);
+fatcleanup:
+ ofile->fat_header = NULL;
+ ofile->fat_archs = NULL;
+cleanup:
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ ofile->member_type = OFILE_UNKNOWN;
+ ofile->object_addr = NULL;
+ ofile->object_size = 0;
+ ofile->object_byte_sex = UNKNOWN_BYTE_SEX;
+ ofile->mh = NULL;
+ ofile->mh64 = NULL;
+ ofile->load_commands = NULL;
+ return(FALSE);
+}
+
+/*
+ * ofile_first_module() set up the ofile structure (the dylib_module field)
+ * for the first module of an MH_DYLIB or MH_DYLIB_STUB file.
+ */
+__private_extern__
+enum bool
+ofile_first_module(
+struct ofile *ofile)
+{
+ unsigned long i, ncmds;
+ struct symtab_command *st;
+ struct dysymtab_command *dyst;
+ struct load_command *lc;
+ enum bool swapped;
+ enum byte_sex host_byte_sex;
+ struct dylib_module m;
+ struct dylib_module_64 m64;
+ char *strings;
+
+ /* These fields are to be filled in by this routine, clear them first */
+ ofile->modtab = NULL;
+ ofile->modtab64 = NULL;
+ ofile->nmodtab = 0;
+ ofile->dylib_module = NULL;
+ ofile->dylib_module64 = NULL;
+ ofile->dylib_module_name = NULL;
+
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_first_module() called on fat file: %s with a "
+ "non-MH_DYLIB architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ }
+ else if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_first_module() called and file type of %s is "
+ "non-MH_DYLIB\n", ofile->file_name);
+ return(FALSE);
+ }
+
+ st = NULL;
+ dyst = NULL;
+ lc = ofile->load_commands;
+ if(ofile->mh != NULL)
+ ncmds = ofile->mh->ncmds;
+ else
+ ncmds = ofile->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(st == NULL && lc->cmd == LC_SYMTAB){
+ st = (struct symtab_command *)lc;
+ }
+ else if(lc->cmd == LC_DYSYMTAB){
+ dyst = (struct dysymtab_command *)lc;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(st == NULL || dyst == NULL){
+#ifndef OTOOL
+ Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
+ "table and/or a dynamic symbol table)");
+#endif
+ return(FALSE);
+ }
+ if(dyst->nmodtab == 0)
+ return(FALSE);
+
+ ofile->nmodtab = dyst->nmodtab;
+ host_byte_sex = get_host_byte_sex();
+ swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
+ strings = (char *)(ofile->object_addr + st->stroff);
+
+ if(ofile->mh != NULL){
+ ofile->modtab = (struct dylib_module *)(ofile->object_addr +
+ dyst->modtaboff);
+ ofile->dylib_module = ofile->modtab;
+ m = *ofile->dylib_module;
+ if(swapped)
+ swap_dylib_module(&m, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m.module_name;
+ }
+ else{
+ ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr +
+ dyst->modtaboff);
+ ofile->dylib_module64 = ofile->modtab64;
+ m64 = *ofile->dylib_module64;
+ if(swapped)
+ swap_dylib_module_64(&m64, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m64.module_name;
+ }
+
+ if(check_dylib_module(ofile, st, dyst, strings, 0) == CHECK_BAD)
+ return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * ofile_next_module() set up the ofile structure (the dylib_module field)
+ * for the next module of an MH_DYLIB or MH_DYLIB_STUB file.
+ */
+__private_extern__
+enum bool
+ofile_next_module(
+struct ofile *ofile)
+{
+ unsigned long i, module_index, ncmds;
+ struct symtab_command *st;
+ struct dysymtab_command *dyst;
+ struct load_command *lc;
+ enum bool swapped;
+ enum byte_sex host_byte_sex;
+ struct dylib_module m;
+ struct dylib_module_64 m64;
+ char *strings;
+
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_next_module() called on fat file: %s with a "
+ "non-MH_DYLIB architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ }
+ else if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_next_module() called and file type of %s is "
+ "non-MH_DYLIB\n", ofile->file_name);
+ return(FALSE);
+ }
+ st = NULL;
+ dyst = NULL;
+ lc = ofile->load_commands;
+ if(ofile->mh != NULL)
+ ncmds = ofile->mh->ncmds;
+ else
+ ncmds = ofile->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(st == NULL && lc->cmd == LC_SYMTAB){
+ st = (struct symtab_command *)lc;
+ }
+ else if(lc->cmd == LC_DYSYMTAB){
+ dyst = (struct dysymtab_command *)lc;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(st == NULL || dyst == NULL){
+#ifndef OTOOL
+ Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
+ "table and/or a dynamic symbol table)");
+#endif
+ return(FALSE);
+ }
+
+ if(ofile->mh != NULL)
+ module_index = (ofile->dylib_module + 1) - ofile->modtab;
+ else
+ module_index = (ofile->dylib_module64 + 1) - ofile->modtab64;
+ if(module_index >= ofile->nmodtab)
+ return(FALSE);
+
+ host_byte_sex = get_host_byte_sex();
+ swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
+ strings = (char *)(ofile->object_addr + st->stroff);
+
+ if(ofile->mh != NULL){
+ ofile->dylib_module++;
+ m = *ofile->dylib_module;
+ if(swapped)
+ swap_dylib_module(&m, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m.module_name;
+ }
+ else{
+ ofile->dylib_module64++;
+ m64 = *ofile->dylib_module64;
+ if(swapped)
+ swap_dylib_module_64(&m64, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m64.module_name;
+ }
+ if(check_dylib_module(ofile, st, dyst, strings, module_index) ==
+ CHECK_BAD)
+ return(FALSE);
+ return(TRUE);
+}
+
+/*
+ * ofile_specific_module() set up the ofile structure (the dylib_module fields)
+ * for the specified module, module_name, of an MH_DYLIB or an MH_DYLIB_STUB
+ * file.
+ */
+__private_extern__
+enum bool
+ofile_specific_module(
+const char *module_name,
+struct ofile *ofile)
+{
+ unsigned long i, ncmds;
+ enum bool swapped;
+ enum byte_sex host_byte_sex;
+ struct symtab_command *st;
+ struct dysymtab_command *dyst;
+ struct load_command *lc;
+ struct dylib_module *p, m;
+ struct dylib_module_64 *p64, m64;
+ char *strings;
+
+ /* These fields are to be filled in by this routine, clear them first */
+ ofile->modtab = NULL;
+ ofile->modtab64 = NULL;
+ ofile->nmodtab = 0;
+ ofile->dylib_module = NULL;
+ ofile->dylib_module64 = NULL;
+ ofile->dylib_module_name = NULL;
+
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_specific_module() called on fat file: %s with a "
+ "non-MH_DYLIB architecture or no architecture selected\n",
+ ofile->file_name);
+ return(FALSE);
+ }
+ }
+ else if(ofile->arch_type != OFILE_Mach_O &&
+ (ofile->mh_filetype != MH_DYLIB &&
+ ofile->mh_filetype != MH_DYLIB_STUB)){
+ error("ofile_specific_module() called and file type of %s is "
+ "non-MH_DYLIB\n", ofile->file_name);
+ return(FALSE);
+ }
+
+ st = NULL;
+ dyst = NULL;
+ lc = ofile->load_commands;
+ if(ofile->mh != NULL)
+ ncmds = ofile->mh->ncmds;
+ else
+ ncmds = ofile->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(st == NULL && lc->cmd == LC_SYMTAB){
+ st = (struct symtab_command *)lc;
+ }
+ else if(lc->cmd == LC_DYSYMTAB){
+ dyst = (struct dysymtab_command *)lc;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(st == NULL || dyst == NULL){
+#ifndef OTOOL
+ Mach_O_error(ofile, "MH_DYLIB format error (does not have a symbol "
+ "table and/or a dynamic symbol table)");
+#endif
+ return(FALSE);
+ }
+ if(dyst->nmodtab == 0)
+ return(FALSE);
+
+ host_byte_sex = get_host_byte_sex();
+ swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
+ strings = (char *)(ofile->object_addr + st->stroff);
+
+ if(ofile->mh != NULL){
+ ofile->nmodtab = dyst->nmodtab;
+ ofile->modtab = (struct dylib_module *)(ofile->object_addr +
+ dyst->modtaboff);
+ p = ofile->modtab;
+ for(i = 0; i < dyst->nmodtab; i++){
+ m = *p;
+ if(swapped)
+ swap_dylib_module(&m, 1, host_byte_sex);
+ ofile->dylib_module = p;
+ if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD)
+ return(FALSE);
+ if(strcmp(module_name, strings + m.module_name) == 0){
+ ofile->dylib_module_name = strings + m.module_name;
+ return(TRUE);
+ }
+ p++;
+ }
+ m = *ofile->dylib_module;
+ if(swapped)
+ swap_dylib_module(&m, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m.module_name;
+ }
+ else{
+ ofile->nmodtab = dyst->nmodtab;
+ ofile->modtab64 = (struct dylib_module_64 *)(ofile->object_addr +
+ dyst->modtaboff);
+ p64 = ofile->modtab64;
+ for(i = 0; i < dyst->nmodtab; i++){
+ m64 = *p64;
+ if(swapped)
+ swap_dylib_module_64(&m64, 1, host_byte_sex);
+ ofile->dylib_module64 = p64;
+ if(check_dylib_module(ofile, st, dyst, strings, i) == CHECK_BAD)
+ return(FALSE);
+ if(strcmp(module_name, strings + m64.module_name) == 0){
+ ofile->dylib_module_name = strings + m64.module_name;
+ return(TRUE);
+ }
+ p64++;
+ }
+ m64 = *ofile->dylib_module64;
+ if(swapped)
+ swap_dylib_module_64(&m64, 1, host_byte_sex);
+ ofile->dylib_module_name = strings + m64.module_name;
+ }
+#ifndef OTOOL
+ Mach_O_error(ofile, "does not contain a module named: %s", module_name);
+#endif
+ ofile->modtab = NULL;
+ ofile->nmodtab = 0;
+ ofile->dylib_module = NULL;
+ ofile->dylib_module_name = NULL;
+ return(FALSE);
+}
+
+#ifdef DEBUG
+__private_extern__
+void
+ofile_print(
+struct ofile *ofile)
+{
+ printf("file_name = %s\n", ofile->file_name);
+ printf("file_addr = 0x%x\n", (unsigned int)ofile->file_addr);
+ printf("file_size = 0x%x\n", (unsigned int)ofile->file_size);
+ printf("file_type = 0x%x\n", (unsigned int)ofile->file_type);
+ printf("fat_header = 0x%x\n", (unsigned int)ofile->fat_header);
+ printf("fat_archs = 0x%x\n", (unsigned int)ofile->fat_archs);
+ printf("narch = 0x%x\n", (unsigned int)ofile->narch);
+ printf("arch_type = 0x%x\n", (unsigned int)ofile->arch_type);
+ printf("arch_flag.name = %s\n", ofile->arch_flag.name);
+ printf("arch_flag.cputype = 0x%x\n",
+ (unsigned int)ofile->arch_flag.cputype);
+ printf("arch_flag.cpusubtype = 0x%x\n",
+ (unsigned int)ofile->arch_flag.cpusubtype);
+ printf("member_offset = 0x%x\n", (unsigned int)ofile->member_offset);
+ printf("member_addr = 0x%x\n", (unsigned int)ofile->member_addr);
+ printf("member_size = 0x%x\n", (unsigned int)ofile->member_size);
+ printf("member_ar_hdr = 0x%x\n", (unsigned int)ofile->member_ar_hdr);
+ printf("member_type = 0x%x\n", (unsigned int)ofile->member_type);
+ printf("archive_cputype = 0x%x\n",
+ (unsigned int)ofile->archive_cputype);
+ printf("archive_cpusubtype = 0x%x\n",
+ (unsigned int)ofile->archive_cpusubtype);
+ printf("object_addr = 0x%x\n", (unsigned int)ofile->object_addr);
+ printf("object_size = 0x%x\n", (unsigned int)ofile->object_size);
+ printf("object_byte_sex = 0x%x\n",
+ (unsigned int)ofile->object_byte_sex);
+ printf("mh = 0x%x\n", (unsigned int)ofile->mh);
+ printf("mh64 = 0x%x\n", (unsigned int)ofile->mh64);
+ printf("load_commands = 0x%x\n", (unsigned int)ofile->load_commands);
+}
+#endif /* DEBUG */
+
+/*
+ * check_fat() checks the fat ofile for correctness (the fat_header and
+ * fat_archs are assumed to be in the host byte sex).
+ */
+static
+enum check_type
+check_fat(
+struct ofile *ofile)
+{
+#ifdef OTOOL
+ return(CHECK_GOOD);
+#else /* !defined OTOOL */
+
+ unsigned long i, j;
+
+ if(ofile->file_type != OFILE_FAT){
+ error("internal error. check_fat() call and file type of: %s is "
+ "not OFILE_FAT\n", ofile->file_name);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_header->nfat_arch == 0){
+ error("fat file: %s malformed (contains zero architecture types)",
+ ofile->file_name);
+ return(CHECK_BAD);
+ }
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ if(ofile->fat_archs[i].offset + ofile->fat_archs[i].size >
+ ofile->file_size){
+ error("fat file: %s truncated or malformed (offset plus size "
+ "of cputype (%d) cpusubtype (%d) extends past the "
+ "end of the file)", ofile->file_name,
+ ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_archs[i].align > MAXSECTALIGN){
+ error("fat file: %s align (2^%u) too large for cputype (%d) "
+ "cpusubtype (%d) (maximum 2^%d)", ofile->file_name,
+ ofile->fat_archs[i].align, ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
+ MAXSECTALIGN);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_archs[i].offset %
+ (1 << ofile->fat_archs[i].align) != 0){
+ error("fat file: %s offset: %u for cputype (%d) cpusubtype "
+ "(%d)) not aligned on it's alignment (2^%u)",
+ ofile->file_name,
+ ofile->fat_archs[i].offset,
+ ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
+ ofile->fat_archs[i].align);
+ return(CHECK_BAD);
+ }
+ }
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){
+ if(ofile->fat_archs[i].cputype ==
+ ofile->fat_archs[j].cputype &&
+ (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
+ error("fat file: %s contains two of the same "
+ "architecture (cputype (%d) cpusubtype (%d))",
+ ofile->file_name, ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ }
+ }
+ return(CHECK_GOOD);
+#endif /* OTOOL */
+}
+
+/*
+ * check_fat_object_in_archive() checks the fat object file which is a member
+ * of a thin archive for correctness (the fat_header and fat_archs are assumed
+ * to be in the host byte sex). This is not a legal form but allowed when
+ * archives_with_fat_objects is TRUE when ofile_map() is called.
+ */
+static
+enum check_type
+check_fat_object_in_archive(
+struct ofile *ofile)
+{
+ unsigned long i, j;
+ uint32_t magic;
+
+ if(ofile->file_type != OFILE_ARCHIVE){
+ error("internal error. check_fat_object_in_archive() called and "
+ "file type of: %s is not OFILE_ARCHIVE\n", ofile->file_name);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_header->nfat_arch == 0){
+ archive_member_error(ofile, "fat file malformed (contains zero "
+ "architecture types)");
+ return(CHECK_BAD);
+ }
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ if(ofile->fat_archs[i].offset + ofile->fat_archs[i].size >
+ ofile->member_size){
+ archive_member_error(ofile, "fat file truncated or malformed "
+ "(offset plus size of cputype (%d) cpusubtype (%d) "
+ "extends past the end of the file)",
+ ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_archs[i].align > MAXSECTALIGN){
+ archive_member_error(ofile, "fat file's align (2^%u) too "
+ "large for cputype (%d) cpusubtype (%d) (maximum 2^%d)",
+ ofile->fat_archs[i].align, ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
+ MAXSECTALIGN);
+ return(CHECK_BAD);
+ }
+ if(ofile->fat_archs[i].offset %
+ (1 << ofile->fat_archs[i].align) != 0){
+ archive_member_error(ofile, "fat file's offset: %u for "
+ "cputype (%d) cpusubtype (%d) not aligned on it's "
+ "alignment (2^%u)", ofile->fat_archs[i].offset,
+ ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK,
+ ofile->fat_archs[i].align);
+ return(CHECK_BAD);
+ }
+
+ /*
+ * The only supported format where fat files are allowed to appear
+ * in archives is when the fat file contains only object files.
+ */
+ if(ofile->fat_archs[i].size < sizeof(struct mach_header)){
+ archive_member_error(ofile, "fat file for cputype (%d) "
+ "cpusubtype (%d) is not an object file (size too small "
+ "to be an object file)", ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ memcpy(&magic,
+ ofile->file_addr + ofile->member_offset +
+ ofile->fat_archs[i].offset,
+ sizeof(uint32_t));
+ if(magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC)){
+#ifdef ALIGNMENT_CHECKS
+ if((ofile->member_offset + ofile->fat_archs[i].offset) %
+ 4 != 0){
+ archive_member_error(ofile, "fat object file's offset in "
+ "archive not a multiple of 4) (must be since "
+ "member is a 32-bit object file)");
+ return(CHECK_BAD);
+ }
+#endif /* ALIGNMENT_CHECKS */
+ }
+ else if(magic == MH_MAGIC_64 || magic == SWAP_INT(MH_MAGIC_64)){
+#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 /* ALIGNMENT_CHECKS_ARCHIVE_64_BIT */
+ }
+ else{
+ archive_member_error(ofile, "fat file for cputype (%d) "
+ "cpusubtype (%d) is not an object file (bad magic "
+ "number)", ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ }
+ for(i = 0; i < ofile->fat_header->nfat_arch; i++){
+ for(j = i + 1; j < ofile->fat_header->nfat_arch; j++){
+ if(ofile->fat_archs[i].cputype ==
+ ofile->fat_archs[j].cputype &&
+ (ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (ofile->fat_archs[j].cpusubtype & ~CPU_SUBTYPE_MASK)){
+ archive_member_error(ofile, "fat file contains two of the "
+ "same architecture (cputype (%d) cpusubtype (%d))",
+ ofile->fat_archs[i].cputype,
+ ofile->fat_archs[i].cpusubtype & ~CPU_SUBTYPE_MASK);
+ return(CHECK_BAD);
+ }
+ }
+ }
+ return(CHECK_GOOD);
+}
+
+/*
+ * check_archive() checks the archive referenced in the ofile for correctness.
+ */
+static
+enum check_type
+check_archive(
+struct ofile *ofile,
+enum bool archives_with_fat_objects)
+{
+#ifdef OTOOL
+ return(CHECK_GOOD);
+#else /* !defined OTOOL */
+ char *addr;
+ unsigned long size, offset;
+ uint32_t magic;
+ enum byte_sex host_byte_sex;
+ enum bool swapped;
+ struct mach_header mh;
+ struct mach_header_64 mh64;
+ struct ar_hdr *ar_hdr;
+ unsigned long ar_name_size;
+
+ /*
+ * Get the address and size of the archive (as well as the cputype and
+ * cpusubtype if known) and make sure it is an archive.
+ */
+ if(ofile->file_type == OFILE_FAT){
+ addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset;
+ size = ofile->fat_archs[ofile->narch].size;
+ ofile->archive_cputype = ofile->fat_archs[ofile->narch].cputype;
+ ofile->archive_cpusubtype =
+ ofile->fat_archs[ofile->narch].cpusubtype;
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE){
+ addr = ofile->file_addr;
+ size = ofile->file_size;
+ ofile->archive_cputype = 0;
+ ofile->archive_cpusubtype = 0;
+ }
+ else{
+ error("internal error. check_archive() call and file type of %s is "
+ "OFILE_UNKNOWN\n", ofile->file_name);
+ return(CHECK_BAD);
+ }
+ if(size < SARMAG || strncmp(addr, ARMAG, SARMAG) != 0){
+ error("internal error. check_archive() call for file %s which does "
+ "not have an archive magic string", ofile->file_name);
+ return(CHECK_BAD);
+ }
+
+ host_byte_sex = get_host_byte_sex();
+ /*
+ * Check this archive out to make sure that it does not contain
+ * any fat files and that all object files it contains have the
+ * same cputype and subsubtype.
+ */
+ offset = SARMAG;
+ if(offset == size)
+ return(CHECK_GOOD);
+ if(offset != size && offset + sizeof(struct ar_hdr) > size){
+ archive_error(ofile, "truncated or malformed (archive header of "
+ "first member extends past the end of the file)");
+ return(CHECK_BAD);
+ }
+ while(size > offset){
+ ar_hdr = (struct ar_hdr *)(addr + offset);
+ ofile->member_offset = offset;
+ ofile->member_addr = addr + offset;
+ ofile->member_size = strtoul(ar_hdr->ar_size, NULL, 10);
+ ofile->member_ar_hdr = ar_hdr;
+ ofile->member_name = ar_hdr->ar_name;
+ ofile->member_name_size = size_ar_name(ofile->member_ar_hdr);
+ offset += sizeof(struct ar_hdr);
+ /*
+ * See if this archive member is using extend format #1 where
+ * the size of the name is in ar_name and the name follows the
+ * archive header.
+ */
+ ar_name_size = 0;
+ if(strncmp(ofile->member_name,AR_EFMT1, sizeof(AR_EFMT1) - 1) == 0){
+ if(check_extend_format_1(ofile, ar_hdr, size - offset,
+ &ar_name_size) == CHECK_BAD)
+ return(CHECK_BAD);
+ ofile->member_name = ar_hdr->ar_name + sizeof(struct ar_hdr);
+ ofile->member_name_size = ar_name_size;
+ offset += ar_name_size;
+ ofile->member_offset += ar_name_size;
+ ofile->member_addr += ar_name_size;
+ ofile->member_size -= ar_name_size;
+ }
+ if(size - offset > sizeof(uint32_t)){
+ memcpy(&magic, addr + offset, sizeof(uint32_t));
+#ifdef __BIG_ENDIAN__
+ if(magic == FAT_MAGIC)
+#endif /* __BIG_ENDIAN__ */
+#ifdef __LITTLE_ENDIAN__
+ if(magic == SWAP_INT(FAT_MAGIC))
+#endif /* __LITTLE_ENDIAN__ */
+ {
+ if(archives_with_fat_objects == FALSE ||
+ ofile->file_type != OFILE_ARCHIVE){
+ archive_member_error(ofile, "is a fat file (not "
+ "allowed in an archive)");
+ return(CHECK_BAD);
+ }
+ }
+ else{
+ if(size - offset >= sizeof(struct mach_header) &&
+ (magic == MH_MAGIC || magic == SWAP_INT(MH_MAGIC))){
+ memcpy(&mh, addr + offset, sizeof(struct mach_header));
+ if(magic == SWAP_INT(MH_MAGIC)){
+ magic = MH_MAGIC;
+ swapped = TRUE;
+ swap_mach_header(&mh, host_byte_sex);
+ }
+ swapped = FALSE;
+ }
+ else if(size - offset >= sizeof(struct mach_header_64) &&
+ (magic == MH_MAGIC_64 ||
+ magic == SWAP_INT(MH_MAGIC_64))){
+ memcpy(&mh64, addr + offset,
+ sizeof(struct mach_header_64));
+ if(magic == SWAP_INT(MH_MAGIC_64)){
+ magic = MH_MAGIC_64;
+ swapped = TRUE;
+ swap_mach_header_64(&mh64, host_byte_sex);
+ }
+ swapped = FALSE;
+ }
+ if(magic == MH_MAGIC){
+ if(ofile->archive_cputype == 0){
+ ofile->archive_cputype = mh.cputype;
+ ofile->archive_cpusubtype = mh.cpusubtype;
+ }
+ else if(ofile->archive_cputype != mh.cputype){
+ archive_member_error(ofile, "cputype (%d) does not "
+ "match previous archive members cputype (%d) "
+ "(all members must match)", mh.cputype,
+ ofile->archive_cputype);
+ }
+ }
+ else if(magic == MH_MAGIC_64){
+ if(ofile->archive_cputype == 0){
+ ofile->archive_cputype = mh64.cputype;
+ ofile->archive_cpusubtype = mh64.cpusubtype;
+ }
+ else if(ofile->archive_cputype != mh64.cputype){
+ archive_member_error(ofile, "cputype (%d) does not "
+ "match previous archive members cputype (%d) "
+ "(all members must match)", mh64.cputype,
+ ofile->archive_cputype);
+ }
+ }
+ }
+ }
+ offset += round(ofile->member_size, sizeof(short));
+ }
+ ofile->member_offset = 0;
+ ofile->member_addr = NULL;
+ ofile->member_size = 0;
+ ofile->member_ar_hdr = NULL;;
+ ofile->member_name = NULL;
+ ofile->member_name_size = 0;
+ return(CHECK_GOOD);
+#endif /* OTOOL */
+}
+
+/*
+ * check_extend_format_1() checks the archive header for extended format #1.
+ */
+static
+enum check_type
+check_extend_format_1(
+struct ofile *ofile,
+struct ar_hdr *ar_hdr,
+unsigned long size_left,
+unsigned long *member_name_size)
+{
+ char *p, *endp, buf[sizeof(ar_hdr->ar_name)+1];
+ unsigned long ar_name_size;
+
+ *member_name_size = 0;
+
+ buf[sizeof(ar_hdr->ar_name)] = '\0';
+ memcpy(buf, ar_hdr->ar_name, sizeof(ar_hdr->ar_name));
+ p = buf + sizeof(AR_EFMT1) - 1;
+ if(isdigit(*p) == 0){
+ archive_error(ofile, "malformed (ar_name: %.*s for archive "
+ "extend format #1 starts with non-digit)",
+ (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
+ return(CHECK_BAD);
+ }
+ ar_name_size = strtoul(p, &endp, 10);
+ if(ar_name_size == ULONG_MAX && errno == ERANGE){
+ archive_error(ofile, "malformed (size in ar_name: %.*s for "
+ "archive extend format #1 overflows unsigned long)",
+ (int)sizeof(ar_hdr->ar_name), ar_hdr->ar_name);
+ return(CHECK_BAD);
+ }
+ while(*endp == ' ' && *endp != '\0')
+ endp++;
+ if(*endp != '\0'){
+ archive_error(ofile, "malformed (size in ar_name: %.*s for "
+ "archive extend format #1 contains non-digit and "
+ "non-space characters)", (int)sizeof(ar_hdr->ar_name),
+ ar_hdr->ar_name);
+ return(CHECK_BAD);
+ }
+ if(ar_name_size > size_left){
+ archive_error(ofile, "truncated or malformed (archive name "
+ "of member extends past the end of the file)");
+ return(CHECK_BAD);
+ }
+ *member_name_size = ar_name_size;
+ return(CHECK_GOOD);
+}
+
+/*
+ * check_Mach_O() checks the object file's mach header and load commands
+ * referenced in the ofile for correctness (this also swaps the mach header
+ * and load commands into the host byte sex if needed).
+ */
+static
+enum check_type
+check_Mach_O(
+struct ofile *ofile)
+{
+#ifdef OTOOL
+ return(CHECK_GOOD);
+#else /* !defined OTOOL */
+ unsigned long size, i, j, ncmds, sizeofcmds, load_command_multiple;
+ cpu_type_t cputype;
+ char *addr, *cmd_name;
+ enum byte_sex host_byte_sex;
+ enum bool swapped;
+ struct mach_header *mh;
+ struct mach_header_64 *mh64;
+ struct load_command *load_commands, *lc, l;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct section *s;
+ struct section_64 *s64;
+ struct symtab_command *st;
+ struct dysymtab_command *dyst;
+ struct symseg_command *ss;
+ struct fvmlib_command *fl;
+ struct dylib_command *dl;
+ struct sub_framework_command *sub;
+ struct sub_umbrella_command *usub;
+ struct sub_library_command *lsub;
+ struct sub_client_command *csub;
+ struct prebound_dylib_command *pbdylib;
+ struct dylinker_command *dyld;
+ struct thread_command *ut;
+ struct ident_command *id;
+ struct routines_command *rc;
+ struct routines_command_64 *rc64;
+ struct twolevel_hints_command *hints;
+ struct linkedit_data_command *code_sig, *split_info;
+ struct prebind_cksum_command *cs;
+ struct uuid_command *uuid;
+ struct rpath_command *rpath;
+ uint32_t flavor, count, nflavor;
+ char *p, *state;
+ unsigned long sizeof_nlist, sizeof_dylib_module;
+ char *struct_dylib_module_name, *struct_nlist_name;
+
+ addr = ofile->object_addr;
+ size = ofile->object_size;
+ mh = ofile->mh;
+ mh64 = ofile->mh64;
+ load_commands = ofile->load_commands;
+ host_byte_sex = get_host_byte_sex();
+ swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
+
+ if(ofile->mh != NULL){
+ if(swapped)
+ swap_mach_header(mh, host_byte_sex);
+ if(mh->sizeofcmds + sizeof(struct mach_header) > size){
+ Mach_O_error(ofile, "truncated or malformed object (load "
+ "commands extend past the end of the file)");
+ return(CHECK_BAD);
+ }
+ ofile->mh_cputype = mh->cputype;
+ ofile->mh_cpusubtype = mh->cpusubtype;
+ ofile->mh_filetype = mh->filetype;
+ ncmds = mh->ncmds;
+ sizeofcmds = mh->sizeofcmds;
+ cputype = mh->cputype;
+ load_command_multiple = 4;
+ sizeof_nlist = sizeof(struct nlist);
+ struct_nlist_name = "struct nlist";
+ sizeof_dylib_module = sizeof(struct dylib_module);
+ struct_dylib_module_name = "struct dylib_module";
+ }
+ else{
+ if(swapped)
+ swap_mach_header_64(mh64, host_byte_sex);
+ if(mh64->sizeofcmds + sizeof(struct mach_header_64) > size){
+ Mach_O_error(ofile, "truncated or malformed object (load "
+ "commands extend past the end of the file)");
+ return(CHECK_BAD);
+ }
+ ofile->mh_cputype = mh64->cputype;
+ ofile->mh_cpusubtype = mh64->cpusubtype;
+ ofile->mh_filetype = mh64->filetype;
+ ncmds = mh64->ncmds;
+ sizeofcmds = mh64->sizeofcmds;
+ cputype = mh64->cputype;
+ load_command_multiple = 8;
+ sizeof_nlist = sizeof(struct nlist_64);
+ struct_nlist_name = "struct nlist_64";
+ sizeof_dylib_module = sizeof(struct dylib_module_64);
+ struct_dylib_module_name = "struct dylib_module_64";
+ }
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->fat_archs[ofile->narch].cputype != ofile->mh_cputype){
+ Mach_O_error(ofile, "malformed fat file (fat header "
+ "architecture: %lu's cputype does not match "
+ "object file's mach header)", ofile->narch);
+ return(CHECK_BAD);
+ }
+ }
+ /*
+ * Make a pass through the load commands checking them to the level
+ * that they can be parsed and all fields with offsets and sizes do
+ * not extend past the end of the file.
+ */
+ st = NULL;
+ dyst = NULL;
+ rc = NULL;
+ rc64 = NULL;
+ hints = NULL;
+ code_sig = NULL;
+ split_info = NULL;
+ cs = NULL;
+ uuid = NULL;
+ for(i = 0, lc = load_commands; i < ncmds; i++){
+ l = *lc;
+ if(swapped)
+ swap_load_command(&l, host_byte_sex);
+ /*
+ * Check load command size for a multiple of load_command_multiple.
+ */
+ if(l.cmdsize % load_command_multiple != 0){
+ Mach_O_error(ofile, "malformed object (load command %lu cmdsize"
+ " not a multiple of %ld)",i,load_command_multiple);
+ return(CHECK_BAD);
+ }
+ /* check that load command does not extends past end of commands */
+ if((char *)lc + l.cmdsize > (char *)load_commands + sizeofcmds){
+ Mach_O_error(ofile, "truncated or malformed object (load "
+ "command %lu extends past the end of the file)",i);
+ return(CHECK_BAD);
+ }
+ /* check that the load command size is not zero */
+ if(l.cmdsize == 0){
+ Mach_O_error(ofile, "malformed object (load command %lu cmdsize"
+ " is zero)", i);
+ return(CHECK_BAD);
+ }
+ switch(l.cmd){
+ case LC_SEGMENT:
+ sg = (struct segment_command *)lc;
+ if(swapped)
+ swap_segment_command(sg, host_byte_sex);
+ if(sg->cmdsize != sizeof(struct segment_command) +
+ sg->nsects * sizeof(struct section)){
+ Mach_O_error(ofile, "malformed object (inconsistent "
+ "cmdsize in LC_SEGMENT command %lu for the "
+ "number of sections)", i);
+ return(CHECK_BAD);
+ }
+ if(sg->fileoff > size){
+ Mach_O_error(ofile, "truncated or malformed object ("
+ "LC_SEGMENT command %lu fileoff field "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(sg->fileoff + sg->filesize > size){
+ Mach_O_error(ofile, "truncated or malformed object ("
+ "LC_SEGMENT command %lu fileoff field "
+ "plus filesize field extends past the end of "
+ "the file)", i);
+ return(CHECK_BAD);
+ }
+ s = (struct section *)
+ ((char *)sg + sizeof(struct segment_command));
+ if(swapped)
+ swap_section(s, sg->nsects, host_byte_sex);
+ for(j = 0 ; j < sg->nsects ; j++){
+ if(s->flags != S_ZEROFILL && s->offset > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field of section %lu in LC_SEGMENT "
+ "command %lu extends past the end of the file)",
+ j, i);
+ return(CHECK_BAD);
+ }
+ if(s->flags != S_ZEROFILL && s->offset + s->size > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field plus size field of section %lu "
+ "in LC_SEGMENT command %lu extends "
+ "past the end of the file)", j, i);
+ return(CHECK_BAD);
+ }
+ if(s->reloff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(reloff field of section %lu in LC_SEGMENT "
+ "command %lu extends past the end of the file)",
+ j, i);
+ return(CHECK_BAD);
+ }
+ if(s->reloff + s->nreloc * sizeof(struct relocation_info) >
+ size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(reloff field plus nreloc field times sizeof("
+ "struct relocation_info) of section %lu in "
+ "LC_SEGMENT command %lu extends past the "
+ "end of the file)", j, i);
+ return(CHECK_BAD);
+ }
+ s++;
+ }
+ break;
+
+ case LC_SEGMENT_64:
+ sg64 = (struct segment_command_64 *)lc;
+ if(swapped)
+ swap_segment_command_64(sg64, host_byte_sex);
+ if(sg64->cmdsize != sizeof(struct segment_command_64) +
+ sg64->nsects * sizeof(struct section_64)){
+ Mach_O_error(ofile, "malformed object (inconsistent "
+ "cmdsize in LC_SEGMENT_64 command %lu for "
+ "the number of sections)", i);
+ return(CHECK_BAD);
+ }
+ if(sg64->fileoff > size){
+ Mach_O_error(ofile, "truncated or malformed object ("
+ "LC_SEGMENT_64 command %lu fileoff field "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(sg64->fileoff + sg64->filesize > size){
+ Mach_O_error(ofile, "truncated or malformed object ("
+ "LC_SEGMENT_64 command %lu fileoff field "
+ "plus filesize field extends past the end of "
+ "the file)", i);
+ return(CHECK_BAD);
+ }
+ s64 = (struct section_64 *)
+ ((char *)sg64 + sizeof(struct segment_command_64));
+ if(swapped)
+ swap_section_64(s64, sg64->nsects, host_byte_sex);
+ for(j = 0 ; j < sg64->nsects ; j++){
+ if(s64->flags != S_ZEROFILL && s64->offset > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field of section %lu in LC_SEGMENT_64 "
+ "command %lu extends past the end of the file)",
+ j, i);
+ return(CHECK_BAD);
+ }
+ if(s64->flags != S_ZEROFILL &&
+ s64->offset + s64->size > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field plus size field of section %lu "
+ "in LC_SEGMENT_64 command %lu extends "
+ "past the end of the file)", j, i);
+ return(CHECK_BAD);
+ }
+ if(s64->reloff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(reloff field of section %lu in LC_SEGMENT_64 "
+ "command %lu extends past the end of the file)",
+ j, i);
+ return(CHECK_BAD);
+ }
+ if(s64->reloff + s64->nreloc *
+ sizeof(struct relocation_info) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(reloff field plus nreloc field times sizeof("
+ "struct relocation_info) of section %lu in "
+ "LC_SEGMENT_64 command %lu extends past the "
+ "end of the file)", j, i);
+ return(CHECK_BAD);
+ }
+ s++;
+ }
+ break;
+
+ case LC_SYMTAB:
+ if(st != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_SYMTAB command)");
+ return(CHECK_BAD);
+ }
+ st = (struct symtab_command *)lc;
+ if(swapped)
+ swap_symtab_command(st, host_byte_sex);
+ if(st->cmdsize != sizeof(struct symtab_command)){
+ Mach_O_error(ofile, "malformed object (LC_SYMTAB command "
+ "%lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(st->symoff > size){
+ Mach_O_error(ofile, "truncated or malformed object (symoff "
+ "field of LC_SYMTAB command %lu extends past the end "
+ "of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(st->symoff + st->nsyms * sizeof_nlist > size){
+ Mach_O_error(ofile, "truncated or malformed object (symoff "
+ "field plus nsyms field times sizeof(%s) of LC_SYMTAB "
+ "command %lu extends past the end of the file)",
+ struct_nlist_name, i);
+ return(CHECK_BAD);
+ }
+ if(st->stroff > size){
+ Mach_O_error(ofile, "truncated or malformed object (stroff "
+ "field of LC_SYMTAB command %lu extends past the end "
+ "of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(st->stroff + st->strsize > size){
+ Mach_O_error(ofile, "truncated or malformed object (stroff "
+ "field plus strsize field of LC_SYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_DYSYMTAB:
+ if(dyst != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_DYSYMTAB command)");
+ return(CHECK_BAD);
+ }
+ dyst = (struct dysymtab_command *)lc;
+ if(swapped)
+ swap_dysymtab_command(dyst, host_byte_sex);
+ if(dyst->cmdsize != sizeof(struct dysymtab_command)){
+ Mach_O_error(ofile, "malformed object (LC_DYSYMTAB command "
+ "%lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->tocoff > size){
+ Mach_O_error(ofile, "truncated or malformed object (tocoff "
+ "field of LC_DYSYMTAB command %lu extends past the end "
+ "of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->tocoff +
+ dyst->ntoc * sizeof(struct dylib_table_of_contents) > size){
+ Mach_O_error(ofile, "truncated or malformed object (tocoff "
+ "field plus ntoc field times sizeof(struct dylib_table"
+ "_of_contents) of LC_DYSYMTAB command %lu extends past "
+ "the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->modtaboff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(modtaboff field of LC_DYSYMTAB command %lu extends "
+ "past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->modtaboff +
+ dyst->nmodtab * sizeof_dylib_module > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(modtaboff field plus nmodtab field times sizeof(%s) "
+ "of LC_DYSYMTAB command %lu extends past the end of "
+ "the file)", struct_dylib_module_name, i);
+ return(CHECK_BAD);
+ }
+ if(dyst->extrefsymoff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(extrefsymoff field of LC_DYSYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->extrefsymoff +
+ dyst->nextrefsyms * sizeof(struct dylib_reference) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(extrefsymoff field plus nextrefsyms field times "
+ "sizeof(struct dylib_reference) of LC_DYSYMTAB command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->indirectsymoff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(indirectsymoff field of LC_DYSYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->indirectsymoff +
+ dyst->nindirectsyms * sizeof(uint32_t) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(indirectsymoff field plus nindirectsyms field times "
+ "sizeof(uint32_t) of LC_DYSYMTAB command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->extreloff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(extreloff field of LC_DYSYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->extreloff +
+ dyst->nextrel * sizeof(struct relocation_info) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(extreloff field plus nextrel field times "
+ "sizeof(struct relocation_info) of LC_DYSYMTAB command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->locreloff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(locreloff field of LC_DYSYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(dyst->locreloff +
+ dyst->nlocrel * sizeof(struct relocation_info) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(locreloff field plus nlocrel field times "
+ "sizeof(struct relocation_info) of LC_DYSYMTAB command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_ROUTINES:
+ if(rc != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_ROUTINES command)");
+ return(CHECK_BAD);
+ }
+ rc = (struct routines_command *)lc;
+ if(swapped)
+ swap_routines_command(rc, host_byte_sex);
+ if(rc->cmdsize != sizeof(struct routines_command)){
+ Mach_O_error(ofile, "malformed object (LC_ROUTINES "
+ "command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_ROUTINES_64:
+ if(rc64 != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_ROUTINES_64 command)");
+ return(CHECK_BAD);
+ }
+ rc64 = (struct routines_command_64 *)lc;
+ if(swapped)
+ swap_routines_command_64(rc64, host_byte_sex);
+ if(rc64->cmdsize != sizeof(struct routines_command_64)){
+ Mach_O_error(ofile, "malformed object (LC_ROUTINES_64 "
+ "command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_TWOLEVEL_HINTS:
+ if(hints != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_TWOLEVEL_HINTS command)");
+ return(CHECK_BAD);
+ }
+ hints = (struct twolevel_hints_command *)lc;
+ if(swapped)
+ swap_twolevel_hints_command(hints, host_byte_sex);
+ if(hints->cmdsize != sizeof(struct twolevel_hints_command)){
+ Mach_O_error(ofile, "malformed object (LC_TWOLEVEL_HINTS "
+ "command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(hints->offset > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field of LC_TWOLEVEL_HINTS command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(hints->offset +
+ hints->nhints * sizeof(struct twolevel_hint) > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(offset field plus nhints field times "
+ "sizeof(struct twolevel_hint) of LC_TWOLEVEL_HINTS "
+ " command %lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_CODE_SIGNATURE:
+ if(code_sig != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_CODE_SIGNATURE command)");
+ return(CHECK_BAD);
+ }
+ code_sig = (struct linkedit_data_command *)lc;
+ if(swapped)
+ swap_linkedit_data_command(code_sig, host_byte_sex);
+ if(code_sig->cmdsize != sizeof(struct linkedit_data_command)){
+ Mach_O_error(ofile, "malformed object (LC_CODE_SIGNATURE "
+ "command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(code_sig->dataoff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(dataoff field of LC_CODE_SIGNATURE command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(code_sig->dataoff + code_sig->datasize > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(dataoff field plus datasize field of "
+ "LC_CODE_SIGNATURE command %lu extends past the end of "
+ "the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SEGMENT_SPLIT_INFO:
+ if(split_info != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_SEGMENT_SPLIT_INFO command)");
+ return(CHECK_BAD);
+ }
+ split_info = (struct linkedit_data_command *)lc;
+ if(swapped)
+ swap_linkedit_data_command(split_info, host_byte_sex);
+ if(split_info->cmdsize != sizeof(struct linkedit_data_command)){
+ Mach_O_error(ofile, "malformed object (LC_SEGMENT_SPLIT_"
+ "INFO command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(split_info->dataoff > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(dataoff field of LC_SEGMENT_SPLIT_INFO command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(split_info->dataoff + split_info->datasize > size){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(dataoff field plus datasize field of LC_SEGMENT_"
+ "SPLIT_INFO command %lu extends past the end of "
+ "the file)", i);
+ return(CHECK_BAD);
+ }
+ if((split_info->datasize % load_command_multiple) != 0){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(datasize field of LC_SEGMENT_SPLIT_INFO command %lu "
+ "is not a multple of %lu)", i, load_command_multiple);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_PREBIND_CKSUM:
+ if(cs != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_PREBIND_CKSUM command)");
+ return(CHECK_BAD);
+ }
+ cs = (struct prebind_cksum_command *)lc;
+ if(swapped)
+ swap_prebind_cksum_command(cs, host_byte_sex);
+ if(cs->cmdsize != sizeof(struct prebind_cksum_command)){
+ Mach_O_error(ofile, "malformed object (LC_PREBIND_CKSUM "
+ "command %lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_UUID:
+ if(uuid != NULL){
+ Mach_O_error(ofile, "malformed object (more than one "
+ "LC_UUID command)");
+ return(CHECK_BAD);
+ }
+ uuid = (struct uuid_command *)lc;
+ if(swapped)
+ swap_uuid_command(uuid, host_byte_sex);
+ if(uuid->cmdsize != sizeof(struct uuid_command)){
+ Mach_O_error(ofile, "malformed object (LC_UUID command %lu " "has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SYMSEG:
+ ss = (struct symseg_command *)lc;
+ if(swapped)
+ swap_symseg_command(ss, host_byte_sex);
+ if(ss->cmdsize != sizeof(struct symseg_command)){
+ Mach_O_error(ofile, "malformed object (LC_SYMSEG command "
+ "%lu has incorrect cmdsize)", i);
+ return(CHECK_BAD);
+ }
+ if(ss->offset > size){
+ Mach_O_error(ofile, "truncated or malformed object (offset "
+ "field of LC_SYMSEG command %lu extends past the end "
+ "of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(ss->offset + ss->size > size){
+ Mach_O_error(ofile, "truncated or malformed object (offset "
+ "field plus size field of LC_SYMTAB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_IDFVMLIB:
+ case LC_LOADFVMLIB:
+ fl = (struct fvmlib_command *)lc;
+ if(swapped)
+ swap_fvmlib_command(fl, host_byte_sex);
+ if(fl->cmdsize < sizeof(struct fvmlib_command)){
+ Mach_O_error(ofile, "malformed object (%s command %lu has "
+ "too small cmdsize field)", fl->cmd == LC_IDFVMLIB ?
+ "LC_IDFVMLIB" : "LC_LOADFVMLIB", i);
+ return(CHECK_BAD);
+ }
+ if(fl->fvmlib.name.offset >= fl->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (name."
+ "offset field of %s command %lu extends past the end "
+ "of the file)", fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB"
+ : "LC_LOADFVMLIB", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_ID_DYLIB:
+ cmd_name = "LC_ID_DYLIB";
+ goto check_dylib_command;
+ case LC_LOAD_DYLIB:
+ cmd_name = "LC_LOAD_DYLIB";
+ goto check_dylib_command;
+ case LC_LOAD_WEAK_DYLIB:
+ cmd_name = "LC_LOAD_WEAK_DYLIB";
+ goto check_dylib_command;
+ case LC_REEXPORT_DYLIB:
+ cmd_name = "LC_REEXPORT_DYLIB";
+ goto check_dylib_command;
+check_dylib_command:
+ dl = (struct dylib_command *)lc;
+ if(swapped)
+ swap_dylib_command(dl, host_byte_sex);
+ if(dl->cmdsize < sizeof(struct dylib_command)){
+ Mach_O_error(ofile, "malformed object (%s command %lu has "
+ "too small cmdsize field)", cmd_name, i);
+ return(CHECK_BAD);
+ }
+ if(dl->dylib.name.offset >= dl->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (name."
+ "offset field of %s command %lu extends past the end "
+ "of the file)", cmd_name, i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SUB_FRAMEWORK:
+ sub = (struct sub_framework_command *)lc;
+ if(swapped)
+ swap_sub_framework_command(sub, host_byte_sex);
+ if(sub->cmdsize < sizeof(struct sub_framework_command)){
+ Mach_O_error(ofile, "malformed object (LC_SUB_FRAMEWORK "
+ "command %lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(sub->umbrella.offset >= sub->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(umbrella.offset field of LC_SUB_FRAMEWORK command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SUB_UMBRELLA:
+ usub = (struct sub_umbrella_command *)lc;
+ if(swapped)
+ swap_sub_umbrella_command(usub, host_byte_sex);
+ if(usub->cmdsize < sizeof(struct sub_umbrella_command)){
+ Mach_O_error(ofile, "malformed object (LC_SUB_UMBRELLA "
+ "command %lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(usub->sub_umbrella.offset >= usub->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(sub_umbrella.offset field of LC_SUB_UMBRELLA command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SUB_LIBRARY:
+ lsub = (struct sub_library_command *)lc;
+ if(swapped)
+ swap_sub_library_command(lsub, host_byte_sex);
+ if(lsub->cmdsize < sizeof(struct sub_library_command)){
+ Mach_O_error(ofile, "malformed object (LC_SUB_LIBRARY "
+ "command %lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(lsub->sub_library.offset >= lsub->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(sub_library.offset field of LC_SUB_LIBRARY command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_SUB_CLIENT:
+ csub = (struct sub_client_command *)lc;
+ if(swapped)
+ swap_sub_client_command(csub, host_byte_sex);
+ if(csub->cmdsize < sizeof(struct sub_client_command)){
+ Mach_O_error(ofile, "malformed object (LC_SUB_CLIENT "
+ "command %lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(csub->client.offset >= csub->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(cleient.offset field of LC_SUB_CLIENT command "
+ "%lu extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_PREBOUND_DYLIB:
+ pbdylib = (struct prebound_dylib_command *)lc;
+ if(swapped)
+ swap_prebound_dylib_command(pbdylib, host_byte_sex);
+ if(pbdylib->cmdsize < sizeof(struct dylib_command)){
+ Mach_O_error(ofile, "malformed object (LC_PREBIND_DYLIB "
+ "command %lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(pbdylib->name.offset >= pbdylib->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (name."
+ "offset field of LC_PREBIND_DYLIB command %lu extends "
+ "past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (linked_"
+ "modules.offset field of LC_PREBIND_DYLIB command %lu "
+ "extends past the end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_ID_DYLINKER:
+ case LC_LOAD_DYLINKER:
+ dyld = (struct dylinker_command *)lc;
+ if(swapped)
+ swap_dylinker_command(dyld, host_byte_sex);
+ if(dyld->cmdsize < sizeof(struct dylinker_command)){
+ Mach_O_error(ofile, "malformed object (%s command %lu has "
+ "too small cmdsize field)",
+ dyld->cmd == LC_ID_DYLINKER ?
+ "LC_ID_DYLINKER" : "LC_LOAD_DYLINKER", i);
+ return(CHECK_BAD);
+ }
+ if(dyld->name.offset >= dyld->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (name."
+ "offset field of %s command %lu extends past the end "
+ "of the file)", dyld->cmd == LC_ID_DYLINKER ?
+ "LC_ID_DYLINKER" : "LC_LOAD_DYLINKER", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+ case LC_UNIXTHREAD:
+ case LC_THREAD:
+ ut = (struct thread_command *)lc;
+ if(swapped)
+ swap_thread_command(ut, host_byte_sex);
+ state = (char *)ut + sizeof(struct thread_command);
+
+ if(cputype == CPU_TYPE_MC680x0){
+ struct m68k_thread_state_regs *cpu;
+ struct m68k_thread_state_68882 *fpu;
+ struct m68k_thread_state_user_reg *user_reg;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M68K_THREAD_STATE_REGS:
+ if(count != M68K_THREAD_STATE_REGS_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M68K_THREAD_STATE_REGS_COUNT for "
+ "flavor number %u which is a M68K_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (struct m68k_thread_state_regs *)state;
+ if(swapped)
+ swap_m68k_thread_state_regs(cpu, host_byte_sex);
+ state += sizeof(struct m68k_thread_state_regs);
+ break;
+ case M68K_THREAD_STATE_68882:
+ if(count != M68K_THREAD_STATE_68882_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M68K_THREAD_STATE_68882_COUNT for "
+ "flavor number %u which is a M68K_THREAD_"
+ "STATE_68882 flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (struct m68k_thread_state_68882 *)state;
+ if(swapped)
+ swap_m68k_thread_state_68882(fpu,host_byte_sex);
+ state += sizeof(struct m68k_thread_state_68882);
+ break;
+ case M68K_THREAD_STATE_USER_REG:
+ if(count != M68K_THREAD_STATE_USER_REG_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M68K_THREAD_STATE_USER_REG_COUNT for "
+ "flavor number %u which is a M68K_THREAD_"
+ "STATE_USER_REG flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ user_reg =
+ (struct m68k_thread_state_user_reg *)state;
+ if(swapped)
+ swap_m68k_thread_state_user_reg(user_reg,
+ host_byte_sex);
+ state += sizeof(struct m68k_thread_state_user_reg);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_POWERPC ||
+ cputype == CPU_TYPE_VEO){
+ ppc_thread_state_t *nrw_cpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case PPC_THREAD_STATE:
+ if(count != PPC_THREAD_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not PPC_THREAD_STATE_COUNT for "
+ "flavor number %u which is a PPC_THREAD_"
+ "STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ nrw_cpu = (ppc_thread_state_t *)state;
+ if(swapped)
+ swap_ppc_thread_state_t(nrw_cpu,
+ host_byte_sex);
+ state += sizeof(ppc_thread_state_t);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+#ifdef PPC_THREAD_STATE64_COUNT
+ if(cputype == CPU_TYPE_POWERPC64){
+ ppc_thread_state64_t *cpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case PPC_THREAD_STATE64:
+ if(count != PPC_THREAD_STATE64_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not PPC_THREAD_STATE64_COUNT for "
+ "flavor number %u which is a PPC_THREAD_"
+ "STATE64 flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (ppc_thread_state64_t *)state;
+ if(swapped)
+ swap_ppc_thread_state64_t(cpu, host_byte_sex);
+ state += sizeof(ppc_thread_state64_t);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+#endif PPC_THREAD_STATE64_COUNT
+ if(cputype == CPU_TYPE_MC88000){
+ m88k_thread_state_grf_t *cpu;
+ m88k_thread_state_xrf_t *fpu;
+ m88k_thread_state_user_t *user;
+ m88110_thread_state_impl_t *spu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M88K_THREAD_STATE_GRF:
+ if(count != M88K_THREAD_STATE_GRF_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M88K_THREAD_STATE_GRF_COUNT for "
+ "flavor number %u which is a M88K_THREAD_"
+ "STATE_GRF flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (m88k_thread_state_grf_t *)state;
+ if(swapped)
+ swap_m88k_thread_state_grf_t(cpu,
+ host_byte_sex);
+ state += sizeof(m88k_thread_state_grf_t);
+ break;
+ case M88K_THREAD_STATE_XRF:
+ if(count != M88K_THREAD_STATE_XRF_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M88K_THREAD_STATE_XRF_COUNT for "
+ "flavor number %u which is a M88K_THREAD_"
+ "STATE_XRF flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (m88k_thread_state_xrf_t *)state;
+ if(swapped)
+ swap_m88k_thread_state_xrf_t(fpu,
+ host_byte_sex);
+ state += sizeof(m88k_thread_state_xrf_t);
+ break;
+ case M88K_THREAD_STATE_USER:
+ if(count != M88K_THREAD_STATE_USER_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M88K_THREAD_STATE_USER_COUNT for "
+ "flavor number %u which is a M88K_THREAD_"
+ "STATE_USER flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ user = (m88k_thread_state_user_t *)state;
+ if(swapped)
+ swap_m88k_thread_state_user_t(user,
+ host_byte_sex);
+ state += sizeof(m88k_thread_state_user_t);
+ break;
+ case M88110_THREAD_STATE_IMPL:
+ if(count != M88110_THREAD_STATE_IMPL_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not M88110_THREAD_STATE_IMPL_COUNT for "
+ "flavor number %u which is a M88110_THREAD"
+ "_STATE_IMPL flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ spu = (m88110_thread_state_impl_t *)state;
+ if(swapped)
+ swap_m88110_thread_state_impl_t(spu,
+ host_byte_sex);
+ state += sizeof(m88110_thread_state_impl_t);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I860){
+#ifdef m68k
+ struct i860_thread_state_regs *cpu;
+#endif
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case I860_THREAD_STATE_REGS:
+#ifdef m68k
+ if(count != I860_THREAD_STATE_REGS_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not I860_THREAD_STATE_REGS_COUNT for "
+ "flavor number %u which is a I860_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (struct i860_thread_state_regs *)state;
+ if(swapped)
+ swap_i860_thread_state_regs(cpu, host_byte_sex);
+ state += sizeof(struct i860_thread_state_regs);
+#else
+ state += count * sizeof(int);
+#endif
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I386){
+ i386_thread_state_t *cpu;
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ struct i386_float_state *fpu;
+ i386_exception_state_t *exc;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ i386_thread_fpstate_t *fpu;
+ i386_thread_exceptstate_t *exc;
+ i386_thread_cthreadstate_t *user;
+#endif /* i386_THREAD_STATE == -1 */
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case i386_THREAD_STATE:
+#if i386_THREAD_STATE == 1
+ case -1:
+#endif /* i386_THREAD_STATE == 1 */
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case 1:
+#endif /* i386_THREAD_STATE == -1 */
+ if(count != i386_THREAD_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not i386_THREAD_STATE_COUNT for flavor "
+ "number %u which is a i386_THREAD_STATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (i386_thread_state_t *)state;
+ if(swapped)
+ swap_i386_thread_state(cpu, host_byte_sex);
+ state += sizeof(i386_thread_state_t);
+ break;
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ case i386_FLOAT_STATE:
+ if(count != i386_FLOAT_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not i386_FLOAT_STATE_COUNT for flavor "
+ "number %u which is a i386_FLOAT_STATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (struct i386_float_state *)state;
+ if(swapped)
+ swap_i386_float_state(fpu, host_byte_sex);
+ state += sizeof(struct i386_float_state);
+ break;
+ case i386_EXCEPTION_STATE:
+ if(count != I386_EXCEPTION_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not I386_EXCEPTION_STATE_COUNT for "
+ "flavor number %u which is a i386_"
+ "EXCEPTION_STATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ exc = (i386_exception_state_t *)state;
+ if(swapped)
+ swap_i386_exception_state(exc,host_byte_sex);
+ state += sizeof(i386_exception_state_t);
+ break;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case i386_THREAD_FPSTATE:
+ if(count != i386_THREAD_FPSTATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not i386_THREAD_FPSTATE_COUNT for flavor "
+ "number %u which is a i386_THREAD_FPSTATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (i386_thread_fpstate_t *)state;
+ if(swapped)
+ swap_i386_thread_fpstate(fpu, host_byte_sex);
+ state += sizeof(i386_thread_fpstate_t);
+ break;
+ case i386_THREAD_EXCEPTSTATE:
+ if(count != i386_THREAD_EXCEPTSTATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not i386_THREAD_EXCEPTSTATE_COUNT for "
+ "flavor number %u which is a i386_THREAD_"
+ "EXCEPTSTATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ exc = (i386_thread_exceptstate_t *)state;
+ if(swapped)
+ swap_i386_thread_exceptstate(exc,host_byte_sex);
+ state += sizeof(i386_thread_exceptstate_t);
+ break;
+ case i386_THREAD_CTHREADSTATE:
+ if(count != i386_THREAD_CTHREADSTATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not i386_THREAD_CTHREADSTATE_COUNT for "
+ "flavor number %u which is a i386_THREAD_"
+ "CTHREADSTATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ user = (i386_thread_cthreadstate_t *)state;
+ if(swapped)
+ swap_i386_thread_cthreadstate(user,
+ host_byte_sex);
+ state += sizeof(i386_thread_cthreadstate_t);
+ break;
+#endif /* i386_THREAD_STATE == -1 */
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+#ifdef x86_THREAD_STATE64_COUNT
+ if(cputype == CPU_TYPE_X86_64){
+ x86_thread_state64_t *cpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case x86_THREAD_STATE64:
+ if(count != x86_THREAD_STATE64_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not x86_THREAD_STATE64_COUNT for "
+ "flavor number %u which is a x86_THREAD_"
+ "STATE64 flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (x86_thread_state64_t *)state;
+ if(swapped)
+ swap_x86_thread_state64(cpu, host_byte_sex);
+ state += sizeof(x86_thread_state64_t);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+#endif /* x86_THREAD_STATE64_COUNT */
+ if(cputype == CPU_TYPE_HPPA){
+ struct hp_pa_integer_thread_state *cpu;
+ struct hp_pa_frame_thread_state *frame;
+ struct hp_pa_fp_thread_state *fpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case HPPA_INTEGER_THREAD_STATE:
+ if(count != HPPA_INTEGER_THREAD_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not HPPA_INTEGER_THREAD_STATE_COUNT for "
+ "flavor number %u which is a "
+ "HPPA_INTEGER_THREAD_STATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (struct hp_pa_integer_thread_state *)state;
+ if(swapped)
+ swap_hppa_integer_thread_state(cpu,
+ host_byte_sex);
+ state += sizeof(struct hp_pa_integer_thread_state);
+ break;
+ case HPPA_FRAME_THREAD_STATE:
+ if(count != HPPA_FRAME_THREAD_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not HPPA_FRAME_THREAD_STATE_COUNT for "
+ "flavor number %u which is a HPPA_FRAME_"
+ "THREAD_STATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ frame = (struct hp_pa_frame_thread_state *)state;
+ if(swapped)
+ swap_hppa_frame_thread_state(frame,host_byte_sex);
+ state += sizeof(struct hp_pa_frame_thread_state);
+ break;
+ case HPPA_FP_THREAD_STATE:
+ if(count != HPPA_FP_THREAD_STATE_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not HPPA_FP_THREAD_STATE_COUNT for "
+ "flavor number %u which is a HPPA_FP_"
+ "THREAD_STATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (struct hp_pa_fp_thread_state *)state;
+ if(swapped)
+ swap_hppa_fp_thread_state(fpu,host_byte_sex);
+ state += sizeof(struct hp_pa_fp_thread_state);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_SPARC){
+ struct sparc_thread_state_regs *cpu;
+ struct sparc_thread_state_fpu *fpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ if(swapped){
+ flavor = SWAP_INT(flavor);
+ *((uint32_t *)state) = flavor;
+ }
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ if(swapped){
+ count = SWAP_INT(count);
+ *((uint32_t *)state) = count;
+ }
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case SPARC_THREAD_STATE_REGS:
+ if(count != SPARC_THREAD_STATE_REGS_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not SPARC_THREAD_STATE_REGS_COUNT for "
+ "flavor number %u which is a SPARC_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ cpu = (struct sparc_thread_state_regs *)state;
+ if(swapped)
+ swap_sparc_thread_state_regs(cpu, host_byte_sex);
+ state += sizeof(struct sparc_thread_state_regs);
+ break;
+ case SPARC_THREAD_STATE_FPU:
+ if(count != SPARC_THREAD_STATE_FPU_COUNT){
+ Mach_O_error(ofile, "malformed object (count "
+ "not SPARC_THREAD_STATE_FPU_COUNT for "
+ "flavor number %u which is a SPARC_THREAD_"
+ "STATE_FPU flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ fpu = (struct sparc_thread_state_fpu *)state;
+ if(swapped)
+ swap_sparc_thread_state_fpu(fpu, host_byte_sex);
+ state += sizeof(struct sparc_thread_state_fpu);
+ break;
+ default:
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown "
+ "flavor for flavor number %u in %s command"
+ " %lu can't byte swap it)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ state += count * sizeof(long);
+ break;
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(swapped){
+ Mach_O_error(ofile, "malformed object (unknown cputype and "
+ "cpusubtype of object and can't byte swap and check %s "
+ "command %lu)", ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(CHECK_BAD);
+ }
+ break;
+ case LC_IDENT:
+ id = (struct ident_command *)lc;
+ if(swapped)
+ swap_ident_command(id, host_byte_sex);
+ if((char *)id + id->cmdsize >
+ (char *)load_commands + sizeofcmds){
+ Mach_O_error(ofile, "truncated or malformed object (cmdsize"
+ "field of LC_IDENT command %lu extends past the end of "
+ "the load commands)", i);
+ return(CHECK_BAD);
+ }
+ break;
+ case LC_RPATH:
+ rpath = (struct rpath_command *)lc;
+ if(swapped)
+ swap_rpath_command(rpath, host_byte_sex);
+ if(rpath->cmdsize < sizeof(struct rpath_command)){
+ Mach_O_error(ofile, "malformed object (LC_RPATH command "
+ "%lu has too small cmdsize field)", i);
+ return(CHECK_BAD);
+ }
+ if(rpath->path.offset >= rpath->cmdsize){
+ Mach_O_error(ofile, "truncated or malformed object (path."
+ "offset field of LC_RPATH command %lu extends past the "
+ "end of the file)", i);
+ return(CHECK_BAD);
+ }
+ break;
+
+#ifndef OFI
+ default:
+ Mach_O_error(ofile, "malformed object (unknown load command "
+ "%lu)", i);
+ return(CHECK_BAD);
+#endif /* !defined(OFI) */
+ }
+
+ lc = (struct load_command *)((char *)lc + l.cmdsize);
+ /* check that next load command does not extends past the end */
+ if((char *)lc > (char *)load_commands + sizeofcmds){
+ Mach_O_error(ofile, "truncated or malformed object (load "
+ "command %lu extends past the end of the file)",
+ i + 1);
+ return(CHECK_BAD);
+ }
+ }
+ if(st == NULL){
+ if(dyst != NULL){
+ Mach_O_error(ofile, "truncated or malformed object (contains "
+ "LC_DYSYMTAB load command without a LC_SYMTAB load command)");
+ return(CHECK_BAD);
+ }
+ }
+ else{
+ if(dyst != NULL){
+ if(dyst->nlocalsym != 0 &&
+ dyst->ilocalsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(ilocalsym in LC_DYSYMTAB load command extends past "
+ "the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+ if(dyst->nlocalsym != 0 &&
+ dyst->ilocalsym + dyst->nlocalsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(ilocalsym plus nlocalsym in LC_DYSYMTAB load command "
+ "extends past the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+
+ if(dyst->nextdefsym != 0 &&
+ dyst->iextdefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(iextdefsym in LC_DYSYMTAB load command extends past "
+ "the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+ if(dyst->nextdefsym != 0 &&
+ dyst->iextdefsym + dyst->nextdefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(iextdefsym plus nextdefsym in LC_DYSYMTAB load "
+ "command extends past the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+
+ if(dyst->nundefsym != 0 &&
+ dyst->iundefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(iundefsym in LC_DYSYMTAB load command extends past "
+ "the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+ if(dyst->nundefsym != 0 &&
+ dyst->iundefsym + dyst->nundefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object "
+ "(iundefsym plus nundefsym in LC_DYSYMTAB load command "
+ "extends past the end of the symbol table)");
+ return(CHECK_BAD);
+ }
+ if(rc != NULL){
+ if(rc->init_module > dyst->nmodtab){
+ Mach_O_error(ofile, "malformed object (init_module in "
+ "LC_ROUTINES load command extends past the "
+ "end of the module table)");
+ return(CHECK_BAD);
+ }
+ }
+ if(rc64 != NULL){
+ if(rc64->init_module > dyst->nmodtab){
+ Mach_O_error(ofile, "malformed object (init_module in "
+ "LC_ROUTINES_64 load command extends past the "
+ "end of the module table)");
+ return(CHECK_BAD);
+ }
+ }
+ if(hints != NULL){
+ if(hints->nhints != dyst->nundefsym){
+ Mach_O_error(ofile, "malformed object (nhints in "
+ "LC_TWOLEVEL_HINTS load command not the same as "
+ "nundefsym in LC_DYSYMTAB load command)");
+ return(CHECK_BAD);
+ }
+ }
+ }
+ }
+ /* check for an inconsistent size of the load commands */
+ if((char *)load_commands + sizeofcmds != (char *)lc){
+ Mach_O_error(ofile, "malformed object (inconsistent sizeofcmds "
+ "field in mach header)");
+ return(CHECK_BAD);
+ }
+
+ /*
+ * Mark this ofile so we know its headers have been swapped. We do this
+ * in case we don't process it the first time so we can swap them back
+ * in case we loop back to it in a fat file to process it later.
+ */
+ if(swapped == TRUE)
+ ofile->headers_swapped = TRUE;
+
+ /* looks good return ok */
+ return(CHECK_GOOD);
+#endif /* OTOOL */
+}
+
+/*
+ * swap_back_Mach_O() is called after the ofile has been processed to swap back
+ * the mach header and load commands if check_Mach_O() above swapped them.
+ */
+static
+void
+swap_back_Mach_O(
+struct ofile *ofile)
+{
+ if(ofile->headers_swapped == TRUE){
+ ofile->headers_swapped = FALSE;
+ if(ofile->mh != NULL)
+ swap_object_headers(ofile->mh, ofile->load_commands);
+ else if(ofile->mh64 != NULL)
+ swap_object_headers(ofile->mh64, ofile->load_commands);
+ }
+}
+
+
+/*
+ * check_dylib_module() checks the object file's dylib_module as referenced
+ * by the dylib_module field in the ofile for correctness.
+ */
+static
+enum check_type
+check_dylib_module(
+struct ofile *ofile,
+struct symtab_command *st,
+struct dysymtab_command *dyst,
+char *strings,
+unsigned long module_index)
+{
+#ifdef OTOOL
+ return(CHECK_GOOD);
+#else /* !defined OTOOL */
+ unsigned long i;
+ enum byte_sex host_byte_sex;
+ enum bool swapped;
+ struct dylib_module m;
+ struct dylib_module_64 m64;
+ uint32_t module_name, nextdefsym, iextdefsym, nlocalsym, ilocalsym, nrefsym;
+ uint32_t irefsym, nextrel, iextrel;
+
+ host_byte_sex = get_host_byte_sex();
+ swapped = (enum bool)(host_byte_sex != ofile->object_byte_sex);
+ if(ofile->mh != NULL){
+ m = *ofile->dylib_module;
+ if(swapped)
+ swap_dylib_module(&m, 1, host_byte_sex);
+ module_name = m.module_name;
+ nextdefsym = m.nextdefsym;
+ iextdefsym = m.iextdefsym;
+ nlocalsym = m.nlocalsym;
+ ilocalsym = m.ilocalsym;
+ nrefsym = m.nrefsym;
+ irefsym = m.irefsym;
+ nextrel = m.nextrel;
+ iextrel = m.iextrel;
+ }
+ else{
+ m64 = *ofile->dylib_module64;
+ if(swapped)
+ swap_dylib_module_64(&m64, 1, host_byte_sex);
+ module_name = m64.module_name;
+ nextdefsym = m64.nextdefsym;
+ iextdefsym = m64.iextdefsym;
+ nlocalsym = m64.nlocalsym;
+ ilocalsym = m64.ilocalsym;
+ nrefsym = m64.nrefsym;
+ irefsym = m64.irefsym;
+ nextrel = m64.nextrel;
+ iextrel = m64.iextrel;
+ }
+
+ if(module_name > st->strsize){
+ Mach_O_error(ofile, "truncated or malformed object (module_name "
+ "of module table entry %lu past the end of the string table)",
+ module_index);
+ return(CHECK_BAD);
+ }
+ for(i = module_name; i < st->strsize && strings[i] != '\0'; i++)
+ ;
+ if(i >= st->strsize){
+ Mach_O_error(ofile, "truncated or malformed object (module_name "
+ "of module table entry %lu extends past the end of the string "
+ "table)", module_index);
+ return(CHECK_BAD);
+ }
+
+ if(nextdefsym != 0){
+ if(iextdefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object (iextdefsym "
+ "field of module table entry %lu past the end of the "
+ "symbol table", module_index);
+ return(CHECK_BAD);
+ }
+ if(iextdefsym + nextdefsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object (iextdefsym "
+ "field of module table entry %lu plus nextdefsym field "
+ "extends past the end of the symbol table", module_index);
+ return(CHECK_BAD);
+ }
+ }
+ if(nlocalsym != 0){
+ if(ilocalsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object (ilocalsym "
+ "field of module table entry %lu past the end of the "
+ "symbol table", module_index);
+ return(CHECK_BAD);
+ }
+ if(ilocalsym + nlocalsym > st->nsyms){
+ Mach_O_error(ofile, "truncated or malformed object (ilocalsym "
+ "field of module table entry %lu plus nlocalsym field "
+ "extends past the end of the symbol table", module_index);
+ return(CHECK_BAD);
+ }
+ }
+ if(nrefsym != 0){
+ if(irefsym > dyst->nextrefsyms){
+ Mach_O_error(ofile, "truncated or malformed object (irefsym "
+ "field of module table entry %lu past the end of the "
+ "reference table", module_index);
+ return(CHECK_BAD);
+ }
+ if(irefsym + nrefsym > dyst->nextrefsyms){
+ Mach_O_error(ofile, "truncated or malformed object (irefsym "
+ "field of module table entry %lu plus nrefsym field "
+ "extends past the end of the reference table",module_index);
+ return(CHECK_BAD);
+ }
+ }
+ if(nextrel != 0){
+ if(iextrel > dyst->extreloff){
+ Mach_O_error(ofile, "truncated or malformed object (iextrel "
+ "field of module table entry %lu past the end of the "
+ "external relocation enrties", module_index);
+ return(CHECK_BAD);
+ }
+ if(iextrel + nextrel > dyst->extreloff){
+ Mach_O_error(ofile, "truncated or malformed object (iextrel "
+ "field of module table entry %lu plus nextrel field "
+ "extends past the end of the external relocation enrties",
+ module_index);
+ return(CHECK_BAD);
+ }
+ }
+ return(CHECK_GOOD);
+#endif /* OTOOL */
+}
+
+__private_extern__
+unsigned long
+size_ar_name(
+const struct ar_hdr *ar_hdr)
+{
+ long i;
+
+ i = sizeof(ar_hdr->ar_name) - 1;
+ if(ar_hdr->ar_name[i] == ' '){
+ do{
+ if(ar_hdr->ar_name[i] != ' ')
+ break;
+ i--;
+ }while(i > 0);
+ }
+ return(i + 1);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/ofile_error.c
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdarg.h>
+#include "stuff/ofile.h"
+#include "stuff/print.h"
+#include "stuff/errors.h"
+
+__private_extern__
+void
+archive_error(
+struct ofile *ofile,
+const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(ofile->file_type == OFILE_FAT){
+ print("%s: for architecture %s archive: %s ",
+ progname, ofile->arch_flag.name, ofile->file_name);
+ }
+ else{
+ print("%s: archive: %s ", progname, ofile->file_name);
+ }
+ vprint(format, ap);
+ print("\n");
+ va_end(ap);
+ errors++;
+}
+
+__private_extern__
+void
+archive_member_error(
+struct ofile *ofile,
+const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(ofile->file_type == OFILE_FAT){
+ print("%s: for architecture %s archive member: %s(%.*s) ",
+ progname, ofile->arch_flag.name, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ else{
+ print("%s: archive member: %s(%.*s) ", progname, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ vprint(format, ap);
+ print("\n");
+ va_end(ap);
+ errors++;
+}
+
+#ifndef OTOOL
+__private_extern__
+void
+Mach_O_error(
+struct ofile *ofile,
+const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ if(ofile->file_type == OFILE_FAT){
+ if(ofile->arch_type == OFILE_ARCHIVE){
+ print("%s: for architecture %s object: %s(%.*s) ", progname,
+ ofile->arch_flag.name, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ else{
+ print("%s: for architecture %s object: %s ", progname,
+ ofile->arch_flag.name, ofile->file_name);
+ }
+ }
+ else if(ofile->file_type == OFILE_ARCHIVE){
+ if(ofile->member_type == OFILE_FAT){
+ print("%s: for object: %s(%.*s) architecture %s ", progname,
+ ofile->file_name, (int)ofile->member_name_size,
+ ofile->arch_flag.name, ofile->member_name);
+ }
+ else{
+ print("%s: object: %s(%.*s) ", progname, ofile->file_name,
+ (int)ofile->member_name_size, ofile->member_name);
+ }
+ }
+ else{
+ print("%s: object: %s ", progname, ofile->file_name);
+ }
+ vprint(format, ap);
+ print("\n");
+ va_end(ap);
+ errors++;
+}
+#endif /* !defined(OTOOL) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/print.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdio.h>
+#include <stdarg.h>
+#include "stuff/print.h"
+
+/*
+ * All printing of all messages for ofile functions goes through this function.
+ * It is broken out here so it can be overridden for some uses.
+ */
+__private_extern__
+void
+vprint(
+const char *format,
+va_list ap)
+{
+ vfprintf(stderr, format, ap);
+}
+
+/*
+ * The print function that just calls the above vprint() function.
+ */
+__private_extern__
+void
+print(
+const char *format,
+...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+ vprint(format, ap);
+ va_end(ap);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/reloc.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <mach/machine.h>
+#include <mach-o/reloc.h>
+#include <mach-o/m88k/reloc.h>
+#include <mach-o/ppc/reloc.h>
+#include <mach-o/i860/reloc.h>
+#include <mach-o/hppa/reloc.h>
+#include <mach-o/sparc/reloc.h>
+#include <mach-o/x86_64/reloc.h>
+#include "stuff/bool.h"
+#include "stuff/errors.h"
+#include "stuff/reloc.h"
+
+/*
+ * reloc_pair_r_type() returns the PAIR constant for the specific cputype for
+ * a paired relocation entry.
+ */
+__private_extern__
+unsigned long
+reloc_pair_r_type(
+cpu_type_t cputype)
+{
+ switch(cputype){
+ case CPU_TYPE_MC680x0:
+ case CPU_TYPE_I386:
+ return(GENERIC_RELOC_PAIR);
+ break;
+ case CPU_TYPE_X86_64:
+ /*
+ * We should never hit this case for x86-64, so drop down to the
+ * fatal error below.
+ */
+ break;
+ case CPU_TYPE_MC88000:
+ return(M88K_RELOC_PAIR);
+ break;
+ case CPU_TYPE_I860:
+ return(I860_RELOC_PAIR);
+ break;
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ case CPU_TYPE_VEO:
+ return(PPC_RELOC_PAIR);
+ break;
+ case CPU_TYPE_HPPA:
+ return(HPPA_RELOC_PAIR);
+ break;
+ case CPU_TYPE_SPARC:
+ return(SPARC_RELOC_PAIR);
+ break;
+ }
+ fatal("internal error: reloc_pair_r_type() called with unknown "
+ "cputype (%u)", cputype);
+ /* can't get here but to shut up the compiler warning ... */
+ return(0);
+}
+
+/*
+ * reloc_has_pair() returns TRUE if the specified r_type for the specified
+ * cputype for has a paired relocation entry.
+ */
+__private_extern__
+enum bool
+reloc_has_pair(
+cpu_type_t cputype,
+unsigned long r_type)
+{
+ switch(cputype){
+ case CPU_TYPE_MC680x0:
+ case CPU_TYPE_I386:
+ if(r_type == GENERIC_RELOC_SECTDIFF ||
+ r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_X86_64:
+ return(FALSE);
+ break;
+ case CPU_TYPE_MC88000:
+ if(r_type == M88K_RELOC_HI16 ||
+ r_type == M88K_RELOC_LO16 ||
+ r_type == M88K_RELOC_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_I860:
+ if(r_type == I860_RELOC_HIGH ||
+ r_type == I860_RELOC_HIGHADJ ||
+ r_type == I860_RELOC_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ case CPU_TYPE_VEO:
+ if(r_type == PPC_RELOC_HI16 ||
+ r_type == PPC_RELOC_LO16 ||
+ r_type == PPC_RELOC_HA16 ||
+ r_type == PPC_RELOC_LO14 ||
+ r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_LOCAL_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
+ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF ||
+ r_type == PPC_RELOC_JBSR)
+ return(TRUE);
+ break;
+ case CPU_TYPE_HPPA:
+ if(r_type == HPPA_RELOC_HI21 ||
+ r_type == HPPA_RELOC_LO14 ||
+ r_type == HPPA_RELOC_BR17 ||
+ r_type == HPPA_RELOC_JBSR ||
+ r_type == HPPA_RELOC_SECTDIFF ||
+ r_type == HPPA_RELOC_HI21_SECTDIFF ||
+ r_type == HPPA_RELOC_LO14_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_SPARC:
+ if (r_type == SPARC_RELOC_HI22 ||
+ r_type == SPARC_RELOC_LO10 ||
+ r_type == SPARC_RELOC_HI22_SECTDIFF ||
+ r_type == SPARC_RELOC_LO10_SECTDIFF ||
+ r_type == SPARC_RELOC_SECTDIFF)
+ return(TRUE);
+ break;
+ default:
+ fatal("internal error: reloc_has_pair() called with unknown "
+ "cputype (%u)", cputype);
+ }
+ return(FALSE);
+}
+
+/*
+ * reloc_is_sectdiff() returns TRUE if the specified r_type for the specified
+ * cputype is a section difference relocation type.
+ */
+__private_extern__
+enum bool
+reloc_is_sectdiff(
+cpu_type_t cputype,
+unsigned long r_type)
+{
+ switch(cputype){
+ case CPU_TYPE_MC680x0:
+ case CPU_TYPE_I386:
+ if(r_type == GENERIC_RELOC_SECTDIFF ||
+ r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_X86_64:
+ /* No sectdiff relocs for x86-64. */
+ return(FALSE);
+ break;
+ case CPU_TYPE_MC88000:
+ if(r_type == M88K_RELOC_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_I860:
+ if(r_type == I860_RELOC_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_VEO:
+ if(r_type == PPC_RELOC_SECTDIFF ||
+ r_type == PPC_RELOC_LOCAL_SECTDIFF ||
+ r_type == PPC_RELOC_HI16_SECTDIFF ||
+ r_type == PPC_RELOC_LO16_SECTDIFF ||
+ r_type == PPC_RELOC_LO14_SECTDIFF ||
+ r_type == PPC_RELOC_HA16_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_HPPA:
+ if(r_type == HPPA_RELOC_SECTDIFF ||
+ r_type == HPPA_RELOC_HI21_SECTDIFF ||
+ r_type == HPPA_RELOC_LO14_SECTDIFF)
+ return(TRUE);
+ break;
+ case CPU_TYPE_SPARC:
+ if(r_type == SPARC_RELOC_SECTDIFF ||
+ r_type == SPARC_RELOC_HI22_SECTDIFF ||
+ r_type == SPARC_RELOC_LO10_SECTDIFF)
+ return(TRUE);
+ break;
+ default:
+ fatal("internal error: reloc_is_sectdiff() called with unknown "
+ "cputype (%u)", cputype);
+ }
+ return(FALSE);
+}
+
+
+
+
+
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/round.c
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2004, Apple Computer, Inc. All rights reserved.
+ *
+ * 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. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
+ * its contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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 "stuff/round.h"
+/*
+ * round() rounds v to a multiple of r.
+ */
+__private_extern__
+unsigned long
+round(
+unsigned long v,
+unsigned long r)
+{
+ r--;
+ v += r;
+ v &= ~(long)r;
+ return(v);
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/set_arch_flag_name.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdio.h>
+#include "stuff/arch.h"
+#include "stuff/allocate.h"
+
+/*
+ * set_arch_flag_name() sets the name field of the specified arch_flag to
+ * match it's cputype and cpusubtype. The string is allocated via malloc by
+ * the routines in "allocate.h" and errors are handled by the routines in
+ * "error.h".
+ */
+__private_extern__
+void
+set_arch_flag_name(
+struct arch_flag *p)
+{
+ const struct arch_flag *arch_flag;
+
+ arch_flag = get_arch_flags();
+ while(arch_flag->name != NULL){
+ if(arch_flag->cputype == p->cputype &&
+ (arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (p->cpusubtype & ~CPU_SUBTYPE_MASK)){
+ p->name = savestr(arch_flag->name);
+ break;
+ }
+ arch_flag++;
+ }
+ if(p->name == NULL){
+ p->name = savestr("cputype (1234567890) cpusubtype (1234567890)");
+ sprintf(p->name, "cputype (%d) cpusubtype (%d)",
+ p->cputype, p->cpusubtype);
+ }
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/swap_headers.c
@@ -0,0 +1,1458 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#define __darwin_i386_exception_state i386_exception_state
+#define __darwin_i386_float_state i386_float_state
+#define __darwin_i386_thread_state i386_thread_state
+
+#include <mach-o/loader.h>
+#include <mach/m68k/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/ppc/thread_status.h>
+#undef MACHINE_THREAD_STATE /* need to undef these to avoid warnings */
+#undef MACHINE_THREAD_STATE_COUNT
+#undef THREAD_STATE_NONE
+#undef VALID_THREAD_STATE_FLAVOR
+#include <mach/m88k/thread_status.h>
+#include <mach/i860/thread_status.h>
+#include <mach/i386/thread_status.h>
+#include <mach/hppa/thread_status.h>
+#include <mach/sparc/thread_status.h>
+#include "stuff/bool.h"
+#include "stuff/bytesex.h"
+#include "stuff/errors.h"
+
+/*
+ * swap_object_headers() swaps the object file headers from the host byte sex
+ * into the non-host byte sex. It returns TRUE if it can and did swap the
+ * headers else returns FALSE and does not touch the headers and prints an error
+ * using the error() routine.
+ */
+__private_extern__
+enum bool
+swap_object_headers(
+void *mach_header,
+struct load_command *load_commands)
+{
+ unsigned long i;
+ uint32_t magic, ncmds, sizeofcmds, cmd_multiple;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ struct mach_header *mh;
+ struct mach_header_64 *mh64;
+ enum byte_sex target_byte_sex;
+ struct load_command *lc, l;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct section *s;
+ struct section_64 *s64;
+ struct symtab_command *st;
+ struct dysymtab_command *dyst;
+ struct symseg_command *ss;
+ struct fvmlib_command *fl;
+ struct thread_command *ut;
+ struct ident_command *id;
+ struct dylib_command *dl;
+ struct sub_framework_command *sub;
+ struct sub_umbrella_command *usub;
+ struct sub_library_command *lsub;
+ struct sub_client_command *csub;
+ struct prebound_dylib_command *pbdylib;
+ struct dylinker_command *dyld;
+ struct routines_command *rc;
+ struct routines_command_64 *rc64;
+ struct twolevel_hints_command *hints;
+ struct prebind_cksum_command *cs;
+ struct uuid_command *uuid;
+ struct linkedit_data_command *ld;
+ struct rpath_command *rpath;
+ uint32_t flavor, count;
+ unsigned long nflavor;
+ char *p, *state, *cmd_name;
+
+ magic = *((uint32_t *)mach_header);
+ if(magic == MH_MAGIC){
+ mh = (struct mach_header *)mach_header;
+ ncmds = mh->ncmds;
+ sizeofcmds = mh->sizeofcmds;
+ cputype = mh->cputype;
+ cpusubtype = mh->cpusubtype;
+ cmd_multiple = 4;
+ mh64 = NULL;
+ }
+ else{
+ mh64 = (struct mach_header_64 *)mach_header;
+ ncmds = mh64->ncmds;
+ sizeofcmds = mh64->sizeofcmds;
+ cputype = mh64->cputype;
+ cpusubtype = mh64->cpusubtype;
+ cmd_multiple = 8;
+ mh = NULL;
+ }
+ /*
+ * Make a pass through the load commands checking them to the level
+ * that they can be parsed and then swapped.
+ */
+ for(i = 0, lc = load_commands; i < ncmds; i++){
+ l = *lc;
+ /* check load command size for a correct multiple size */
+ if(lc->cmdsize % cmd_multiple != 0){
+ error("in swap_object_headers(): malformed load command %lu "
+ "(cmdsize not a multiple of %u)", i, cmd_multiple);
+ return(FALSE);
+ }
+ /* check that load command does not extends past end of commands */
+ if((char *)lc + lc->cmdsize >
+ (char *)load_commands + sizeofcmds){
+ error("in swap_object_headers(): truncated or malformed load "
+ "command %lu (extends past the end of the all load "
+ "commands)", i);
+ return(FALSE);
+ }
+ /* check that the load command size is not zero */
+ if(lc->cmdsize == 0){
+ error("in swap_object_headers(): malformed load command %lu "
+ "(cmdsize is zero)", i);
+ return(FALSE);
+ }
+ switch(lc->cmd){
+ case LC_SEGMENT:
+ sg = (struct segment_command *)lc;
+ if(sg->cmdsize != sizeof(struct segment_command) +
+ sg->nsects * sizeof(struct section)){
+ error("in swap_object_headers(): malformed load command "
+ "(inconsistent cmdsize in LC_SEGMENT command %lu for "
+ "the number of sections)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SEGMENT_64:
+ sg64 = (struct segment_command_64 *)lc;
+ if(sg64->cmdsize != sizeof(struct segment_command_64) +
+ sg64->nsects * sizeof(struct section_64)){
+ error("in swap_object_headers(): malformed load command "
+ "(inconsistent cmdsize in LC_SEGMENT_64 command %lu "
+ "for the number of sections)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SYMTAB:
+ st = (struct symtab_command *)lc;
+ if(st->cmdsize != sizeof(struct symtab_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SYMTAB command %lu has incorrect cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_DYSYMTAB:
+ dyst = (struct dysymtab_command *)lc;
+ if(dyst->cmdsize != sizeof(struct dysymtab_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_DYSYMTAB command %lu has incorrect cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SYMSEG:
+ ss = (struct symseg_command *)lc;
+ if(ss->cmdsize != sizeof(struct symseg_command)){
+ error("in swap_object_headers(): malformed load command "
+ "(LC_SYMSEG command %lu has incorrect cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_IDFVMLIB:
+ case LC_LOADFVMLIB:
+ fl = (struct fvmlib_command *)lc;
+ if(fl->cmdsize < sizeof(struct fvmlib_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(%s command %lu has too small cmdsize field)",
+ fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" :
+ "LC_LOADFVMLIB", i);
+ return(FALSE);
+ }
+ if(fl->fvmlib.name.offset >= fl->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (name.offset field of %s command %lu "
+ "extends past the end of all load commands)",
+ fl->cmd == LC_IDFVMLIB ? "LC_IDFVMLIB" :
+ "LC_LOADFVMLIB", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_ID_DYLIB:
+ cmd_name = "LC_ID_DYLIB";
+ goto check_dylib_command;
+ case LC_LOAD_DYLIB:
+ cmd_name = "LC_LOAD_DYLIB";
+ goto check_dylib_command;
+ case LC_LOAD_WEAK_DYLIB:
+ cmd_name = "LC_LOAD_WEAK_DYLIB";
+ goto check_dylib_command;
+ case LC_REEXPORT_DYLIB:
+ cmd_name = "LC_REEXPORT_DYLIB";
+ goto check_dylib_command;
+check_dylib_command:
+ dl = (struct dylib_command *)lc;
+ if(dl->cmdsize < sizeof(struct dylib_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(%s command %lu has too small cmdsize field)",
+ cmd_name, i);
+ return(FALSE);
+ }
+ if(dl->dylib.name.offset >= dl->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (name.offset field of %s command %lu "
+ "extends past the end of all load commands)",
+ cmd_name, i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SUB_FRAMEWORK:
+ sub = (struct sub_framework_command *)lc;
+ if(sub->cmdsize < sizeof(struct sub_framework_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SUB_FRAMEWORK command %lu has too small cmdsize "
+ "field)", i);
+ return(FALSE);
+ }
+ if(sub->umbrella.offset >= sub->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (umbrella.offset field of "
+ "LC_SUB_FRAMEWORK command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SUB_UMBRELLA:
+ usub = (struct sub_umbrella_command *)lc;
+ if(usub->cmdsize < sizeof(struct sub_umbrella_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SUB_UMBRELLA command %lu has too small cmdsize "
+ "field)", i);
+ return(FALSE);
+ }
+ if(usub->sub_umbrella.offset >= usub->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (sub_umbrella.offset field of "
+ "LC_SUB_UMBRELLA command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SUB_LIBRARY:
+ lsub = (struct sub_library_command *)lc;
+ if(lsub->cmdsize < sizeof(struct sub_library_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SUB_LIBRARY command %lu has too small cmdsize "
+ "field)", i);
+ return(FALSE);
+ }
+ if(lsub->sub_library.offset >= lsub->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (sub_library.offset field of "
+ "LC_SUB_LIBRARY command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SUB_CLIENT:
+ csub = (struct sub_client_command *)lc;
+ if(csub->cmdsize < sizeof(struct sub_client_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SUB_CLIENT command %lu has too small cmdsize "
+ "field)", i);
+ return(FALSE);
+ }
+ if(csub->client.offset >= csub->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (client.offset field of "
+ "LC_SUB_CLIENT command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_PREBOUND_DYLIB:
+ pbdylib = (struct prebound_dylib_command *)lc;
+ if(pbdylib->cmdsize < sizeof(struct prebound_dylib_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_PREBOUND_DYLIB command %lu has too small "
+ "cmdsize field)", i);
+ return(FALSE);
+ }
+ if(pbdylib->name.offset >= pbdylib->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (name.offset field of "
+ "LC_PREBOUND_DYLIB command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ if(pbdylib->linked_modules.offset >= pbdylib->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (linked_modules.offset field of "
+ "LC_PREBOUND_DYLIB command %lu extends past the end "
+ "of all load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_ID_DYLINKER:
+ case LC_LOAD_DYLINKER:
+ dyld = (struct dylinker_command *)lc;
+ if(dyld->cmdsize < sizeof(struct dylinker_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(%s command %lu has too small cmdsize field)",
+ dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" :
+ "LC_LOAD_DYLINKER", i);
+ return(FALSE);
+ }
+ if(dyld->name.offset >= dyld->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (name.offset field of %s command %lu "
+ "extends past the end of all load commands)",
+ dyld->cmd == LC_ID_DYLINKER ? "LC_ID_DYLINKER" :
+ "LC_LOAD_DYLINKER", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_UNIXTHREAD:
+ case LC_THREAD:
+ ut = (struct thread_command *)lc;
+ state = (char *)ut + sizeof(struct thread_command);
+
+ if(cputype == CPU_TYPE_MC680x0){
+ struct m68k_thread_state_regs *cpu;
+ struct m68k_thread_state_68882 *fpu;
+ struct m68k_thread_state_user_reg *user_reg;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M68K_THREAD_STATE_REGS:
+ if(count != M68K_THREAD_STATE_REGS_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M68K_THREAD_STATE_REGS_COUNT for "
+ "flavor number %lu which is a M68K_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (struct m68k_thread_state_regs *)state;
+ state += sizeof(struct m68k_thread_state_regs);
+ break;
+ case M68K_THREAD_STATE_68882:
+ if(count != M68K_THREAD_STATE_68882_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M68K_THREAD_STATE_68882_COUNT for "
+ "flavor number %lu which is a M68K_THREAD_"
+ "STATE_68882 flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (struct m68k_thread_state_68882 *)state;
+ state += sizeof(struct m68k_thread_state_68882);
+ break;
+ case M68K_THREAD_STATE_USER_REG:
+ if(count != M68K_THREAD_STATE_USER_REG_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M68K_THREAD_STATE_USER_REG_COUNT for "
+ "flavor number %lu which is a M68K_THREAD_"
+ "STATE_USER_REG flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ user_reg =
+ (struct m68k_thread_state_user_reg *)state;
+ state += sizeof(struct m68k_thread_state_user_reg);
+ break;
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_POWERPC ||
+ cputype == CPU_TYPE_VEO ||
+ cputype == CPU_TYPE_POWERPC64){
+ ppc_thread_state_t *cpu;
+ ppc_float_state_t *fpu;
+ ppc_exception_state_t *except;
+ ppc_thread_state64_t *cpu64;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case PPC_THREAD_STATE:
+ if(count != PPC_THREAD_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not PPC_THREAD_STATE_COUNT for "
+ "flavor number %lu which is a PPC_THREAD_"
+ "STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (ppc_thread_state_t *)state;
+ state += sizeof(ppc_thread_state_t);
+ break;
+ case PPC_FLOAT_STATE:
+ if(count != PPC_FLOAT_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not PPC_FLOAT_STATE_COUNT for "
+ "flavor number %lu which is a PPC_FLOAT_"
+ "STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (ppc_float_state_t *)state;
+ state += sizeof(ppc_float_state_t);
+ break;
+ case PPC_EXCEPTION_STATE:
+ if(count != PPC_EXCEPTION_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not PPC_EXCEPTION_STATE_COUNT for "
+ "flavor number %lu which is a PPC_EXCEPT"
+ "ION_STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ except = (ppc_exception_state_t *)state;
+ state += sizeof(ppc_exception_state_t);
+ break;
+ case PPC_THREAD_STATE64:
+ if(count != PPC_THREAD_STATE64_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not PPC_THREAD_STATE64_COUNT for "
+ "flavor number %lu which is a PPC_THREAD_"
+ "STATE64 flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu64 = (ppc_thread_state64_t *)state;
+ state += sizeof(ppc_thread_state64_t);
+ break;
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_MC88000){
+ m88k_thread_state_grf_t *cpu;
+ m88k_thread_state_xrf_t *fpu;
+ m88k_thread_state_user_t *user;
+ m88110_thread_state_impl_t *spu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M88K_THREAD_STATE_GRF:
+ if(count != M88K_THREAD_STATE_GRF_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M88K_THREAD_STATE_GRF_COUNT for "
+ "flavor number %lu which is a M88K_THREAD_"
+ "STATE_GRF flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (m88k_thread_state_grf_t *)state;
+ state += sizeof(m88k_thread_state_grf_t);
+ break;
+ case M88K_THREAD_STATE_XRF:
+ if(count != M88K_THREAD_STATE_XRF_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M88K_THREAD_STATE_XRF_COUNT for "
+ "flavor number %lu which is a M88K_THREAD_"
+ "STATE_XRF flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (m88k_thread_state_xrf_t *)state;
+ state += sizeof(m88k_thread_state_xrf_t);
+ break;
+ case M88K_THREAD_STATE_USER:
+ if(count != M88K_THREAD_STATE_USER_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M88K_THREAD_STATE_USER_COUNT for "
+ "flavor number %lu which is a M88K_THREAD_"
+ "STATE_USER flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ user = (m88k_thread_state_user_t *)state;
+ state += sizeof(m88k_thread_state_user_t);
+ break;
+ case M88110_THREAD_STATE_IMPL:
+ if(count != M88110_THREAD_STATE_IMPL_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not M88110_THREAD_STATE_IMPL_COUNT for "
+ "flavor number %lu which is a M88110_THREAD"
+ "_STATE_IMPL flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ spu = (m88110_thread_state_impl_t *)state;
+ state += sizeof(m88110_thread_state_impl_t);
+ break;
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I860){
+ struct i860_thread_state_regs *cpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case I860_THREAD_STATE_REGS:
+ if(count != I860_THREAD_STATE_REGS_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not I860_THREAD_STATE_REGS_COUNT for "
+ "flavor number %lu which is a I860_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (struct i860_thread_state_regs *)state;
+ state += sizeof(struct i860_thread_state_regs);
+ break;
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I386
+#ifdef x86_THREAD_STATE64
+ || cputype == CPU_TYPE_X86_64
+#endif /* x86_THREAD_STATE64 */
+ ){
+ i386_thread_state_t *cpu;
+#ifdef x86_THREAD_STATE64
+ x86_thread_state64_t *cpu64;
+#endif /* x86_THREAD_STATE64 */
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ struct i386_float_state *fpu;
+ i386_exception_state_t *exc;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ i386_thread_fpstate_t *fpu;
+ i386_thread_exceptstate_t *exc;
+ i386_thread_cthreadstate_t *user;
+#endif /* i386_THREAD_STATE == -1 */
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case i386_THREAD_STATE:
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ case -1:
+#endif /* i386_THREAD_STATE == 1 */
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case 1:
+#endif /* i386_THREAD_STATE == -1 */
+ if(count != i386_THREAD_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not i386_THREAD_STATE_COUNT for flavor "
+ "number %lu which is a i386_THREAD_STATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (i386_thread_state_t *)state;
+ state += sizeof(i386_thread_state_t);
+ break;
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ case i386_FLOAT_STATE:
+ if(count != i386_FLOAT_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not i386_FLOAT_STATE_COUNT for flavor "
+ "number %lu which is a i386_FLOAT_STATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (struct i386_float_state *)state;
+ state += sizeof(struct i386_float_state);
+ break;
+ case i386_EXCEPTION_STATE:
+ if(count != I386_EXCEPTION_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not I386_EXCEPTION_STATE_COUNT for "
+ "flavor number %lu which is a i386_"
+ "EXCEPTION_STATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ exc = (i386_exception_state_t *)state;
+ state += sizeof(i386_exception_state_t);
+ break;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case i386_THREAD_FPSTATE:
+ if(count != i386_THREAD_FPSTATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not i386_THREAD_FPSTATE_COUNT for flavor "
+ "number %lu which is a i386_THREAD_FPSTATE "
+ "flavor in %s command %lu)", nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (i386_thread_fpstate_t *)state;
+ state += sizeof(i386_thread_fpstate_t);
+ break;
+ case i386_THREAD_EXCEPTSTATE:
+ if(count != i386_THREAD_EXCEPTSTATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not i386_THREAD_EXCEPTSTATE_COUNT for "
+ "flavor number %lu which is a i386_THREAD_"
+ "EXCEPTSTATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ exc = (i386_thread_exceptstate_t *)state;
+ state += sizeof(i386_thread_fpstate_t);
+ break;
+ case i386_THREAD_CTHREADSTATE:
+ if(count != i386_THREAD_CTHREADSTATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not i386_THREAD_CTHREADSTATE_COUNT for "
+ "flavor number %lu which is a i386_THREAD_"
+ "CTHREADSTATE flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ user = (i386_thread_cthreadstate_t *)state;
+ state += sizeof(i386_thread_fpstate_t);
+ break;
+#endif /* i386_THREAD_STATE == -1 */
+#ifdef x86_THREAD_STATE64
+ case x86_THREAD_STATE64:
+ if(count != x86_THREAD_STATE64_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not x86_THREAD_STATE64_COUNT for "
+ "flavor number %lu which is an x86_THREAD_"
+ "STATE64 flavor in %s command %lu)",
+ nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu64 = (x86_thread_state64_t *)state;
+ state += sizeof(x86_thread_state64_t);
+ break;
+#endif /* x86_THREAD_STATE64 */
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_HPPA){
+ struct hp_pa_integer_thread_state *cpu;
+ struct hp_pa_frame_thread_state *frame;
+ struct hp_pa_fp_thread_state *fpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case HPPA_INTEGER_THREAD_STATE:
+ if(count != HPPA_INTEGER_THREAD_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not HPPA_INTEGER_THREAD_STATE_COUNT for "
+ "flavor number %lu which is a HPPA_INTEGER"
+ "_THREAD_STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (struct hp_pa_integer_thread_state *)state;
+ state += sizeof(struct hp_pa_integer_thread_state);
+ break;
+ case HPPA_FRAME_THREAD_STATE:
+ if(count != HPPA_FRAME_THREAD_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not HPPA_FRAME_THREAD_STATE_COUNT for "
+ "flavor number %lu which is a HPPA_FRAME"
+ "_THREAD_STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ frame = (struct hp_pa_frame_thread_state *)state;
+ state += sizeof(struct hp_pa_frame_thread_state);
+ break;
+ case HPPA_FP_THREAD_STATE:
+ if(count != HPPA_FP_THREAD_STATE_COUNT){
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not HPPA_FP_THREAD_STATE_COUNT for "
+ "flavor number %lu which is a HPPA_FP"
+ "_THREAD_STATE flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (struct hp_pa_fp_thread_state *)state;
+ state += sizeof(struct hp_pa_fp_thread_state);
+ break;
+ default:
+ error("in swap_object_headers(): malformed "
+ "load commands (unknown "
+ "flavor %u for flavor number %lu in %s command"
+ " %lu can't byte swap it)", flavor, nflavor,
+ ut->cmd == LC_UNIXTHREAD ? "LC_UNIXTHREAD" :
+ "LC_THREAD", i);
+ return(FALSE);
+ }
+ nflavor++;
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_SPARC) {
+ struct sparc_thread_state_regs *cpu;
+ struct sparc_thread_state_fpu *fpu;
+
+ nflavor = 0;
+ p = (char *)ut + ut->cmdsize;
+ while (state < p) {
+ flavor = *((uint32_t *) state);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *) state);
+ state += sizeof(uint32_t);
+ switch (flavor) {
+ case SPARC_THREAD_STATE_REGS:
+ if (count != SPARC_THREAD_STATE_REGS_COUNT) {
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not SPARC_THREAD_STATE_REGS_COUNT for "
+ "flavor number %lu which is a SPARC_THREAD_"
+ "STATE_REGS flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ cpu = (struct sparc_thread_state_regs *) state;
+ state += sizeof(struct sparc_thread_state_regs);
+ break;
+ case SPARC_THREAD_STATE_FPU:
+ if (count != SPARC_THREAD_STATE_FPU_COUNT) {
+ error("in swap_object_headers(): malformed "
+ "load commands (count "
+ "not SPARC_THREAD_STATE_FPU_COUNT for "
+ "flavor number %lu which is a SPARC_THREAD_"
+ "STATE_FPU flavor in %s command %lu)",
+ nflavor, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ }
+ fpu = (struct sparc_thread_state_fpu *) state;
+ state += sizeof(struct sparc_thread_state_fpu);
+ break;
+ }
+ }
+ break;
+ }
+
+ error("in swap_object_headers(): malformed load commands "
+ "(unknown cputype (%d) and cpusubtype (%d) of object and "
+ "can't byte swap %s command %lu)", cputype,
+ cpusubtype, ut->cmd == LC_UNIXTHREAD ?
+ "LC_UNIXTHREAD" : "LC_THREAD", i);
+ return(FALSE);
+ case LC_IDENT:
+ id = (struct ident_command *)lc;
+ if((char *)id + id->cmdsize >
+ (char *)load_commands + sizeofcmds){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (cmdsize field of LC_IDENT command %lu "
+ "extends past the end of the load commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_ROUTINES:
+ rc = (struct routines_command *)lc;
+ if(rc->cmdsize != sizeof(struct routines_command)){
+ error("in swap_object_headers(): malformed load commands ("
+ "LC_ROUTINES command %lu has incorrect cmdsize",
+ i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_ROUTINES_64:
+ rc64 = (struct routines_command_64 *)lc;
+ if(rc64->cmdsize != sizeof(struct routines_command_64)){
+ error("in swap_object_headers(): malformed load commands ("
+ "LC_ROUTINES_64 command %lu has incorrect cmdsize",
+ i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_TWOLEVEL_HINTS:
+ hints = (struct twolevel_hints_command *)lc;
+ if(hints->cmdsize != sizeof(struct twolevel_hints_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_TWOLEVEL_HINTS command %lu has incorrect "
+ "cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_PREBIND_CKSUM:
+ cs = (struct prebind_cksum_command *)lc;
+ if(cs->cmdsize != sizeof(struct prebind_cksum_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_PREBIND_CKSUM command %lu has incorrect cmdsize",
+ i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_UUID:
+ uuid = (struct uuid_command *)lc;
+ if(uuid->cmdsize != sizeof(struct uuid_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_UUID command %lu has incorrect cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_CODE_SIGNATURE:
+ ld = (struct linkedit_data_command *)lc;
+ if(ld->cmdsize != sizeof(struct linkedit_data_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_CODE_SIGNATURE command %lu has incorrect "
+ "cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_SEGMENT_SPLIT_INFO:
+ ld = (struct linkedit_data_command *)lc;
+ if(ld->cmdsize != sizeof(struct linkedit_data_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_SEGMENT_SPLIT_INFO command %lu has incorrect "
+ "cmdsize", i);
+ return(FALSE);
+ }
+ break;
+
+ case LC_RPATH:
+ rpath = (struct rpath_command *)lc;
+ if(rpath->cmdsize < sizeof(struct rpath_command)){
+ error("in swap_object_headers(): malformed load commands "
+ "(LC_RPATH command %lu has too small cmdsize field)",
+ i);
+ return(FALSE);
+ }
+ if(rpath->path.offset >= rpath->cmdsize){
+ error("in swap_object_headers(): truncated or malformed "
+ "load commands (path.offset field of LC_RPATH "
+ "command %lu extends past the end of all load "
+ "commands)", i);
+ return(FALSE);
+ }
+ break;
+
+ default:
+ error("in swap_object_headers(): malformed load commands "
+ "(unknown load command %lu)", i);
+ return(FALSE);
+ }
+
+ lc = (struct load_command *)((char *)lc + l.cmdsize);
+ /* check that next load command does not extends past the end */
+ if((char *)lc > (char *)load_commands + sizeofcmds){
+ error("in swap_object_headers(): truncated or malformed load "
+ "commands (load command %lu extends past the end of all "
+ "load commands)", i + 1);
+ return(FALSE);
+ }
+ }
+ /* check for an inconsistent size of the load commands */
+ if((char *)load_commands + sizeofcmds != (char *)lc){
+ error("in swap_object_headers(): malformed load commands "
+ "(inconsistent sizeofcmds field in mach header)");
+ return(FALSE);
+ }
+
+
+ /*
+ * Now knowing the load commands can be parsed swap them.
+ */
+ target_byte_sex = get_host_byte_sex() == BIG_ENDIAN_BYTE_SEX ?
+ LITTLE_ENDIAN_BYTE_SEX : BIG_ENDIAN_BYTE_SEX;
+ for(i = 0, lc = load_commands; i < ncmds; i++){
+ l = *lc;
+ switch(lc->cmd){
+ case LC_SEGMENT:
+ sg = (struct segment_command *)lc;
+ s = (struct section *)
+ ((char *)sg + sizeof(struct segment_command));
+ swap_section(s, sg->nsects, target_byte_sex);
+ swap_segment_command(sg, target_byte_sex);
+ break;
+
+ case LC_SEGMENT_64:
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)
+ ((char *)sg64 + sizeof(struct segment_command_64));
+ swap_section_64(s64, sg64->nsects, target_byte_sex);
+ swap_segment_command_64(sg64, target_byte_sex);
+ break;
+
+ case LC_SYMTAB:
+ st = (struct symtab_command *)lc;
+ swap_symtab_command(st, target_byte_sex);
+ break;
+
+ case LC_DYSYMTAB:
+ dyst = (struct dysymtab_command *)lc;
+ swap_dysymtab_command(dyst, target_byte_sex);
+ break;
+
+ case LC_SYMSEG:
+ ss = (struct symseg_command *)lc;
+ swap_symseg_command(ss, target_byte_sex);
+ break;
+
+ case LC_IDFVMLIB:
+ case LC_LOADFVMLIB:
+ fl = (struct fvmlib_command *)lc;
+ swap_fvmlib_command(fl, target_byte_sex);
+ break;
+
+ case LC_ID_DYLIB:
+ case LC_LOAD_DYLIB:
+ case LC_LOAD_WEAK_DYLIB:
+ case LC_REEXPORT_DYLIB:
+ dl = (struct dylib_command *)lc;
+ swap_dylib_command(dl, target_byte_sex);
+ break;
+
+ case LC_SUB_FRAMEWORK:
+ sub = (struct sub_framework_command *)lc;
+ swap_sub_framework_command(sub, target_byte_sex);
+ break;
+
+ case LC_SUB_UMBRELLA:
+ usub = (struct sub_umbrella_command *)lc;
+ swap_sub_umbrella_command(usub, target_byte_sex);
+ break;
+
+ case LC_SUB_LIBRARY:
+ lsub = (struct sub_library_command *)lc;
+ swap_sub_library_command(lsub, target_byte_sex);
+ break;
+
+ case LC_SUB_CLIENT:
+ csub = (struct sub_client_command *)lc;
+ swap_sub_client_command(csub, target_byte_sex);
+ break;
+
+ case LC_PREBOUND_DYLIB:
+ pbdylib = (struct prebound_dylib_command *)lc;
+ swap_prebound_dylib_command(pbdylib, target_byte_sex);
+ break;
+
+ case LC_ID_DYLINKER:
+ case LC_LOAD_DYLINKER:
+ dyld = (struct dylinker_command *)lc;
+ swap_dylinker_command(dyld, target_byte_sex);
+ break;
+
+ case LC_UNIXTHREAD:
+ case LC_THREAD:
+ ut = (struct thread_command *)lc;
+ state = (char *)ut + sizeof(struct thread_command);
+ p = (char *)ut + ut->cmdsize;
+ swap_thread_command(ut, target_byte_sex);
+
+ if(cputype == CPU_TYPE_MC680x0){
+ struct m68k_thread_state_regs *cpu;
+ struct m68k_thread_state_68882 *fpu;
+ struct m68k_thread_state_user_reg *user_reg;
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M68K_THREAD_STATE_REGS:
+ cpu = (struct m68k_thread_state_regs *)state;
+ swap_m68k_thread_state_regs(cpu, target_byte_sex);
+ state += sizeof(struct m68k_thread_state_regs);
+ break;
+ case M68K_THREAD_STATE_68882:
+ fpu = (struct m68k_thread_state_68882 *)state;
+ swap_m68k_thread_state_68882(fpu, target_byte_sex);
+ state += sizeof(struct m68k_thread_state_68882);
+ break;
+ case M68K_THREAD_STATE_USER_REG:
+ user_reg =
+ (struct m68k_thread_state_user_reg *)state;
+ swap_m68k_thread_state_user_reg(user_reg,
+ target_byte_sex);
+ state += sizeof(struct m68k_thread_state_user_reg);
+ break;
+ }
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_POWERPC ||
+ cputype == CPU_TYPE_VEO ||
+ cputype == CPU_TYPE_POWERPC64){
+ ppc_thread_state_t *cpu;
+ ppc_thread_state64_t *cpu64;
+ ppc_float_state_t *fpu;
+ ppc_exception_state_t *except;
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case PPC_THREAD_STATE:
+ cpu = (ppc_thread_state_t *)state;
+ swap_ppc_thread_state_t(cpu, target_byte_sex);
+ state += sizeof(ppc_thread_state_t);
+ break;
+ case PPC_THREAD_STATE64:
+ cpu64 = (ppc_thread_state64_t *)state;
+ swap_ppc_thread_state64_t(cpu64, target_byte_sex);
+ state += sizeof(ppc_thread_state64_t);
+ break;
+ case PPC_FLOAT_STATE:
+ fpu = (ppc_float_state_t *)state;
+ swap_ppc_float_state_t(fpu, target_byte_sex);
+ state += sizeof(ppc_float_state_t);
+ case PPC_EXCEPTION_STATE:
+ except = (ppc_exception_state_t *)state;
+ swap_ppc_exception_state_t(except, target_byte_sex);
+ state += sizeof(ppc_exception_state_t);
+ break;
+ }
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_MC88000){
+ m88k_thread_state_grf_t *cpu;
+ m88k_thread_state_xrf_t *fpu;
+ m88k_thread_state_user_t *user;
+ m88110_thread_state_impl_t *spu;
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case M88K_THREAD_STATE_GRF:
+ cpu = (m88k_thread_state_grf_t *)state;
+ swap_m88k_thread_state_grf_t(cpu,
+ target_byte_sex);
+ state += sizeof(m88k_thread_state_grf_t);
+ break;
+ case M88K_THREAD_STATE_XRF:
+ fpu = (m88k_thread_state_xrf_t *)state;
+ swap_m88k_thread_state_xrf_t(fpu,
+ target_byte_sex);
+ state += sizeof(m88k_thread_state_xrf_t);
+ break;
+ case M88K_THREAD_STATE_USER:
+ user = (m88k_thread_state_user_t *)state;
+ swap_m88k_thread_state_user_t(user,
+ target_byte_sex);
+ state += sizeof(m88k_thread_state_user_t);
+ break;
+ case M88110_THREAD_STATE_IMPL:
+ spu = (m88110_thread_state_impl_t *)state;
+ swap_m88110_thread_state_impl_t(spu,
+ target_byte_sex);
+ state += sizeof(m88110_thread_state_impl_t);
+ break;
+ }
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I860){
+ struct i860_thread_state_regs *cpu;
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case I860_THREAD_STATE_REGS:
+ cpu = (struct i860_thread_state_regs *)state;
+ swap_i860_thread_state_regs(cpu, target_byte_sex);
+ state += sizeof(struct i860_thread_state_regs);
+ break;
+ }
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_I386
+#ifdef x86_THREAD_STATE64
+ || cputype == CPU_TYPE_X86_64
+#endif /* x86_THREAD_STATE64 */
+ ){
+ i386_thread_state_t *cpu;
+#ifdef x86_THREAD_STATE64
+ x86_thread_state64_t *cpu64;
+#endif /* x86_THREAD_STATE64 */
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ struct i386_float_state *fpu;
+ i386_exception_state_t *exc;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ i386_thread_fpstate_t *fpu;
+ i386_thread_exceptstate_t *exc;
+ i386_thread_cthreadstate_t *user;
+#endif /* i386_THREAD_STATE == -1 */
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case i386_THREAD_STATE:
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ case -1:
+#endif /* i386_THREAD_STATE == 1 */
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case 1:
+#endif /* i386_THREAD_STATE == -1 */
+ cpu = (i386_thread_state_t *)state;
+ swap_i386_thread_state(cpu, target_byte_sex);
+ state += sizeof(i386_thread_state_t);
+ break;
+/* current i386 thread states */
+#if i386_THREAD_STATE == 1
+ case i386_FLOAT_STATE:
+ fpu = (struct i386_float_state *)state;
+ swap_i386_float_state(fpu, target_byte_sex);
+ state += sizeof(struct i386_float_state);
+ break;
+ case i386_EXCEPTION_STATE:
+ exc = (i386_exception_state_t *)state;
+ swap_i386_exception_state(exc, target_byte_sex);
+ state += sizeof(i386_exception_state_t);
+ break;
+#endif /* i386_THREAD_STATE == 1 */
+
+/* i386 thread states on older releases */
+#if i386_THREAD_STATE == -1
+ case i386_THREAD_FPSTATE:
+ fpu = (i386_thread_fpstate_t *)state;
+ swap_i386_thread_fpstate(fpu, target_byte_sex);
+ state += sizeof(i386_thread_fpstate_t);
+ break;
+ case i386_THREAD_EXCEPTSTATE:
+ exc = (i386_thread_exceptstate_t *)state;
+ swap_i386_thread_exceptstate(exc, target_byte_sex);
+ state += sizeof(i386_thread_exceptstate_t);
+ break;
+ case i386_THREAD_CTHREADSTATE:
+ user = (i386_thread_cthreadstate_t *)state;
+ swap_i386_thread_cthreadstate(user,target_byte_sex);
+ state += sizeof(i386_thread_cthreadstate_t);
+ break;
+#endif /* i386_THREAD_STATE == -1 */
+#ifdef x86_THREAD_STATE64
+ case x86_THREAD_STATE64:
+ cpu64 = (x86_thread_state64_t *)state;
+ swap_x86_thread_state64(cpu64, target_byte_sex);
+ state += sizeof(x86_thread_state64_t);
+ break;
+#endif /* x86_THREAD_STATE64 */
+ }
+ }
+ break;
+ }
+ if(cputype == CPU_TYPE_HPPA){
+ struct hp_pa_integer_thread_state *cpu;
+ struct hp_pa_frame_thread_state *frame;
+ struct hp_pa_fp_thread_state *fpu;
+
+ while(state < p){
+ flavor = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((uint32_t *)state);
+ *((uint32_t *)state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch(flavor){
+ case HPPA_INTEGER_THREAD_STATE:
+ cpu = (struct hp_pa_integer_thread_state *)state;
+ swap_hppa_integer_thread_state(cpu,
+ target_byte_sex);
+ state += sizeof(struct hp_pa_integer_thread_state);
+ break;
+ case HPPA_FRAME_THREAD_STATE:
+ frame = (struct hp_pa_frame_thread_state *)state;
+ swap_hppa_frame_thread_state(frame,
+ target_byte_sex);
+ state += sizeof(struct hp_pa_frame_thread_state);
+ break;
+ case HPPA_FP_THREAD_STATE:
+ fpu = (struct hp_pa_fp_thread_state *)state;
+ swap_hppa_fp_thread_state(fpu,
+ target_byte_sex);
+ state += sizeof(struct hp_pa_fp_thread_state);
+ break;
+ }
+ }
+ break;
+ }
+
+ if(cputype == CPU_TYPE_SPARC) {
+ struct sparc_thread_state_regs *cpu;
+ struct sparc_thread_state_fpu *fpu;
+
+ while (state < p) {
+ flavor = *((uint32_t *) state);
+ *((uint32_t *) state) = SWAP_INT(flavor);
+ state += sizeof(uint32_t);
+ count = *((unsigned int *) state);
+ *((unsigned int *) state) = SWAP_INT(count);
+ state += sizeof(uint32_t);
+ switch (flavor) {
+ case SPARC_THREAD_STATE_REGS:
+ cpu = (struct sparc_thread_state_regs *) state;
+ swap_sparc_thread_state_regs(cpu, target_byte_sex);
+ state += sizeof(struct sparc_thread_state_regs);
+ break;
+ case SPARC_THREAD_STATE_FPU:
+ fpu = (struct sparc_thread_state_fpu *) state;
+ swap_sparc_thread_state_fpu(fpu, target_byte_sex);
+ state += sizeof(struct sparc_thread_state_fpu);
+ break;
+ }
+ }
+ break;
+ }
+ break;
+
+ case LC_IDENT:
+ id = (struct ident_command *)lc;
+ swap_ident_command(id, target_byte_sex);
+ break;
+
+ case LC_ROUTINES:
+ rc = (struct routines_command *)lc;
+ swap_routines_command(rc, target_byte_sex);
+ break;
+
+ case LC_ROUTINES_64:
+ rc64 = (struct routines_command_64 *)lc;
+ swap_routines_command_64(rc64, target_byte_sex);
+ break;
+
+ case LC_TWOLEVEL_HINTS:
+ hints = (struct twolevel_hints_command *)lc;
+ swap_twolevel_hints_command(hints, target_byte_sex);
+ break;
+
+ case LC_PREBIND_CKSUM:
+ cs = (struct prebind_cksum_command *)lc;
+ swap_prebind_cksum_command(cs, target_byte_sex);
+ break;
+
+ case LC_UUID:
+ uuid = (struct uuid_command *)lc;
+ swap_uuid_command(uuid, target_byte_sex);
+ break;
+
+ case LC_CODE_SIGNATURE:
+ case LC_SEGMENT_SPLIT_INFO:
+ ld = (struct linkedit_data_command *)lc;
+ swap_linkedit_data_command(ld, target_byte_sex);
+ break;
+
+ case LC_RPATH:
+ rpath = (struct rpath_command *)lc;
+ swap_rpath_command(rpath, target_byte_sex);
+ break;
+ }
+
+ lc = (struct load_command *)((char *)lc + l.cmdsize);
+ }
+ if(mh != NULL)
+ swap_mach_header(mh, target_byte_sex);
+ else
+ swap_mach_header_64(mh64, target_byte_sex);
+
+ return(TRUE);
+}
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/symbol_list.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <ctype.h>
+#include <stuff/symbol_list.h>
+#include <stuff/allocate.h>
+#include <stuff/errors.h>
+
+static int cmp_qsort_name(
+ const struct symbol_list *sym1,
+ const struct symbol_list *sym2);
+
+/*
+ * This is called to setup a symbol list from a file. It reads the file with
+ * the strings in it and places them in an array of symbol_list structures and
+ * then sorts them by name.
+ *
+ * The file that contains the symbol names must have symbol names one per line,
+ * leading and trailing white space is removed and lines starting with a '#'
+ * and lines with only white space are ignored.
+ */
+__private_extern__
+void
+setup_symbol_list(
+char *file,
+struct symbol_list **list,
+unsigned long *size)
+{
+ int fd;
+ unsigned long i, j, len, strings_size;
+ struct stat stat_buf;
+ char *strings, *p, *line;
+
+ if((fd = open(file, O_RDONLY)) < 0){
+ system_error("can't open: %s", file);
+ return;
+ }
+ if(fstat(fd, &stat_buf) == -1){
+ system_error("can't stat: %s", file);
+ close(fd);
+ return;
+ }
+ strings_size = stat_buf.st_size;
+ strings = (char *)allocate(strings_size + 2);
+ strings[strings_size] = '\n';
+ strings[strings_size + 1] = '\0';
+ if(read(fd, strings, strings_size) != (int)strings_size){
+ system_error("can't read: %s", file);
+ close(fd);
+ return;
+ }
+ /*
+ * Change the newlines to '\0' and count the number of lines with
+ * symbol names. Lines starting with '#' are comments and lines
+ * contain all space characters do not contain symbol names.
+ */
+ p = strings;
+ line = p;
+ for(i = 0; i < strings_size + 1; i++){
+ if(*p == '\n' || *p == '\r'){
+ *p = '\0';
+ if(*line != '#'){
+ while(*line != '\0' && isspace(*line))
+ line++;
+ if(*line != '\0')
+ (*size)++;
+ }
+ p++;
+ line = p;
+ }
+ else{
+ p++;
+ }
+ }
+ *list = (struct symbol_list *)
+ allocate((*size) * sizeof(struct symbol_list));
+
+ /*
+ * Place the strings in the list trimming leading and trailing spaces
+ * from the lines with symbol names.
+ */
+ p = strings;
+ line = p;
+ for(i = 0; i < (*size); ){
+ p += strlen(p) + 1;
+ if(*line != '#' && *line != '\0'){
+ while(*line != '\0' && isspace(*line))
+ line++;
+ if(*line != '\0'){
+ (*list)[i].name = line;
+ (*list)[i].seen = FALSE;
+ i++;
+ len = strlen(line);
+ j = len - 1;
+ while(j > 0 && isspace(line[j])){
+ j--;
+ }
+ if(j > 0 && j + 1 < len && isspace(line[j+1]))
+ line[j+1] = '\0';
+ }
+ }
+ line = p;
+ }
+
+ qsort(*list, *size, sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))cmp_qsort_name);
+
+ /* remove duplicates on the list */
+ for(i = 0; i < (*size); i++){
+ if(i + 1 < (*size)){
+ if(strcmp((*list)[i].name, (*list)[i+1].name) == 0){
+ for(j = 1; j < ((*size) - i - 1); j++){
+ (*list)[i + j].name = (*list)[i + j + 1].name;
+ }
+ *size = *size - 1;
+ /*
+ * Since there may be more than two of the same name
+ * check this one again against the next one in the
+ * list before moving on.
+ */
+ i--;
+ }
+ }
+ }
+
+#ifdef DEBUG
+ printf("symbol list:\n");
+ for(i = 0; i < (*size); i++){
+ printf("0x%x name = %s\n", &((*list)[i]),(*list)[i].name);
+ }
+#endif /* DEBUG */
+}
+
+/*
+ * Function for qsort for comparing symbol list names.
+ */
+static
+int
+cmp_qsort_name(
+const struct symbol_list *sym1,
+const struct symbol_list *sym2)
+{
+ return(strcmp(sym1->name, sym2->name));
+}
+
+/*
+ * Function for bsearch for finding a symbol name.
+ */
+__private_extern__
+int
+symbol_list_bsearch(
+const char *name,
+const struct symbol_list *sym)
+{
+ return(strcmp(name, sym->name));
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/unix_standard_mode.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2004 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <stdlib.h>
+#include <strings.h>
+#include "stuff/bool.h"
+#include "stuff/unix_standard_mode.h"
+
+/*
+ * get_unix_standard_mode() returns TRUE if we are running in UNIX standard
+ * command mode (the default).
+ */
+__private_extern__
+enum bool
+get_unix_standard_mode(
+void)
+{
+ static enum bool checked_environment_variable = FALSE;
+ static enum bool unix_standard_mode = TRUE;
+ char *p;
+
+ if(checked_environment_variable == FALSE){
+ checked_environment_variable = TRUE;
+ /*
+ * Pick up the UNIX standard command mode environment variable.
+ */
+ p = getenv("COMMAND_MODE");
+ if(p != NULL){
+ if(strcasecmp("legacy", p) == 0)
+ unix_standard_mode = FALSE;
+ }
+ }
+ return(unix_standard_mode);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/libstuff/writeout.c
@@ -0,0 +1,1375 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#ifndef RLD
+#include <sys/time.h>
+#include <mach/mach.h>
+#include "stuff/openstep_mach.h"
+#include <libc.h>
+#ifndef __OPENSTEP__
+#include <utime.h>
+#endif
+#include "stuff/ofile.h"
+#include "stuff/breakout.h"
+#include "stuff/allocate.h"
+#include "stuff/round.h"
+#include "stuff/errors.h"
+
+static void copy_new_symbol_info(
+ char *p,
+ unsigned long *size,
+ struct dysymtab_command *dyst,
+ struct dysymtab_command *old_dyst,
+ struct twolevel_hints_command *hints_cmd,
+ struct twolevel_hints_command *old_hints_cmd,
+ struct object *object);
+
+static void make_table_of_contents(
+ struct arch *archs,
+ char *output,
+ long toc_time,
+ enum bool sort_toc,
+ enum bool commons_in_toc,
+ enum bool library_warnings);
+
+static enum bool toc_symbol(
+ struct nlist *symbol,
+ enum bool commons_in_toc,
+ struct section **sections);
+
+static enum bool toc_symbol_64(
+ struct nlist_64 *symbol64,
+ enum bool commons_in_toc,
+ struct section_64 **sections64);
+
+static enum bool toc(
+ uint32_t n_strx,
+ uint8_t n_type,
+ uint64_t n_value,
+ enum bool commons_in_toc,
+ enum bool attr_no_toc);
+
+static int toc_entry_name_qsort(
+ const struct toc_entry *toc1,
+ const struct toc_entry *toc2);
+
+static int toc_entry_index_qsort(
+ const struct toc_entry *toc1,
+ const struct toc_entry *toc2);
+
+static enum bool check_sort_toc_entries(
+ struct arch *arch,
+ char *output,
+ enum bool library_warnings);
+
+static void warn_member(
+ struct arch *arch,
+ struct member *member,
+ const char *format, ...)
+#ifndef __MWERKS__
+ __attribute__ ((format (printf, 3, 4)))
+#endif
+ ;
+
+/*
+ * writeout() creates an ofile from the data structure pointed to by
+ * archs (of narchs size) into the specified output file (output). The file is
+ * created with the mode, mode. If there are libraries in the data structures
+ * a new table of contents is created and is sorted if sort_toc is TRUE and
+ * commons symbols are included in the table of contents if commons_in_toc is
+ * TRUE. The normal use will have sort_toc == TRUE and commons_in_toc == FALSE.
+ * If warnings about unusual libraries are printed if library_warnings == TRUE.
+ */
+__private_extern__
+void
+writeout(
+struct arch *archs,
+unsigned long narchs,
+char *output,
+unsigned short mode,
+enum bool sort_toc,
+enum bool commons_in_toc,
+enum bool library_warnings,
+unsigned long *throttle)
+{
+ unsigned long fsync;
+ int fd;
+#ifndef __OPENSTEP__
+ struct utimbuf timep;
+#else
+ time_t timep[2];
+#endif
+ mach_port_t my_mach_host_self;
+ char *file, *p;
+ unsigned long file_size;
+ long toc_time;
+ enum bool seen_archive;
+ kern_return_t r;
+
+ seen_archive = FALSE;
+ toc_time = time(0);
+
+ writeout_to_mem(archs, narchs, output, (void **)&file, &file_size,
+ sort_toc, commons_in_toc, library_warnings,
+ &seen_archive);
+
+ /*
+ * Create the output file. The unlink() is done to handle the problem
+ * when the outputfile is not writable but the directory allows the
+ * file to be removed (since the file may not be there the return code
+ * of the unlink() is ignored).
+ */
+ (void)unlink(output);
+ if(throttle != NULL)
+ fsync = O_FSYNC;
+ else
+ fsync = 0;
+ if(output != NULL){
+ if((fd = open(output, O_WRONLY|O_CREAT|O_TRUNC|fsync, mode)) == -1){
+ system_error("can't create output file: %s", output);
+ goto cleanup;
+ }
+#ifdef F_NOCACHE
+ /* tell filesystem to NOT cache the file when reading or writing */
+ (void)fcntl(fd, F_NOCACHE, 1);
+#endif
+ }
+ else{
+ throttle = NULL;
+ fd = fileno(stdout);
+ }
+ if(throttle != NULL){
+#define WRITE_SIZE (32 * 1024)
+ struct timeval start, end;
+ struct timezone tz;
+ unsigned long bytes_written, bytes_per_second, write_size;
+ double time_used, time_should_have_took, usecs_to_kill;
+ static struct host_sched_info info = { 0 };
+ unsigned int count;
+ kern_return_t r;
+
+ p = file;
+ bytes_written = 0;
+ bytes_per_second = 0;
+ count = HOST_SCHED_INFO_COUNT;
+ my_mach_host_self = mach_host_self();
+ if((r = host_info(my_mach_host_self, HOST_SCHED_INFO, (host_info_t)
+ (&info), &count)) != KERN_SUCCESS){
+ mach_port_deallocate(mach_task_self(), my_mach_host_self);
+ my_mach_error(r, "can't get host sched info");
+ }
+ mach_port_deallocate(mach_task_self(), my_mach_host_self);
+ if(gettimeofday(&start, &tz) == -1)
+ goto no_throttle;
+#undef THROTTLE_DEBUG
+ do {
+ if((file + file_size) - p < WRITE_SIZE)
+ write_size = (file + file_size) - p;
+ else
+ write_size = WRITE_SIZE;
+ if(write(fd, p, write_size) != (int)write_size){
+ system_error("can't write output file: %s", output);
+ goto cleanup;
+ }
+ p += write_size;
+ if(p < file + file_size || *throttle == ULONG_MAX){
+ bytes_written += write_size;
+ (void)gettimeofday(&end, &tz);
+#ifdef THROTTLE_DEBUG
+ printf("start sec = %u usec = %u\n", start.tv_sec,
+ start.tv_usec);
+ printf("end sec = %u usec = %u\n", end.tv_sec,
+ end.tv_usec);
+#endif
+ time_used = end.tv_sec - start.tv_sec;
+ if(end.tv_usec >= start.tv_usec)
+ time_used +=
+ ((double)(end.tv_usec - start.tv_usec)) / 1000000.0;
+ else
+ time_used += -1.0 +
+ ((double)(1000000 + end.tv_usec - start.tv_usec) /
+ 1000000.0);
+ bytes_per_second = ((double)bytes_written / time_used);
+#ifdef THROTTLE_DEBUG
+ printf("time_used = %f bytes_written = %lu bytes_per_second"
+ " = %lu throttle = %lu\n", time_used, bytes_written,
+ bytes_per_second, *throttle);
+#endif
+ if(bytes_per_second > *throttle){
+ time_should_have_took =
+ (double)bytes_written * (1.0/(double)(*throttle));
+ usecs_to_kill =
+ (time_should_have_took - time_used) * 1000000.0;
+#ifdef THROTTLE_DEBUG
+ printf("time should have taken = %f usecs to kill %f\n",
+ time_should_have_took, usecs_to_kill);
+#endif
+ usleep((u_int)usecs_to_kill);
+ bytes_written = 0;
+ bytes_per_second = 0;
+ (void)gettimeofday(&start, &tz);
+ }
+ }
+ } while(p < file + file_size);
+ if(*throttle == ULONG_MAX)
+ *throttle = bytes_per_second;
+ }
+ else{
+no_throttle:
+ if(write(fd, file, file_size) != (int)file_size){
+ system_error("can't write output file: %s", output);
+ goto cleanup;
+ }
+ }
+ if(output != NULL && close(fd) == -1){
+ system_fatal("can't close output file: %s", output);
+ goto cleanup;
+ }
+ if(seen_archive == TRUE){
+#ifndef __OPENSTEP__
+ timep.actime = toc_time - 5;
+ timep.modtime = toc_time - 5;
+ if(utime(output, &timep) == -1)
+#else
+ timep[0] = toc_time - 5;
+ timep[1] = toc_time - 5;
+ if(utime(output, timep) == -1)
+#endif
+ {
+ system_fatal("can't set the modifiy times in output file: %s",
+ output);
+ goto cleanup;
+ }
+ }
+cleanup:
+ if((r = vm_deallocate(mach_task_self(), (vm_address_t)file,
+ file_size)) != KERN_SUCCESS){
+ my_mach_error(r, "can't vm_deallocate() buffer for output file");
+ return;
+ }
+}
+
+
+/*
+ * writeout_to_mem() creates an ofile in memory from the data structure pointed
+ * to by archs (of narchs size). Upon successful return, *outputbuf will point
+ * to a vm_allocate'd buffer representing the ofile which should be
+ * vm_deallocated when it is no longer needed. length will point to the length
+ * of the outputbuf buffer. The filename parameter is used for error reporting
+ * - if filename is NULL, a dummy file name is used. If there are libraries in
+ * the data structures a new table of contents is created and is sorted if
+ * sort_toc is TRUE and commons symbols are included in the table of contents
+ * if commons_in_toc is TRUE. The normal use will have sort_toc == TRUE and
+ * commons_in_toc == FALSE. If warnings about unusual libraries are printed if
+ * library_warnings == TRUE.
+ */
+__private_extern__
+void
+writeout_to_mem(
+struct arch *archs,
+unsigned long narchs,
+char *filename,
+void **outputbuf,
+unsigned long *length,
+enum bool sort_toc,
+enum bool commons_in_toc,
+enum bool library_warnings,
+enum bool *seen_archive)
+{
+ unsigned long i, j, k, file_size, offset, pad, size;
+ uint32_t i32;
+ enum byte_sex target_byte_sex, host_byte_sex;
+ char *file, *p;
+ kern_return_t r;
+ struct fat_header *fat_header;
+ struct fat_arch *fat_arch;
+ struct dysymtab_command dyst;
+ struct twolevel_hints_command hints_cmd;
+ struct load_command lc, *lcp;
+ struct dylib_command dl, *dlp;
+ long toc_time, timestamp, index;
+ uint32_t ncmds;
+ enum bool swapped;
+
+ /*
+ * If filename is NULL, we use a dummy file name.
+ */
+ if(filename == NULL)
+ filename = "(file written out to memory)";
+
+ /*
+ * The time the table of contents' are set to and the time to base the
+ * modification time of the output file to be set to.
+ */
+ *seen_archive = FALSE;
+ toc_time = time(0);
+
+ fat_arch = NULL; /* here to quite compiler maybe warning message */
+ fat_header = NULL;
+
+ if(narchs == 0){
+ error("no contents for file: %s (not created)", filename);
+ return;
+ }
+
+ host_byte_sex = get_host_byte_sex();
+
+ /*
+ * Calculate the total size of the file and the final size of each
+ * architecture.
+ */
+ if(narchs > 1 || archs[0].fat_arch != NULL)
+ file_size = sizeof(struct fat_header) +
+ sizeof(struct fat_arch) * narchs;
+ else
+ file_size = 0;
+ for(i = 0; i < narchs; i++){
+ /*
+ * For each arch that is an archive recreate the table of contents.
+ */
+ if(archs[i].type == OFILE_ARCHIVE){
+ *seen_archive = TRUE;
+ make_table_of_contents(archs + i, filename, toc_time, sort_toc,
+ commons_in_toc, library_warnings);
+ archs[i].library_size += SARMAG + archs[i].toc_size;
+ if(archs[i].fat_arch != NULL)
+ file_size = round(file_size, 1 << archs[i].fat_arch->align);
+ file_size += archs[i].library_size;
+ if(archs[i].fat_arch != NULL)
+ archs[i].fat_arch->size = archs[i].library_size;
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ size = archs[i].object->object_size
+ - archs[i].object->input_sym_info_size
+ + archs[i].object->output_sym_info_size;
+ if(archs[i].fat_arch != NULL)
+ file_size = round(file_size, 1 << archs[i].fat_arch->align);
+ file_size += size;
+ if(archs[i].fat_arch != NULL)
+ archs[i].fat_arch->size = size;
+ }
+ else{ /* archs[i].type == OFILE_UNKNOWN */
+ if(archs[i].fat_arch != NULL)
+ file_size = round(file_size, 1 << archs[i].fat_arch->align);
+ file_size += archs[i].unknown_size;
+ if(archs[i].fat_arch != NULL)
+ archs[i].fat_arch->size = archs[i].unknown_size;
+ }
+ }
+
+ /*
+ * This buffer is vm_allocate'ed to make sure all holes are filled with
+ * zero bytes.
+ */
+ if((r = vm_allocate(mach_task_self(), (vm_address_t *)&file,
+ file_size, TRUE)) != KERN_SUCCESS)
+ mach_fatal(r, "can't vm_allocate() buffer for output file: %s of "
+ "size %lu", filename, file_size);
+
+ /*
+ * If there is more than one architecture then fill in the fat file
+ * header and the fat_arch structures in the buffer.
+ */
+ if(narchs > 1 || archs[0].fat_arch != NULL){
+ fat_header = (struct fat_header *)file;
+ fat_header->magic = FAT_MAGIC;
+ fat_header->nfat_arch = narchs;
+ offset = sizeof(struct fat_header) +
+ sizeof(struct fat_arch) * narchs;
+ fat_arch = (struct fat_arch *)(file + sizeof(struct fat_header));
+ for(i = 0; i < narchs; i++){
+ fat_arch[i].cputype = archs[i].fat_arch->cputype;
+ fat_arch[i].cpusubtype = archs[i].fat_arch->cpusubtype;
+ offset = round(offset, 1 << archs[i].fat_arch->align);
+ fat_arch[i].offset = offset;
+ fat_arch[i].size = archs[i].fat_arch->size;
+ fat_arch[i].align = archs[i].fat_arch->align;
+ offset += archs[i].fat_arch->size;
+ }
+ }
+
+ /*
+ * Now put each arch in the buffer.
+ */
+ for(i = 0; i < narchs; i++){
+ if(archs[i].fat_arch != NULL)
+ p = file + fat_arch[i].offset;
+ else
+ p = file;
+
+ if(archs[i].type == OFILE_ARCHIVE){
+ *seen_archive = TRUE;
+ /*
+ * If the input files only contains non-object files then the
+ * byte sex of the output can't be determined which is needed
+ * for the two binary long's of the table of contents. But
+ * since these will be zero (the same in both byte sexes)
+ * because there are no symbols in the table of contents if
+ * there are no object files.
+ */
+
+ /* put in the archive magic string */
+ memcpy(p, ARMAG, SARMAG);
+ p += SARMAG;
+
+ /*
+ * Warn for what really is a bad library that has an empty
+ * table of contents but this is allowed in the original
+ * bsd4.3 ranlib(1) implementation.
+ */
+ if(library_warnings == TRUE && archs[i].ntocs == 0){
+ if(narchs > 1 || archs[i].fat_arch != NULL)
+ warning("warning library: %s for architecture: %s the "
+ "table of contents is empty (no object file "
+ "members in the library)", filename,
+ archs[i].fat_arch_name);
+ else
+ warning("warning for library: %s the table of contents "
+ "is empty (no object file members in the "
+ "library)", filename);
+ }
+
+ /*
+ * Pick the byte sex to write the table of contents in.
+ */
+ target_byte_sex = UNKNOWN_BYTE_SEX;
+ for(j = 0;
+ j < archs[i].nmembers && target_byte_sex ==UNKNOWN_BYTE_SEX;
+ j++){
+ if(archs[i].members[j].type == OFILE_Mach_O)
+ target_byte_sex =
+ archs[i].members[j].object->object_byte_sex;
+ }
+ if(target_byte_sex == UNKNOWN_BYTE_SEX)
+ target_byte_sex = host_byte_sex;
+
+ /*
+ * Put in the table of contents member:
+ * the archive header
+ * a 32-bit for the number of bytes of the ranlib structs
+ * the ranlib structs
+ * a 32-bit for the number of bytes of the ranlib strings
+ * the strings for the ranlib structs
+ */
+ memcpy(p, (char *)(&archs[i].toc_ar_hdr),sizeof(struct ar_hdr));
+ p += sizeof(struct ar_hdr);
+
+ if(archs[i].toc_long_name == TRUE){
+ memcpy(p, archs[i].toc_name, archs[i].toc_name_size);
+ p += archs[i].toc_name_size +
+ (round(sizeof(struct ar_hdr), 8) -
+ sizeof(struct ar_hdr));
+ }
+
+ i32 = archs[i].ntocs * sizeof(struct ranlib);
+ if(target_byte_sex != host_byte_sex)
+ i32 = SWAP_INT(i32);
+ memcpy(p, (char *)&i32, sizeof(uint32_t));
+ p += sizeof(uint32_t);
+
+ if(target_byte_sex != host_byte_sex)
+ swap_ranlib(archs[i].toc_ranlibs, archs[i].ntocs,
+ target_byte_sex);
+ memcpy(p, (char *)archs[i].toc_ranlibs,
+ archs[i].ntocs * sizeof(struct ranlib));
+ p += archs[i].ntocs * sizeof(struct ranlib);
+
+ i32 = archs[i].toc_strsize;
+ if(target_byte_sex != host_byte_sex)
+ i32 = SWAP_INT(i32);
+ memcpy(p, (char *)&i32, sizeof(uint32_t));
+ p += sizeof(uint32_t);
+
+ memcpy(p, (char *)archs[i].toc_strings, archs[i].toc_strsize);
+ p += archs[i].toc_strsize;
+
+ /*
+ * Put in the archive header and member contents for each
+ * member in the buffer.
+ */
+ for(j = 0; j < archs[i].nmembers; j++){
+ memcpy(p, (char *)(archs[i].members[j].ar_hdr),
+ sizeof(struct ar_hdr));
+ p += sizeof(struct ar_hdr);
+
+ if(archs[i].members[j].member_long_name == TRUE){
+ memcpy(p, archs[i].members[j].member_name,
+ archs[i].members[j].member_name_size);
+ p += round(archs[i].members[j].member_name_size, 8) +
+ (round(sizeof(struct ar_hdr), 8) -
+ sizeof(struct ar_hdr));
+ }
+
+ if(archs[i].members[j].type == OFILE_Mach_O){
+ /*
+ * ofile_map swaps the headers to the host_byte_sex if
+ * the object's byte sex is not the same as the host
+ * byte sex so if this is the case swap them back
+ * before writing them out.
+ */
+ memset(&dyst, '\0', sizeof(struct dysymtab_command));
+ if(archs[i].members[j].object->dyst != NULL)
+ dyst = *(archs[i].members[j].object->dyst);
+ if(archs[i].members[j].object->hints_cmd != NULL)
+ hints_cmd = *(archs[i].members[j].object->hints_cmd);
+ if(archs[i].members[j].object->object_byte_sex !=
+ host_byte_sex){
+ if(archs[i].members[j].object->mh != NULL){
+ if(swap_object_headers(
+ archs[i].members[j].object->mh,
+ archs[i].members[j].object->load_commands)
+ == FALSE)
+ fatal("internal error: "
+ "swap_object_headers() failed");
+ if(archs[i].members[j].object->output_nsymbols
+ != 0)
+ swap_nlist(
+ archs[i].members[j].object->
+ output_symbols,
+ archs[i].members[j].object->
+ output_nsymbols,
+ archs[i].members[j].object->
+ object_byte_sex);
+ }
+ else{
+ if(swap_object_headers(
+ archs[i].members[j].object->mh64,
+ archs[i].members[j].object->load_commands)
+ == FALSE)
+ fatal("internal error: "
+ "swap_object_headers() failed");
+ if(archs[i].members[j].object->output_nsymbols
+ != 0)
+ swap_nlist_64(
+ archs[i].members[j].object->
+ output_symbols64,
+ archs[i].members[j].object->
+ output_nsymbols,
+ archs[i].members[j].object->
+ object_byte_sex);
+ }
+ }
+ if(archs[i].members[j].object->
+ output_sym_info_size == 0 &&
+ archs[i].members[j].object->
+ input_sym_info_size == 0){
+ size = archs[i].members[j].object->object_size;
+ memcpy(p, archs[i].members[j].object->object_addr,
+ size);
+ }
+ else{
+ size = archs[i].members[j].object->object_size
+ - archs[i].members[j].object->
+ input_sym_info_size;
+ memcpy(p, archs[i].members[j].object->object_addr,
+ size);
+ copy_new_symbol_info(p, &size, &dyst,
+ archs[i].members[j].object->dyst, &hints_cmd,
+ archs[i].members[j].object->hints_cmd,
+ archs[i].members[j].object);
+ }
+ p += size;
+ pad = round(size, 8) - size;
+ }
+ else{
+ memcpy(p, archs[i].members[j].unknown_addr,
+ archs[i].members[j].unknown_size);
+ p += archs[i].members[j].unknown_size;
+ pad = round(archs[i].members[j].unknown_size, 8) -
+ archs[i].members[j].unknown_size;
+ }
+ /* as with the UNIX ar(1) program pad with '\n' chars */
+ for(k = 0; k < pad; k++)
+ *p++ = '\n';
+ }
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ memset(&dyst, '\0', sizeof(struct dysymtab_command));
+ if(archs[i].object->dyst != NULL)
+ dyst = *(archs[i].object->dyst);
+ if(archs[i].object->hints_cmd != NULL)
+ hints_cmd = *(archs[i].object->hints_cmd);
+ if(archs[i].object->mh_filetype == MH_DYLIB){
+ /*
+ * To avoid problems with prebinding and multiple
+ * cpusubtypes we stager the time stamps of fat dylibs
+ * that have more than one cpusubtype.
+ */
+ timestamp = 0;
+ for(index = i - 1; timestamp == 0 && index >= 0; index--){
+ if(archs[index].type == OFILE_Mach_O &&
+ archs[index].object->mh_filetype == MH_DYLIB &&
+ archs[index].object->mh_cputype ==
+ archs[i].object->mh_cputype){
+ if(archs[index].object->mh != NULL)
+ ncmds = archs[index].object->mh->ncmds;
+ else
+ ncmds = archs[index].object->mh64->ncmds;
+ lcp = archs[index].object->load_commands;
+ swapped = archs[index].object->object_byte_sex !=
+ host_byte_sex;
+ if(swapped)
+ ncmds = SWAP_INT(ncmds);
+ for(j = 0; j < ncmds; j++){
+ lc = *lcp;
+ if(swapped)
+ swap_load_command(&lc, host_byte_sex);
+ if(lc.cmd == LC_ID_DYLIB){
+ dlp = (struct dylib_command *)lcp;
+ dl = *dlp;
+ if(swapped)
+ swap_dylib_command(&dl, host_byte_sex);
+ timestamp = dl.dylib.timestamp - 1;
+ break;
+ }
+ lcp = (struct load_command *)
+ ((char *)lcp + lc.cmdsize);
+ }
+ }
+ }
+ if(timestamp == 0)
+ timestamp = toc_time;
+ lcp = archs[i].object->load_commands;
+ if(archs[i].object->mh != NULL)
+ ncmds = archs[i].object->mh->ncmds;
+ else
+ ncmds = archs[i].object->mh64->ncmds;
+ for(j = 0; j < ncmds; j++){
+ if(lcp->cmd == LC_ID_DYLIB){
+ dlp = (struct dylib_command *)lcp;
+ if(archs[i].dont_update_LC_ID_DYLIB_timestamp ==
+ FALSE)
+ dlp->dylib.timestamp = timestamp;
+ break;
+ }
+ lcp = (struct load_command *)((char *)lcp +
+ lcp->cmdsize);
+ }
+ }
+ if(archs[i].object->object_byte_sex != host_byte_sex){
+ if(archs[i].object->mh != NULL){
+ if(swap_object_headers(archs[i].object->mh,
+ archs[i].object->load_commands) == FALSE)
+ fatal("internal error: swap_object_headers() "
+ "failed");
+ if(archs[i].object->output_nsymbols != 0)
+ swap_nlist(archs[i].object->output_symbols,
+ archs[i].object->output_nsymbols,
+ archs[i].object->object_byte_sex);
+ }
+ else{
+ if(swap_object_headers(archs[i].object->mh64,
+ archs[i].object->load_commands) == FALSE)
+ fatal("internal error: swap_object_headers() "
+ "failed");
+ if(archs[i].object->output_nsymbols != 0)
+ swap_nlist_64(archs[i].object->output_symbols64,
+ archs[i].object->output_nsymbols,
+ archs[i].object->object_byte_sex);
+ }
+ }
+ if(archs[i].object->output_sym_info_size == 0 &&
+ archs[i].object->input_sym_info_size == 0){
+ size = archs[i].object->object_size;
+ memcpy(p, archs[i].object->object_addr, size);
+ }
+ else{
+ size = archs[i].object->object_size
+ - archs[i].object->input_sym_info_size;
+ memcpy(p, archs[i].object->object_addr, size);
+ copy_new_symbol_info(p, &size, &dyst,
+ archs[i].object->dyst, &hints_cmd,
+ archs[i].object->hints_cmd,
+ archs[i].object);
+ }
+ }
+ else{ /* archs[i].type == OFILE_UNKNOWN */
+ memcpy(p, archs[i].unknown_addr, archs[i].unknown_size);
+ }
+ }
+#ifdef __LITTLE_ENDIAN__
+ if(narchs > 1 || archs[0].fat_arch != NULL){
+ swap_fat_header(fat_header, BIG_ENDIAN_BYTE_SEX);
+ swap_fat_arch(fat_arch, narchs, BIG_ENDIAN_BYTE_SEX);
+ }
+#endif /* __LITTLE_ENDIAN__ */
+ *outputbuf = file;
+ *length = file_size;
+}
+
+/*
+ * copy_new_symbol_info() copies the new and updated symbolic information into
+ * the buffer for the object.
+ */
+static
+void
+copy_new_symbol_info(
+char *p,
+unsigned long *size,
+struct dysymtab_command *dyst,
+struct dysymtab_command *old_dyst,
+struct twolevel_hints_command *hints_cmd,
+struct twolevel_hints_command *old_hints_cmd,
+struct object *object)
+{
+ if(old_dyst != NULL){
+ memcpy(p + *size, object->output_loc_relocs,
+ dyst->nlocrel * sizeof(struct relocation_info));
+ *size += dyst->nlocrel *
+ sizeof(struct relocation_info);
+ if(object->output_split_info_data_size != 0){
+ if(object->output_split_info_data != NULL)
+ memcpy(p + *size, object->output_split_info_data,
+ object->output_split_info_data_size);
+ *size += object->output_split_info_data_size;
+ }
+ if(object->mh != NULL){
+ memcpy(p + *size, object->output_symbols,
+ object->output_nsymbols * sizeof(struct nlist));
+ *size += object->output_nsymbols *
+ sizeof(struct nlist);
+ }
+ else{
+ memcpy(p + *size, object->output_symbols64,
+ object->output_nsymbols * sizeof(struct nlist_64));
+ *size += object->output_nsymbols *
+ sizeof(struct nlist_64);
+ }
+ if(old_hints_cmd != NULL){
+ memcpy(p + *size, object->output_hints,
+ hints_cmd->nhints * sizeof(struct twolevel_hint));
+ *size += hints_cmd->nhints *
+ sizeof(struct twolevel_hint);
+ }
+ memcpy(p + *size, object->output_ext_relocs,
+ dyst->nextrel * sizeof(struct relocation_info));
+ *size += dyst->nextrel *
+ sizeof(struct relocation_info);
+ memcpy(p + *size, object->output_indirect_symtab,
+ dyst->nindirectsyms * sizeof(uint32_t));
+ *size += dyst->nindirectsyms * sizeof(uint32_t) +
+ object->input_indirectsym_pad;
+ memcpy(p + *size, object->output_tocs,
+ object->output_ntoc *sizeof(struct dylib_table_of_contents));
+ *size += object->output_ntoc *
+ sizeof(struct dylib_table_of_contents);
+ if(object->mh != NULL){
+ memcpy(p + *size, object->output_mods,
+ object->output_nmodtab * sizeof(struct dylib_module));
+ *size += object->output_nmodtab *
+ sizeof(struct dylib_module);
+ }
+ else{
+ memcpy(p + *size, object->output_mods64,
+ object->output_nmodtab * sizeof(struct dylib_module_64));
+ *size += object->output_nmodtab *
+ sizeof(struct dylib_module_64);
+ }
+ memcpy(p + *size, object->output_refs,
+ object->output_nextrefsyms * sizeof(struct dylib_reference));
+ *size += object->output_nextrefsyms *
+ sizeof(struct dylib_reference);
+ memcpy(p + *size, object->output_strings,
+ object->output_strings_size);
+ *size += object->output_strings_size;
+ if(object->output_code_sig_data_size != 0){
+ *size = round(*size, 16);
+ if(object->output_code_sig_data != NULL)
+ memcpy(p + *size, object->output_code_sig_data,
+ object->output_code_sig_data_size);
+ *size += object->output_code_sig_data_size;
+ }
+ }
+ else{
+ if(object->mh != NULL){
+ memcpy(p + *size, object->output_symbols,
+ object->output_nsymbols * sizeof(struct nlist));
+ *size += object->output_nsymbols *
+ sizeof(struct nlist);
+ }
+ else{
+ memcpy(p + *size, object->output_symbols64,
+ object->output_nsymbols * sizeof(struct nlist_64));
+ *size += object->output_nsymbols *
+ sizeof(struct nlist_64);
+ }
+ memcpy(p + *size, object->output_strings,
+ object->output_strings_size);
+ *size += object->output_strings_size;
+ if(object->output_code_sig_data_size != 0){
+ *size = round(*size, 16);
+ if(object->output_code_sig_data != NULL)
+ memcpy(p + *size, object->output_code_sig_data,
+ object->output_code_sig_data_size);
+ *size += object->output_code_sig_data_size;
+ }
+ }
+}
+
+/*
+ * make_table_of_contents() make the table of contents for the specified arch
+ * and fills in the toc_* fields in the arch. Output is the name of the output
+ * file for error messages.
+ */
+static
+void
+make_table_of_contents(
+struct arch *arch,
+char *output,
+long toc_time,
+enum bool sort_toc,
+enum bool commons_in_toc,
+enum bool library_warnings)
+{
+ unsigned long i, j, k, r, s, nsects;
+ struct member *member;
+ struct object *object;
+ struct load_command *lc;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct nlist *symbols;
+ struct nlist_64 *symbols64;
+ unsigned long nsymbols;
+ char *strings;
+ unsigned long strings_size;
+ enum bool sorted;
+ unsigned short toc_mode;
+ int oumask, numask;
+ char *ar_name;
+ struct section *section;
+ struct section_64 *section64;
+ uint32_t ncmds;
+
+ symbols = NULL; /* here to quite compiler maybe warning message */
+ symbols64 = NULL;
+ strings = NULL; /* here to quite compiler maybe warning message */
+
+ /*
+ * First pass over the members to count how many ranlib structs are
+ * needed and the size of the strings in the toc that are needed.
+ */
+ for(i = 0; i < arch->nmembers; i++){
+ member = arch->members + i;
+ if(member->type == OFILE_Mach_O){
+ object = member->object;
+ nsymbols = 0;
+ nsects = 0;
+ lc = object->load_commands;
+ if(object->mh != NULL)
+ ncmds = object->mh->ncmds;
+ else
+ ncmds = object->mh64->ncmds;
+ for(j = 0; j < ncmds; j++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ nsects += sg->nsects;
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ nsects += sg64->nsects;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->mh != NULL){
+ object->sections = allocate(nsects *
+ sizeof(struct section *));
+ object->sections64 = NULL;
+ }
+ else{
+ object->sections = NULL;
+ object->sections64 = allocate(nsects *
+ sizeof(struct section_64 *));
+ }
+ nsects = 0;
+ lc = object->load_commands;
+ for(j = 0; j < ncmds; j++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ section = (struct section *)
+ ((char *)sg + sizeof(struct segment_command));
+ for(k = 0; k < sg->nsects; k++){
+ object->sections[nsects++] = section++;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ section64 = (struct section_64 *)
+ ((char *)sg64 + sizeof(struct segment_command_64));
+ for(k = 0; k < sg64->nsects; k++){
+ object->sections64[nsects++] = section64++;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->output_sym_info_size == 0){
+ lc = object->load_commands;
+ for(j = 0; j < ncmds; j++){
+ if(lc->cmd == LC_SYMTAB){
+ object->st = (struct symtab_command *)lc;
+ break;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->st != NULL && object->st->nsyms != 0){
+ if(object->mh != NULL){
+ symbols = (struct nlist *)(object->object_addr +
+ object->st->symoff);
+ if(object->object_byte_sex != get_host_byte_sex())
+ swap_nlist(symbols, object->st->nsyms,
+ get_host_byte_sex());
+ }
+ else{
+ symbols64 = (struct nlist_64 *)
+ (object->object_addr + object->st->symoff);
+ if(object->object_byte_sex != get_host_byte_sex())
+ swap_nlist_64(symbols64, object->st->nsyms,
+ get_host_byte_sex());
+ }
+ nsymbols = object->st->nsyms;
+ strings = object->object_addr + object->st->stroff;
+ strings_size = object->st->strsize;
+ }
+ }
+ else /* object->output_sym_info_size != 0 */ {
+ if(object->mh != NULL)
+ symbols = object->output_symbols;
+ else
+ symbols64 = object->output_symbols64;
+ nsymbols = object->output_nsymbols;
+ strings = object->output_strings;
+ strings_size = object->output_strings_size;
+ }
+ for(j = 0; j < nsymbols; j++){
+ if(object->mh != NULL){
+ if(toc_symbol(symbols + j, commons_in_toc,
+ object->sections) == TRUE){
+ arch->ntocs++;
+ arch->toc_strsize +=
+ strlen(strings + symbols[j].n_un.n_strx) + 1;
+ }
+ }
+ else{
+ if(toc_symbol_64(symbols64 + j, commons_in_toc,
+ object->sections64) == TRUE){
+ arch->ntocs++;
+ arch->toc_strsize +=
+ strlen(strings + symbols64[j].n_un.n_strx) + 1;
+ }
+ }
+ }
+ }
+ }
+
+ /*
+ * Allocate the space for the table of content entries, the ranlib
+ * structs and strings for the table of contents.
+ */
+ arch->toc_entries = allocate(sizeof(struct toc_entry) * arch->ntocs);
+ arch->toc_ranlibs = allocate(sizeof(struct ranlib) * arch->ntocs);
+ arch->toc_strsize = round(arch->toc_strsize, 8);
+ arch->toc_strings = allocate(arch->toc_strsize);
+
+ /*
+ * Second pass over the members to fill in the toc_entry structs and
+ * the strings for the table of contents. The symbol_name field is
+ * filled in with a pointer to a string contained in arch->toc_strings
+ * for easy sorting and conversion to an index. The member_index field
+ * is filled in with the member index plus one to allow marking with
+ * its negative value by check_sort_toc_entries() and easy conversion to
+ * the real offset.
+ */
+ r = 0;
+ s = 0;
+ for(i = 0; i < arch->nmembers; i++){
+ member = arch->members + i;
+ if(member->type == OFILE_Mach_O){
+ object = member->object;
+ nsymbols = 0;
+ if(object->output_sym_info_size == 0){
+ if(object->st != NULL){
+ if(object->mh != NULL)
+ symbols = (struct nlist *)
+ (object->object_addr + object->st->symoff);
+ else
+ symbols64 = (struct nlist_64 *)
+ (object->object_addr + object->st->symoff);
+ nsymbols = object->st->nsyms;
+ strings = object->object_addr + object->st->stroff;
+ strings_size = object->st->strsize;
+ }
+ else{
+ symbols = NULL;
+ nsymbols = 0;
+ strings = NULL;
+ strings_size = 0;
+ }
+ }
+ else{
+ if(object->mh != NULL)
+ symbols = object->output_symbols;
+ else
+ symbols64 = object->output_symbols64;
+ nsymbols = object->output_nsymbols;
+ strings = object->output_strings;
+ strings_size = object->output_strings_size;
+ }
+ for(j = 0; j < nsymbols; j++){
+ if(object->mh != NULL){
+ if((uint32_t)symbols[j].n_un.n_strx > strings_size)
+ continue;
+ if(toc_symbol(symbols + j, commons_in_toc,
+ object->sections) == TRUE){
+ strcpy(arch->toc_strings + s,
+ strings + symbols[j].n_un.n_strx);
+ arch->toc_entries[r].symbol_name =
+ arch->toc_strings + s;
+ arch->toc_entries[r].member_index = i + 1;
+ r++;
+ s += strlen(strings + symbols[j].n_un.n_strx) + 1;
+ }
+ }
+ else{
+ if((uint32_t)symbols64[j].n_un.n_strx >
+ strings_size)
+ continue;
+ if(toc_symbol_64(symbols64 + j, commons_in_toc,
+ object->sections64) == TRUE){
+ strcpy(arch->toc_strings + s,
+ strings + symbols64[j].n_un.n_strx);
+ arch->toc_entries[r].symbol_name =
+ arch->toc_strings + s;
+ arch->toc_entries[r].member_index = i + 1;
+ r++;
+ s += strlen(strings + symbols64[j].n_un.n_strx) + 1;
+ }
+ }
+ }
+ if(object->output_sym_info_size == 0){
+ if(object->object_byte_sex != get_host_byte_sex()){
+ if(object->mh != NULL)
+ swap_nlist(symbols, nsymbols,
+ object->object_byte_sex);
+ else
+ swap_nlist_64(symbols64, nsymbols,
+ object->object_byte_sex);
+ }
+ }
+ }
+ }
+
+ /*
+ * If the table of contents is to be sorted by symbol name then try to
+ * sort it and leave it sorted if no duplicates.
+ */
+ if(sort_toc == TRUE){
+ qsort(arch->toc_entries, arch->ntocs, sizeof(struct toc_entry),
+ (int (*)(const void *, const void *))toc_entry_name_qsort);
+ sorted = check_sort_toc_entries(arch, output, library_warnings);
+ if(sorted == FALSE){
+ qsort(arch->toc_entries, arch->ntocs, sizeof(struct toc_entry),
+ (int (*)(const void *, const void *))
+ toc_entry_index_qsort);
+ arch->toc_long_name = FALSE;
+ }
+ }
+ else{
+ sorted = FALSE;
+ arch->toc_long_name = FALSE;
+ }
+
+ /*
+ * Now set the ran_off and ran_un.ran_strx fields of the ranlib structs.
+ * To do this the size of the toc member must be know because it comes
+ * first in the library. The size of the toc member is made up of the
+ * sizeof an archive header struct, plus the sizeof the name if we are
+ * using extended format #1 for the long name, then the toc which is
+ * (as defined in ranlib.h):
+ * a 32-bit int for the number of bytes of the ranlib structs
+ * the ranlib structures
+ * a 32-bit int for the number of bytes of the strings
+ * the strings
+ */
+ /*
+ * We use a long name for the table of contents only for the sorted
+ * case. Which the name is SYMDEF_SORTED is "__.SYMDEF SORTED".
+ * This code assumes SYMDEF_SORTED is 16 characters.
+ */
+ if(arch->toc_long_name == TRUE){
+ /*
+ * This assumes that "__.SYMDEF SORTED" is 16 bytes and
+ * (round(sizeof(struct ar_hdr), 8) - sizeof(struct ar_hdr)
+ * is 4 bytes.
+ */
+ ar_name = AR_EFMT1 "20";
+ arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1;
+ arch->toc_name = SYMDEF_SORTED;
+ }
+ else{
+ if(sorted == TRUE){
+ ar_name = SYMDEF_SORTED;
+ arch->toc_name_size = sizeof(SYMDEF_SORTED) - 1;
+ arch->toc_name = ar_name;
+ }
+ else{
+ ar_name = SYMDEF;
+ arch->toc_name_size = sizeof(SYMDEF) - 1;
+ arch->toc_name = ar_name;
+ }
+ }
+ arch->toc_size = sizeof(struct ar_hdr) +
+ sizeof(uint32_t) +
+ arch->ntocs * sizeof(struct ranlib) +
+ sizeof(uint32_t) +
+ arch->toc_strsize;
+ if(arch->toc_long_name == TRUE)
+ arch->toc_size += arch->toc_name_size +
+ (round(sizeof(struct ar_hdr), 8) -
+ sizeof(struct ar_hdr));
+ for(i = 0; i < arch->nmembers; i++)
+ arch->members[i].offset += SARMAG + arch->toc_size;
+ for(i = 0; i < arch->ntocs; i++){
+ arch->toc_ranlibs[i].ran_un.ran_strx =
+ arch->toc_entries[i].symbol_name - arch->toc_strings;
+ arch->toc_ranlibs[i].ran_off =
+ arch->members[arch->toc_entries[i].member_index - 1].offset;
+ }
+
+ numask = 0;
+ oumask = umask(numask);
+ toc_mode = S_IFREG | (0666 & ~oumask);
+ (void)umask(oumask);
+
+ sprintf((char *)(&arch->toc_ar_hdr), "%-*s%-*ld%-*u%-*u%-*o%-*ld",
+ (int)sizeof(arch->toc_ar_hdr.ar_name),
+ ar_name,
+ (int)sizeof(arch->toc_ar_hdr.ar_date),
+ toc_time,
+ (int)sizeof(arch->toc_ar_hdr.ar_uid),
+ (unsigned short)getuid(),
+ (int)sizeof(arch->toc_ar_hdr.ar_gid),
+ (unsigned short)getgid(),
+ (int)sizeof(arch->toc_ar_hdr.ar_mode),
+ (unsigned int)toc_mode,
+ (int)sizeof(arch->toc_ar_hdr.ar_size),
+ (long)(arch->toc_size - sizeof(struct ar_hdr)));
+ /*
+ * This has to be done by hand because sprintf puts a null
+ * at the end of the buffer.
+ */
+ memcpy(arch->toc_ar_hdr.ar_fmag, ARFMAG,
+ (int)sizeof(arch->toc_ar_hdr.ar_fmag));
+}
+
+/*
+ * toc_symbol() returns TRUE if the symbol is to be included in the table of
+ * contents otherwise it returns FALSE.
+ */
+static
+enum bool
+toc_symbol(
+struct nlist *symbol,
+enum bool commons_in_toc,
+struct section **sections)
+{
+ return(toc(symbol->n_un.n_strx,
+ symbol->n_type,
+ symbol->n_value,
+ commons_in_toc,
+ (symbol->n_type & N_TYPE) == N_SECT &&
+ sections[symbol->n_sect - 1]->flags & S_ATTR_NO_TOC));
+}
+
+static
+enum bool
+toc_symbol_64(
+struct nlist_64 *symbol64,
+enum bool commons_in_toc,
+struct section_64 **sections64)
+{
+ return(toc(symbol64->n_un.n_strx,
+ symbol64->n_type,
+ symbol64->n_value,
+ commons_in_toc,
+ (symbol64->n_type & N_TYPE) == N_SECT &&
+ sections64[symbol64->n_sect-1]->flags & S_ATTR_NO_TOC));
+}
+
+static
+enum bool
+toc(
+uint32_t n_strx,
+uint8_t n_type,
+uint64_t n_value,
+enum bool commons_in_toc,
+enum bool attr_no_toc)
+{
+ /* if the name is NULL then it won't be in the table of contents */
+ if(n_strx == 0)
+ return(FALSE);
+ /* if symbol is not external then it won't be in the toc */
+ if((n_type & N_EXT) == 0)
+ return(FALSE);
+ /* if symbol is undefined then it won't be in the toc */
+ if((n_type & N_TYPE) == N_UNDF && n_value == 0)
+ return(FALSE);
+ /* if symbol is common and the commons are not to be in the toc */
+ if((n_type & N_TYPE) == N_UNDF && n_value != 0 &&
+ commons_in_toc == FALSE)
+ return(FALSE);
+ /* if the symbols is in a section marked NO_TOC then ... */
+ if(attr_no_toc != 0)
+ return(FALSE);
+
+ return(TRUE);
+}
+
+/*
+ * Function for qsort() for comparing toc_entry structures by name.
+ */
+static
+int
+toc_entry_name_qsort(
+const struct toc_entry *toc1,
+const struct toc_entry *toc2)
+{
+ return(strcmp(toc1->symbol_name, toc2->symbol_name));
+}
+
+/*
+ * Function for qsort() for comparing toc_entry structures by index.
+ */
+static
+int
+toc_entry_index_qsort(
+const struct toc_entry *toc1,
+const struct toc_entry *toc2)
+{
+ if(toc1->member_index < toc2->member_index)
+ return(-1);
+ if(toc1->member_index > toc2->member_index)
+ return(1);
+ /* toc1->member_index == toc2->member_index */
+ return(0);
+}
+
+/*
+ * check_sort_toc_entries() checks the table of contents for the specified arch
+ * which is sorted by name for more then one object defining the same symbol.
+ * If this is the case it prints each symbol that is defined in more than one
+ * object along with the object it is defined in. It returns TRUE if there are
+ * no multiple definitions and FALSE otherwise.
+ */
+static
+enum bool
+check_sort_toc_entries(
+struct arch *arch,
+char *output,
+enum bool library_warnings)
+{
+ unsigned long i;
+ enum bool multiple_defs;
+ struct member *member;
+
+ if(arch->ntocs == 0 || arch->ntocs == 1)
+ return(TRUE);
+
+ /*
+ * Since the symbol table is sorted by name look to any two adjcent
+ * entries with the same name. If such entries are found print them
+ * only once (marked by changing the sign of their member_index).
+ */
+ multiple_defs = FALSE;
+ for(i = 0; i < arch->ntocs - 1; i++){
+ if(strcmp(arch->toc_entries[i].symbol_name,
+ arch->toc_entries[i+1].symbol_name) == 0){
+ if(multiple_defs == FALSE){
+ if(library_warnings == FALSE)
+ return(FALSE);
+ fprintf(stderr, "%s: same symbol defined in more than one "
+ "member ", progname);
+ if(arch->fat_arch != NULL)
+ fprintf(stderr, "for architecture: %s ",
+ arch->fat_arch_name);
+ fprintf(stderr, "in: %s (table of contents will not be "
+ "sorted)\n", output);
+ multiple_defs = TRUE;
+ }
+ if(arch->toc_entries[i].member_index > 0){
+ member = arch->members +
+ arch->toc_entries[i].member_index - 1;
+ warn_member(arch, member, "defines symbol: %s",
+ arch->toc_entries[i].symbol_name);
+ arch->toc_entries[i].member_index =
+ -(arch->toc_entries[i].member_index);
+ }
+ if(arch->toc_entries[i+1].member_index > 0){
+ member = arch->members +
+ arch->toc_entries[i+1].member_index - 1;
+ warn_member(arch, member, "defines symbol: %s",
+ arch->toc_entries[i+1].symbol_name);
+ arch->toc_entries[i+1].member_index =
+ -(arch->toc_entries[i+1].member_index);
+ }
+ }
+ }
+
+ if(multiple_defs == FALSE)
+ return(TRUE);
+ else{
+ for(i = 0; i < arch->ntocs; i++)
+ if(arch->toc_entries[i].member_index < 0)
+ arch->toc_entries[i].member_index =
+ -(arch->toc_entries[i].member_index);
+ return(FALSE);
+ }
+}
+
+/*
+ * warn_member() is like the error routines it prints the program name the
+ * member name specified and message specified.
+ */
+static
+void
+warn_member(
+struct arch *arch,
+struct member *member,
+const char *format, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "%s: ", progname);
+ if(arch->fat_arch != NULL)
+ fprintf(stderr, "for architecture: %s ", arch->fat_arch_name);
+
+ if(member->input_ar_hdr != NULL){
+ fprintf(stderr, "file: %s(%.*s) ", member->input_file_name,
+ (int)member->member_name_size, member->member_name);
+ }
+ else
+ fprintf(stderr, "file: %s ", member->input_file_name);
+
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+}
+#endif /* !defined(RLD) */
new file mode 100644
--- /dev/null
+++ b/striptease/strip.c
@@ -0,0 +1,4816 @@
+/*
+ * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+/*
+ * The strip(1) and nmedit(l) program. This understands only Mach-O format
+ * files (with the restriction the symbol table is at the end of the file) and
+ * fat files with Mach-O files in them.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <libc.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <mach-o/loader.h>
+#include <mach-o/reloc.h>
+#include <mach-o/nlist.h>
+#include <mach-o/stab.h>
+#include "stuff/breakout.h"
+#include "stuff/allocate.h"
+#include "stuff/errors.h"
+#include "stuff/round.h"
+#include "stuff/reloc.h"
+#include "stuff/reloc.h"
+#include "stuff/symbol_list.h"
+#include "stuff/unix_standard_mode.h"
+
+/* These are set from the command line arguments */
+__private_extern__
+char *progname = NULL; /* name of the program for error messages (argv[0]) */
+static char *output_file;/* name of the output file */
+static char *sfile; /* filename of global symbol names to keep */
+static char *Rfile; /* filename of global symbol names to remove */
+static long Aflag; /* save only absolute symbols with non-zero value and
+ .objc_class_name_* symbols */
+static long iflag; /* -i ignore symbols in -s file not in object */
+#ifdef NMEDIT
+static long pflag; /* make all defined global symbols private extern */
+#else /* !defined(NMEDIT) */
+static char *dfile; /* filename of filenames of debugger symbols to keep */
+static long uflag; /* save undefined symbols */
+static long rflag; /* save symbols referenced dynamically */
+static long nflag; /* save N_SECT global symbols */
+static long Sflag; /* -S strip only debugger symbols N_STAB */
+static long xflag; /* -x strip non-globals */
+static long Xflag; /* -X strip local symbols with 'L' names */
+static long cflag; /* -c strip section contents from dynamic libraries
+ files to create stub libraries */
+static long no_uuid; /* -no_uuid strip LC_UUID load commands */
+static long strip_all = 1;
+/*
+ * This is set on an object by object basis if the strip_all flag is still set
+ * and the object is an executable that is for use with the dynamic linker.
+ * This has the same effect as -r and -u.
+ */
+static enum bool default_dyld_executable = FALSE;
+#endif /* NMEDIT */
+
+/*
+ * Data structures to perform selective stripping of symbol table entries.
+ * save_symbols is the names of the symbols from the -s <file> argument.
+ * remove_symbols is the names of the symbols from the -R <file> argument.
+ */
+static struct symbol_list *save_symbols = NULL;
+static unsigned long nsave_symbols = 0;
+static struct symbol_list *remove_symbols = NULL;
+static unsigned long nremove_symbols = 0;
+
+/*
+ * saves points to an array of longs that is allocated. This array is a map of
+ * old symbol indexes to new symbol indexes. The new symbol indexes are
+ * plus 1 and zero value means that old symbol is not in the new symbol table.
+ * ref_saves is used in the same way but for the reference table.
+ * nmedits is an array and indexed by the symbol index the value indicates if
+ * the symbol was edited and turned into a non-global.
+ */
+static long *saves = NULL;
+#ifndef NMEDIT
+static long *ref_saves = NULL;
+#else
+static enum bool *nmedits = NULL;
+#endif
+
+/*
+ * These hold the new symbol and string table created by strip_symtab()
+ * and the new counts of local, defined external and undefined symbols.
+ */
+static struct nlist *new_symbols = NULL;
+static struct nlist_64 *new_symbols64 = NULL;
+static unsigned long new_nsyms = 0;
+static char *new_strings = NULL;
+static unsigned long new_strsize = 0;
+static unsigned long new_nlocalsym = 0;
+static unsigned long new_nextdefsym = 0;
+static unsigned long new_nundefsym = 0;
+
+/*
+ * These hold the new table of contents, reference table and module table for
+ * dylibs.
+ */
+static struct dylib_table_of_contents *new_tocs = NULL;
+static unsigned long new_ntoc = 0;
+static struct dylib_reference *new_refs = NULL;
+static unsigned long new_nextrefsyms = 0;
+#ifdef NMEDIT
+static struct dylib_module *new_mods = NULL;
+static struct dylib_module_64 *new_mods64 = NULL;
+static unsigned long new_nmodtab = 0;
+#endif
+
+#ifndef NMEDIT
+/*
+ * The list of file names to save debugging symbols from.
+ */
+static char **debug_filenames = NULL;
+static long ndebug_filenames = 0;
+struct undef_map {
+ unsigned long index;
+ struct nlist symbol;
+};
+struct undef_map64 {
+ unsigned long index;
+ struct nlist_64 symbol64;
+};
+static char *qsort_strings = NULL;
+#endif /* !defined(NMEDIT) */
+
+
+/* Internal routines */
+static void usage(
+ void);
+
+static void strip_file(
+ char *input_file,
+ struct arch_flag *arch_flags,
+ unsigned long narch_flags,
+ enum bool all_archs);
+
+static void strip_arch(
+ struct arch *archs,
+ unsigned long narchs,
+ struct arch_flag *arch_flags,
+ unsigned long narch_flags,
+ enum bool all_archs);
+
+static void strip_object(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+
+static void check_object_relocs(
+ struct arch *arch,
+ struct member *member,
+ struct object *object,
+ char *segname,
+ char *sectname,
+ unsigned long long sectsize,
+ char *contents,
+ struct relocation_info *relocs,
+ uint32_t nreloc,
+ struct nlist *symbols,
+ struct nlist_64 *symbols64,
+ unsigned long nsyms,
+ char *strings,
+ long *missing_reloc_symbols,
+ enum byte_sex host_byte_sex);
+
+static void check_indirect_symtab(
+ struct arch *arch,
+ struct member *member,
+ struct object *object,
+ unsigned long nitems,
+ unsigned long reserved1,
+ unsigned long section_type,
+ char *contents,
+ struct nlist *symbols,
+ struct nlist_64 *symbols64,
+ unsigned long nsyms,
+ char *strings,
+ long *missing_reloc_symbols,
+ enum byte_sex host_byte_sex);
+
+#ifndef NMEDIT
+static enum bool strip_symtab(
+ struct arch *arch,
+ struct member *member,
+ struct object *object,
+ struct nlist *symbols,
+ struct nlist_64 *symbols64,
+ unsigned long nsyms,
+ char *strings,
+ unsigned long strsize,
+ struct dylib_table_of_contents *tocs,
+ unsigned long ntoc,
+ struct dylib_module *mods,
+ struct dylib_module_64 *mods64,
+ unsigned long nmodtab,
+ struct dylib_reference *refs,
+ unsigned long nextrefsyms,
+ uint32_t *indirectsyms,
+ unsigned long nindirectsyms);
+
+static void strip_LC_UUID_commands(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+
+#ifndef NMEDIT
+static void strip_LC_CODE_SIGNATURE_commands(
+ struct arch *arch,
+ struct member *member,
+ struct object *object);
+#endif /* !(NMEDIT) */
+
+static enum bool private_extern_reference_by_module(
+ unsigned long symbol_index,
+ struct dylib_reference *refs,
+ unsigned long nextrefsyms);
+
+static enum bool symbol_pointer_used(
+ unsigned long symbol_index,
+ uint32_t *indirectsyms,
+ unsigned long nindirectsyms);
+
+static int cmp_qsort_undef_map(
+ const struct undef_map *sym1,
+ const struct undef_map *sym2);
+
+static int cmp_qsort_undef_map_64(
+ const struct undef_map64 *sym1,
+ const struct undef_map64 *sym2);
+#endif /* !defined(NMEDIT) */
+
+#ifdef NMEDIT
+static enum bool edit_symtab(
+ struct arch *arch,
+ struct member *member,
+ struct object *object,
+ struct nlist *symbols,
+ struct nlist_64 *symbols64,
+ unsigned long nsyms,
+ char *strings,
+ unsigned long strsize,
+ struct dylib_table_of_contents *tocs,
+ unsigned long ntoc,
+ struct dylib_module *mods,
+ struct dylib_module_64 *mods64,
+ unsigned long nmodtab,
+ struct dylib_reference *refs,
+ unsigned long nextrefsyms);
+#endif /* NMEDIT */
+
+#ifndef NMEDIT
+static void setup_debug_filenames(
+ char *dfile);
+
+static int cmp_qsort_filename(
+ const char **name1,
+ const char **name2);
+
+static int cmp_bsearch_filename(
+ const char *name1,
+ const char **name2);
+#endif /* NMEDIT */
+
+#ifdef NMEDIT
+/*
+ * This variable and routines are used for nmedit(1) only.
+ */
+static char *global_strings = NULL;
+
+static int cmp_qsort_global(
+ const struct nlist **sym1,
+ const struct nlist **sym2);
+
+static int cmp_qsort_global_64(
+ const struct nlist_64 **sym1,
+ const struct nlist_64 **sym2);
+
+static int cmp_bsearch_global_stab(
+ const char *name,
+ const struct nlist **sym);
+
+static int cmp_bsearch_global_stab_64(
+ const char *name,
+ const struct nlist_64 **sym);
+
+static int cmp_bsearch_global(
+ const char *name,
+ const struct nlist **sym);
+
+static int cmp_bsearch_global_64(
+ const char *name,
+ const struct nlist_64 **sym);
+#endif /* NMEDIT */
+
+int
+main(
+int argc,
+char *argv[],
+char *envp[])
+{
+ int i;
+ unsigned long j, args_left, files_specified;
+ struct arch_flag *arch_flags;
+ unsigned long narch_flags;
+ enum bool all_archs;
+ struct symbol_list *sp;
+
+ progname = argv[0];
+
+ arch_flags = NULL;
+ narch_flags = 0;
+ all_archs = FALSE;
+
+ files_specified = 0;
+ args_left = 1;
+ for (i = 1; i < argc; i++){
+ if(argv[i][0] == '-'){
+ if(argv[i][1] == '\0'){
+ args_left = 0;
+ break;
+ }
+ if(strcmp(argv[i], "-o") == 0){
+ if(i + 1 >= argc)
+ fatal("-o requires an argument");
+ if(output_file != NULL)
+ fatal("only one -o option allowed");
+ output_file = argv[i + 1];
+ i++;
+ }
+ else if(strcmp(argv[i], "-s") == 0){
+ if(i + 1 >= argc)
+ fatal("-s requires an argument");
+ if(sfile != NULL)
+ fatal("only one -s option allowed");
+ sfile = argv[i + 1];
+ i++;
+ }
+ else if(strcmp(argv[i], "-R") == 0){
+ if(i + 1 >= argc)
+ fatal("-R requires an argument");
+ if(Rfile != NULL)
+ fatal("only one -R option allowed");
+ Rfile = argv[i + 1];
+ i++;
+ }
+#ifndef NMEDIT
+ else if(strcmp(argv[i], "-d") == 0){
+ if(i + 1 >= argc)
+ fatal("-d requires an argument");
+ if(dfile != NULL)
+ fatal("only one -d option allowed");
+ dfile = argv[i + 1];
+ i++;
+ }
+ else if(strcmp(argv[i], "-no_uuid") == 0){
+ no_uuid = 1;
+ }
+#endif /* !defined(NMEDIT) */
+ else if(strcmp(argv[i], "-arch") == 0){
+ if(i + 1 == argc){
+ error("missing argument(s) to %s option", argv[i]);
+ usage();
+ }
+ if(strcmp("all", argv[i+1]) == 0){
+ all_archs = TRUE;
+ }
+ else{
+ arch_flags = reallocate(arch_flags,
+ (narch_flags + 1) * sizeof(struct arch_flag));
+ if(get_arch_from_flag(argv[i+1],
+ arch_flags + narch_flags) == 0){
+ error("unknown architecture specification flag: "
+ "%s %s", argv[i], argv[i+1]);
+ arch_usage();
+ usage();
+ }
+ for(j = 0; j < narch_flags; j++){
+ if(arch_flags[j].cputype ==
+ arch_flags[narch_flags].cputype &&
+ (arch_flags[j].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[narch_flags].cpusubtype &
+ ~CPU_SUBTYPE_MASK) &&
+ strcmp(arch_flags[j].name,
+ arch_flags[narch_flags].name) == 0)
+ break;
+ }
+ if(j == narch_flags)
+ narch_flags++;
+ }
+ i++;
+ }
+ else{
+ for(j = 1; argv[i][j] != '\0'; j++){
+ switch(argv[i][j]){
+#ifdef NMEDIT
+ case 'p':
+ pflag = 1;
+ break;
+#else /* !defined(NMEDIT) */
+ case 'S':
+ Sflag = 1;
+ strip_all = 0;
+ break;
+ case 'X':
+ Xflag = 1;
+ strip_all = 0;
+ break;
+ case 'x':
+ xflag = 1;
+ strip_all = 0;
+ break;
+ case 'i':
+ iflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ strip_all = 0;
+ break;
+ case 'r':
+ rflag = 1;
+ strip_all = 0;
+ break;
+ case 'n':
+ nflag = 1;
+ strip_all = 0;
+ break;
+#endif /* !defined(NMEDIT) */
+ case 'A':
+ Aflag = 1;
+#ifndef NMEDIT
+ strip_all = 0;
+#endif /* !defined(NMEDIT) */
+ break;
+#ifndef NMEDIT
+ case 'c':
+ cflag = 1;
+ strip_all = 0;
+ break;
+#endif /* NMEDIT */
+ default:
+ error("unrecognized option: %s", argv[i]);
+ usage();
+ }
+ }
+ }
+ }
+ else
+ files_specified++;
+ }
+ if(args_left == 0)
+ files_specified += argc - (i + 1);
+
+ if(files_specified > 1 && output_file != NULL){
+ error("-o <filename> can only be used when one file is specified");
+ usage();
+ }
+
+ if(sfile){
+ setup_symbol_list(sfile, &save_symbols, &nsave_symbols);
+ }
+#ifdef NMEDIT
+ else{
+ if(Rfile == NULL && pflag == 0){
+ error("-s <filename>, -R <filename> or -p argument required");
+ usage();
+ }
+ }
+#endif /* NMEDIT */
+
+ if(Rfile){
+ setup_symbol_list(Rfile, &remove_symbols, &nremove_symbols);
+ if(sfile){
+ for(j = 0; j < nremove_symbols ; j++){
+ sp = bsearch(remove_symbols[j].name,
+ save_symbols, nsave_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ error("symbol name: %s is listed in both -s %s and -R "
+ "%s files (can't be both saved and removed)",
+ remove_symbols[j].name, sfile, Rfile);
+ }
+ }
+ if(errors)
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ /* the default when no -arch flags is present is to strip all archs */
+ if(narch_flags == 0)
+ all_archs = TRUE;
+
+#ifndef NMEDIT
+ if(dfile){
+ setup_debug_filenames(dfile);
+ }
+#endif /* !defined(NMEDIT) */
+
+ files_specified = 0;
+ args_left = 1;
+ for (i = 1; i < argc; i++) {
+ if(args_left && argv[i][0] == '-'){
+ if(argv[i][1] == '\0')
+ args_left = 0;
+ else if(strcmp(argv[i], "-o") == 0 ||
+ strcmp(argv[i], "-s") == 0 ||
+ strcmp(argv[i], "-R") == 0 ||
+#ifndef NMEDIT
+ strcmp(argv[i], "-d") == 0 ||
+#endif /* !defined(NMEDIT) */
+ strcmp(argv[i], "-arch") == 0)
+ i++;
+ }
+ else{
+ char resolved_path[PATH_MAX + 1];
+
+ if(realpath(argv[i], resolved_path) == NULL)
+ strip_file(argv[i], arch_flags, narch_flags, all_archs);
+ else
+ strip_file(resolved_path, arch_flags,narch_flags,all_archs);
+ files_specified++;
+ }
+ }
+ if(files_specified == 0)
+ fatal("no files specified");
+
+ if(errors)
+ return(EXIT_FAILURE);
+ else
+ return(EXIT_SUCCESS);
+}
+
+static
+void
+usage(
+void)
+{
+#ifndef NMEDIT
+ fprintf(stderr, "Usage: %s [-AnuSXx] [-] [-d filename] [-s filename] "
+ "[-R filename] [-o output] file [...] \n", progname);
+#else /* defined(NMEDIT) */
+ fprintf(stderr, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
+ "[-o output] file [...] \n",
+ progname);
+#endif /* NMEDIT */
+ exit(EXIT_FAILURE);
+}
+
+static
+void
+strip_file(
+char *input_file,
+struct arch_flag *arch_flags,
+unsigned long narch_flags,
+enum bool all_archs)
+{
+ struct arch *archs;
+ unsigned long narchs;
+ struct stat stat_buf;
+ unsigned long previous_errors;
+ enum bool unix_standard_mode;
+ int cwd_fd;
+ char *rename_file;
+#ifndef NMEDIT
+ char *p;
+#endif
+
+ archs = NULL;
+ narchs = 0;
+ previous_errors = errors;
+ errors = 0;
+
+ /* breakout the file for processing */
+ breakout(input_file, &archs, &narchs, FALSE);
+ if(errors)
+ return;
+
+ /* checkout the file for symbol table replacement processing */
+ checkout(archs, narchs);
+
+ /* process the symbols in the input file */
+ strip_arch(archs, narchs, arch_flags, narch_flags, all_archs);
+ if(errors)
+ return;
+
+ /* create the output file */
+ if(stat(input_file, &stat_buf) == -1)
+ system_error("can't stat input file: %s", input_file);
+ if(output_file != NULL){
+ writeout(archs, narchs, output_file, stat_buf.st_mode & 0777,
+ TRUE, FALSE, FALSE, NULL);
+ }
+ else{
+ unix_standard_mode = get_unix_standard_mode();
+ rename_file = NULL;
+ cwd_fd = -1;
+#ifdef NMEDIT
+ output_file = makestr(input_file, ".nmedit", NULL);
+#else /* !defined(NMEDIT) */
+ /*
+ * In UNIX standard conformance mode we are not allowed to replace
+ * a file that is not writeable.
+ */
+ if(unix_standard_mode == TRUE &&
+ access(input_file, W_OK) == -1){
+ system_error("file: %s is not writable", input_file);
+ goto strip_file_return;
+ }
+ output_file = makestr(input_file, ".strip", NULL);
+
+ /*
+ * The UNIX standard conformance test suite expects files of
+ * MAXPATHLEN to work.
+ */
+ if(strlen(output_file) >= MAXPATHLEN){
+ /*
+ * If there is a directory path in the name try to change
+ * the current working directory to that path.
+ */
+ if((p = rindex(output_file, '/')) != NULL){
+ if((cwd_fd = open(".", O_RDONLY, 0)) == -1){
+ system_error("can't open current working directory");
+ goto strip_file_return;
+ }
+ *p = '\0';
+ if(chdir(output_file) == -1){
+ system_error("can't change current working directory "
+ "to: %s", output_file);
+ goto strip_file_return;
+ }
+ p = rindex(input_file, '/');
+ rename_file = makestr(p + 1, NULL);
+ }
+ /*
+ * Create what might be a short enough name.
+ */
+ free(output_file);
+ output_file = makestr("strip.XXXXXX", NULL);
+ output_file = mktemp(output_file);
+ }
+#endif /* NMEDIT */
+ writeout(archs, narchs, output_file, stat_buf.st_mode & 0777,
+ TRUE, FALSE, FALSE, NULL);
+ if(rename_file != NULL){
+ if(rename(output_file, rename_file) == -1)
+ system_error("can't move temporary file: %s to file: %s",
+ output_file, rename_file);
+ free(rename_file);
+ }
+ else{
+ if(rename(output_file, input_file) == -1)
+ system_error("can't move temporary file: %s to input "
+ "file: %s", output_file, input_file);
+ }
+ free(output_file);
+ output_file = NULL;
+
+ /*
+ * If we changed the current working directory change back to
+ * the previous working directory.
+ */
+ if(cwd_fd != -1){
+ if(fchdir(cwd_fd) == -1)
+ system_error("can't change back to previous working "
+ "directory");
+ if(close(cwd_fd) == -1)
+ system_error("can't close previous working directory");
+ }
+ }
+
+#ifndef NMEDIT
+strip_file_return:
+#endif /* !defined(NMEDIT) */
+ /* clean-up data structures */
+ free_archs(archs, narchs);
+
+ errors += previous_errors;
+}
+
+static
+void
+strip_arch(
+struct arch *archs,
+unsigned long narchs,
+struct arch_flag *arch_flags,
+unsigned long narch_flags,
+enum bool all_archs)
+{
+ unsigned long i, j, k, offset, size, missing_syms;
+ cpu_type_t cputype;
+ cpu_subtype_t cpusubtype;
+ struct arch_flag host_arch_flag;
+ enum bool arch_process, any_processing, *arch_flag_processed, family;
+ const struct arch_flag *family_arch_flag;
+
+ /*
+ * Using the specified arch_flags process specified objects for those
+ * architecures.
+ */
+ any_processing = FALSE;
+ arch_flag_processed = NULL;
+ if(narch_flags != 0)
+ arch_flag_processed = allocate(narch_flags * sizeof(enum bool));
+ memset(arch_flag_processed, '\0', narch_flags * sizeof(enum bool));
+ for(i = 0; i < narchs; i++){
+ /*
+ * Determine the architecture (cputype and cpusubtype) of arch[i]
+ */
+ cputype = 0;
+ cpusubtype = 0;
+ if(archs[i].type == OFILE_ARCHIVE){
+ for(j = 0; j < archs[i].nmembers; j++){
+ if(archs[i].members[j].type == OFILE_Mach_O){
+ cputype = archs[i].members[j].object->mh_cputype;
+ cpusubtype = archs[i].members[j].object->mh_cpusubtype;
+ break;
+ }
+ }
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ cputype = archs[i].object->mh_cputype;
+ cpusubtype = archs[i].object->mh_cpusubtype;
+ }
+ else if(archs[i].fat_arch != NULL){
+ cputype = archs[i].fat_arch->cputype;
+ cpusubtype = archs[i].fat_arch->cpusubtype;
+ }
+ arch_process = FALSE;
+ if(all_archs == TRUE){
+ arch_process = TRUE;
+ }
+ else if(narch_flags != 0){
+ family = FALSE;
+ if(narch_flags == 1){
+ family_arch_flag =
+ get_arch_family_from_cputype(arch_flags[0].cputype);
+ if(family_arch_flag != NULL)
+ family = (enum bool)
+ ((family_arch_flag->cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (arch_flags[0].cpusubtype & ~CPU_SUBTYPE_MASK));
+ }
+ for(j = 0; j < narch_flags; j++){
+ if(arch_flags[j].cputype == cputype &&
+ ((arch_flags[j].cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (cpusubtype & ~CPU_SUBTYPE_MASK) ||
+ family == TRUE)){
+ arch_process = TRUE;
+ arch_flag_processed[j] = TRUE;
+ break;
+ }
+ }
+ }
+ else{
+ (void)get_arch_from_host(&host_arch_flag, NULL);
+ if(host_arch_flag.cputype == cputype &&
+ (host_arch_flag.cpusubtype & ~CPU_SUBTYPE_MASK) ==
+ (cpusubtype & ~CPU_SUBTYPE_MASK))
+ arch_process = TRUE;
+ }
+ if(narchs != 1 && arch_process == FALSE)
+ continue;
+ any_processing = TRUE;
+
+ /*
+ * Now this arch[i] has been selected to be processed so process it
+ * according to its type.
+ */
+ if(archs[i].type == OFILE_ARCHIVE){
+ for(j = 0; j < archs[i].nmembers; j++){
+ if(archs[i].members[j].type == OFILE_Mach_O){
+ strip_object(archs + i, archs[i].members + j,
+ archs[i].members[j].object);
+ }
+ }
+ missing_syms = 0;
+ if(iflag == 0){
+ for(k = 0; k < nsave_symbols; k++){
+ if(save_symbols[k].seen == FALSE){
+ if(missing_syms == 0){
+ error_arch(archs + i, NULL, "symbols names "
+ "listed in: %s not in: ", sfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", save_symbols[k].name);
+ }
+ }
+ }
+ for(k = 0; k < nsave_symbols; k++){
+ save_symbols[k].seen = FALSE;
+ }
+ missing_syms = 0;
+ if(iflag == 0){
+ for(k = 0; k < nremove_symbols; k++){
+ if(remove_symbols[k].seen == FALSE){
+ if(missing_syms == 0){
+ error_arch(archs + i, NULL, "symbols names "
+ "listed in: %s not defined in: ",
+ Rfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", remove_symbols[k].name);
+ }
+ }
+ }
+ for(k = 0; k < nremove_symbols; k++){
+ remove_symbols[k].seen = FALSE;
+ }
+ /*
+ * Reset the library offsets and size.
+ */
+ offset = 0;
+ for(j = 0; j < archs[i].nmembers; j++){
+ archs[i].members[j].offset = offset;
+ size = 0;
+ if(archs[i].members[j].member_long_name == TRUE){
+ size = round(archs[i].members[j].member_name_size, 8) +
+ (round(sizeof(struct ar_hdr), 8) -
+ sizeof(struct ar_hdr));
+ archs[i].toc_long_name = TRUE;
+ }
+ if(archs[i].members[j].object != NULL){
+ size +=
+ round(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));
+ /*
+ * This has to be done by hand because sprintf puts a
+ * null at the end of the buffer.
+ */
+ memcpy(archs[i].members[j].ar_hdr->ar_fmag, ARFMAG,
+ (int)sizeof(archs[i].members[j].ar_hdr->ar_fmag));
+ }
+ else{
+ size += archs[i].members[j].unknown_size;
+ }
+ offset += sizeof(struct ar_hdr) + size;
+ }
+ archs[i].library_size = offset;
+ }
+ else if(archs[i].type == OFILE_Mach_O){
+ strip_object(archs + i, NULL, archs[i].object);
+ }
+ else {
+ warning_arch(archs + i, NULL, "can't process non-object and "
+ "non-archive file: ");
+ return;
+ }
+ }
+ if(all_archs == FALSE && narch_flags != 0){
+ for(i = 0; i < narch_flags; i++){
+ if(arch_flag_processed[i] == FALSE)
+ error("file: %s does not contain architecture: %s",
+ archs[0].file_name, arch_flags[i].name);
+ }
+ free(arch_flag_processed);
+ }
+ if(any_processing == FALSE)
+ fatal("no processing done on input file: %s (specify a -arch flag)",
+ archs[0].file_name);
+}
+
+static
+void
+strip_object(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ enum byte_sex host_byte_sex;
+ struct nlist *symbols;
+ struct nlist_64 *symbols64;
+ unsigned long nsyms;
+ char *strings;
+ unsigned long strsize;
+ unsigned long offset;
+ struct dylib_table_of_contents *tocs;
+ unsigned long ntoc;
+ struct dylib_module *mods;
+ struct dylib_module_64 *mods64;
+ unsigned long nmodtab;
+ struct dylib_reference *refs;
+ unsigned long nextrefsyms;
+ uint32_t *indirectsyms;
+ unsigned long nindirectsyms;
+ unsigned long i, j;
+ struct load_command *lc;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct section *s;
+ struct section_64 *s64;
+ struct relocation_info *relocs;
+ struct scattered_relocation_info *sreloc;
+ long missing_reloc_symbols;
+ unsigned long stride, section_type, nitems;
+ char *contents;
+#ifndef NMEDIT
+ uint32_t flags;
+ unsigned long k;
+#endif
+ uint32_t ncmds;
+
+ host_byte_sex = get_host_byte_sex();
+
+ /* Don't do anything to stub dylibs which have no load commands. */
+ if(object->mh_filetype == MH_DYLIB_STUB){
+ if((object->mh != NULL && object->mh->ncmds == 0) ||
+ (object->mh64 != NULL && object->mh64->ncmds == 0)){
+ return;
+ }
+ }
+ if(object->st == NULL || object->st->nsyms == 0){
+ warning_arch(arch, member, "input object file stripped: ");
+ return;
+ }
+
+ nsyms = object->st->nsyms;
+ if(object->mh != NULL){
+ symbols = (struct nlist *)
+ (object->object_addr + object->st->symoff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_nlist(symbols, nsyms, host_byte_sex);
+ symbols64 = NULL;
+ }
+ else{
+ symbols = NULL;
+ symbols64 = (struct nlist_64 *)
+ (object->object_addr + object->st->symoff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_nlist_64(symbols64, nsyms, host_byte_sex);
+ }
+ strings = object->object_addr + object->st->stroff;
+ strsize = object->st->strsize;
+
+#ifndef NMEDIT
+ if(object->mh != NULL)
+ flags = object->mh->flags;
+ else
+ flags = object->mh64->flags;
+ if(object->mh_filetype == MH_DYLIB &&
+ (flags & MH_PREBOUND) != MH_PREBOUND){
+ arch->dont_update_LC_ID_DYLIB_timestamp = TRUE;
+ }
+ if(object->mh_filetype != MH_DYLIB && cflag)
+ fatal_arch(arch, member, "-c can't be used on non-dynamic "
+ "library: ");
+#endif /* !(NMEDIT) */
+ if(object->mh_filetype == MH_DYLIB_STUB)
+ fatal_arch(arch, member, "dynamic stub library can't be changed "
+ "once created: ");
+
+ if(object->mh_filetype == MH_DYLIB){
+ tocs = (struct dylib_table_of_contents *)
+ (object->object_addr + object->dyst->tocoff);
+ ntoc = object->dyst->ntoc;
+ nmodtab = object->dyst->nmodtab;
+ if(object->mh != NULL){
+ mods = (struct dylib_module *)
+ (object->object_addr + object->dyst->modtaboff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_dylib_module(mods, nmodtab, host_byte_sex);
+ mods64 = NULL;
+ }
+ else{
+ mods = NULL;
+ mods64 = (struct dylib_module_64 *)
+ (object->object_addr + object->dyst->modtaboff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_dylib_module_64(mods64, nmodtab, host_byte_sex);
+ }
+ refs = (struct dylib_reference *)
+ (object->object_addr + object->dyst->extrefsymoff);
+ nextrefsyms = object->dyst->nextrefsyms;
+ if(object->object_byte_sex != host_byte_sex){
+ swap_dylib_table_of_contents(tocs, ntoc, host_byte_sex);
+ swap_dylib_reference(refs, nextrefsyms, host_byte_sex);
+ }
+#ifndef NMEDIT
+ /*
+ * In the -c flag is specified then strip the section contents of
+ * this dynamic library and change it into a stub library. When
+ * creating a stub library the timestamp is not changed.
+ */
+ if(cflag){
+ arch->dont_update_LC_ID_DYLIB_timestamp = TRUE;
+
+ lc = object->load_commands;
+ if(object->mh != NULL){
+ ncmds = object->mh->ncmds;
+ object->mh_filetype = MH_DYLIB_STUB;
+ object->mh->filetype = MH_DYLIB_STUB;
+ }
+ else{
+ ncmds = object->mh64->ncmds;
+ object->mh_filetype = MH_DYLIB_STUB;
+ object->mh64->filetype = MH_DYLIB_STUB;
+ }
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ if(strcmp(sg->segname, SEG_LINKEDIT) != 0){
+ /*
+ * Zero out the section offset, reloff, and size
+ * fields as the section contents are being removed.
+ */
+ s = (struct section *)
+ ((char *)sg + sizeof(struct segment_command));
+ 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.
+ */
+ section_type = s[j].flags & SECTION_TYPE;
+ if(section_type != S_SYMBOL_STUBS &&
+ section_type != S_LAZY_SYMBOL_POINTERS &&
+ section_type != S_NON_LAZY_SYMBOL_POINTERS){
+ s[j].size = 0;
+ }
+ s[j].addr = 0;
+ s[j].offset = 0;
+ s[j].reloff = 0;
+ }
+ /* zero out file offset and size in the segment */
+ sg->fileoff = 0;
+ sg->filesize = 0;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ if(strcmp(sg64->segname, SEG_LINKEDIT) != 0){
+ /*
+ * Zero out the section offset, reloff, and size
+ * fields as the section contents are being removed.
+ */
+ s64 = (struct section_64 *)
+ ((char *)sg64 +
+ sizeof(struct segment_command_64));
+ 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.
+ */
+ section_type = s64[j].flags & SECTION_TYPE;
+ if(section_type != S_SYMBOL_STUBS &&
+ section_type != S_LAZY_SYMBOL_POINTERS &&
+ section_type != S_NON_LAZY_SYMBOL_POINTERS){
+ s64[j].size = 0;
+ }
+ s64[j].addr = 0;
+ s64[j].offset = 0;
+ s64[j].reloff = 0;
+ }
+ /* zero out file offset and size in the segment */
+ sg64->fileoff = 0;
+ sg64->filesize = 0;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ /*
+ * To get the right amount of the file copied out by writeout()
+ * for the case when we are stripping out the section contents
+ * we reduce the object size by the size of the section contents
+ * including the padding after the load commands. Then this
+ * size minus the size of the input symbolic information is
+ * copied out.
+ */
+ if(object->mh != NULL){
+ object->object_size -= (object->seg_linkedit->fileoff -
+ (sizeof(struct mach_header) +
+ object->mh->sizeofcmds));
+ /*
+ * Set the file offset to the link edit information to be
+ * right after the load commands.
+ */
+ object->seg_linkedit->fileoff =
+ sizeof(struct mach_header) +
+ object->mh->sizeofcmds;
+ }
+ else{
+ object->object_size -= (object->seg_linkedit64->fileoff -
+ (sizeof(struct mach_header_64) +
+ object->mh64->sizeofcmds));
+ /*
+ * Set the file offset to the link edit information to be
+ * right after the load commands.
+ */
+ object->seg_linkedit64->fileoff =
+ sizeof(struct mach_header_64) +
+ object->mh64->sizeofcmds;
+ }
+ }
+#endif /* !(NMEDIT) */
+ }
+ else{
+ tocs = NULL;
+ ntoc = 0;
+ mods = NULL;
+ mods64 = NULL;
+ nmodtab = 0;
+ refs = NULL;
+ nextrefsyms = 0;
+ }
+
+ /*
+ * coalesced symbols can be stripped only if they are not used via an
+ * symbol pointer. So to know that strip_symtab() needs to be passed
+ * the indirect symbol table.
+ */
+ if(object->dyst != NULL && object->dyst->nindirectsyms != 0){
+ nindirectsyms = object->dyst->nindirectsyms;
+ indirectsyms = (uint32_t *)
+ (object->object_addr + object->dyst->indirectsymoff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_indirect_symbols(indirectsyms, nindirectsyms,
+ host_byte_sex);
+ }
+ else{
+ indirectsyms = NULL;
+ nindirectsyms = 0;
+ }
+
+ if(object->mh != NULL)
+ object->input_sym_info_size =
+ nsyms * sizeof(struct nlist) +
+ strsize;
+ else
+ object->input_sym_info_size =
+ nsyms * sizeof(struct nlist_64) +
+ strsize;
+#ifndef NMEDIT
+ if(object->mh != NULL)
+ flags = object->mh->flags;
+ else
+ flags = object->mh64->flags;
+ if(strip_all &&
+ (flags & MH_DYLDLINK) == MH_DYLDLINK &&
+ object->mh_filetype == MH_EXECUTE)
+ default_dyld_executable = TRUE;
+ else
+ default_dyld_executable = FALSE;
+#endif /* !defined(NMEDIT) */
+
+#ifndef NMEDIT
+ if(sfile != NULL || Rfile != NULL || dfile != NULL || Aflag || uflag ||
+ Sflag || xflag || Xflag || nflag || rflag ||
+ default_dyld_executable || object->mh_filetype == MH_DYLIB ||
+ object->mh_filetype == MH_DYLINKER)
+#endif /* !defined(NMEDIT) */
+ {
+#ifdef NMEDIT
+ if(edit_symtab(arch, member, object, symbols, symbols64, nsyms,
+ strings, strsize, tocs, ntoc, mods, mods64, nmodtab, refs,
+ nextrefsyms) == FALSE)
+ return;
+#else /* !defined(NMEDIT) */
+ if(strip_symtab(arch, member, object, symbols, symbols64, nsyms,
+ strings, strsize, tocs, ntoc, mods, mods64, nmodtab, refs,
+ nextrefsyms, indirectsyms, nindirectsyms) == FALSE)
+ return;
+ if(no_uuid == TRUE)
+ strip_LC_UUID_commands(arch, member, object);
+#endif /* !defined(NMEDIT) */
+ if(object->mh != NULL)
+ object->output_sym_info_size =
+ new_nsyms * sizeof(struct nlist) +
+ new_strsize;
+ else
+ object->output_sym_info_size =
+ new_nsyms * sizeof(struct nlist_64) +
+ new_strsize;
+
+ object->st->nsyms = new_nsyms;
+ object->st->strsize = new_strsize;
+
+ if(object->mh != NULL)
+ object->output_symbols = new_symbols;
+ else
+ object->output_symbols64 = new_symbols64;
+ object->output_nsymbols = new_nsyms;
+ object->output_strings = new_strings;
+ object->output_strings_size = new_strsize;
+
+ 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;
+ }
+ if(object->code_sig_cmd != NULL){
+#ifndef NMEDIT
+ if(!cflag)
+#endif /* !(NMEDIT) */
+ {
+ object->output_code_sig_data = object->object_addr +
+ object->code_sig_cmd->dataoff;
+ object->output_code_sig_data_size =
+ object->code_sig_cmd->datasize;
+ }
+ }
+
+ if(object->dyst != NULL){
+ object->dyst->ilocalsym = 0;
+ object->dyst->nlocalsym = new_nlocalsym;
+ object->dyst->iextdefsym = new_nlocalsym;
+ object->dyst->nextdefsym = new_nextdefsym;
+ 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);
+ }
+
+ /*
+ * If the -c option is specified the object's filetype will
+ * have been changed from MH_DYLIB to MH_DYLIB_STUB above.
+ */
+ if(object->mh_filetype == MH_DYLIB ||
+ object->mh_filetype == MH_DYLIB_STUB){
+ object->output_tocs = new_tocs;
+ object->output_ntoc = new_ntoc;
+#ifdef NMEDIT
+ if(object->mh != NULL)
+ object->output_mods = new_mods;
+ else
+ object->output_mods64 = new_mods64;
+ object->output_nmodtab = new_nmodtab;
+#else
+ object->output_mods = mods;
+ object->output_nmodtab = nmodtab;
+#endif
+ object->output_refs = new_refs;
+ object->output_nextrefsyms = new_nextrefsyms;
+ if(object->object_byte_sex != host_byte_sex){
+ swap_dylib_table_of_contents(new_tocs, new_ntoc,
+ object->object_byte_sex);
+#ifdef NMEDIT
+ if(object->mh != NULL)
+ swap_dylib_module(new_mods, new_nmodtab,
+ object->object_byte_sex);
+ else
+ swap_dylib_module_64(new_mods64, new_nmodtab,
+ object->object_byte_sex);
+#else
+ if(object->mh != NULL)
+ swap_dylib_module(mods, nmodtab,
+ object->object_byte_sex);
+ else
+ swap_dylib_module_64(mods64, nmodtab,
+ object->object_byte_sex);
+#endif
+ swap_dylib_reference(new_refs, new_nextrefsyms,
+ object->object_byte_sex);
+ }
+ }
+ object->input_sym_info_size +=
+ object->dyst->nlocrel * sizeof(struct relocation_info) +
+ object->dyst->nextrel * sizeof(struct relocation_info) +
+ object->dyst->ntoc * sizeof(struct dylib_table_of_contents)+
+ object->dyst->nextrefsyms * sizeof(struct dylib_reference);
+ if(object->mh != NULL){
+ object->input_sym_info_size +=
+ object->dyst->nmodtab * sizeof(struct dylib_module) +
+ object->dyst->nindirectsyms * sizeof(uint32_t);
+ }
+ else{
+ object->input_sym_info_size +=
+ object->dyst->nmodtab * sizeof(struct dylib_module_64) +
+ 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 relocation info also gets
+ * stripped.
+ */
+ if(!cflag)
+#endif /* !(NMEDIT) */
+ {
+ object->output_sym_info_size +=
+ object->dyst->nlocrel * sizeof(struct relocation_info) +
+ object->dyst->nextrel * sizeof(struct relocation_info);
+ }
+ object->output_sym_info_size +=
+ new_ntoc * sizeof(struct dylib_table_of_contents)+
+ new_nextrefsyms * sizeof(struct dylib_reference) +
+ object->dyst->nindirectsyms * sizeof(uint32_t) +
+ object->input_indirectsym_pad;
+ if(object->mh != NULL){
+ object->output_sym_info_size +=
+ object->dyst->nmodtab * sizeof(struct dylib_module);
+ }
+ else{
+ object->output_sym_info_size +=
+ object->dyst->nmodtab * sizeof(struct dylib_module_64);
+ }
+ if(object->hints_cmd != NULL){
+ object->input_sym_info_size +=
+ object->hints_cmd->nhints *
+ sizeof(struct twolevel_hint);
+ object->output_sym_info_size +=
+ object->hints_cmd->nhints *
+ sizeof(struct twolevel_hint);
+ }
+ if(object->split_info_cmd != NULL){
+ object->input_sym_info_size +=
+ object->split_info_cmd->datasize;
+ object->output_sym_info_size +=
+ object->split_info_cmd->datasize;
+ }
+ if(object->code_sig_cmd != NULL){
+ object->input_sym_info_size =
+ round(object->input_sym_info_size, 16);
+ object->input_sym_info_size +=
+ object->code_sig_cmd->datasize;
+#ifndef NMEDIT
+ if(cflag){
+ strip_LC_CODE_SIGNATURE_commands(arch, member, object);
+ }
+ else
+#endif /* !(NMEDIT) */
+ {
+ object->output_sym_info_size =
+ round(object->output_sym_info_size, 16);
+ object->output_sym_info_size +=
+ object->code_sig_cmd->datasize;
+ }
+ }
+
+ object->dyst->ntoc = new_ntoc;
+ object->dyst->nextrefsyms = new_nextrefsyms;
+
+ if(object->seg_linkedit != NULL ||
+ object->seg_linkedit64 != NULL){
+ if(object->mh != NULL)
+ offset = object->seg_linkedit->fileoff;
+ else
+ offset = object->seg_linkedit64->fileoff;
+ }
+ else{
+ offset = ULONG_MAX;
+ if(object->dyst->nlocrel != 0 &&
+ object->dyst->locreloff < offset)
+ offset = object->dyst->locreloff;
+ if(object->st->nsyms != 0 &&
+ object->st->symoff < offset)
+ offset = object->st->symoff;
+ if(object->dyst->nextrel != 0 &&
+ object->dyst->extreloff < offset)
+ offset = object->dyst->extreloff;
+ if(object->dyst->nindirectsyms != 0 &&
+ object->dyst->indirectsymoff < offset)
+ offset = object->dyst->indirectsymoff;
+ if(object->dyst->ntoc != 0 &&
+ object->dyst->tocoff < offset)
+ offset = object->dyst->tocoff;
+ if(object->dyst->nmodtab != 0 &&
+ object->dyst->modtaboff < offset)
+ offset = object->dyst->modtaboff;
+ if(object->dyst->nextrefsyms != 0 &&
+ object->dyst->extrefsymoff < offset)
+ offset = object->dyst->extrefsymoff;
+ if(object->st->strsize != 0 &&
+ object->st->stroff < offset)
+ offset = object->st->stroff;
+ }
+
+ if(object->dyst->nlocrel != 0){
+ object->output_loc_relocs = (struct relocation_info *)
+ (object->object_addr + object->dyst->locreloff);
+#ifndef NMEDIT
+ /*
+ * When stripping out the section contents to create a
+ * dynamic library stub the relocation info also gets
+ * stripped.
+ */
+ if(cflag){
+ object->dyst->nlocrel = 0;
+ object->dyst->locreloff = 0;
+ }
+ else
+#endif /* defined(NMEDIT) */
+ {
+ object->dyst->locreloff = offset;
+ offset += object->dyst->nlocrel *
+ sizeof(struct relocation_info);
+ }
+ }
+ else
+ object->dyst->locreloff = 0;
+
+ if(object->split_info_cmd != NULL){
+ object->split_info_cmd->dataoff = offset;
+ offset += object->split_info_cmd->datasize;
+ }
+
+ if(object->st->nsyms != 0){
+ 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
+ object->st->symoff = 0;
+
+ if(object->hints_cmd != NULL){
+ if(object->hints_cmd->nhints != 0){
+ object->output_hints = (struct twolevel_hint *)
+ (object->object_addr + object->hints_cmd->offset);
+ object->hints_cmd->offset = offset;
+ offset += object->hints_cmd->nhints *
+ sizeof(struct twolevel_hint);
+ }
+ else
+ object->hints_cmd->offset = 0;
+ }
+
+ if(object->dyst->nextrel != 0){
+ object->output_ext_relocs = (struct relocation_info *)
+ (object->object_addr + object->dyst->extreloff);
+#ifndef NMEDIT
+ /*
+ * When stripping out the section contents to create a
+ * dynamic library stub the relocation info also gets
+ * stripped.
+ */
+ if(cflag){
+ object->dyst->nextrel = 0;
+ object->dyst->extreloff = 0;
+ }
+ else
+#endif /* defined(NMEDIT) */
+ {
+ object->dyst->extreloff = offset;
+ offset += object->dyst->nextrel *
+ sizeof(struct relocation_info);
+ }
+ }
+ else
+ object->dyst->extreloff = 0;
+
+ if(object->dyst->nindirectsyms != 0){
+ object->dyst->indirectsymoff = offset;
+ offset += object->dyst->nindirectsyms * sizeof(uint32_t) +
+ object->input_indirectsym_pad;
+ }
+ else
+ object->dyst->indirectsymoff = 0;;
+
+ if(object->dyst->ntoc != 0){
+ object->dyst->tocoff = offset;
+ offset += object->dyst->ntoc *
+ sizeof(struct dylib_table_of_contents);
+ }
+ else
+ object->dyst->tocoff = 0;
+
+ if(object->dyst->nmodtab != 0){
+#ifndef NMEDIT
+ /*
+ * When stripping out the section contents to create a
+ * dynamic library stub zero out the fields in the module
+ * table for the sections and relocation information and
+ * clear Objective-C address and size from modules.
+ */
+ if(cflag){
+ if(object->mh != NULL){
+ for(k = 0; k < object->dyst->nmodtab; k++){
+ mods[k].iinit_iterm = 0;
+ mods[k].ninit_nterm = 0;
+ mods[k].iextrel = 0;
+ mods[k].nextrel = 0;
+ mods[k].objc_module_info_addr = 0;
+ mods[k].objc_module_info_size = 0;
+ }
+ }
+ else{
+ for(k = 0; k < object->dyst->nmodtab; k++){
+ mods64[k].iinit_iterm = 0;
+ mods64[k].ninit_nterm = 0;
+ mods64[k].iextrel = 0;
+ mods64[k].nextrel = 0;
+ mods64[k].objc_module_info_addr = 0;
+ mods64[k].objc_module_info_size = 0;
+ }
+ }
+ }
+#endif /* !(NMEDIT) */
+ object->dyst->modtaboff = offset;
+ if(object->mh != NULL)
+ offset += object->dyst->nmodtab *
+ sizeof(struct dylib_module);
+ else
+ offset += object->dyst->nmodtab *
+ sizeof(struct dylib_module_64);
+ }
+ else
+ object->dyst->modtaboff = 0;
+
+ if(object->dyst->nextrefsyms != 0){
+ object->dyst->extrefsymoff = offset;
+ offset += object->dyst->nextrefsyms *
+ sizeof(struct dylib_reference);
+ }
+ else
+ object->dyst->extrefsymoff = 0;
+
+ if(object->st->strsize != 0){
+ object->st->stroff = offset;
+ offset += object->st->strsize;
+ }
+ else
+ object->st->stroff = 0;
+
+ if(object->code_sig_cmd != NULL){
+ offset = round(offset, 16);
+ object->code_sig_cmd->dataoff = offset;
+ offset += object->code_sig_cmd->datasize;
+ }
+ }
+ else{
+ if(new_strsize != 0){
+ if(object->mh != NULL)
+ object->st->stroff = object->st->symoff +
+ new_nsyms * sizeof(struct nlist);
+ else
+ object->st->stroff = object->st->symoff +
+ new_nsyms * sizeof(struct nlist_64);
+ }
+ else
+ object->st->stroff = 0;
+ if(new_nsyms == 0)
+ object->st->symoff = 0;
+ }
+ }
+#ifndef NMEDIT
+ else{
+ if(saves != NULL)
+ free(saves);
+ saves = (long *)allocate(object->st->nsyms * sizeof(long));
+ bzero(saves, object->st->nsyms * sizeof(long));
+
+ object->output_sym_info_size = 0;
+ object->st->symoff = 0;
+ object->st->nsyms = 0;
+ object->st->stroff = 0;
+ object->st->strsize = 0;
+ if(object->dyst != NULL){
+ object->dyst->ilocalsym = 0;
+ object->dyst->nlocalsym = 0;
+ object->dyst->iextdefsym = 0;
+ object->dyst->nextdefsym = 0;
+ object->dyst->iundefsym = 0;
+ object->dyst->nundefsym = 0;
+ }
+ /*
+ * We set these so that checking can be done below to report the
+ * symbols that can't be stripped because of relocation entries
+ * or indirect symbol table entries. If these table are non-zero
+ * number of entries it will be an error as we are trying to
+ * strip everything.
+ */
+ if(object->dyst != NULL){
+ if(object->dyst->nextrel != 0){
+ object->output_ext_relocs = (struct relocation_info *)
+ (object->object_addr + object->dyst->extreloff);
+ }
+ if(object->dyst->nindirectsyms != 0){
+ object->output_indirect_symtab = (uint32_t *)
+ (object->object_addr +
+ object->dyst->indirectsymoff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_indirect_symbols(
+ object->output_indirect_symtab,
+ object->dyst->nindirectsyms,
+ object->object_byte_sex);
+ }
+ /*
+ * Since this file has a dynamic symbol table and if this file
+ * has local relocation entries on input make sure they are
+ * there on output. This is a rare case that it will not have
+ * external relocs or indirect symbols but can happen as is the
+ * case with the dynamic linker itself.
+ */
+ if(object->dyst->nlocrel != 0){
+ object->output_loc_relocs = (struct relocation_info *)
+ (object->object_addr + object->dyst->locreloff);
+ object->output_sym_info_size +=
+ object->dyst->nlocrel * sizeof(struct relocation_info);
+ }
+ }
+ }
+#endif /* !defined(NMEDIT) */
+
+ /*
+ * Always clear the prebind checksum if any when creating a new file.
+ */
+ if(object->cs != NULL)
+ object->cs->cksum = 0;
+
+ if(object->seg_linkedit != NULL){
+ object->seg_linkedit->filesize += object->output_sym_info_size -
+ object->input_sym_info_size;
+ object->seg_linkedit->vmsize = object->seg_linkedit->filesize;
+ }
+ else if(object->seg_linkedit64 != NULL){
+ /* Do this in two steps to avoid 32/64-bit casting problems. */
+ object->seg_linkedit64->filesize -= object->input_sym_info_size;
+ object->seg_linkedit64->filesize += object->output_sym_info_size;
+ object->seg_linkedit64->vmsize = object->seg_linkedit64->filesize;
+ }
+
+ /*
+ * Check and update the external relocation entries to make sure
+ * referenced symbols are not stripped and refer to the new symbol
+ * table indexes.
+ *
+ * The external relocation entries can be located in one of two places,
+ * first off of the sections or second off of the dynamic symtab.
+ */
+ missing_reloc_symbols = 0;
+ lc = object->load_commands;
+ if(object->mh != NULL)
+ ncmds = object->mh->ncmds;
+ else
+ ncmds = object->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT &&
+ object->seg_linkedit != (struct segment_command *)lc){
+ sg = (struct segment_command *)lc;
+ s = (struct section *)((char *)sg +
+ sizeof(struct segment_command));
+ for(j = 0; j < sg->nsects; j++){
+ if(s->nreloc != 0){
+ if(s->reloff + s->nreloc *
+ sizeof(struct relocation_info) >
+ object->object_size){
+ fatal_arch(arch, member, "truncated or malformed "
+ "object (relocation entries for section (%.16s,"
+ "%.16s) extends past the end of the file)",
+ s->segname, s->sectname);
+ }
+ relocs = (struct relocation_info *)
+ (object->object_addr + s->reloff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, s->nreloc,
+ host_byte_sex);
+ if(s->offset + s->size > object->object_size){
+ fatal_arch(arch, member, "truncated or malformed "
+ "object (contents of section (%.16s,"
+ "%.16s) extends past the end of the file)",
+ s->segname, s->sectname);
+ }
+ contents = object->object_addr + s->offset;
+ check_object_relocs(arch, member, object, s->segname,
+ s->sectname, s->size, contents, relocs, s->nreloc,
+ symbols, symbols64, nsyms, strings,
+ &missing_reloc_symbols, host_byte_sex);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, s->nreloc,
+ object->object_byte_sex);
+ }
+ s++;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64 &&
+ object->seg_linkedit64 != (struct segment_command_64 *)lc){
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)((char *)sg64 +
+ sizeof(struct segment_command_64));
+ for(j = 0; j < sg64->nsects; j++){
+ if(s64->nreloc != 0){
+ if(s64->reloff + s64->nreloc *
+ sizeof(struct relocation_info) >
+ object->object_size){
+ fatal_arch(arch, member, "truncated or malformed "
+ "object (relocation entries for section (%.16s,"
+ "%.16s) extends past the end of the file)",
+ s64->segname, s64->sectname);
+ }
+ relocs = (struct relocation_info *)
+ (object->object_addr + s64->reloff);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, s64->nreloc,
+ host_byte_sex);
+ if(s64->offset + s64->size > object->object_size){
+ fatal_arch(arch, member, "truncated or malformed "
+ "object (contents of section (%.16s,"
+ "%.16s) extends past the end of the file)",
+ s64->segname, s64->sectname);
+ }
+ contents = object->object_addr + s64->offset;
+ check_object_relocs(arch, member, object, s64->segname,
+ s64->sectname, s64->size, contents, relocs,
+ s64->nreloc, symbols, symbols64, nsyms, strings,
+ &missing_reloc_symbols, host_byte_sex);
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, s64->nreloc,
+ object->object_byte_sex);
+ }
+ s64++;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->dyst != NULL && object->dyst->nextrel != 0){
+ relocs = object->output_ext_relocs;
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, object->dyst->nextrel,
+ host_byte_sex);
+
+ for(i = 0; i < object->dyst->nextrel; i++){
+ if((relocs[i].r_address & R_SCATTERED) == 0 &&
+ relocs[i].r_extern == 1){
+ if(relocs[i].r_symbolnum > nsyms){
+ fatal_arch(arch, member, "bad r_symbolnum for external "
+ "relocation entry %ld in: ", i);
+ }
+ if(saves[relocs[i].r_symbolnum] == 0){
+ if(missing_reloc_symbols == 0){
+ error_arch(arch, member, "symbols referenced by "
+ "relocation entries that can't be stripped in: ");
+ missing_reloc_symbols = 1;
+ }
+ if(object->mh != NULL){
+ fprintf(stderr, "%s\n", strings + symbols
+ [relocs[i].r_symbolnum].n_un.n_strx);
+ }
+ else {
+ fprintf(stderr, "%s\n", strings + symbols64
+ [relocs[i].r_symbolnum].n_un.n_strx);
+ }
+ saves[relocs[i].r_symbolnum] = -1;
+ }
+ if(saves[relocs[i].r_symbolnum] != -1){
+ relocs[i].r_symbolnum =
+ saves[relocs[i].r_symbolnum] - 1;
+ }
+ }
+ else{
+ fatal_arch(arch, member, "bad external relocation entry "
+ "%ld (not external) in: ", i);
+ }
+ if((relocs[i].r_address & R_SCATTERED) == 0){
+ if(reloc_has_pair(object->mh_cputype, relocs[i].r_type))
+ i++;
+ }
+ else{
+ sreloc = (struct scattered_relocation_info *)relocs + i;
+ if(reloc_has_pair(object->mh_cputype, sreloc->r_type))
+ i++;
+ }
+ }
+ if(object->object_byte_sex != host_byte_sex)
+ swap_relocation_info(relocs, object->dyst->nextrel,
+ object->object_byte_sex);
+ }
+
+ /*
+ * Check and update the indirect symbol table entries to make sure
+ * referenced symbols are not stripped and refer to the new symbol
+ * table indexes.
+ */
+ if(object->dyst != NULL && object->dyst->nindirectsyms != 0){
+ if(object->object_byte_sex != host_byte_sex)
+ swap_indirect_symbols(object->output_indirect_symtab,
+ object->dyst->nindirectsyms, host_byte_sex);
+
+ lc = object->load_commands;
+ if(object->mh != NULL)
+ ncmds = object->mh->ncmds;
+ else
+ ncmds = object->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT &&
+ object->seg_linkedit != (struct segment_command *)lc){
+ sg = (struct segment_command *)lc;
+ s = (struct section *)((char *)sg +
+ sizeof(struct segment_command));
+ for(j = 0; j < sg->nsects; j++){
+ section_type = s->flags & SECTION_TYPE;
+ if(section_type == S_LAZY_SYMBOL_POINTERS ||
+ section_type == S_NON_LAZY_SYMBOL_POINTERS)
+ stride = 4;
+ else if(section_type == S_SYMBOL_STUBS)
+ stride = s->reserved2;
+ else{
+ s++;
+ continue;
+ }
+ nitems = s->size / stride;
+ contents = object->object_addr + s->offset;
+ check_indirect_symtab(arch, member, object, nitems,
+ s->reserved1, section_type, contents, symbols,
+ symbols64, nsyms, strings, &missing_reloc_symbols,
+ host_byte_sex);
+ s++;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64 &&
+ object->seg_linkedit64 != (struct segment_command_64 *)lc){
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)((char *)sg64 +
+ sizeof(struct segment_command_64));
+ for(j = 0; j < sg64->nsects; j++){
+ section_type = s64->flags & SECTION_TYPE;
+ if(section_type == S_LAZY_SYMBOL_POINTERS ||
+ section_type == S_NON_LAZY_SYMBOL_POINTERS)
+ stride = 8;
+ else if(section_type == S_SYMBOL_STUBS)
+ stride = s64->reserved2;
+ else{
+ s64++;
+ continue;
+ }
+ nitems = s64->size / stride;
+ contents = object->object_addr + s64->offset;
+ check_indirect_symtab(arch, member, object, nitems,
+ s64->reserved1, section_type, contents, symbols,
+ symbols64, nsyms, strings, &missing_reloc_symbols,
+ host_byte_sex);
+ s64++;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+
+ if(object->object_byte_sex != host_byte_sex)
+ swap_indirect_symbols(object->output_indirect_symtab,
+ object->dyst->nindirectsyms, object->object_byte_sex);
+ }
+
+ /*
+ * Issue a warning if object file has a code signature that the
+ * operation will invalidate it.
+ */
+ if(object->code_sig_cmd != NULL)
+ warning_arch(arch, member, "changes being made to the file will "
+ "invalidate the code signature in: ");
+}
+
+/*
+ * check_object_relocs() is used to check and update the external relocation
+ * entries from a section in an object file, to make sure referenced symbols
+ * are not stripped and are changed to refer to the new symbol table indexes.
+ */
+static
+void
+check_object_relocs(
+struct arch *arch,
+struct member *member,
+struct object *object,
+char *segname,
+char *sectname,
+unsigned long long sectsize,
+char *contents,
+struct relocation_info *relocs,
+uint32_t nreloc,
+struct nlist *symbols,
+struct nlist_64 *symbols64,
+unsigned long nsyms,
+char *strings,
+long *missing_reloc_symbols,
+enum byte_sex host_byte_sex)
+{
+ unsigned long k, n_strx;
+ uint64_t n_value;
+#ifdef NMEDIT
+ unsigned long value, n_ext;
+ uint64_t value64;
+#endif
+ struct scattered_relocation_info *sreloc;
+
+ for(k = 0; k < nreloc; k++){
+ if((relocs[k].r_address & R_SCATTERED) == 0 &&
+ relocs[k].r_extern == 1){
+ if(relocs[k].r_symbolnum > nsyms){
+ fatal_arch(arch, member, "bad r_symbolnum for relocation "
+ "entry %ld in section (%.16s,%.16s) in: ", k, segname,
+ sectname);
+ }
+ if(object->mh != NULL){
+ n_strx = symbols[relocs[k].r_symbolnum].n_un.n_strx;
+ n_value = symbols[relocs[k].r_symbolnum].n_value;
+ }
+ else{
+ n_strx = symbols64[relocs[k].r_symbolnum].n_un.n_strx;
+ n_value = symbols64[relocs[k].r_symbolnum].n_value;
+ }
+#ifndef NMEDIT
+ if(saves[relocs[k].r_symbolnum] == 0){
+ if(*missing_reloc_symbols == 0){
+ error_arch(arch, member, "symbols referenced by "
+ "relocation entries that can't be stripped in: ");
+ *missing_reloc_symbols = 1;
+ }
+ fprintf(stderr, "%s\n", strings + n_strx);
+ saves[relocs[k].r_symbolnum] = -1;
+ }
+#else /* defined(NMEDIT) */
+ /*
+ * We are letting nmedit change global coalesed symbols into
+ * statics in MH_OBJECT file types only. Relocation entries to
+ * global coalesced symbols are external relocs.
+ */
+ if(object->mh != NULL)
+ n_ext = new_symbols[saves[relocs[k].r_symbolnum] - 1].
+ n_type & N_EXT;
+ else
+ n_ext = new_symbols64[saves[relocs[k].r_symbolnum] - 1].
+ n_type & N_EXT;
+ if(n_ext != N_EXT &&
+ object->mh_cputype != CPU_TYPE_X86_64){
+ /*
+ * We need to do the relocation for this external relocation
+ * entry so the item to be relocated is correct for a local
+ * relocation entry. We don't need to do this for x86-64.
+ */
+ if(relocs[k].r_address + sizeof(long) > sectsize){
+ fatal_arch(arch, member, "truncated or malformed "
+ "object (r_address of relocation entry %lu of "
+ "section (%.16s,%.16s) extends past the end "
+ "of the section)", k, segname, sectname);
+ }
+ if(object->mh != NULL){
+ value = *(unsigned long *)
+ (contents + relocs[k].r_address);
+ if(object->object_byte_sex != host_byte_sex)
+ value = SWAP_LONG(value);
+ /*
+ * We handle a very limited form here. Only VANILLA
+ * (r_type == 0) long (r_length==2) absolute or pcrel
+ * that won't need a scattered relocation entry.
+ */
+ if(relocs[k].r_type != 0 ||
+ relocs[k].r_length != 2){
+ fatal_arch(arch, member, "don't have "
+ "code to convert external relocation "
+ "entry %ld in section (%.16s,%.16s) "
+ "for global coalesced symbol: %s "
+ "in: ", k, segname, sectname,
+ strings + n_strx);
+ }
+ value += n_value;
+ if(object->object_byte_sex != host_byte_sex)
+ value = SWAP_LONG(value);
+ *(unsigned long *)(contents + relocs[k].r_address) =
+ value;
+ }
+ else{
+ value64 = *(uint64_t *)(contents + relocs[k].r_address);
+ if(object->object_byte_sex != host_byte_sex)
+ value64 = SWAP_LONG_LONG(value64);
+ /*
+ * We handle a very limited form here. Only VANILLA
+ * (r_type == 0) quad (r_length==3) absolute or pcrel
+ * that won't need a scattered relocation entry.
+ */
+ if(relocs[k].r_type != 0 ||
+ relocs[k].r_length != 3){
+ fatal_arch(arch, member, "don't have "
+ "code to convert external relocation "
+ "entry %ld in section (%.16s,%.16s) "
+ "for global coalesced symbol: %s "
+ "in: ", k, segname, sectname,
+ strings + n_strx);
+ }
+ value64 += n_value;
+ if(object->object_byte_sex != host_byte_sex)
+ value64 = SWAP_LONG_LONG(value);
+ *(uint64_t *)(contents + relocs[k].r_address) = value64;
+ }
+ /*
+ * Turn the extern reloc into a local.
+ */
+ if(object->mh != NULL)
+ relocs[k].r_symbolnum =
+ new_symbols[saves[relocs[k].r_symbolnum] - 1].n_sect;
+ else
+ relocs[k].r_symbolnum =
+ new_symbols64[saves[relocs[k].r_symbolnum] - 1].n_sect;
+ relocs[k].r_extern = 0;
+ }
+#endif /* NMEDIT */
+ if(relocs[k].r_extern == 1 &&
+ saves[relocs[k].r_symbolnum] != -1){
+ relocs[k].r_symbolnum = saves[relocs[k].r_symbolnum] - 1;
+ }
+ }
+ if((relocs[k].r_address & R_SCATTERED) == 0){
+ if(reloc_has_pair(object->mh_cputype, relocs[k].r_type) == TRUE)
+ k++;
+ }
+ else{
+ sreloc = (struct scattered_relocation_info *)relocs + k;
+ if(reloc_has_pair(object->mh_cputype, sreloc->r_type) == TRUE)
+ k++;
+ }
+ }
+}
+
+/*
+ * check_indirect_symtab() checks and updates the indirect symbol table entries
+ * to make sure referenced symbols are not stripped and refer to the new symbol
+ * table indexes.
+ */
+static
+void
+check_indirect_symtab(
+struct arch *arch,
+struct member *member,
+struct object *object,
+unsigned long nitems,
+unsigned long reserved1,
+unsigned long section_type,
+char *contents,
+struct nlist *symbols,
+struct nlist_64 *symbols64,
+unsigned long nsyms,
+char *strings,
+long *missing_reloc_symbols,
+enum byte_sex host_byte_sex)
+{
+ unsigned long k, index;
+ uint8_t n_type;
+ uint32_t n_strx, value;
+ uint64_t value64;
+ enum bool made_local;
+
+ for(k = 0; k < nitems; k++){
+ made_local = FALSE;
+ index = object->output_indirect_symtab[reserved1 + k];
+ if(index == INDIRECT_SYMBOL_LOCAL ||
+ index == INDIRECT_SYMBOL_ABS ||
+ index == (INDIRECT_SYMBOL_LOCAL | INDIRECT_SYMBOL_ABS))
+ continue;
+ if(index > nsyms)
+ fatal_arch(arch, member,"indirect symbol table entry %ld (past " "the end of the symbol table) in: ", reserved1 + k);
+#ifdef NMEDIT
+ if(pflag == 0 && nmedits[index] == TRUE && saves[index] != -1)
+#else
+ if(saves[index] == 0)
+#endif
+ {
+ /*
+ * Indirect symbol table entries for defined symbols in a
+ * non-lazy pointer section that are not saved are changed to
+ * INDIRECT_SYMBOL_LOCAL which their values just have to be
+ * slid if the are not absolute symbols.
+ */
+ if(object->mh != NULL){
+ n_type = symbols[index].n_type;
+ n_strx = symbols[index].n_un.n_strx;
+ }
+ else{
+ n_type = symbols64[index].n_type;
+ n_strx = symbols64[index].n_un.n_strx;
+ }
+ if((n_type && N_TYPE) != N_UNDF &&
+ (n_type && N_TYPE) != N_PBUD &&
+ section_type == S_NON_LAZY_SYMBOL_POINTERS){
+ object->output_indirect_symtab[reserved1 + k] =
+ INDIRECT_SYMBOL_LOCAL;
+ if((n_type & N_TYPE) == N_ABS)
+ object->output_indirect_symtab[reserved1 + k] |=
+ INDIRECT_SYMBOL_ABS;
+ made_local = TRUE;
+ /*
+ * When creating a stub shared library the section contents
+ * are not updated since they will be stripped.
+ */
+ if(object->mh_filetype != MH_DYLIB_STUB){
+ if(object->mh != NULL){
+ value = symbols[index].n_value;
+ if(object->object_byte_sex != host_byte_sex)
+ value = SWAP_LONG(value);
+ *(uint32_t *)(contents + k * 4) = value;
+ }
+ else{
+ value64 = symbols64[index].n_value;
+ if(object->object_byte_sex != host_byte_sex)
+ value64 = SWAP_LONG_LONG(value64);
+ *(uint64_t *)(contents + k * 8) = value64;
+ }
+ }
+ }
+#ifdef NMEDIT
+ else {
+ object->output_indirect_symtab[reserved1 + k] =
+ saves[index] - 1;
+ }
+#else /* !defined(NMEDIT) */
+ else{
+ if(*missing_reloc_symbols == 0){
+ error_arch(arch, member, "symbols referenced by "
+ "indirect symbol table entries that can't be "
+ "stripped in: ");
+ *missing_reloc_symbols = 1;
+ }
+ fprintf(stderr, "%s\n", strings + n_strx);
+ saves[index] = -1;
+ }
+#endif /* !defined(NMEDIT) */
+ }
+#ifdef NMEDIT
+ else
+#else /* !defined(NMEDIT) */
+ if(made_local == FALSE && saves[index] != -1)
+#endif /* !defined(NMEDIT) */
+ {
+ object->output_indirect_symtab[reserved1+k] = saves[index] - 1;
+ }
+ }
+}
+
+#ifndef NMEDIT
+/*
+ * This is called if there is a -d option specified. It reads the file with
+ * the strings in it and places them in the array debug_filenames and sorts
+ * them by name. The file that contains the file names must have names one
+ * per line with no white space (except the newlines).
+ */
+static
+void
+setup_debug_filenames(
+char *dfile)
+{
+ int fd, i, strings_size;
+ struct stat stat_buf;
+ char *strings, *p;
+
+ if((fd = open(dfile, O_RDONLY)) < 0){
+ system_error("can't open: %s", dfile);
+ return;
+ }
+ if(fstat(fd, &stat_buf) == -1){
+ system_error("can't stat: %s", dfile);
+ close(fd);
+ return;
+ }
+ strings_size = stat_buf.st_size;
+ strings = (char *)allocate(strings_size + 1);
+ strings[strings_size] = '\0';
+ if(read(fd, strings, strings_size) != strings_size){
+ system_error("can't read: %s", dfile);
+ close(fd);
+ return;
+ }
+ p = strings;
+ for(i = 0; i < strings_size; i++){
+ if(*p == '\n'){
+ *p = '\0';
+ ndebug_filenames++;
+ }
+ p++;
+ }
+ debug_filenames = (char **)allocate(ndebug_filenames * sizeof(char *));
+ p = strings;
+ for(i = 0; i < ndebug_filenames; i++){
+ debug_filenames[i] = p;
+ p += strlen(p) + 1;
+ }
+ qsort(debug_filenames, ndebug_filenames, sizeof(char *),
+ (int (*)(const void *, const void *))cmp_qsort_filename);
+
+#ifdef DEBUG
+ printf("Debug filenames:\n");
+ for(i = 0; i < ndebug_filenames; i++){
+ printf("filename = %s\n", debug_filenames[i]);
+ }
+#endif /* DEBUG */
+}
+
+/*
+ * Strip the symbol table to the level specified by the command line arguments.
+ * The new symbol table is built and new_symbols is left pointing to it. The
+ * number of new symbols is left in new_nsyms, the new string table is built
+ * and new_stings is left pointing to it and new_strsize is left containing it.
+ * This routine returns zero if successfull and non-zero otherwise.
+ */
+static
+enum bool
+strip_symtab(
+struct arch *arch,
+struct member *member,
+struct object *object,
+struct nlist *symbols,
+struct nlist_64 *symbols64,
+unsigned long nsyms,
+char *strings,
+unsigned long strsize,
+struct dylib_table_of_contents *tocs,
+unsigned long ntoc,
+struct dylib_module *mods,
+struct dylib_module_64 *mods64,
+unsigned long nmodtab,
+struct dylib_reference *refs,
+unsigned long nextrefsyms,
+uint32_t *indirectsyms,
+unsigned long nindirectsyms)
+{
+ unsigned long i, j, k, n, inew_syms, save_debug, missing_syms;
+ unsigned long missing_symbols;
+ char *p, *q, **pp, *basename;
+ struct symbol_list *sp;
+ unsigned long new_ext_strsize, len, *changes, inew_undefsyms;
+ unsigned char nsects;
+ struct load_command *lc;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct section *s, **sections;
+ struct section_64 *s64, **sections64;
+ uint32_t ncmds, mh_flags, s_flags, n_strx;
+ struct nlist *sym;
+ struct undef_map *undef_map;
+ struct undef_map64 *undef_map64;
+ uint8_t n_type, n_sect;
+ uint16_t n_desc;
+ uint64_t n_value;
+ uint32_t module_name, iextdefsym, nextdefsym, ilocalsym, nlocalsym;
+ uint32_t irefsym, nrefsym;
+
+ save_debug = 0;
+ if(saves != NULL)
+ free(saves);
+ saves = (long *)allocate(nsyms * sizeof(long));
+ bzero(saves, nsyms * sizeof(long));
+ changes = NULL;
+ for(i = 0; i < nsave_symbols; i++)
+ save_symbols[i].sym = NULL;
+ for(i = 0; i < nremove_symbols; i++)
+ remove_symbols[i].sym = NULL;
+ if(member == NULL){
+ for(i = 0; i < nsave_symbols; i++)
+ save_symbols[i].seen = FALSE;
+ for(i = 0; i < nremove_symbols; i++)
+ remove_symbols[i].seen = FALSE;
+ }
+
+ new_nsyms = 0;
+ new_strsize = sizeof(long);
+ new_nlocalsym = 0;
+ new_nextdefsym = 0;
+ new_nundefsym = 0;
+ new_ext_strsize = 0;
+
+ /*
+ * Gather an array of section struct pointers so we can later determine
+ * if we run into a global symbol in a coalesced section and not strip
+ * those symbols.
+ * statics.
+ */
+ nsects = 0;
+ lc = object->load_commands;
+ if(object->mh != NULL)
+ ncmds = object->mh->ncmds;
+ else
+ ncmds = object->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ nsects += sg->nsects;
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ nsects += sg64->nsects;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->mh != NULL){
+ sections = allocate(nsects * sizeof(struct section *));
+ sections64 = NULL;
+ }
+ else{
+ sections = NULL;
+ sections64 = allocate(nsects * sizeof(struct section_64 *));
+ }
+ nsects = 0;
+ lc = object->load_commands;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ s = (struct section *)((char *)sg +
+ sizeof(struct segment_command));
+ for(j = 0; j < sg->nsects; j++)
+ sections[nsects++] = s++;
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)((char *)sg64 +
+ sizeof(struct segment_command_64));
+ for(j = 0; j < sg64->nsects; j++)
+ sections64[nsects++] = s64++;
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+
+ for(i = 0; i < nsyms; i++){
+ s_flags = 0;
+ if(object->mh != NULL){
+ mh_flags = object->mh->flags;
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ n_sect = symbols[i].n_sect;
+ if((n_type & N_TYPE) == N_SECT){
+ if(n_sect == 0 || n_sect > nsects){
+ error_arch(arch, member, "bad n_sect for symbol "
+ "table entry %ld in: ", i);
+ return(FALSE);
+ }
+ s_flags = sections[n_sect - 1]->flags;
+ }
+ n_desc = symbols[i].n_desc;
+ n_value = symbols[i].n_value;
+ }
+ else{
+ mh_flags = object->mh64->flags;
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ n_sect = symbols64[i].n_sect;
+ if((n_type & N_TYPE) == N_SECT){
+ if(n_sect == 0 || n_sect > nsects){
+ error_arch(arch, member, "bad n_sect for symbol "
+ "table entry %ld in: ", i);
+ return(FALSE);
+ }
+ s_flags = sections64[n_sect - 1]->flags;
+ }
+ n_desc = symbols64[i].n_desc;
+ n_value = symbols64[i].n_value;
+ }
+ if(n_strx != 0){
+ if(n_strx > strsize){
+ error_arch(arch, member, "bad string index for symbol "
+ "table entry %ld in: ", i);
+ return(FALSE);
+ }
+ }
+ if((n_type & N_TYPE) == N_INDR){
+ if(n_value != 0){
+ if(n_value > strsize){
+ error_arch(arch, member, "bad string index for "
+ "indirect symbol table entry %ld in: ", i);
+ return(FALSE);
+ }
+ }
+ }
+ if((n_type & N_EXT) == 0){ /* local symbol */
+ /*
+ * strip -x or -X on an x86_64 .o file should do nothing.
+ */
+ if(object->mh == NULL &&
+ object->mh64->cputype == CPU_TYPE_X86_64 &&
+ object->mh64->filetype == MH_OBJECT &&
+ (xflag == 1 || Xflag == 1)){
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ /*
+ * The cases a local symbol might be saved is with -X -S or
+ * with -d filename.
+ */
+ else if((!strip_all && (Xflag || Sflag)) || dfile){
+ if(n_type & N_STAB){ /* debug symbol */
+ if(dfile && n_type == N_SO){
+ if(n_strx != 0){
+ basename = strrchr(strings + n_strx, '/');
+ if(basename != NULL)
+ basename++;
+ else
+ basename = strings + n_strx;
+ pp = bsearch(basename, debug_filenames,
+ ndebug_filenames, sizeof(char *),
+ (int (*)(const void *, const void *)
+ )cmp_bsearch_filename);
+ /*
+ * Save the bracketing N_SO. For each N_SO that
+ * has a filename there is an N_SO that has a
+ * name of "" which ends the stabs for that file
+ */
+ if(*basename != '\0'){
+ if(pp != NULL)
+ save_debug = 1;
+ else
+ save_debug = 0;
+ }
+ else{
+ /*
+ * This is a bracketing SO so if we are
+ * currently saving debug symbols save this
+ * last one and turn off saving debug syms.
+ */
+ if(save_debug){
+ if(n_strx != 0)
+ new_strsize += strlen(strings +
+ n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ save_debug = 0;
+ }
+ }
+ else{
+ save_debug = 0;
+ }
+ }
+ if(saves[i] == 0 && (!Sflag || save_debug)){
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ else{ /* non-debug local symbol */
+ if(xflag == 0 && (Sflag || Xflag)){
+ if(Xflag == 0 ||
+ (n_strx != 0 &&
+ strings[n_strx] != 'L')){
+ /*
+ * If this file is a for the dynamic linker and
+ * this symbol is in a section marked so that
+ * static symbols are stripped then don't
+ * keep this symbol.
+ */
+ if((mh_flags & MH_DYLDLINK) != MH_DYLDLINK ||
+ (n_type & N_TYPE) != N_SECT ||
+ (s_flags & S_ATTR_STRIP_STATIC_SYMS) !=
+ S_ATTR_STRIP_STATIC_SYMS){
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ }
+ /*
+ * Treat a local symbol that was a private extern as if
+ * were global if it is referenced by a module and save
+ * it.
+ */
+ if((n_type & N_PEXT) == N_PEXT){
+ if(saves[i] == 0 &&
+ private_extern_reference_by_module(
+ i, refs ,nextrefsyms) == TRUE){
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ /*
+ * We need to save symbols that were private externs
+ * that are used with indirect symbols.
+ */
+ if(saves[i] == 0 &&
+ symbol_pointer_used(i, indirectsyms,
+ nindirectsyms) == TRUE){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ }
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ }
+ }
+ /*
+ * Treat a local symbol that was a private extern as if were
+ * global if it is not referenced by a module.
+ */
+ else if((n_type & N_PEXT) == N_PEXT){
+ if(saves[i] == 0 && sfile){
+ sp = bsearch(strings + n_strx,
+ save_symbols, nsave_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym == NULL){
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ }
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ if(saves[i] == 0 &&
+ private_extern_reference_by_module(
+ i, refs ,nextrefsyms) == TRUE){
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ /*
+ * We need to save symbols that were private externs that
+ * are used with indirect symbols.
+ */
+ if(saves[i] == 0 &&
+ symbol_pointer_used(i, indirectsyms, nindirectsyms) ==
+ TRUE){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ }
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ }
+ else{ /* global symbol */
+ /*
+ * strip -R on an x86_64 .o file should do nothing.
+ */
+ if(Rfile &&
+ (object->mh != NULL ||
+ object->mh64->cputype != CPU_TYPE_X86_64 ||
+ object->mh64->filetype != MH_OBJECT)){
+ sp = bsearch(strings + n_strx,
+ remove_symbols, nremove_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if((n_type & N_TYPE) == N_UNDF ||
+ (n_type & N_TYPE) == N_PBUD){
+ error_arch(arch, member, "symbol: %s undefined"
+ " and can't be stripped from: ",
+ sp->name);
+ }
+ else if(sp->sym != NULL){
+ sym = (struct nlist *)sp->sym;
+ if((sym->n_type & N_PEXT) != N_PEXT)
+ error_arch(arch, member, "more than one symbol "
+ "for: %s found in: ", sp->name);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ }
+ if(n_desc & REFERENCED_DYNAMICALLY){
+ error_arch(arch, member, "symbol: %s is dynamically"
+ " referenced and can't be stripped "
+ "from: ", sp->name);
+ }
+ if((n_type & N_TYPE) == N_SECT &&
+ (s_flags & SECTION_TYPE) == S_COALESCED){
+ error_arch(arch, member, "symbol: %s is a global "
+ "coalesced symbol and can't be "
+ "stripped from: ", sp->name);
+ }
+ /* don't save this symbol */
+ continue;
+ }
+ }
+ if(Aflag && (n_type & N_TYPE) == N_ABS &&
+ (n_value != 0 ||
+ (n_strx != 0 &&
+ strncmp(strings + n_strx,
+ ".objc_class_name_",
+ sizeof(".objc_class_name_") - 1) == 0))){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ if(saves[i] == 0 && (uflag || default_dyld_executable) &&
+ ((((n_type & N_TYPE) == N_UNDF) &&
+ n_value == 0) ||
+ (n_type & N_TYPE) == N_PBUD)){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+ new_nundefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ if(saves[i] == 0 && nflag &&
+ (n_type & N_TYPE) == N_SECT){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ if(saves[i] == 0 && sfile){
+ sp = bsearch(strings + n_strx,
+ save_symbols, nsave_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym != NULL){
+ sym = (struct nlist *)sp->sym;
+ if((sym->n_type & N_PEXT) != N_PEXT)
+ error_arch(arch, member, "more than one symbol "
+ "for: %s found in: ", sp->name);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ if((n_type & N_TYPE) == N_UNDF ||
+ (n_type & N_TYPE) == N_PBUD)
+ new_nundefsym++;
+ else
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ }
+ /*
+ * We only need to save coalesced symbols that are used as
+ * indirect symbols in 32-bit applications.
+ *
+ * In 64-bit applications, we only need to save coalesced
+ * symbols that are used as weak definitions.
+ */
+ if(object->mh != NULL &&
+ saves[i] == 0 &&
+ (n_type & N_TYPE) == N_SECT &&
+ (s_flags & SECTION_TYPE) == S_COALESCED &&
+ symbol_pointer_used(i, indirectsyms, nindirectsyms) == TRUE){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ if(saves[i] == 0 &&
+ (n_type & N_TYPE) == N_SECT &&
+ (n_desc & N_WEAK_DEF) != 0){
+ if(n_strx != 0){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ if(saves[i] == 0 && ((Xflag || Sflag || xflag) ||
+ ((rflag || default_dyld_executable) &&
+ n_desc & REFERENCED_DYNAMICALLY))){
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ if((n_type & N_TYPE) == N_INDR){
+ len = strlen(strings + n_value) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+ if((n_type & N_TYPE) == N_UNDF ||
+ (n_type & N_TYPE) == N_PBUD)
+ new_nundefsym++;
+ else
+ new_nextdefsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ }
+ }
+ /*
+ * The module table's module names are placed with the external strings.
+ * So size them and add this to the external string size.
+ */
+ for(i = 0; i < nmodtab; i++){
+ if(object->mh != NULL)
+ module_name = mods[i].module_name;
+ else
+ module_name = mods64[i].module_name;
+ if(module_name == 0 || module_name > strsize){
+ error_arch(arch, member, "bad string index for module_name "
+ "of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ len = strlen(strings + module_name) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+
+ /*
+ * Updating the reference table may require a symbol not yet listed as
+ * as saved to be present in the output file. If a defined external
+ * symbol is removed and there is a undefined reference to it in the
+ * reference table an undefined symbol needs to be created for it in
+ * the output file. If this happens the number of new symbols and size
+ * of the new strings are adjusted. And the array changes[] is set to
+ * map the old symbol index to the new symbol index for the symbol that
+ * is changed to an undefined symbol.
+ */
+ missing_symbols = 0;
+ if(ref_saves != NULL)
+ free(ref_saves);
+ ref_saves = (long *)allocate(nextrefsyms * sizeof(long));
+ bzero(ref_saves, nextrefsyms * sizeof(long));
+ changes = (unsigned long *)allocate(nsyms * sizeof(long));
+ bzero(changes, nsyms * sizeof(long));
+ new_nextrefsyms = 0;
+ for(i = 0; i < nextrefsyms; i++){
+ if(refs[i].isym > nsyms){
+ error_arch(arch, member, "bad symbol table index for "
+ "reference table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(saves[refs[i].isym]){
+ new_nextrefsyms++;
+ ref_saves[i] = new_nextrefsyms;
+ }
+ else{
+ if(refs[i].flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY ||
+ refs[i].flags == REFERENCE_FLAG_UNDEFINED_LAZY){
+ if(changes[refs[i].isym] == 0){
+ if(object->mh != NULL)
+ n_strx = symbols[refs[i].isym].n_un.n_strx;
+ else
+ n_strx = symbols64[refs[i].isym].n_un.n_strx;
+ len = strlen(strings + n_strx) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ new_nundefsym++;
+ new_nsyms++;
+ changes[refs[i].isym] = new_nsyms;
+ new_nextrefsyms++;
+ ref_saves[i] = new_nextrefsyms;
+ }
+ }
+ else{
+ if(refs[i].flags ==
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY ||
+ refs[i].flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY){
+ if(missing_symbols == 0){
+ error_arch(arch, member, "private extern symbols "
+ "referenced by modules can't be stripped in: ");
+ missing_symbols = 1;
+ }
+ if(object->mh != NULL)
+ n_strx = symbols[refs[i].isym].n_un.n_strx;
+ else
+ n_strx = symbols64[refs[i].isym].n_un.n_strx;
+ fprintf(stderr, "%s\n", strings + n_strx);
+ saves[refs[i].isym] = -1;
+ }
+ }
+ }
+ }
+ if(missing_symbols == 1)
+ return(FALSE);
+
+ if(member == NULL){
+ missing_syms = 0;
+ if(iflag == 0){
+ for(i = 0; i < nsave_symbols; i++){
+ if(save_symbols[i].sym == NULL){
+ if(missing_syms == 0){
+ error_arch(arch, member, "symbols names listed "
+ "in: %s not in: ", sfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", save_symbols[i].name);
+ }
+ }
+ }
+ missing_syms = 0;
+ /*
+ * strip -R on an x86_64 .o file should do nothing.
+ */
+ if(iflag == 0 &&
+ (object->mh != NULL ||
+ object->mh64->cputype != CPU_TYPE_X86_64 ||
+ object->mh64->filetype != MH_OBJECT)){
+ for(i = 0; i < nremove_symbols; i++){
+ if(remove_symbols[i].sym == NULL){
+ if(missing_syms == 0){
+ error_arch(arch, member, "symbols names listed "
+ "in: %s not in: ", Rfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", remove_symbols[i].name);
+ }
+ }
+ }
+ }
+
+ if(object->mh != NULL){
+ new_symbols = (struct nlist *)
+ allocate(new_nsyms * sizeof(struct nlist));
+ new_symbols64 = NULL;
+ }
+ else{
+ new_symbols = NULL;
+ new_symbols64 = (struct nlist_64 *)
+ allocate(new_nsyms * sizeof(struct nlist_64));
+ }
+ new_strsize = round(new_strsize, sizeof(long));
+ new_strings = (char *)allocate(new_strsize);
+ new_strings[new_strsize - 3] = '\0';
+ new_strings[new_strsize - 2] = '\0';
+ new_strings[new_strsize - 1] = '\0';
+
+ memset(new_strings, '\0', sizeof(long));
+ p = new_strings + sizeof(long);
+ q = p + new_ext_strsize;
+
+ /* if all strings were stripped set the size to zero */
+ if(new_strsize == sizeof(long))
+ new_strsize = 0;
+
+ /*
+ * Now create a symbol table and string table in this order
+ * symbol table
+ * local symbols
+ * external defined symbols
+ * undefined symbols
+ * string table
+ * external strings
+ * local strings
+ */
+ inew_syms = 0;
+ for(i = 0; i < nsyms; i++){
+ if(saves[i]){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) == 0){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[i];
+ else
+ new_symbols64[inew_syms] = symbols64[i];
+ if(n_strx != 0){
+ strcpy(q, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ q - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ q - new_strings;
+ q += strlen(q) + 1;
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+ }
+ for(i = 0; i < nsyms; i++){
+ if(saves[i]){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ n_value = symbols[i].n_value;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ n_value = symbols64[i].n_value;
+ }
+ if((n_type & N_EXT) == N_EXT &&
+ ((n_type & N_TYPE) != N_UNDF &&
+ (n_type & N_TYPE) != N_PBUD)){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[i];
+ else
+ new_symbols64[inew_syms] = symbols64[i];
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ p - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ if((n_type & N_TYPE) == N_INDR){
+ if(n_value != 0){
+ strcpy(p, strings + n_value);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_value =
+ p - new_strings;
+ else
+ new_symbols64[inew_syms].n_value =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+ }
+ /*
+ * Build the new undefined symbols into a map and sort it.
+ */
+ inew_undefsyms = 0;
+ if(object->mh != NULL){
+ undef_map = (struct undef_map *)allocate(new_nundefsym *
+ sizeof(struct undef_map));
+ undef_map64 = NULL;
+ }
+ else{
+ undef_map = NULL;
+ undef_map64 = (struct undef_map64 *)allocate(new_nundefsym *
+ sizeof(struct undef_map64));
+ }
+ for(i = 0; i < nsyms; i++){
+ if(saves[i]){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) == N_EXT &&
+ ((n_type & N_TYPE) == N_UNDF ||
+ (n_type & N_TYPE) == N_PBUD)){
+ if(object->mh != NULL)
+ undef_map[inew_undefsyms].symbol = symbols[i];
+ else
+ undef_map64[inew_undefsyms].symbol64 = symbols64[i];
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ undef_map[inew_undefsyms].symbol.n_un.n_strx =
+ p - new_strings;
+ else
+ undef_map64[inew_undefsyms].symbol64.n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ if(object->mh != NULL)
+ undef_map[inew_undefsyms].index = i;
+ else
+ undef_map64[inew_undefsyms].index = i;
+ inew_undefsyms++;
+ }
+ }
+ }
+ for(i = 0; i < nsyms; i++){
+ if(changes[i]){
+ if(object->mh != NULL)
+ n_strx = symbols[i].n_un.n_strx;
+ else
+ n_strx = symbols64[i].n_un.n_strx;
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ undef_map[inew_undefsyms].symbol.n_un.n_strx =
+ p - new_strings;
+ else
+ undef_map64[inew_undefsyms].symbol64.n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ if(object->mh != NULL){
+ undef_map[inew_undefsyms].symbol.n_type = N_UNDF | N_EXT;
+ undef_map[inew_undefsyms].symbol.n_sect = NO_SECT;
+ undef_map[inew_undefsyms].symbol.n_desc = 0;
+ undef_map[inew_undefsyms].symbol.n_value = 0;
+ undef_map[inew_undefsyms].index = i;
+ }
+ else{
+ undef_map64[inew_undefsyms].symbol64.n_type = N_UNDF |N_EXT;
+ undef_map64[inew_undefsyms].symbol64.n_sect = NO_SECT;
+ undef_map64[inew_undefsyms].symbol64.n_desc = 0;
+ undef_map64[inew_undefsyms].symbol64.n_value = 0;
+ undef_map64[inew_undefsyms].index = i;
+ }
+ inew_undefsyms++;
+ }
+ }
+ /* Sort the undefined symbols by name */
+ qsort_strings = new_strings;
+ if(object->mh != NULL)
+ qsort(undef_map, new_nundefsym, sizeof(struct undef_map),
+ (int (*)(const void *, const void *))cmp_qsort_undef_map);
+ else
+ qsort(undef_map64, new_nundefsym, sizeof(struct undef_map64),
+ (int (*)(const void *, const void *))cmp_qsort_undef_map_64);
+ /* Copy the symbols now in sorted order into new_symbols */
+ for(i = 0; i < new_nundefsym; i++){
+ if(object->mh != NULL){
+ new_symbols[inew_syms] = undef_map[i].symbol;
+ inew_syms++;
+ saves[undef_map[i].index] = inew_syms;
+ }
+ else{
+ new_symbols64[inew_syms] = undef_map64[i].symbol64;
+ inew_syms++;
+ saves[undef_map64[i].index] = inew_syms;
+ }
+ }
+
+ /*
+ * Fixup the module table's module name strings adding them to the
+ * string table. Also fix the indexes into the symbol table for
+ * external and local symbols. And fix up the indexes into the
+ * reference table.
+ */
+ for(i = 0; i < nmodtab; i++){
+ if(object->mh != NULL){
+ strcpy(p, strings + mods[i].module_name);
+ mods[i].module_name = p - new_strings;
+ iextdefsym = mods[i].iextdefsym;
+ nextdefsym = mods[i].nextdefsym;
+ ilocalsym = mods[i].ilocalsym;
+ nlocalsym = mods[i].nlocalsym;
+ irefsym = mods[i].irefsym;
+ nrefsym = mods[i].nrefsym;
+ }
+ else{
+ strcpy(p, strings + mods64[i].module_name);
+ mods64[i].module_name = p - new_strings;
+ iextdefsym = mods64[i].iextdefsym;
+ nextdefsym = mods64[i].nextdefsym;
+ ilocalsym = mods64[i].ilocalsym;
+ nlocalsym = mods64[i].nlocalsym;
+ irefsym = mods64[i].irefsym;
+ nrefsym = mods64[i].nrefsym;
+ }
+ p += strlen(p) + 1;
+
+ if(iextdefsym > nsyms){
+ error_arch(arch, member, "bad index into externally defined "
+ "symbols of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(iextdefsym + nextdefsym > nsyms){
+ error_arch(arch, member, "bad number of externally defined "
+ "symbols of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ for(j = iextdefsym; j < iextdefsym + nextdefsym; j++){
+ if(saves[j] != 0 && changes[j] == 0)
+ break;
+ }
+ n = 0;
+ for(k = j; k < iextdefsym + nextdefsym; k++){
+ if(saves[k] != 0 && changes[k] == 0)
+ n++;
+ }
+ if(n == 0){
+ if(object->mh != NULL){
+ mods[i].iextdefsym = 0;
+ mods[i].nextdefsym = 0;
+ }
+ else{
+ mods64[i].iextdefsym = 0;
+ mods64[i].nextdefsym = 0;
+ }
+ }
+ else{
+ if(object->mh != NULL){
+ mods[i].iextdefsym = saves[j] - 1;
+ mods[i].nextdefsym = n;
+ }
+ else{
+ mods64[i].iextdefsym = saves[j] - 1;
+ mods64[i].nextdefsym = n;
+ }
+ }
+
+ if(ilocalsym > nsyms){
+ error_arch(arch, member, "bad index into symbols for local "
+ "symbols of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(ilocalsym + nlocalsym > nsyms){
+ error_arch(arch, member, "bad number of local "
+ "symbols of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ for(j = ilocalsym; j < ilocalsym + nlocalsym; j++){
+ if(saves[j] != 0)
+ break;
+ }
+ n = 0;
+ for(k = j; k < ilocalsym + nlocalsym; k++){
+ if(saves[k] != 0)
+ n++;
+ }
+ if(n == 0){
+ if(object->mh != NULL){
+ mods[i].ilocalsym = 0;
+ mods[i].nlocalsym = 0;
+ }
+ else{
+ mods64[i].ilocalsym = 0;
+ mods64[i].nlocalsym = 0;
+ }
+ }
+ else{
+ if(object->mh != NULL){
+ mods[i].ilocalsym = saves[j] - 1;
+ mods[i].nlocalsym = n;
+ }
+ else{
+ mods64[i].ilocalsym = saves[j] - 1;
+ mods64[i].nlocalsym = n;
+ }
+ }
+
+ if(irefsym > nextrefsyms){
+ error_arch(arch, member, "bad index into reference table "
+ "of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(irefsym + nrefsym > nextrefsyms){
+ error_arch(arch, member, "bad number of reference table "
+ "entries of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ for(j = irefsym; j < irefsym + nrefsym; j++){
+ if(ref_saves[j] != 0)
+ break;
+ }
+ n = 0;
+ for(k = j; k < irefsym + nrefsym; k++){
+ if(ref_saves[k] != 0)
+ n++;
+ }
+ if(n == 0){
+ if(object->mh != NULL){
+ mods[i].irefsym = 0;
+ mods[i].nrefsym = 0;
+ }
+ else{
+ mods64[i].irefsym = 0;
+ mods64[i].nrefsym = 0;
+ }
+ }
+ else{
+ if(object->mh != NULL){
+ mods[i].irefsym = ref_saves[j] - 1;
+ mods[i].nrefsym = n;
+ }
+ else{
+ mods64[i].irefsym = ref_saves[j] - 1;
+ mods64[i].nrefsym = n;
+ }
+ }
+ }
+
+ /*
+ * Create a new reference table.
+ */
+ new_refs = allocate(new_nextrefsyms * sizeof(struct dylib_reference));
+ j = 0;
+ for(i = 0; i < nextrefsyms; i++){
+ if(ref_saves[i]){
+ if(saves[refs[i].isym]){
+ new_refs[j].isym = saves[refs[i].isym] - 1;
+ new_refs[j].flags = refs[i].flags;
+ }
+ else{
+ if(refs[i].flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY ||
+ refs[i].flags == REFERENCE_FLAG_UNDEFINED_LAZY){
+ new_refs[j].isym = changes[refs[i].isym] - 1;
+ new_refs[j].flags = refs[i].flags;
+ }
+ }
+ j++;
+ }
+ }
+
+ /*
+ * Create a new dylib table of contents.
+ */
+ new_ntoc = 0;
+ for(i = 0; i < ntoc; i++){
+ if(tocs[i].symbol_index >= nsyms){
+ error_arch(arch, member, "bad symbol index for table of "
+ "contents table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(saves[tocs[i].symbol_index] != 0 &&
+ changes[tocs[i].symbol_index] == 0)
+ new_ntoc++;
+ }
+ new_tocs = allocate(new_ntoc * sizeof(struct dylib_table_of_contents));
+ j = 0;
+ for(i = 0; i < ntoc; i++){
+ if(saves[tocs[i].symbol_index] != 0 &&
+ changes[tocs[i].symbol_index] == 0){
+ new_tocs[j].symbol_index = saves[tocs[i].symbol_index] - 1;
+ new_tocs[j].module_index = tocs[i].module_index;
+ j++;
+ }
+ }
+
+ if(undef_map != NULL)
+ free(undef_map);
+ if(undef_map64 != NULL)
+ free(undef_map64);
+ if(changes != NULL)
+ free(changes);
+ if(sections != NULL)
+ free(sections);
+ if(sections64 != NULL)
+ free(sections64);
+
+ if(errors == 0)
+ return(TRUE);
+ else
+ return(FALSE);
+}
+
+/*
+ * strip_LC_UUID_commands() is called when -no_uuid is specified to remove any
+ * LC_UUID load commands from the object's load commands.
+ */
+static
+void
+strip_LC_UUID_commands(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ uint32_t i, ncmds, nuuids, mh_sizeofcmds, sizeofcmds;
+ struct load_command *lc1, *lc2, *new_load_commands;
+ struct segment_command *sg;
+
+ /*
+ * See if there are any LC_UUID load commands.
+ */
+ nuuids = 0;
+ lc1 = arch->object->load_commands;
+ if(arch->object->mh != NULL){
+ ncmds = arch->object->mh->ncmds;
+ mh_sizeofcmds = arch->object->mh->sizeofcmds;
+ }
+ else{
+ ncmds = arch->object->mh64->ncmds;
+ mh_sizeofcmds = arch->object->mh64->sizeofcmds;
+ }
+ for(i = 0; i < ncmds; i++){
+ if(lc1->cmd == LC_UUID){
+ nuuids++;
+ }
+ lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
+ }
+ /* if no LC_UUID load commands just return */
+ if(nuuids == 0)
+ return;
+
+ /*
+ * Allocate space for the new load commands as zero it out so any holes
+ * will be zero bytes.
+ */
+ new_load_commands = allocate(mh_sizeofcmds);
+ memset(new_load_commands, '\0', mh_sizeofcmds);
+
+ /*
+ * Copy all the load commands except the LC_UUID load commands into the
+ * allocated space for the new load commands.
+ */
+ lc1 = arch->object->load_commands;
+ lc2 = new_load_commands;
+ sizeofcmds = 0;
+ for(i = 0; i < ncmds; i++){
+ if(lc1->cmd != LC_UUID){
+ memcpy(lc2, lc1, lc1->cmdsize);
+ sizeofcmds += lc2->cmdsize;
+ lc2 = (struct load_command *)((char *)lc2 + lc2->cmdsize);
+ }
+ lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
+ }
+
+ /*
+ * Finally copy the updated load commands over the existing load
+ * commands.
+ */
+ memcpy(arch->object->load_commands, new_load_commands, sizeofcmds);
+ if(mh_sizeofcmds > sizeofcmds){
+ memset((char *)arch->object->load_commands + sizeofcmds, '\0',
+ (mh_sizeofcmds - sizeofcmds));
+ }
+ ncmds -= nuuids;
+ if(arch->object->mh != NULL) {
+ arch->object->mh->sizeofcmds = sizeofcmds;
+ arch->object->mh->ncmds = ncmds;
+ } else {
+ arch->object->mh64->sizeofcmds = sizeofcmds;
+ arch->object->mh64->ncmds = ncmds;
+ }
+ free(new_load_commands);
+
+ /* reset the pointers into the load commands */
+ lc1 = arch->object->load_commands;
+ for(i = 0; i < ncmds; i++){
+ switch(lc1->cmd){
+ case LC_SYMTAB:
+ arch->object->st = (struct symtab_command *)lc1;
+ break;
+ case LC_DYSYMTAB:
+ arch->object->dyst = (struct dysymtab_command *)lc1;
+ break;
+ case LC_TWOLEVEL_HINTS:
+ arch->object->hints_cmd = (struct twolevel_hints_command *)lc1;
+ break;
+ case LC_PREBIND_CKSUM:
+ arch->object->cs = (struct prebind_cksum_command *)lc1;
+ break;
+ case LC_SEGMENT:
+ sg = (struct segment_command *)lc1;
+ if(strcmp(sg->segname, SEG_LINKEDIT) == 0)
+ arch->object->seg_linkedit = sg;
+ break;
+ case LC_SEGMENT_SPLIT_INFO:
+ object->split_info_cmd = (struct linkedit_data_command *)lc1;
+ break;
+ case LC_CODE_SIGNATURE:
+ object->code_sig_cmd = (struct linkedit_data_command *)lc1;
+ break;
+ }
+ lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
+ }
+}
+
+#ifndef NMEDIT
+/*
+ * strip_LC_CODE_SIGNATURE_commands() is called when -c is specified to remove
+ * any LC_CODE_SIGNATURE load commands from the object's load commands.
+ */
+static
+void
+strip_LC_CODE_SIGNATURE_commands(
+struct arch *arch,
+struct member *member,
+struct object *object)
+{
+ uint32_t i, ncmds, mh_sizeofcmds, sizeofcmds;
+ struct load_command *lc1, *lc2, *new_load_commands;
+ struct segment_command *sg;
+
+ /*
+ * See if there is an LC_CODE_SIGNATURE load command and if no command
+ * just return.
+ */
+ if(object->code_sig_cmd == NULL)
+ return;
+
+ /*
+ * Allocate space for the new load commands and zero it out so any holes
+ * will be zero bytes.
+ */
+ if(arch->object->mh != NULL){
+ ncmds = arch->object->mh->ncmds;
+ mh_sizeofcmds = arch->object->mh->sizeofcmds;
+ }
+ else{
+ ncmds = arch->object->mh64->ncmds;
+ mh_sizeofcmds = arch->object->mh64->sizeofcmds;
+ }
+ new_load_commands = allocate(mh_sizeofcmds);
+ memset(new_load_commands, '\0', mh_sizeofcmds);
+
+ /*
+ * Copy all the load commands except the LC_CODE_SIGNATURE load commands
+ * into the allocated space for the new load commands.
+ */
+ lc1 = arch->object->load_commands;
+ lc2 = new_load_commands;
+ sizeofcmds = 0;
+ for(i = 0; i < ncmds; i++){
+ if(lc1->cmd != LC_CODE_SIGNATURE){
+ memcpy(lc2, lc1, lc1->cmdsize);
+ sizeofcmds += lc2->cmdsize;
+ lc2 = (struct load_command *)((char *)lc2 + lc2->cmdsize);
+ }
+ lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
+ }
+
+ /*
+ * Finally copy the updated load commands over the existing load
+ * commands.
+ */
+ memcpy(arch->object->load_commands, new_load_commands, sizeofcmds);
+ if(mh_sizeofcmds > sizeofcmds){
+ memset((char *)arch->object->load_commands + sizeofcmds, '\0',
+ (mh_sizeofcmds - sizeofcmds));
+ }
+ ncmds -= 1;
+ if(arch->object->mh != NULL) {
+ arch->object->mh->sizeofcmds = sizeofcmds;
+ arch->object->mh->ncmds = ncmds;
+ } else {
+ arch->object->mh64->sizeofcmds = sizeofcmds;
+ arch->object->mh64->ncmds = ncmds;
+ }
+ free(new_load_commands);
+
+ /* reset the pointers into the load commands */
+ object->code_sig_cmd = NULL;
+ lc1 = arch->object->load_commands;
+ for(i = 0; i < ncmds; i++){
+ switch(lc1->cmd){
+ case LC_SYMTAB:
+ arch->object->st = (struct symtab_command *)lc1;
+ break;
+ case LC_DYSYMTAB:
+ arch->object->dyst = (struct dysymtab_command *)lc1;
+ break;
+ case LC_TWOLEVEL_HINTS:
+ arch->object->hints_cmd = (struct twolevel_hints_command *)lc1;
+ break;
+ case LC_PREBIND_CKSUM:
+ arch->object->cs = (struct prebind_cksum_command *)lc1;
+ break;
+ case LC_SEGMENT:
+ sg = (struct segment_command *)lc1;
+ if(strcmp(sg->segname, SEG_LINKEDIT) == 0)
+ arch->object->seg_linkedit = sg;
+ break;
+ case LC_SEGMENT_SPLIT_INFO:
+ object->split_info_cmd = (struct linkedit_data_command *)lc1;
+ break;
+ }
+ lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
+ }
+
+ /*
+ * To get the right amount of the file copied out by writeout() for the
+ * case when we are stripping out the section contents we already reduce
+ * the object size by the size of the section contents including the
+ * padding after the load commands. So here we need to further reduce
+ * it by the load command for the LC_CODE_SIGNATURE (a struct
+ * linkedit_data_command) we are removing.
+ */
+ object->object_size -= sizeof(struct linkedit_data_command);
+ /*
+ * Then this size minus the size of the input symbolic information is
+ * what is copied out from the file by writeout(). Which in this case
+ * is just the new headers.
+ */
+
+ /*
+ * Finally for -c the file offset to the link edit information is to be
+ * right after the load commands. So reset this for the updated size
+ * of the load commands without the LC_CODE_SIGNATURE.
+ */
+ if(object->mh != NULL)
+ object->seg_linkedit->fileoff = sizeof(struct mach_header) +
+ sizeofcmds;
+ else
+ object->seg_linkedit64->fileoff = sizeof(struct mach_header_64) +
+ sizeofcmds;
+}
+#endif /* !(NMEDIT) */
+
+/*
+ * private_extern_reference_by_module() is passed a symbol_index of a private
+ * extern symbol and the module table. If the symbol_index appears in the
+ * module symbol table this returns TRUE else it returns FALSE.
+ */
+static
+enum bool
+private_extern_reference_by_module(
+unsigned long symbol_index,
+struct dylib_reference *refs,
+unsigned long nextrefsyms)
+{
+ unsigned long i;
+
+ for(i = 0; i < nextrefsyms; i++){
+ if(refs[i].isym == symbol_index){
+ if(refs[i].flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY ||
+ refs[i].flags == REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY){
+ return(TRUE);
+ }
+ }
+ }
+ return(FALSE);
+}
+
+/*
+ * symbol_pointer_used() is passed a symbol_index and the indirect table. If
+ * the symbol_index appears in the indirect symbol table this returns TRUE else
+ * it returns FALSE.
+ */
+static
+enum bool
+symbol_pointer_used(
+unsigned long symbol_index,
+uint32_t *indirectsyms,
+unsigned long nindirectsyms)
+{
+ unsigned long i;
+
+ for(i = 0; i < nindirectsyms; i++){
+ if(indirectsyms[i] == symbol_index)
+ return(TRUE);
+ }
+ return(FALSE);
+}
+
+/*
+ * Function for qsort for comparing undefined map entries.
+ */
+static
+int
+cmp_qsort_undef_map(
+const struct undef_map *sym1,
+const struct undef_map *sym2)
+{
+ return(strcmp(qsort_strings + sym1->symbol.n_un.n_strx,
+ qsort_strings + sym2->symbol.n_un.n_strx));
+}
+
+static
+int
+cmp_qsort_undef_map_64(
+const struct undef_map64 *sym1,
+const struct undef_map64 *sym2)
+{
+ return(strcmp(qsort_strings + sym1->symbol64.n_un.n_strx,
+ qsort_strings + sym2->symbol64.n_un.n_strx));
+}
+#endif /* !defined(NMEDIT) */
+
+#ifndef NMEDIT
+/*
+ * Function for qsort for comparing object names.
+ */
+static
+int
+cmp_qsort_filename(
+const char **name1,
+const char **name2)
+{
+ return(strcmp(*name1, *name2));
+}
+
+/*
+ * Function for bsearch for finding a object name.
+ */
+static
+int
+cmp_bsearch_filename(
+const char *name1,
+const char **name2)
+{
+ return(strcmp(name1, *name2));
+}
+#endif /* !defined(NMEDIT) */
+
+#ifdef NMEDIT
+static
+enum bool
+edit_symtab(
+struct arch *arch,
+struct member *member,
+struct object *object,
+struct nlist *symbols,
+struct nlist_64 *symbols64,
+unsigned long nsyms,
+char *strings,
+unsigned long strsize,
+struct dylib_table_of_contents *tocs,
+unsigned long ntoc,
+struct dylib_module *mods,
+struct dylib_module_64 *mods64,
+unsigned long nmodtab,
+struct dylib_reference *refs,
+unsigned long nextrefsyms)
+{
+ unsigned long i, j, k;
+ unsigned char data_n_sect, nsects;
+ struct load_command *lc;
+ struct segment_command *sg;
+ struct segment_command_64 *sg64;
+ struct section *s, **sections;
+ struct section_64 *s64, **sections64;
+
+ unsigned long missing_syms;
+ struct symbol_list *sp;
+ struct nlist **global_symbol;
+ struct nlist_64 **global_symbol64;
+ enum bool global_symbol_found;
+ char *global_name, save_char;
+ enum bool dwarf_debug_map;
+ enum byte_sex host_byte_sex;
+ long missing_reloc_symbols;
+ enum bool edit_symtab_return;
+
+ char *p, *q;
+ unsigned long new_ext_strsize, len, inew_syms;
+
+ struct nlist **changed_globals;
+ struct nlist_64 **changed_globals64;
+ unsigned long nchanged_globals;
+ uint32_t ncmds, s_flags, n_strx, module_name, ilocalsym, nlocalsym;
+ uint32_t iextdefsym, nextdefsym;
+ uint8_t n_type, n_sect, global_symbol_n_sect;
+ uint64_t n_value;
+ enum bool warned_about_global_coalesced_symbols;
+
+ edit_symtab_return = TRUE;
+ host_byte_sex = get_host_byte_sex();
+ missing_reloc_symbols = 0;
+ warned_about_global_coalesced_symbols = FALSE;
+
+ if(nmedits != NULL)
+ free(nmedits);
+ nmedits = allocate(nsyms * sizeof(enum bool));
+ for(i = 0; i < nsyms; i++)
+ nmedits[i] = FALSE;
+
+ /*
+ * If nmedit is operating on a dynamic library then symbols are turned
+ * into private externs with the extern bit off not into static symbols.
+ */
+ if(object->mh_filetype == MH_DYLIB && pflag == TRUE){
+ error_arch(arch, member, "can't use -p with dynamic libraries");
+ return(FALSE);
+ }
+
+ /*
+ * As part of the MAJOR guess for the second pass to fix stabs for the
+ * globals symbols that get turned into non-global symbols. We need to
+ * change the stabs. To do this we to know if a N_GSYM is for a data
+ * symbol or not to know to turn it into an N_STSYM or a N_FUN.
+ * This logic as determined by compiling test cases with and without
+ * the key word 'static' and looking at the difference between the STABS
+ * the compiler generates and trying to match that here.
+ *
+ * We also use this loop and the next to gather an array of section
+ * struct pointers so we can later determine if we run into a global
+ * symbol in a coalesced section and not turn those symbols into
+ * statics.
+ */
+ j = 0;
+ nsects = 0;
+ n_sect = 1;
+ data_n_sect = NO_SECT;
+ lc = object->load_commands;
+ if(object->mh != NULL)
+ ncmds = object->mh->ncmds;
+ else
+ ncmds = object->mh64->ncmds;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ s = (struct section *)((char *)sg +
+ sizeof(struct segment_command));
+ nsects += sg->nsects;
+ for(j = 0; j < sg->nsects; j++){
+ if(strcmp(s->segname, SEG_DATA) == 0 &&
+ strcmp(s->sectname, SECT_DATA) == 0 &&
+ data_n_sect == NO_SECT){
+ data_n_sect = n_sect;
+ break;
+ }
+ n_sect++;
+ s++;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)((char *)sg64 +
+ sizeof(struct segment_command_64));
+ nsects += sg64->nsects;
+ for(j = 0; j < sg64->nsects; j++){
+ if(strcmp(s64->segname, SEG_DATA) == 0 &&
+ strcmp(s64->sectname, SECT_DATA) == 0 &&
+ data_n_sect == NO_SECT){
+ data_n_sect = n_sect;
+ break;
+ }
+ n_sect++;
+ s64++;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ if(object->mh != NULL){
+ sections = allocate(nsects * sizeof(struct section *));
+ sections64 = NULL;
+ }
+ else{
+ sections = NULL;
+ sections64 = allocate(nsects * sizeof(struct section_64 *));
+ }
+ nsects = 0;
+ lc = object->load_commands;
+ for(i = 0; i < ncmds; i++){
+ if(lc->cmd == LC_SEGMENT){
+ sg = (struct segment_command *)lc;
+ s = (struct section *)((char *)sg +
+ sizeof(struct segment_command));
+ for(j = 0; j < sg->nsects; j++){
+ sections[nsects++] = s++;
+ }
+ }
+ else if(lc->cmd == LC_SEGMENT_64){
+ sg64 = (struct segment_command_64 *)lc;
+ s64 = (struct section_64 *)((char *)sg64 +
+ sizeof(struct segment_command_64));
+ for(j = 0; j < sg64->nsects; j++){
+ sections64[nsects++] = s64++;
+ }
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+
+ /*
+ * Zero out the saved symbols so they can be recorded for this file.
+ */
+ for(i = 0; i < nsave_symbols; i++)
+ save_symbols[i].sym = NULL;
+ for(i = 0; i < nremove_symbols; i++)
+ remove_symbols[i].sym = NULL;
+ if(member == NULL){
+ for(i = 0; i < nsave_symbols; i++)
+ save_symbols[i].seen = FALSE;
+ for(i = 0; i < nremove_symbols; i++)
+ remove_symbols[i].seen = FALSE;
+ }
+
+ nchanged_globals = 0;
+ if(object->mh != NULL){
+ changed_globals = allocate(nsyms * sizeof(struct nlist *));
+ changed_globals64 = NULL;
+ for(i = 0; i < nsyms; i++)
+ changed_globals[i] = NULL;
+ }
+ else{
+ changed_globals = NULL;
+ changed_globals64 = allocate(nsyms * sizeof(struct nlist_64 *));
+ for(i = 0; i < nsyms; i++)
+ changed_globals64[i] = NULL;
+ }
+
+ /*
+ * These are the variables for the new symbol table and new string
+ * table. Since this routine only turns globals into non-globals the
+ * number of symbols does not change. But the count of local, defined
+ * external symbols does change.
+ */
+ new_nsyms = nsyms;
+ new_nlocalsym = 0;
+ new_nextdefsym = 0;
+ new_nundefsym = 0;
+
+ new_strsize = sizeof(long);
+ new_ext_strsize = 0;
+
+ /*
+ * First pass: turn the globals symbols into non-global symbols.
+ */
+ for(i = 0; i < nsyms; i++){
+ len = 0;
+ s_flags = 0;
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ n_sect = symbols[i].n_sect;
+ if((n_type & N_TYPE) == N_SECT)
+ s_flags = sections[n_sect - 1]->flags;
+ n_value = symbols[i].n_value;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ n_sect = symbols64[i].n_sect;
+ if((n_type & N_TYPE) == N_SECT)
+ s_flags = sections64[n_sect - 1]->flags;
+ n_value = symbols64[i].n_value;
+ }
+ if(n_strx != 0){
+ if(n_strx > strsize){
+ error_arch(arch, member, "bad string index for symbol "
+ "table entry %lu in: ", i);
+ return(FALSE);
+ }
+ len = strlen(strings + n_strx) + 1;
+ }
+ if(n_type & N_EXT){
+ if((n_type & N_TYPE) != N_UNDF &&
+ (n_type & N_TYPE) != N_PBUD){
+ if((n_type & N_TYPE) == N_SECT){
+ if(n_sect > nsects){
+ error_arch(arch, member, "bad n_sect for symbol "
+ "table entry %lu in: ", i);
+ return(FALSE);
+ }
+ if(((s_flags & SECTION_TYPE) == S_COALESCED) &&
+ pflag == FALSE &&
+ object->mh_filetype != MH_OBJECT){
+ /* this remains a global defined symbol */
+ if(warned_about_global_coalesced_symbols == FALSE){
+ warning_arch(arch, member, "can't make global "
+ "coalesced symbols (like %s) into static "
+ "symbols (use ld(1)'s "
+ "-exported_symbols_list option) in a final "
+ "linked image: ", strings + n_strx);
+ warned_about_global_coalesced_symbols = TRUE;
+ }
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ sp = bsearch(strings + n_strx,
+ remove_symbols, nremove_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym != NULL){
+ error_arch(arch, member, "more than one "
+ "symbol for: %s found in: ", sp->name);
+ return(FALSE);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ warning_arch(arch, member, "can't make "
+ "global coalesced symbol: %s into a "
+ "static symbol in: ", sp->name);
+ }
+ }
+ /*
+ * In case the user has listed this coalesced
+ * symbol in the save list look for it and mark it
+ * as seen so we don't complain about not seeing it.
+ */
+ sp = bsearch(strings + n_strx,
+ save_symbols, nsave_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym != NULL){
+ error_arch(arch, member, "more than one "
+ "symbol for: %s found in: ", sp->name);
+ return(FALSE);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ }
+ }
+ continue; /* leave this symbol unchanged */
+ }
+ }
+ sp = bsearch(strings + n_strx,
+ remove_symbols, nremove_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym != NULL){
+ error_arch(arch, member, "more than one symbol "
+ "for: %s found in: ", sp->name);
+ return(FALSE);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ goto change_symbol;
+ }
+ }
+ else{
+ /*
+ * If there is no list of saved symbols, then all
+ * symbols will be saved unless listed in the remove
+ * list.
+ */
+ if(sfile == NULL){
+ /*
+ * There is no save list, so if there is also no
+ * remove list but the -p flag is specified or it is
+ * a dynamic library then change all symbols.
+ */
+ if((pflag || object->mh_filetype == MH_DYLIB)
+ && nremove_symbols == 0)
+ goto change_symbol;
+ /* this remains a global defined symbol */
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ continue; /* leave this symbol unchanged */
+ }
+ }
+ sp = bsearch(strings + n_strx,
+ save_symbols, nsave_symbols,
+ sizeof(struct symbol_list),
+ (int (*)(const void *, const void *))
+ symbol_list_bsearch);
+ if(sp != NULL){
+ if(sp->sym != NULL){
+ error_arch(arch, member, "more than one symbol "
+ "for: %s found in: ", sp->name);
+ return(FALSE);
+ }
+ else{
+ if(object->mh != NULL)
+ sp->sym = &(symbols[i]);
+ else
+ sp->sym = &(symbols64[i]);
+ sp->seen = TRUE;
+ /* this remains a global defined symbol */
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ }
+ }
+ else{
+ if(Aflag && n_type == (N_EXT | N_ABS) &&
+ (n_value != 0 ||
+ (n_strx != 0 &&
+ strncmp(strings + n_strx,
+ ".objc_class_name_",
+ sizeof(".objc_class_name_") - 1) == 0))){
+ /* this remains a global defined symbol */
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ }
+ else{
+change_symbol:
+ if((n_type & N_TYPE) != N_INDR){
+ nmedits[i] = TRUE;
+ if(object->mh != NULL)
+ changed_globals[nchanged_globals++] =
+ symbols + i;
+ else
+ changed_globals64[nchanged_globals++] =
+ symbols64 + i;
+ if(pflag){
+ /* this remains a global defined symbol */
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ }
+ else{
+ /* this will become a non-global symbol */
+ new_nlocalsym++;
+ new_strsize += len;
+ }
+ }
+ else{
+ /* this remains a global defined symbol */
+ new_nextdefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ }
+ }
+ }
+ }
+ else{
+ /* this is an undefined symbol */
+ new_nundefsym++;
+ new_ext_strsize += len;
+ new_strsize += len;
+ }
+ }
+ else{
+ /* this is a local symbol */
+ new_nlocalsym++;
+ new_strsize += len;
+ }
+ }
+
+ /*
+ * The module table's module names are placed with the external
+ * strings. So size them and add this to the external string size.
+ */
+ for(i = 0; i < nmodtab; i++){
+ if(object->mh != NULL)
+ module_name = mods[i].module_name;
+ else
+ module_name = mods64[i].module_name;
+ if(module_name == 0 || module_name > strsize){
+ error_arch(arch, member, "bad string index for module_name "
+ "of module table entry %ld in: ", i);
+ return(FALSE);
+ }
+ len = strlen(strings + module_name) + 1;
+ new_strsize += len;
+ new_ext_strsize += len;
+ }
+
+ /*
+ * Warn about symbols to be saved that were missing.
+ */
+ if(member == NULL){
+ missing_syms = 0;
+ if(iflag == 0){
+ for(i = 0; i < nsave_symbols; i++){
+ if(save_symbols[i].sym == NULL){
+ if(missing_syms == 0){
+ error_arch(arch, member, "symbols names listed "
+ "in: %s not in: ", sfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", save_symbols[i].name);
+ }
+ }
+ for(i = 0; i < nremove_symbols; i++){
+ if(remove_symbols[i].sym == NULL){
+ if(missing_syms == 0){
+ error_arch(arch, member, "symbols names listed "
+ "in: %s not in: ", Rfile);
+ missing_syms = 1;
+ }
+ fprintf(stderr, "%s\n", remove_symbols[i].name);
+ }
+ }
+ }
+ }
+
+ /*
+ * Second pass: fix stabs for the globals symbols that got turned into
+ * non-global symbols. This is a MAJOR guess. The specific changes
+ * to do here were determined by compiling test cases with and without
+ * the key word 'static' and looking at the difference between the STABS
+ * the compiler generates and trying to match that here.
+ */
+ global_strings = strings;
+ if(object->mh != NULL)
+ qsort(changed_globals, nchanged_globals, sizeof(struct nlist *),
+ (int (*)(const void *, const void *))cmp_qsort_global);
+ else
+ qsort(changed_globals64, nchanged_globals,sizeof(struct nlist_64 *),
+ (int (*)(const void *, const void *))cmp_qsort_global_64);
+ dwarf_debug_map = FALSE;
+ for(i = 0; i < nsyms; i++){
+ uint16_t n_desc;
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ n_desc = symbols[i].n_desc;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ n_desc = symbols64[i].n_desc;
+ }
+ if(n_type == N_SO)
+ dwarf_debug_map = FALSE;
+ else if (n_type == N_OSO)
+ dwarf_debug_map = n_desc != 0;
+ else if (dwarf_debug_map && n_type == N_GSYM){
+ global_name = strings + n_strx;
+ if(object->mh != NULL){
+ global_symbol = bsearch(global_name, changed_globals,
+ nchanged_globals,sizeof(struct nlist *),
+ (int (*)(const void *, const void *))
+ cmp_bsearch_global);
+ if(global_symbol != NULL){
+ symbols[i].n_type = N_STSYM;
+ symbols[i].n_sect = (*global_symbol)->n_sect;
+ symbols[i].n_value = (*global_symbol)->n_value;
+ }
+ }
+ else{
+ global_symbol64 = bsearch(global_name, changed_globals64,
+ nchanged_globals,
+ sizeof(struct nlist_64 *),
+ (int (*)(const void *, const void *))
+ cmp_bsearch_global_64);
+ if(global_symbol64 != NULL){
+ symbols64[i].n_type = N_STSYM;
+ symbols64[i].n_sect = (*global_symbol64)->n_sect;
+ symbols64[i].n_value = (*global_symbol64)->n_value;
+ }
+ }
+ }
+ else if(! dwarf_debug_map &&
+ (n_type == N_GSYM || n_type == N_FUN) &&
+ (n_strx != 0 && strings[n_strx] != '\0')){
+ global_name = strings + n_strx;
+ if((global_name[0] == '+' || global_name[0] == '-') &&
+ global_name[1] == '['){
+ j = 2;
+ while(j + n_strx < strsize && global_name[j] != ']')
+ j++;
+ if(j + n_strx < strsize && global_name[j] == ']')
+ j++;
+ }
+ else
+ j = 0;
+ while(j + n_strx < strsize && global_name[j] != ':')
+ j++;
+ if(j + n_strx >= strsize){
+ error_arch(arch, member, "bad N_STAB symbol name for entry "
+ "%lu (does not contain ':' separating name from type) "
+ "in: ", i);
+ return(FALSE);
+ }
+ save_char = global_name[j];
+ global_name[j] = '\0';
+
+ global_symbol_found = FALSE;
+ global_symbol_n_sect = 0;
+ if(object->mh != NULL){
+ global_symbol = bsearch(global_name, changed_globals,
+ nchanged_globals,sizeof(struct nlist *),
+ (int (*)(const void *, const void *))
+ cmp_bsearch_global_stab);
+ global_symbol64 = NULL;
+ if(global_symbol != NULL){
+ global_symbol_found = TRUE;
+ global_symbol_n_sect = (*global_symbol)->n_sect;
+ }
+ }
+ else{
+ global_symbol64 = bsearch(global_name, changed_globals64,
+ nchanged_globals,
+ sizeof(struct nlist_64 *),
+ (int (*)(const void *, const void *))
+ cmp_bsearch_global_stab_64);
+ global_symbol = NULL;
+ if(global_symbol64 != NULL){
+ global_symbol_found = TRUE;
+ global_symbol_n_sect = (*global_symbol64)->n_sect;
+ }
+ }
+ global_name[j] = save_char;
+ if(global_symbol_found == TRUE){
+ if(n_type == N_GSYM){
+ if(global_symbol_n_sect == data_n_sect){
+ if(object->mh != NULL)
+ symbols[i].n_type = N_STSYM;
+ else
+ symbols64[i].n_type = N_STSYM;
+ }
+ else{
+ if(object->mh != NULL)
+ symbols[i].n_type = N_FUN;
+ else
+ symbols64[i].n_type = N_FUN;
+ }
+ if(object->mh != NULL){
+ symbols[i].n_sect = (*global_symbol)->n_sect;
+ symbols[i].n_value = (*global_symbol)->n_value;
+ symbols[i].n_desc = (*global_symbol)->n_desc;
+ }
+ else{
+ symbols64[i].n_sect = (*global_symbol64)->n_sect;
+ symbols64[i].n_value = (*global_symbol64)->n_value;
+ symbols64[i].n_desc = (*global_symbol64)->n_desc;
+ }
+ if(j + 1 + n_strx >= strsize ||
+ global_name[j+1] != 'G'){
+ error_arch(arch, member, "bad N_GSYM symbol name "
+ "for entry %lu (does not have type 'G' after "
+ "':' in name) in: ", i);
+ return(FALSE);
+ }
+ global_name[j+1] = 'S';
+ }
+ else{ /* n_type == N_FUN */
+ if(j + 1 + n_strx >= strsize ||
+ global_name[j+1] == 'F'){
+ global_name[j+1] = 'f';
+ }
+ }
+ }
+ }
+ }
+ global_strings = NULL;
+
+ /*
+ * Now what needs to be done is to create the new symbol table moving
+ * those global symbols being changed into non-globals into the areas
+ * in the symbol table for local symbols. The symbol table and string
+ * table must be in this order:
+ *
+ * symbol table
+ * local symbols
+ * external defined symbols
+ * undefined symbols
+ * string table
+ * external strings
+ * local strings
+ */
+ if(saves != NULL)
+ free(saves);
+ saves = (long *)allocate(nsyms * sizeof(long));
+ bzero(saves, nsyms * sizeof(long));
+
+ if(object->mh != NULL){
+ new_symbols = (struct nlist *)
+ allocate(new_nsyms * sizeof(struct nlist));
+ new_symbols64 = NULL;
+ }
+ else{
+ new_symbols = NULL;
+ new_symbols64 = (struct nlist_64 *)
+ allocate(new_nsyms * sizeof(struct nlist_64));
+ }
+ new_strsize = round(new_strsize, sizeof(long));
+ new_strings = (char *)allocate(new_strsize);
+ new_strings[new_strsize - 3] = '\0';
+ new_strings[new_strsize - 2] = '\0';
+ new_strings[new_strsize - 1] = '\0';
+
+ memset(new_strings, '\0', sizeof(long));
+ p = new_strings + sizeof(long);
+ q = p + new_ext_strsize;
+
+ /*
+ * If this is a dynamic library the movement of the symbols has to be
+ * done with respect to the modules. As the local symbols, and external
+ * defined symbols are grouped together for each module. Then a new
+ * module table needs to be created with the new indexes into the symbol
+ * table for each module.
+ */
+ new_nmodtab = nmodtab;
+ new_ntoc = ntoc;
+ new_nextrefsyms = nextrefsyms;
+ if(object->mh_filetype == MH_DYLIB && nmodtab != 0){
+ if(object->mh != NULL){
+ new_mods = allocate(nmodtab * sizeof(struct dylib_module));
+ new_mods64 = NULL;
+ }
+ else{
+ new_mods = NULL;
+ new_mods64 = allocate(nmodtab * sizeof(struct dylib_module_64));
+ }
+
+ inew_syms = 0;
+ /*
+ * This first loop through the module table sets the index and
+ * counts of the local symbols for each module.
+ */
+ for(i = 0; i < nmodtab; i++){
+ /*
+ * First put the existing local symbols into the new symbol
+ * table.
+ */
+ if(object->mh != NULL){
+ new_mods[i].ilocalsym = inew_syms;
+ new_mods[i].nlocalsym = 0;
+ ilocalsym = mods[i].ilocalsym;
+ nlocalsym = mods[i].nlocalsym;
+ }
+ else{
+ new_mods64[i].ilocalsym = inew_syms;
+ new_mods64[i].nlocalsym = 0;
+ ilocalsym = mods64[i].ilocalsym;
+ nlocalsym = mods64[i].nlocalsym;
+ }
+ for(j = ilocalsym; j < ilocalsym + nlocalsym; j++){
+ if(object->mh != NULL){
+ n_strx = symbols[j].n_un.n_strx;
+ n_type = symbols[j].n_type;
+ }
+ else{
+ n_strx = symbols64[j].n_un.n_strx;
+ n_type = symbols64[j].n_type;
+ }
+ if((n_type & N_EXT) == 0){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[j];
+ else
+ new_symbols64[inew_syms] = symbols64[j];
+ if(n_strx != 0){
+ strcpy(q, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ q - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ q - new_strings;
+ q += strlen(q) + 1;
+ }
+ inew_syms++;
+ saves[j] = inew_syms;
+ if(object->mh != NULL)
+ new_mods[i].nlocalsym++;
+ else
+ new_mods64[i].nlocalsym++;
+ }
+ }
+ /*
+ * Next put the global symbols that were changed into
+ * non-global symbols into the new symbol table and moved their
+ * counts to the local symbol counts.
+ */
+ if(object->mh != NULL){
+ iextdefsym = mods[i].iextdefsym;
+ nextdefsym = mods[i].nextdefsym;
+ }
+ else{
+ iextdefsym = mods64[i].iextdefsym;
+ nextdefsym = mods64[i].nextdefsym;
+ }
+ for(j = iextdefsym; j < iextdefsym + nextdefsym; j++){
+ if(object->mh != NULL){
+ n_strx = symbols[j].n_un.n_strx;
+ n_type = symbols[j].n_type;
+ }
+ else{
+ n_strx = symbols64[j].n_un.n_strx;
+ n_type = symbols64[j].n_type;
+ }
+ if((n_type & N_EXT) != 0){
+ if(nmedits[j] == TRUE){
+ /*
+ * Change the new symbol to a private extern symbol
+ * with the extern bit off.
+ */
+ if(object->mh != NULL){
+ new_symbols[inew_syms] = symbols[j];
+ new_symbols[inew_syms].n_type |= N_PEXT;
+ new_symbols[inew_syms].n_type &= ~N_EXT;
+ }
+ else{
+ new_symbols64[inew_syms] = symbols64[j];
+ new_symbols64[inew_syms].n_type |= N_PEXT;
+ new_symbols64[inew_syms].n_type &= ~N_EXT;
+ }
+ if(n_strx != 0){
+ strcpy(q, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ q - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ q - new_strings;
+ q += strlen(q) + 1;
+ }
+ inew_syms++;
+ saves[j] = inew_syms;
+ if(object->mh != NULL)
+ new_mods[i].nlocalsym++;
+ else
+ new_mods64[i].nlocalsym++;
+ }
+ }
+ }
+ }
+ /*
+ * Next put the unchanged defined global symbols into the new
+ * symbol table.
+ */
+ for(i = 0; i < nmodtab; i++){
+ if(object->mh != NULL){
+ new_mods[i].iextdefsym = inew_syms;
+ new_mods[i].nextdefsym = 0;
+ iextdefsym = mods[i].iextdefsym;
+ nextdefsym = mods[i].nextdefsym;
+ }
+ else{
+ new_mods64[i].iextdefsym = inew_syms;
+ new_mods64[i].nextdefsym = 0;
+ iextdefsym = mods64[i].iextdefsym;
+ nextdefsym = mods64[i].nextdefsym;
+ }
+ for(j = iextdefsym; j < iextdefsym + nextdefsym; j++){
+ if(object->mh != NULL){
+ n_strx = symbols[j].n_un.n_strx;
+ n_type = symbols[j].n_type;
+ }
+ else{
+ n_strx = symbols64[j].n_un.n_strx;
+ n_type = symbols64[j].n_type;
+ }
+ if((n_type & N_EXT) != 0){
+ if(nmedits[j] == FALSE){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[j];
+ else
+ new_symbols64[inew_syms] = symbols64[j];
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ p - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ inew_syms++;
+ saves[j] = inew_syms;
+ if(object->mh != NULL)
+ new_mods[i].nextdefsym++;
+ else
+ new_mods64[i].nextdefsym++;
+ }
+ }
+ }
+ }
+ /*
+ * Last put the undefined symbols into the new symbol table.
+ */
+ for(i = 0; i < nsyms; i++){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) != 0 &&
+ ((n_type & N_TYPE) == N_UNDF ||
+ (n_type & N_TYPE) == N_PBUD)){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[i];
+ else
+ new_symbols64[inew_syms] = symbols64[i];
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ p - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+
+ /*
+ * Place the module table's module names with the external strings
+ * and set the names in the new module table. And then copy the
+ * other unchanged fields.
+ */
+ for(i = 0; i < nmodtab; i++){
+ if(object->mh != NULL){
+ strcpy(p, strings + mods[i].module_name);
+ new_mods[i].module_name = p - new_strings;
+ p += strlen(p) + 1;
+
+ new_mods[i].irefsym = mods[i].irefsym;
+ new_mods[i].nrefsym = mods[i].nrefsym;
+ new_mods[i].iextrel = mods[i].iextrel;
+ new_mods[i].nextrel = mods[i].nextrel;
+ new_mods[i].iinit_iterm = mods[i].iinit_iterm;
+ new_mods[i].ninit_nterm = mods[i].ninit_nterm;
+ new_mods[i].objc_module_info_addr =
+ mods[i].objc_module_info_addr;
+ new_mods[i].objc_module_info_size =
+ mods[i].objc_module_info_size;
+ }
+ else{
+ strcpy(p, strings + mods64[i].module_name);
+ new_mods64[i].module_name = p - new_strings;
+ p += strlen(p) + 1;
+
+ new_mods64[i].irefsym = mods64[i].irefsym;
+ new_mods64[i].nrefsym = mods64[i].nrefsym;
+ new_mods64[i].iextrel = mods64[i].iextrel;
+ new_mods64[i].nextrel = mods64[i].nextrel;
+ new_mods64[i].iinit_iterm = mods64[i].iinit_iterm;
+ new_mods64[i].ninit_nterm = mods64[i].ninit_nterm;
+ new_mods64[i].objc_module_info_addr =
+ mods64[i].objc_module_info_addr;
+ new_mods64[i].objc_module_info_size =
+ mods64[i].objc_module_info_size;
+ }
+ }
+
+ /*
+ * Update the reference table with the new symbol indexes for all
+ * entries and change type of reference (the flags field) for those
+ * symbols that got changed from globals to non-globals.
+ */
+ new_nextrefsyms = nextrefsyms;
+ new_refs = allocate(new_nextrefsyms *
+ sizeof(struct dylib_reference));
+ j = 0;
+ for(i = 0; i < nextrefsyms; i++){
+ if(nmedits[refs[i].isym] == TRUE){
+ if(refs[i].flags == REFERENCE_FLAG_DEFINED)
+ new_refs[i].flags =
+ REFERENCE_FLAG_PRIVATE_DEFINED;
+ else if(refs[i].flags == REFERENCE_FLAG_UNDEFINED_NON_LAZY)
+ new_refs[i].flags =
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY;
+ else if(refs[i].flags == REFERENCE_FLAG_UNDEFINED_LAZY)
+ new_refs[i].flags =
+ REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY;
+ else
+ new_refs[i].flags = refs[i].flags;
+ }
+ else{
+ new_refs[i].flags = refs[i].flags;
+ }
+ new_refs[i].isym = saves[refs[i].isym] - 1;
+ }
+
+ /*
+ * Create a new dylib table of contents without the global symbols
+ * that got turned into non-globals.
+ */
+ new_ntoc = ntoc - nchanged_globals;
+ new_tocs = allocate(new_ntoc *
+ sizeof(struct dylib_table_of_contents));
+ k = 0;
+ for(i = 0; i < ntoc; i++){
+ if(tocs[i].symbol_index >= nsyms){
+ error_arch(arch, member, "bad symbol index for table of "
+ "contents table entry %ld in: ", i);
+ return(FALSE);
+ }
+ if(nmedits[tocs[i].symbol_index] == FALSE){
+ new_tocs[k].symbol_index = saves[tocs[i].symbol_index] - 1;
+ new_tocs[k].module_index = tocs[i].module_index;
+ k++;
+ }
+ }
+ }
+ /*
+ * If is not a dynamic library so all global symbols changed into
+ * statics can be moved to the end of the local symbols. If the pflag
+ * is set then the changed symbols remain global and just get the
+ * private extern bit set.
+ */
+ else{
+ /*
+ * First put the existing local symbols into the new symbol table.
+ */
+ inew_syms = 0;
+ for(i = 0; i < nsyms; i++){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) == 0){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[i];
+ else
+ new_symbols64[inew_syms] = symbols64[i];
+ if(n_strx != 0){
+ strcpy(q, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ q - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ q - new_strings;
+ q += strlen(q) + 1;
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+ /*
+ * Next put the global symbols that were changed into statics
+ * symbols into the new symbol table.
+ */
+ if(pflag == FALSE){
+ for(i = 0; i < nsyms; i++){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) != 0){
+ if(nmedits[i] == TRUE){
+ /*
+ * Change the new symbol to not be an extern symbol
+ * by turning off the extern bit.
+ */
+ if(object->mh != NULL){
+ new_symbols[inew_syms] = symbols[i];
+ new_symbols[inew_syms].n_type &= ~N_EXT;
+ new_symbols[inew_syms].n_desc &= ~N_WEAK_DEF;
+ }
+ else{
+ new_symbols64[inew_syms] = symbols64[i];
+ new_symbols64[inew_syms].n_type &= ~N_EXT;
+ new_symbols64[inew_syms].n_desc &= ~N_WEAK_DEF;
+ }
+ if(n_strx != 0){
+ strcpy(q, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ q - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ q - new_strings;
+ q += strlen(q) + 1;
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+ }
+ }
+ /*
+ * Last put the unchanged global symbols into the new symbol table
+ * and symbols changed into private externs.
+ */
+ for(i = 0; i < nsyms; i++){
+ if(object->mh != NULL){
+ n_strx = symbols[i].n_un.n_strx;
+ n_type = symbols[i].n_type;
+ }
+ else{
+ n_strx = symbols64[i].n_un.n_strx;
+ n_type = symbols64[i].n_type;
+ }
+ if((n_type & N_EXT) != 0){
+ if(nmedits[i] == FALSE || pflag == TRUE){
+ if(object->mh != NULL)
+ new_symbols[inew_syms] = symbols[i];
+ else
+ new_symbols64[inew_syms] = symbols64[i];
+ if(nmedits[i] == TRUE && pflag == TRUE){
+ /*
+ * Change the new symbol to be a private extern
+ * symbol by turning on the private extern bit.
+ */
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_type |= N_PEXT;
+ else
+ new_symbols64[inew_syms].n_type |= N_PEXT;
+ }
+ if(n_strx != 0){
+ strcpy(p, strings + n_strx);
+ if(object->mh != NULL)
+ new_symbols[inew_syms].n_un.n_strx =
+ p - new_strings;
+ else
+ new_symbols64[inew_syms].n_un.n_strx =
+ p - new_strings;
+ p += strlen(p) + 1;
+ }
+ inew_syms++;
+ saves[i] = inew_syms;
+ }
+ }
+ }
+ }
+
+ if(sections != NULL);
+ free(sections);
+ if(sections64 != NULL);
+ free(sections64);
+
+ if(errors == 0)
+ return(TRUE);
+ else
+ return(FALSE);
+}
+
+/*
+ * Function for qsort for comparing global symbol names.
+ */
+static
+int
+cmp_qsort_global(
+const struct nlist **sym1,
+const struct nlist **sym2)
+{
+ return(strcmp(global_strings + (*sym1)->n_un.n_strx,
+ global_strings + (*sym2)->n_un.n_strx));
+}
+
+static
+int
+cmp_qsort_global_64(
+const struct nlist_64 **sym1,
+const struct nlist_64 **sym2)
+{
+ return(strcmp(global_strings + (*sym1)->n_un.n_strx,
+ global_strings + (*sym2)->n_un.n_strx));
+}
+
+/*
+ * Function for bsearch for finding a global symbol that matches a stab name.
+ */
+static
+int
+cmp_bsearch_global_stab(
+const char *name,
+const struct nlist **sym)
+{
+ /*
+ * The +1 is for the '_' on the global symbol that is not on the
+ * stab string that is trying to be matched.
+ */
+ return(strcmp(name, global_strings + (*sym)->n_un.n_strx + 1));
+}
+
+static
+int
+cmp_bsearch_global_stab_64(
+const char *name,
+const struct nlist_64 **sym)
+{
+ /*
+ * The +1 is for the '_' on the global symbol that is not on the
+ * stab string that is trying to be matched.
+ */
+ return(strcmp(name, global_strings + (*sym)->n_un.n_strx + 1));
+}
+
+/*
+ * Function for bsearch for finding a global symbol that matches a stab name
+ * in the debug map.
+ */
+static
+int
+cmp_bsearch_global(
+const char *name,
+const struct nlist **sym)
+{
+ return(strcmp(name, global_strings + (*sym)->n_un.n_strx));
+}
+
+static
+int
+cmp_bsearch_global_64(
+const char *name,
+const struct nlist_64 **sym)
+{
+ return(strcmp(name, global_strings + (*sym)->n_un.n_strx));
+}
+#endif /* defined(NMEDIT) */
--- a/striptease/tease.c
+++ b/striptease/tease.c
@@ -49,30 +49,35 @@
/* These are set from the command line arguments */
__private_extern__
char *progname = NULL; /* name of the program for error messages (argv[0]) */
static char *output_file;/* name of the output file */
static char *sfile; /* filename of global symbol names to keep */
static char *Rfile; /* filename of global symbol names to remove */
static long Aflag; /* save only absolute symbols with non-zero value and
.objc_class_name_* symbols */
+static long aflag; /* -a save all symbols, just regenerate symbol table */
static long iflag; /* -i ignore symbols in -s file not in object */
#ifdef NMEDIT
static long pflag; /* make all defined global symbols private extern */
#else /* !defined(NMEDIT) */
static char *dfile; /* filename of filenames of debugger symbols to keep */
static long uflag; /* save undefined symbols */
static long rflag; /* save symbols referenced dynamically */
static long nflag; /* save N_SECT global symbols */
static long Sflag; /* -S strip only debugger symbols N_STAB */
static long xflag; /* -x strip non-globals */
static long Xflag; /* -X strip local symbols with 'L' names */
+static long tflag; /* -t strip local symbols except those in the text
+ section with names that don't begin with 'L' */
static long cflag; /* -c strip section contents from dynamic libraries
files to create stub libraries */
static long no_uuid; /* -no_uuid strip LC_UUID load commands */
+static long no_code_signature;
+ /* -no_code_signature strip LC_CODE_SIGNATURE cmds */
static long strip_all = 1;
/*
* This is set on an object by object basis if the strip_all flag is still set
* and the object is an executable that is for use with the dynamic linker.
* This has the same effect as -r and -u.
*/
static enum bool default_dyld_executable = FALSE;
#endif /* NMEDIT */
@@ -373,16 +378,19 @@ char *envp[])
if(dfile != NULL)
fatal("only one -d option allowed");
dfile = argv[i + 1];
i++;
}
else if(strcmp(argv[i], "-no_uuid") == 0){
no_uuid = 1;
}
+ else if(strcmp(argv[i], "-no_code_signature") == 0){
+ no_code_signature = 1;
+ }
#endif /* !defined(NMEDIT) */
else if(strcmp(argv[i], "-arch") == 0){
if(i + 1 == argc){
error("missing argument(s) to %s option", argv[i]);
usage();
}
if(strcmp("all", argv[i+1]) == 0){
all_archs = TRUE;
@@ -427,16 +435,20 @@ char *envp[])
case 'X':
Xflag = 1;
strip_all = 0;
break;
case 'x':
xflag = 1;
strip_all = 0;
break;
+ case 't':
+ tflag = 1;
+ strip_all = 0;
+ break;
case 'i':
iflag = 1;
break;
case 'u':
uflag = 1;
strip_all = 0;
break;
case 'r':
@@ -450,16 +462,20 @@ char *envp[])
#endif /* !defined(NMEDIT) */
case 'A':
Aflag = 1;
#ifndef NMEDIT
strip_all = 0;
#endif /* !defined(NMEDIT) */
break;
#ifndef NMEDIT
+ case 'a':
+ aflag = 1;
+ strip_all = 0;
+ break;
case 'c':
cflag = 1;
strip_all = 0;
break;
#endif /* NMEDIT */
default:
error("unrecognized option: %s", argv[i]);
usage();
@@ -555,18 +571,19 @@ char *envp[])
}
static
void
usage(
void)
{
#ifndef NMEDIT
- fprintf(stderr, "Usage: %s [-AnuSXx] [-] [-d filename] [-s filename] "
- "[-R filename] [-o output] file [...] \n", progname);
+ fprintf(stderr, "Usage: %s [-AanuStXx] [-no_uuid] [-no_code_signature] "
+ "[-] [-d filename] [-s filename] [-R filename] [-o output] "
+ "file [...]\n", progname);
#else /* defined(NMEDIT) */
fprintf(stderr, "Usage: %s -s filename [-R filename] [-p] [-A] [-] "
"[-o output] file [...] \n",
progname);
#endif /* NMEDIT */
exit(EXIT_FAILURE);
}
@@ -1174,18 +1191,18 @@ struct object *object)
(flags & MH_DYLDLINK) == MH_DYLDLINK &&
object->mh_filetype == MH_EXECUTE)
default_dyld_executable = TRUE;
else
default_dyld_executable = FALSE;
#endif /* !defined(NMEDIT) */
#ifndef NMEDIT
- if(sfile != NULL || Rfile != NULL || dfile != NULL || Aflag || uflag ||
- Sflag || xflag || Xflag || nflag || rflag ||
+ if(sfile != NULL || Rfile != NULL || dfile != NULL || Aflag || aflag ||
+ uflag || Sflag || xflag || Xflag || tflag || nflag || rflag ||
default_dyld_executable || object->mh_filetype == MH_DYLIB ||
object->mh_filetype == MH_DYLINKER)
#endif /* !defined(NMEDIT) */
{
#ifdef NMEDIT
if(edit_symtab(arch, member, object, symbols, symbols64, nsyms,
strings, strsize, tocs, ntoc, mods, mods64, nmodtab, refs,
nextrefsyms) == FALSE)
@@ -1221,17 +1238,17 @@ 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;
}
if(object->code_sig_cmd != NULL){
#ifndef NMEDIT
- if(!cflag)
+ if(!cflag && !no_code_signature)
#endif /* !(NMEDIT) */
{
object->output_code_sig_data = object->object_addr +
object->code_sig_cmd->dataoff;
object->output_code_sig_data_size =
object->code_sig_cmd->datasize;
}
}
@@ -1349,17 +1366,17 @@ struct object *object)
object->split_info_cmd->datasize;
}
if(object->code_sig_cmd != NULL){
object->input_sym_info_size =
round(object->input_sym_info_size, 16);
object->input_sym_info_size +=
object->code_sig_cmd->datasize;
#ifndef NMEDIT
- if(cflag){
+ if(cflag || no_code_signature){
strip_LC_CODE_SIGNATURE_commands(arch, member, object);
}
else
#endif /* !(NMEDIT) */
{
object->output_sym_info_size =
round(object->output_sym_info_size, 16);
object->output_sym_info_size +=
@@ -2255,16 +2272,17 @@ unsigned long nindirectsyms)
struct nlist *sym;
struct undef_map *undef_map;
struct undef_map64 *undef_map64;
uint8_t n_type, n_sect;
uint16_t n_desc;
uint64_t n_value;
uint32_t module_name, iextdefsym, nextdefsym, ilocalsym, nlocalsym;
uint32_t irefsym, nrefsym;
+ unsigned char text_nsect;
save_debug = 0;
if(saves != NULL)
free(saves);
saves = (long *)allocate(nsyms * sizeof(long));
bzero(saves, nsyms * sizeof(long));
changes = NULL;
for(i = 0; i < nsave_symbols; i++)
@@ -2287,16 +2305,17 @@ unsigned long nindirectsyms)
/*
* Gather an array of section struct pointers so we can later determine
* if we run into a global symbol in a coalesced section and not strip
* those symbols.
* statics.
*/
nsects = 0;
+ text_nsect = NO_SECT;
lc = object->load_commands;
if(object->mh != NULL)
ncmds = object->mh->ncmds;
else
ncmds = object->mh64->ncmds;
for(i = 0; i < ncmds; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
@@ -2318,25 +2337,33 @@ unsigned long nindirectsyms)
}
nsects = 0;
lc = object->load_commands;
for(i = 0; i < ncmds; i++){
if(lc->cmd == LC_SEGMENT){
sg = (struct segment_command *)lc;
s = (struct section *)((char *)sg +
sizeof(struct segment_command));
- for(j = 0; j < sg->nsects; j++)
+ for(j = 0; j < sg->nsects; j++){
+ if(strcmp((s + j)->sectname, SECT_TEXT) == 0 &&
+ strcmp((s + j)->segname, SEG_TEXT) == 0)
+ text_nsect = nsects + 1;
sections[nsects++] = s++;
+ }
}
else if(lc->cmd == LC_SEGMENT_64){
sg64 = (struct segment_command_64 *)lc;
s64 = (struct section_64 *)((char *)sg64 +
sizeof(struct segment_command_64));
- for(j = 0; j < sg64->nsects; j++)
+ for(j = 0; j < sg64->nsects; j++){
+ if(strcmp((s64 + j)->sectname, SECT_TEXT) == 0 &&
+ strcmp((s64 + j)->segname, SEG_TEXT) == 0)
+ text_nsect = nsects + 1;
sections64[nsects++] = s64++;
+ }
}
lc = (struct load_command *)((char *)lc + lc->cmdsize);
}
for(i = 0; i < nsyms; i++){
s_flags = 0;
if(object->mh != NULL){
mh_flags = object->mh->flags;
@@ -2382,34 +2409,41 @@ unsigned long nindirectsyms)
if(n_value > strsize){
error_arch(arch, member, "bad string index for "
"indirect symbol table entry %ld in: ", i);
return(FALSE);
}
}
}
if((n_type & N_EXT) == 0){ /* local symbol */
- /*
- * strip -x or -X on an x86_64 .o file should do nothing.
- */
- if(object->mh == NULL &&
- object->mh64->cputype == CPU_TYPE_X86_64 &&
- object->mh64->filetype == MH_OBJECT &&
- (xflag == 1 || Xflag == 1)){
+ if(aflag){
if(n_strx != 0)
new_strsize += strlen(strings + n_strx) + 1;
new_nlocalsym++;
new_nsyms++;
saves[i] = new_nsyms;
}
/*
- * The cases a local symbol might be saved is with -X -S or
- * with -d filename.
+ * strip -x, -X, or -t on an x86_64 .o file should do nothing.
*/
- else if((!strip_all && (Xflag || Sflag)) || dfile){
+ else if(object->mh == NULL &&
+ object->mh64->cputype == CPU_TYPE_X86_64 &&
+ object->mh64->filetype == MH_OBJECT &&
+ (xflag == 1 || Xflag == 1 || tflag == 1)){
+ if(n_strx != 0)
+ new_strsize += strlen(strings + n_strx) + 1;
+ new_nlocalsym++;
+ new_nsyms++;
+ saves[i] = new_nsyms;
+ }
+ /*
+ * The cases a local symbol might be saved are with -X, -S, -t,
+ * or with -d filename.
+ */
+ else if((!strip_all && (Xflag || tflag || Sflag)) || dfile){
if(n_type & N_STAB){ /* debug symbol */
if(dfile && n_type == N_SO){
if(n_strx != 0){
basename = strrchr(strings + n_strx, '/');
if(basename != NULL)
basename++;
else
basename = strings + n_strx;
@@ -2453,20 +2487,28 @@ unsigned long nindirectsyms)
if(n_strx != 0)
new_strsize += strlen(strings + n_strx) + 1;
new_nlocalsym++;
new_nsyms++;
saves[i] = new_nsyms;
}
}
else{ /* non-debug local symbol */
- if(xflag == 0 && (Sflag || Xflag)){
- if(Xflag == 0 ||
- (n_strx != 0 &&
- strings[n_strx] != 'L')){
+ if(xflag == 0 && (Sflag || Xflag || tflag)){
+ /*
+ * No -x (strip all local), and one of -S (strip
+ * debug), -X (strip 'L' local), or -t (strip
+ * local except non-'L' text) was given.
+ */
+ if((Xflag && n_strx != 0 &&
+ strings[n_strx] != 'L') ||
+ (tflag && (n_type & N_TYPE) == N_SECT &&
+ n_sect == text_nsect && n_strx != 0 &&
+ strings[n_strx] != 'L') ||
+ (Sflag && !Xflag && !tflag)) {
/*
* If this file is a for the dynamic linker and
* this symbol is in a section marked so that
* static symbols are stripped then don't
* keep this symbol.
*/
if((mh_flags & MH_DYLDLINK) != MH_DYLDLINK ||
(n_type & N_TYPE) != N_SECT ||
@@ -2709,17 +2751,18 @@ unsigned long nindirectsyms)
len = strlen(strings + n_strx) + 1;
new_strsize += len;
new_ext_strsize += len;
}
new_nextdefsym++;
new_nsyms++;
saves[i] = new_nsyms;
}
- if(saves[i] == 0 && ((Xflag || Sflag || xflag) ||
+ if(saves[i] == 0 &&
+ ((Xflag || Sflag || xflag || tflag || aflag) ||
((rflag || default_dyld_executable) &&
n_desc & REFERENCED_DYNAMICALLY))){
len = strlen(strings + n_strx) + 1;
new_strsize += len;
new_ext_strsize += len;
if((n_type & N_TYPE) == N_INDR){
len = strlen(strings + n_value) + 1;
new_strsize += len;
@@ -3495,42 +3538,45 @@ struct object *object)
break;
case LC_SEGMENT_SPLIT_INFO:
object->split_info_cmd = (struct linkedit_data_command *)lc1;
break;
}
lc1 = (struct load_command *)((char *)lc1 + lc1->cmdsize);
}
- /*
- * To get the right amount of the file copied out by writeout() for the
- * case when we are stripping out the section contents we already reduce
- * the object size by the size of the section contents including the
- * padding after the load commands. So here we need to further reduce
- * it by the load command for the LC_CODE_SIGNATURE (a struct
- * linkedit_data_command) we are removing.
- */
- object->object_size -= sizeof(struct linkedit_data_command);
- /*
- * Then this size minus the size of the input symbolic information is
- * what is copied out from the file by writeout(). Which in this case
- * is just the new headers.
- */
+ if(cflag){
+ /*
+ * To get the right amount of the file copied out by writeout() for
+ * the case when we are stripping out the section contents we
+ * already reduce the object size by the size of the section
+ * contents including the padding after the load commands. So here
+ * we need to further reduce it by the load command for the
+ * LC_CODE_SIGNATURE (a struct linkedit_data_command) we are
+ * removing.
+ */
+ object->object_size -= sizeof(struct linkedit_data_command);
+ /*
+ * Then this size minus the size of the input symbolic information
+ * is what is copied out from the file by writeout(). Which in this
+ * case is just the new headers.
+ */
- /*
- * Finally for -c the file offset to the link edit information is to be
- * right after the load commands. So reset this for the updated size
- * of the load commands without the LC_CODE_SIGNATURE.
- */
- if(object->mh != NULL)
- object->seg_linkedit->fileoff = sizeof(struct mach_header) +
- sizeofcmds;
- else
- object->seg_linkedit64->fileoff = sizeof(struct mach_header_64) +
- sizeofcmds;
+ /*
+ * Finally for -c the file offset to the link edit information is to
+ * be right after the load commands. So reset this for the updated
+ * size of the load commands without the LC_CODE_SIGNATURE.
+ */
+ if(object->mh != NULL)
+ object->seg_linkedit->fileoff = sizeof(struct mach_header) +
+ sizeofcmds;
+ else
+ object->seg_linkedit64->fileoff =
+ sizeof(struct mach_header_64) + sizeofcmds;
+ }
}
#endif /* !(NMEDIT) */
/*
* private_extern_reference_by_module() is passed a symbol_index of a private
* extern symbol and the module table. If the symbol_index appears in the
* module symbol table this returns TRUE else it returns FALSE.
*/