diff --git a/camino/striptease/include/architecture/m88k/reg_help.h b/camino/striptease/include/architecture/m88k/reg_help.h new file mode 100644 index 00000000000..61c9b761cc1 --- /dev/null +++ b/camino/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 + +/* 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_ */ diff --git a/camino/striptease/include/architecture/nrw/reg_help.h b/camino/striptease/include/architecture/nrw/reg_help.h new file mode 100644 index 00000000000..2437e838613 --- /dev/null +++ b/camino/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_ */ diff --git a/camino/striptease/include/architecture/sparc/reg.h b/camino/striptease/include/architecture/sparc/reg.h new file mode 100644 index 00000000000..6ff70e4f7ff --- /dev/null +++ b/camino/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*/ diff --git a/camino/striptease/include/mach-o/dyld.h b/camino/striptease/include/mach-o/dyld.h new file mode 100644 index 00000000000..c7ab7b7bc28 --- /dev/null +++ b/camino/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 +#include +#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_ */ diff --git a/camino/striptease/include/mach-o/fat.h b/camino/striptease/include/mach-o/fat.h new file mode 100644 index 00000000000..e2bcf433d51 --- /dev/null +++ b/camino/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. + */ + +/* + * 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 +#include +#include + +#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_ */ diff --git a/camino/striptease/include/mach-o/hppa/reloc.h b/camino/striptease/include/mach-o/hppa/reloc.h new file mode 100644 index 00000000000..12a3a635924 --- /dev/null +++ b/camino/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 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 */ + 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 */ diff --git a/camino/striptease/include/mach-o/i860/reloc.h b/camino/striptease/include/mach-o/i860/reloc.h new file mode 100644 index 00000000000..4a48e52bc0d --- /dev/null +++ b/camino/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 */ +}; diff --git a/camino/striptease/include/mach-o/loader.h b/camino/striptease/include/mach-o/loader.h new file mode 100644 index 00000000000..a93304f9e57 --- /dev/null +++ b/camino/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 + +/* + * 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 + +/* + * 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 + +/* + * is expected to define the flavors of the thread + * states and the structures of those flavors for each machine. + */ +#include +#include + +/* + * 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 . + */ +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 . + * 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 + * and . + */ +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 + * 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 . + * 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_ */ diff --git a/camino/striptease/include/mach-o/m68k/reloc.h b/camino/striptease/include/mach-o/m68k/reloc.h new file mode 100644 index 00000000000..12a3a635924 --- /dev/null +++ b/camino/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 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 */ + 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 */ diff --git a/camino/striptease/include/mach-o/m88k/reloc.h b/camino/striptease/include/mach-o/m88k/reloc.h new file mode 100644 index 00000000000..e67011e8288 --- /dev/null +++ b/camino/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 */ +}; diff --git a/camino/striptease/include/mach-o/nlist.h b/camino/striptease/include/mach-o/nlist.h new file mode 100644 index 00000000000..40ccb96d5db --- /dev/null +++ b/camino/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 + +/* + * 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 */ + 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 */ + 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 + */ + +/* + * 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_ */ diff --git a/camino/striptease/include/mach-o/ppc/reloc.h b/camino/striptease/include/mach-o/ppc/reloc.h new file mode 100644 index 00000000000..7b564cc0abc --- /dev/null +++ b/camino/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. */ +}; diff --git a/camino/striptease/include/mach-o/ranlib.h b/camino/striptease/include/mach-o/ranlib.h new file mode 100644 index 00000000000..66a1f091207 --- /dev/null +++ b/camino/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 +#include /* 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_ */ diff --git a/camino/striptease/include/mach-o/reloc.h b/camino/striptease/include/mach-o/reloc.h new file mode 100644 index 00000000000..e36f4f734d1 --- /dev/null +++ b/camino/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 + +/* + * 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 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_ */ diff --git a/camino/striptease/include/mach-o/sparc/reloc.h b/camino/striptease/include/mach-o/sparc/reloc.h new file mode 100644 index 00000000000..582c26bf865 --- /dev/null +++ b/camino/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 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 */ diff --git a/camino/striptease/include/mach-o/stab.h b/camino/striptease/include/mach-o/stab.h new file mode 100644 index 00000000000..e9e15b27ab8 --- /dev/null +++ b/camino/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 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_ */ diff --git a/camino/striptease/include/mach-o/x86_64/reloc.h b/camino/striptease/include/mach-o/x86_64/reloc.h new file mode 100644 index 00000000000..74edf082c70 --- /dev/null +++ b/camino/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 +}; diff --git a/camino/striptease/include/mach/hppa/thread_status.h b/camino/striptease/include/mach/hppa/thread_status.h new file mode 100644 index 00000000000..49de98b5e65 --- /dev/null +++ b/camino/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 + + +#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_ */ diff --git a/camino/striptease/include/mach/i860/thread_status.h b/camino/striptease/include/mach/i860/thread_status.h new file mode 100644 index 00000000000..7e14a93045f --- /dev/null +++ b/camino/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_ */ diff --git a/camino/striptease/include/mach/m68k/thread_status.h b/camino/striptease/include/mach/m68k/thread_status.h new file mode 100644 index 00000000000..cdfdb2c1dd4 --- /dev/null +++ b/camino/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_ */ diff --git a/camino/striptease/include/mach/m88k/thread_status.h b/camino/striptease/include/mach/m88k/thread_status.h new file mode 100644 index 00000000000..b525c6646c1 --- /dev/null +++ b/camino/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 +#import + +/************************************************************************** + * Data Typedefs used by thread_getstatus() and thread_setstatus() * + * NOTE: FP control and status regs described in * + **************************************************************************/ + +#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_ */ diff --git a/camino/striptease/include/mach/machine.h b/camino/striptease/include/mach/machine.h new file mode 100644 index 00000000000..b2555520258 --- /dev/null +++ b/camino/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 rather than 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 +#import + +/* + * 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_ */ diff --git a/camino/striptease/include/mach/sparc/thread_status.h b/camino/striptease/include/mach/sparc/thread_status.h new file mode 100644 index 00000000000..a52a33272de --- /dev/null +++ b/camino/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 + +/* + * 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_ */ diff --git a/camino/striptease/include/stuff/allocate.h b/camino/striptease/include/stuff/allocate.h new file mode 100644 index 00000000000..6ff6df0fb45 --- /dev/null +++ b/camino/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, ...); diff --git a/camino/striptease/include/stuff/arch.h b/camino/striptease/include/stuff/arch.h new file mode 100644 index 00000000000..f31d0193ac6 --- /dev/null +++ b/camino/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 +#include + +/* + * 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_ */ diff --git a/camino/striptease/include/stuff/bool.h b/camino/striptease/include/stuff/bool.h new file mode 100644 index 00000000000..df476cf0a23 --- /dev/null +++ b/camino/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 */ diff --git a/camino/striptease/include/stuff/breakout.h b/camino/striptease/include/stuff/breakout.h new file mode 100644 index 00000000000..42b9fa4faee --- /dev/null +++ b/camino/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 + ; diff --git a/camino/striptease/include/stuff/bytesex.h b/camino/striptease/include/stuff/bytesex.h new file mode 100644 index 00000000000..a0d9ab8c394 --- /dev/null +++ b/camino/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 +#include +#include +#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 +#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 +#include +#include +#include +#include +#include +#include +#include +#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_ */ diff --git a/camino/striptease/include/stuff/crc32.h b/camino/striptease/include/stuff/crc32.h new file mode 100644 index 00000000000..5d3302d8241 --- /dev/null +++ b/camino/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); diff --git a/camino/striptease/include/stuff/errors.h b/camino/striptease/include/stuff/errors.h new file mode 100644 index 00000000000..581223f9743 --- /dev/null +++ b/camino/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 + ; diff --git a/camino/striptease/include/stuff/ofile.h b/camino/striptease/include/stuff/ofile.h new file mode 100644 index 00000000000..16ca7497a08 --- /dev/null +++ b/camino/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 +#ifndef AR_EFMT1 +#define AR_EFMT1 "#1/" /* extended format #1 */ +#endif +#import +#ifdef OFI +#import +#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_ */ diff --git a/camino/striptease/include/stuff/openstep_mach.h b/camino/striptease/include/stuff/openstep_mach.h new file mode 100644 index 00000000000..ca52f5f0fe4 --- /dev/null +++ b/camino/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__ */ diff --git a/camino/striptease/include/stuff/print.h b/camino/striptease/include/stuff/print.h new file mode 100644 index 00000000000..c075e99da0e --- /dev/null +++ b/camino/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 + +__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); diff --git a/camino/striptease/include/stuff/reloc.h b/camino/striptease/include/stuff/reloc.h new file mode 100644 index 00000000000..b10e26777a1 --- /dev/null +++ b/camino/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 +#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); diff --git a/camino/striptease/include/stuff/round.h b/camino/striptease/include/stuff/round.h new file mode 100644 index 00000000000..120327407a3 --- /dev/null +++ b/camino/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); diff --git a/camino/striptease/include/stuff/symbol_list.h b/camino/striptease/include/stuff/symbol_list.h new file mode 100644 index 00000000000..615ea33622b --- /dev/null +++ b/camino/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 +#include + +/* + * 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); diff --git a/camino/striptease/include/stuff/unix_standard_mode.h b/camino/striptease/include/stuff/unix_standard_mode.h new file mode 100644 index 00000000000..7d7753288e1 --- /dev/null +++ b/camino/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); diff --git a/camino/striptease/libstuff/allocate.c b/camino/striptease/libstuff/allocate.c new file mode 100644 index 00000000000..1d6546d7a90 --- /dev/null +++ b/camino/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 +#include +#include +#include + +#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); +} diff --git a/camino/striptease/libstuff/arch.c b/camino/striptease/libstuff/arch.c new file mode 100644 index 00000000000..401c5488fa7 --- /dev/null +++ b/camino/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 +#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 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 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); +} diff --git a/camino/striptease/libstuff/arch_usage.c b/camino/striptease/libstuff/arch_usage.c new file mode 100644 index 00000000000..ae09e20ce16 --- /dev/null +++ b/camino/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 /* first to get rid of pre-comp warning */ +#include +#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) */ diff --git a/camino/striptease/libstuff/breakout.c b/camino/striptease/libstuff/breakout.c new file mode 100644 index 00000000000..d82b6e0a472 --- /dev/null +++ b/camino/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 +#include +#include +#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) */ diff --git a/camino/striptease/libstuff/bytesex.c b/camino/striptease/libstuff/bytesex.c new file mode 100644 index 00000000000..62bbbd6de85 --- /dev/null +++ b/camino/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 +#include +#include +#include +#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 +#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 +#include +#include +#include +#include +#include +#include +#include +#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); + } +} diff --git a/camino/striptease/libstuff/checkout.c b/camino/striptease/libstuff/checkout.c new file mode 100644 index 00000000000..faf3d86892c --- /dev/null +++ b/camino/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 +#include +#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) */ diff --git a/camino/striptease/libstuff/crc32.c b/camino/striptease/libstuff/crc32.c new file mode 100644 index 00000000000..57ca0feb7b7 --- /dev/null +++ b/camino/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 + +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); +} diff --git a/camino/striptease/libstuff/errors.c b/camino/striptease/libstuff/errors.c new file mode 100644 index 00000000000..70a3915a289 --- /dev/null +++ b/camino/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 +#include +#include +#include +#include +#include +#include + +#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) */ diff --git a/camino/striptease/libstuff/fatal_arch.c b/camino/striptease/libstuff/fatal_arch.c new file mode 100644 index 00000000000..f16c8a45309 --- /dev/null +++ b/camino/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 +#include +#include +#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) */ diff --git a/camino/striptease/libstuff/fatals.c b/camino/striptease/libstuff/fatals.c new file mode 100644 index 00000000000..20b45d3a6ef --- /dev/null +++ b/camino/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 +#include +#include +#include +#include +#include +#include + +#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) */ diff --git a/camino/striptease/libstuff/get_arch_from_host.c b/camino/striptease/libstuff/get_arch_from_host.c new file mode 100644 index 00000000000..be2ae5374e2 --- /dev/null +++ b/camino/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 +#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) */ diff --git a/camino/striptease/libstuff/ofile.c b/camino/striptease/libstuff/ofile.c new file mode 100644 index 00000000000..3ddd4efeb0a --- /dev/null +++ b/camino/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 +#include +#include "stuff/openstep_mach.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#import +#import +#import +#import +#import +#import +#include +#include +#include "stuff/bool.h" +#ifdef OFI +#include +#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 */ + +/* */ +/* 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) */ diff --git a/camino/striptease/libstuff/ofile_error.c b/camino/striptease/libstuff/ofile_error.c new file mode 100644 index 00000000000..6cd36df16d0 --- /dev/null +++ b/camino/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 +#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) */ diff --git a/camino/striptease/libstuff/print.c b/camino/striptease/libstuff/print.c new file mode 100644 index 00000000000..9902a9b8d93 --- /dev/null +++ b/camino/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 +#include +#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) */ diff --git a/camino/striptease/libstuff/reloc.c b/camino/striptease/libstuff/reloc.c new file mode 100644 index 00000000000..0f28b7d7809 --- /dev/null +++ b/camino/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 +#include +#include +#include +#include +#include +#include +#include +#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); +} + + + + + diff --git a/camino/striptease/libstuff/round.c b/camino/striptease/libstuff/round.c new file mode 100644 index 00000000000..b408694f593 --- /dev/null +++ b/camino/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); +} diff --git a/camino/striptease/libstuff/set_arch_flag_name.c b/camino/striptease/libstuff/set_arch_flag_name.c new file mode 100644 index 00000000000..ee4bd84f808 --- /dev/null +++ b/camino/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 +#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) */ diff --git a/camino/striptease/libstuff/swap_headers.c b/camino/striptease/libstuff/swap_headers.c new file mode 100644 index 00000000000..6fd510c991c --- /dev/null +++ b/camino/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 +#include +#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 +#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 +#include +#include +#include +#include +#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); +} diff --git a/camino/striptease/libstuff/symbol_list.c b/camino/striptease/libstuff/symbol_list.c new file mode 100644 index 00000000000..a754cb3d290 --- /dev/null +++ b/camino/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 +#include +#include +#include +#include +#include +#include +#include +#include + +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) */ diff --git a/camino/striptease/libstuff/unix_standard_mode.c b/camino/striptease/libstuff/unix_standard_mode.c new file mode 100644 index 00000000000..7a07579bc1a --- /dev/null +++ b/camino/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 +#include +#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) */ diff --git a/camino/striptease/libstuff/writeout.c b/camino/striptease/libstuff/writeout.c new file mode 100644 index 00000000000..d0e52527a12 --- /dev/null +++ b/camino/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 +#include +#include "stuff/openstep_mach.h" +#include +#ifndef __OPENSTEP__ +#include +#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) */ diff --git a/camino/striptease/tease.c b/camino/striptease/tease.c index 517d7b36fcf..66af9f71985 100644 --- a/camino/striptease/tease.c +++ b/camino/striptease/tease.c @@ -54,6 +54,7 @@ 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 */ @@ -65,9 +66,13 @@ 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 @@ -378,6 +383,9 @@ char *envp[]) 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){ @@ -432,6 +440,10 @@ char *envp[]) xflag = 1; strip_all = 0; break; + case 't': + tflag = 1; + strip_all = 0; + break; case 'i': iflag = 1; break; @@ -455,6 +467,10 @@ char *envp[]) #endif /* !defined(NMEDIT) */ break; #ifndef NMEDIT + case 'a': + aflag = 1; + strip_all = 0; + break; case 'c': cflag = 1; strip_all = 0; @@ -560,8 +576,9 @@ 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", @@ -1179,8 +1196,8 @@ struct object *object) #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) */ @@ -1226,7 +1243,7 @@ struct object *object) } 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 + @@ -1354,7 +1371,7 @@ struct object *object) 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 @@ -2260,6 +2277,7 @@ unsigned long nindirectsyms) 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) @@ -2292,6 +2310,7 @@ unsigned long nindirectsyms) * statics. */ nsects = 0; + text_nsect = NO_SECT; lc = object->load_commands; if(object->mh != NULL) ncmds = object->mh->ncmds; @@ -2323,15 +2342,23 @@ unsigned long nindirectsyms) 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); } @@ -2387,13 +2414,7 @@ unsigned long nindirectsyms) } } 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++; @@ -2401,10 +2422,23 @@ unsigned long nindirectsyms) 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){ @@ -2458,10 +2492,18 @@ unsigned long nindirectsyms) } } 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 @@ -2714,7 +2756,8 @@ unsigned long nindirectsyms) 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; @@ -3500,32 +3543,35 @@ struct object *object) 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) */