--- /dev/null
+APPLE PUBLIC SOURCE LICENSE
+Version 2.0 - August 6, 2003
+
+Please read this License carefully before downloading this software.
+By downloading or using this software, you are agreeing to be bound by
+the terms of this License. If you do not or cannot agree to the terms
+of this License, please do not download or use the software.
+
+1. General; Definitions. This License applies to any program or other
+work which Apple Computer, Inc. ("Apple") makes publicly available and
+which contains a notice placed by Apple identifying such program or
+work as "Original Code" and stating that it is subject to the terms of
+this Apple Public Source License version 2.0 ("License"). As used in
+this License:
+
+1.1 "Applicable Patent Rights" mean: (a) in the case where Apple is
+the grantor of rights, (i) claims of patents that are now or hereafter
+acquired, owned by or assigned to Apple and (ii) that cover subject
+matter contained in the Original Code, but only to the extent
+necessary to use, reproduce and/or distribute the Original Code
+without infringement; and (b) in the case where You are the grantor of
+rights, (i) claims of patents that are now or hereafter acquired,
+owned by or assigned to You and (ii) that cover subject matter in Your
+Modifications, taken alone or in combination with Original Code.
+
+1.2 "Contributor" means any person or entity that creates or
+contributes to the creation of Modifications.
+
+1.3 "Covered Code" means the Original Code, Modifications, the
+combination of Original Code and any Modifications, and/or any
+respective portions thereof.
+
+1.4 "Externally Deploy" means: (a) to sublicense, distribute or
+otherwise make Covered Code available, directly or indirectly, to
+anyone other than You; and/or (b) to use Covered Code, alone or as
+part of a Larger Work, in any way to provide a service, including but
+not limited to delivery of content, through electronic communication
+with a client other than You.
+
+1.5 "Larger Work" means a work which combines Covered Code or portions
+thereof with code not governed by the terms of this License.
+
+1.6 "Modifications" mean any addition to, deletion from, and/or change
+to, the substance and/or structure of the Original Code, any previous
+Modifications, the combination of Original Code and any previous
+Modifications, and/or any respective portions thereof. When code is
+released as a series of files, a Modification is: (a) any addition to
+or deletion from the contents of a file containing Covered Code;
+and/or (b) any new file or other representation of computer program
+statements that contains any part of Covered Code.
+
+1.7 "Original Code" means (a) the Source Code of a program or other
+work as originally made available by Apple under this License,
+including the Source Code of any updates or upgrades to such programs
+or works made available by Apple under this License, and that has been
+expressly identified by Apple as such in the header file(s) of such
+work; and (b) the object code compiled from such Source Code and
+originally made available by Apple under this License.
+
+1.8 "Source Code" means the human readable form of a program or other
+work that is suitable for making modifications to it, including all
+modules it contains, plus any associated interface definition files,
+scripts used to control compilation and installation of an executable
+(object code).
+
+1.9 "You" or "Your" means an individual or a legal entity exercising
+rights under this License. For legal entities, "You" or "Your"
+includes any entity which controls, is controlled by, or is under
+common control with, You, where "control" means (a) the power, direct
+or indirect, to cause the direction or management of such entity,
+whether by contract or otherwise, or (b) ownership of fifty percent
+(50%) or more of the outstanding shares or beneficial ownership of
+such entity.
+
+2. Permitted Uses; Conditions & Restrictions. Subject to the terms
+and conditions of this License, Apple hereby grants You, effective on
+the date You accept this License and download the Original Code, a
+world-wide, royalty-free, non-exclusive license, to the extent of
+Apple's Applicable Patent Rights and copyrights covering the Original
+Code, to do the following:
+
+2.1 Unmodified Code. You may use, reproduce, display, perform,
+internally distribute within Your organization, and Externally Deploy
+verbatim, unmodified copies of the Original Code, for commercial or
+non-commercial purposes, provided that in each instance:
+
+(a) You must retain and reproduce in all copies of Original Code the
+copyright and other proprietary notices and disclaimers of Apple as
+they appear in the Original Code, and keep intact all notices in the
+Original Code that refer to this License; and
+
+(b) You must include a copy of this License with every copy of Source
+Code of Covered Code and documentation You distribute or Externally
+Deploy, and You may not offer or impose any terms on such Source Code
+that alter or restrict this License or the recipients' rights
+hereunder, except as permitted under Section 6.
+
+2.2 Modified Code. You may modify Covered Code and use, reproduce,
+display, perform, internally distribute within Your organization, and
+Externally Deploy Your Modifications and Covered Code, for commercial
+or non-commercial purposes, provided that in each instance You also
+meet all of these conditions:
+
+(a) You must satisfy all the conditions of Section 2.1 with respect to
+the Source Code of the Covered Code;
+
+(b) You must duplicate, to the extent it does not already exist, the
+notice in Exhibit A in each file of the Source Code of all Your
+Modifications, and cause the modified files to carry prominent notices
+stating that You changed the files and the date of any change; and
+
+(c) If You Externally Deploy Your Modifications, You must make
+Source Code of all Your Externally Deployed Modifications either
+available to those to whom You have Externally Deployed Your
+Modifications, or publicly available. Source Code of Your Externally
+Deployed Modifications must be released under the terms set forth in
+this License, including the license grants set forth in Section 3
+below, for as long as you Externally Deploy the Covered Code or twelve
+(12) months from the date of initial External Deployment, whichever is
+longer. You should preferably distribute the Source Code of Your
+Externally Deployed Modifications electronically (e.g. download from a
+web site).
+
+2.3 Distribution of Executable Versions. In addition, if You
+Externally Deploy Covered Code (Original Code and/or Modifications) in
+object code, executable form only, You must include a prominent
+notice, in the code itself as well as in related documentation,
+stating that Source Code of the Covered Code is available under the
+terms of this License with information on how and where to obtain such
+Source Code.
+
+2.4 Third Party Rights. You expressly acknowledge and agree that
+although Apple and each Contributor grants the licenses to their
+respective portions of the Covered Code set forth herein, no
+assurances are provided by Apple or any Contributor that the Covered
+Code does not infringe the patent or other intellectual property
+rights of any other entity. Apple and each Contributor disclaim any
+liability to You for claims brought by any other entity based on
+infringement of intellectual property rights or otherwise. As a
+condition to exercising the rights and licenses granted hereunder, You
+hereby assume sole responsibility to secure any other intellectual
+property rights needed, if any. For example, if a third party patent
+license is required to allow You to distribute the Covered Code, it is
+Your responsibility to acquire that license before distributing the
+Covered Code.
+
+3. Your Grants. In consideration of, and as a condition to, the
+licenses granted to You under this License, You hereby grant to any
+person or entity receiving or distributing Covered Code under this
+License a non-exclusive, royalty-free, perpetual, irrevocable license,
+under Your Applicable Patent Rights and other intellectual property
+rights (other than patent) owned or controlled by You, to use,
+reproduce, display, perform, modify, sublicense, distribute and
+Externally Deploy Your Modifications of the same scope and extent as
+Apple's licenses under Sections 2.1 and 2.2 above.
+
+4. Larger Works. You may create a Larger Work by combining Covered
+Code with other code not governed by the terms of this License and
+distribute the Larger Work as a single product. In each such instance,
+You must make sure the requirements of this License are fulfilled for
+the Covered Code or any portion thereof.
+
+5. Limitations on Patent License. Except as expressly stated in
+Section 2, no other patent rights, express or implied, are granted by
+Apple herein. Modifications and/or Larger Works may require additional
+patent licenses from Apple which Apple may grant in its sole
+discretion.
+
+6. Additional Terms. You may choose to offer, and to charge a fee for,
+warranty, support, indemnity or liability obligations and/or other
+rights consistent with the scope of the license granted herein
+("Additional Terms") to one or more recipients of Covered Code.
+However, You may do so only on Your own behalf and as Your sole
+responsibility, and not on behalf of Apple or any Contributor. You
+must obtain the recipient's agreement that any such Additional Terms
+are offered by You alone, and You hereby agree to indemnify, defend
+and hold Apple and every Contributor harmless for any liability
+incurred by or claims asserted against Apple or such Contributor by
+reason of any such Additional Terms.
+
+7. Versions of the License. Apple may publish revised and/or new
+versions of this License from time to time. Each version will be given
+a distinguishing version number. Once Original Code has been published
+under a particular version of this License, You may continue to use it
+under the terms of that version. You may also choose to use such
+Original Code under the terms of any subsequent version of this
+License published by Apple. No one other than Apple has the right to
+modify the terms applicable to Covered Code created under this
+License.
+
+8. NO WARRANTY OR SUPPORT. The Covered Code may contain in whole or in
+part pre-release, untested, or not fully tested works. The Covered
+Code may contain errors that could cause failures or loss of data, and
+may be incomplete or contain inaccuracies. You expressly acknowledge
+and agree that use of the Covered Code, or any portion thereof, is at
+Your sole and entire risk. THE COVERED CODE IS PROVIDED "AS IS" AND
+WITHOUT WARRANTY, UPGRADES OR SUPPORT OF ANY KIND AND APPLE AND
+APPLE'S LICENSOR(S) (COLLECTIVELY REFERRED TO AS "APPLE" FOR THE
+PURPOSES OF SECTIONS 8 AND 9) AND ALL CONTRIBUTORS EXPRESSLY DISCLAIM
+ALL WARRANTIES AND/OR CONDITIONS, EXPRESS OR IMPLIED, INCLUDING, BUT
+NOT LIMITED TO, THE IMPLIED WARRANTIES AND/OR CONDITIONS OF
+MERCHANTABILITY, OF SATISFACTORY QUALITY, OF FITNESS FOR A PARTICULAR
+PURPOSE, OF ACCURACY, OF QUIET ENJOYMENT, AND NONINFRINGEMENT OF THIRD
+PARTY RIGHTS. APPLE AND EACH CONTRIBUTOR DOES NOT WARRANT AGAINST
+INTERFERENCE WITH YOUR ENJOYMENT OF THE COVERED CODE, THAT THE
+FUNCTIONS CONTAINED IN THE COVERED CODE WILL MEET YOUR REQUIREMENTS,
+THAT THE OPERATION OF THE COVERED CODE WILL BE UNINTERRUPTED OR
+ERROR-FREE, OR THAT DEFECTS IN THE COVERED CODE WILL BE CORRECTED. NO
+ORAL OR WRITTEN INFORMATION OR ADVICE GIVEN BY APPLE, AN APPLE
+AUTHORIZED REPRESENTATIVE OR ANY CONTRIBUTOR SHALL CREATE A WARRANTY.
+You acknowledge that the Covered Code is not intended for use in the
+operation of nuclear facilities, aircraft navigation, communication
+systems, or air traffic control machines in which case the failure of
+the Covered Code could lead to death, personal injury, or severe
+physical or environmental damage.
+
+9. LIMITATION OF LIABILITY. TO THE EXTENT NOT PROHIBITED BY LAW, IN NO
+EVENT SHALL APPLE OR ANY CONTRIBUTOR BE LIABLE FOR ANY INCIDENTAL,
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR RELATING
+TO THIS LICENSE OR YOUR USE OR INABILITY TO USE THE COVERED CODE, OR
+ANY PORTION THEREOF, WHETHER UNDER A THEORY OF CONTRACT, WARRANTY,
+TORT (INCLUDING NEGLIGENCE), PRODUCTS LIABILITY OR OTHERWISE, EVEN IF
+APPLE OR SUCH CONTRIBUTOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES AND NOTWITHSTANDING THE FAILURE OF ESSENTIAL PURPOSE OF ANY
+REMEDY. SOME JURISDICTIONS DO NOT ALLOW THE LIMITATION OF LIABILITY OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS LIMITATION MAY NOT APPLY
+TO YOU. In no event shall Apple's total liability to You for all
+damages (other than as may be required by applicable law) under this
+License exceed the amount of fifty dollars ($50.00).
+
+10. Trademarks. This License does not grant any rights to use the
+trademarks or trade names "Apple", "Apple Computer", "Mac", "Mac OS",
+"QuickTime", "QuickTime Streaming Server" or any other trademarks,
+service marks, logos or trade names belonging to Apple (collectively
+"Apple Marks") or to any trademark, service mark, logo or trade name
+belonging to any Contributor. You agree not to use any Apple Marks in
+or as part of the name of products derived from the Original Code or
+to endorse or promote products derived from the Original Code other
+than as expressly permitted by and in strict compliance at all times
+with Apple's third party trademark usage guidelines which are posted
+at http://www.apple.com/legal/guidelinesfor3rdparties.html.
+
+11. Ownership. Subject to the licenses granted under this License,
+each Contributor retains all rights, title and interest in and to any
+Modifications made by such Contributor. Apple retains all rights,
+title and interest in and to the Original Code and any Modifications
+made by or on behalf of Apple ("Apple Modifications"), and such Apple
+Modifications will not be automatically subject to this License. Apple
+may, at its sole discretion, choose to license such Apple
+Modifications under this License, or on different terms from those
+contained in this License or may choose not to license them at all.
+
+12. Termination.
+
+12.1 Termination. This License and the rights granted hereunder will
+terminate:
+
+(a) automatically without notice from Apple if You fail to comply with
+any term(s) of this License and fail to cure such breach within 30
+days of becoming aware of such breach;
+
+(b) immediately in the event of the circumstances described in Section
+13.5(b); or
+
+(c) automatically without notice from Apple if You, at any time during
+the term of this License, commence an action for patent infringement
+against Apple; provided that Apple did not first commence
+an action for patent infringement against You in that instance.
+
+12.2 Effect of Termination. Upon termination, You agree to immediately
+stop any further use, reproduction, modification, sublicensing and
+distribution of the Covered Code. All sublicenses to the Covered Code
+which have been properly granted prior to termination shall survive
+any termination of this License. Provisions which, by their nature,
+should remain in effect beyond the termination of this License shall
+survive, including but not limited to Sections 3, 5, 8, 9, 10, 11,
+12.2 and 13. No party will be liable to any other for compensation,
+indemnity or damages of any sort solely as a result of terminating
+this License in accordance with its terms, and termination of this
+License will be without prejudice to any other right or remedy of
+any party.
+
+13. Miscellaneous.
+
+13.1 Government End Users. The Covered Code is a "commercial item" as
+defined in FAR 2.101. Government software and technical data rights in
+the Covered Code include only those rights customarily provided to the
+public as defined in this License. This customary commercial license
+in technical data and software is provided in accordance with FAR
+12.211 (Technical Data) and 12.212 (Computer Software) and, for
+Department of Defense purchases, DFAR 252.227-7015 (Technical Data --
+Commercial Items) and 227.7202-3 (Rights in Commercial Computer
+Software or Computer Software Documentation). Accordingly, all U.S.
+Government End Users acquire Covered Code with only those rights set
+forth herein.
+
+13.2 Relationship of Parties. This License will not be construed as
+creating an agency, partnership, joint venture or any other form of
+legal association between or among You, Apple or any Contributor, and
+You will not represent to the contrary, whether expressly, by
+implication, appearance or otherwise.
+
+13.3 Independent Development. Nothing in this License will impair
+Apple's right to acquire, license, develop, have others develop for
+it, market and/or distribute technology or products that perform the
+same or similar functions as, or otherwise compete with,
+Modifications, Larger Works, technology or products that You may
+develop, produce, market or distribute.
+
+13.4 Waiver; Construction. Failure by Apple or any Contributor to
+enforce any provision of this License will not be deemed a waiver of
+future enforcement of that or any other provision. Any law or
+regulation which provides that the language of a contract shall be
+construed against the drafter will not apply to this License.
+
+13.5 Severability. (a) If for any reason a court of competent
+jurisdiction finds any provision of this License, or portion thereof,
+to be unenforceable, that provision of the License will be enforced to
+the maximum extent permissible so as to effect the economic benefits
+and intent of the parties, and the remainder of this License will
+continue in full force and effect. (b) Notwithstanding the foregoing,
+if applicable law prohibits or restricts You from fully and/or
+specifically complying with Sections 2 and/or 3 or prevents the
+enforceability of either of those Sections, this License will
+immediately terminate and You must immediately discontinue any use of
+the Covered Code and destroy all copies of it that are in your
+possession or control.
+
+13.6 Dispute Resolution. Any litigation or other dispute resolution
+between You and Apple relating to this License shall take place in the
+Northern District of California, and You and Apple hereby consent to
+the personal jurisdiction of, and venue in, the state and federal
+courts within that District with respect to this License. The
+application of the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded.
+
+13.7 Entire Agreement; Governing Law. This License constitutes the
+entire agreement between the parties with respect to the subject
+matter hereof. This License shall be governed by the laws of the
+United States and the State of California, except that body of
+California law concerning conflicts of law.
+
+Where You are located in the province of Quebec, Canada, the following
+clause applies: The parties hereby confirm that they have requested
+that this License and all related documents be drafted in English. Les
+parties ont exige que le present contrat et tous les documents
+connexes soient rediges en anglais.
+
+EXHIBIT A.
+
+"Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights
+Reserved.
+
+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."
--- /dev/null
+.TH DYLD 1 "January 15, 2005" "Apple Computer, Inc."
+.SH NAME
+dyld \- the dynamic link editor
+.SH SYNOPSIS
+DYLD_FRAMEWORK_PATH
+.br
+DYLD_FALLBACK_FRAMEWORK_PATH
+.br
+DYLD_LIBRARY_PATH
+.br
+DYLD_FALLBACK_LIBRARY_PATH
+.br
+DYLD_ROOT_PATH
+.br
+DYLD_INSERT_LIBRARIES
+.br
+DYLD_FORCE_FLAT_NAMESPACE
+.br
+DYLD_IMAGE_SUFFIX
+.br
+DYLD_PRINT_OPTS
+.br
+DYLD_PRINT_ENV
+.br
+DYLD_PRINT_LIBRARIES
+.br
+DYLD_PRINT_LIBRARIES_POST_LAUNCH
+.br
+DYLD_BIND_AT_LAUNCH
+.br
+DYLD_PREBIND_DEBUG
+.br
+DYLD_NEW_LOCAL_SHARED_REGIONS
+.br
+DYLD_IGNORE_PREBINDING
+.br
+DYLD_PRINT_APIS
+.br
+DYLD_PRINT_BINDINGS
+.br
+DYLD_PRINT_INITIALIZERS
+.br
+DYLD_PRINT_REBASINGS
+.br
+DYLD_PRINT_SEGMENTS
+.br
+DYLD_PRINT_STATISTICS
+.SH DESCRIPTION
+The dynamic linker uses the following environment variables.
+They affect any program that uses the dynamic linker.
+.TP
+.B DYLD_FRAMEWORK_PATH
+This is a colon separated list of directories that contain frameworks.
+The dynamic linker searches these directories before it searches for the
+framework by its install name.
+It allows you to test new versions of existing
+frameworks. (A framework is a library install name that ends in the form
+XXX.framework/Versions/YYY/XXX or XXX.framework/XXX, where XXX and YYY are any
+name.)
+.IP
+For each framework that a program uses, the dynamic linker looks for the
+framework in each directory in
+.SM DYLD_FRAMEWORK_PATH
+in turn. If it looks in all the directories and can't find the framework, it
+searches the directories in
+.SM DYLD_LIBRARY_PATH
+in turn. If it still can't find the framework, it then searches
+.SM DYLD_FALLBACK_FRAMEWORK_PATH
+and
+.SM DYLD_FALLBACK_LIBRARY_PATH
+in turn.
+.IP
+Use the
+.B \-L
+option to
+.IR otool (1).
+to discover the frameworks and shared libraries that the executable
+is linked against.
+.TP
+.B DYLD_FALLBACK_FRAMEWORK_PATH
+This is a colon separated list of directories that contain frameworks.
+It is used as the default location for frameworks not found in their install
+path.
+
+By default, it is set to
+/Library/Frameworks:/Network/Library/Frameworks:/System/Library/Frameworks
+.TP
+.B DYLD_LIBRARY_PATH
+This is a colon separated list of directories that contain libraries. The
+dynamic linker searches these directories before it searches the default
+locations for libraries. It allows you to test new versions of existing
+libraries.
+.IP
+For each library that a program uses, the dynamic linker looks for it in each
+directory in
+.SM DYLD_LIBRARY_PATH
+in turn. If it still can't find the library, it then searches
+.SM DYLD_FALLBACK_FRAMEWORK_PATH
+and
+.SM DYLD_FALLBACK_LIBRARY_PATH
+in turn.
+.IP
+Use the
+.B \-L
+option to
+.IR otool (1).
+to discover the frameworks and shared libraries that the executable
+is linked against.
+.TP
+.B DYLD_FALLBACK_LIBRARY_PATH
+This is a colon separated list of directories that contain libraries.
+It is used as the default location for libraries not found in their install
+path.
+By default, it is set
+to $(HOME)/lib:/usr/local/lib:/lib:/usr/lib.
+.TP
+.B DYLD_ROOT_PATH
+This is a colon separated list of directories. The dynamic linker will prepend each of
+this directory paths to every image access until a file is found.
+.TP
+.B DYLD_INSERT_LIBRARIES
+This is a colon separated list of dynamic libraries to load before the ones
+specified in the program. This lets you test new modules of existing dynamic
+shared libraries that are used in flat-namespace images by loading a temporary
+dynamic shared library with just the new modules. Note that this has no
+effect on images built a two-level namespace images using a dynamic shared
+library unless
+.SM DYLD_FORCE_FLAT_NAMESPACE
+is also used.
+.TP
+.B DYLD_FORCE_FLAT_NAMESPACE
+Force all images in the program to be linked as flat-namespace images and ignore
+any two-level namespace bindings. This may cause programs to fail to execute
+with a multiply defined symbol error if two-level namespace images are used to
+allow the images to have multiply defined symbols.
+.TP
+.B DYLD_IMAGE_SUFFIX
+This is set to a string of a suffix to try to be used for all shared libraries
+used by the program. For libraries ending in ".dylib" the suffix is applied
+just before the ".dylib". For all other libraries the suffix is appended to the
+library name. This is useful for using conventional "_profile" and "_debug"
+libraries and frameworks.
+.TP
+.B DYLD_PRINT_OPTS
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the command line options.
+.TP
+.B DYLD_PRINT_ENV
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the environment variables.
+.TP
+.B DYLD_PRINT_LIBRARIES
+When this is set, the dynamic linker writes to file descriptor 2 (normally
+standard error) the filenames of the libraries the program is using.
+This is useful to make sure that the use of
+.SM DYLD_LIBRARY_PATH
+is getting what you want.
+.TP
+.B DYLD_PRINT_LIBRARIES_POST_LAUNCH
+This does the same as
+.SM DYLD_PRINT_LIBRARIES
+but the printing starts after the program gets to its entry point.
+.TP
+.B DYLD_BIND_AT_LAUNCH
+When this is set, the dynamic linker binds all undefined symbols
+the program needs at launch time. This includes function symbols that can are normally lazily bound at the time of their first call.
+.TP
+.B DYLD_PREBIND_DEBUG
+When this is set, the dynamic linker prints diagnostics about
+launching prebound programs and libraries. This lets you determine why a
+program is not being launched prebound.
+You can view the recorded library time stamps with the
+.B \-Lv
+option to
+.IR otool (1).
+.TP
+.PP
+For secure programs that are UNIX set uid or set gid, the dynamic linker will
+not use the dyld environment variables for path searching and library insertion,
+unless the program is run as the real user. For secure programs, the dynamic
+linker clears out the value of the dyld path and insertion environment
+variables. This is so that if a program is
+.IR exec (2)'ed
+from a secure program too will not have it's libraries searched for, as well.
+For statically linked secure programs that
+.IR exec (2)
+other programs that might use the dynamic linker, they too should clear out the
+values of the dyld path and insertion environment variables.
+.TP
+.B DYLD_NEW_LOCAL_SHARED_REGIONS
+When set, the dynamic linker directs the system to provide a new set of shared
+regions as the repository for library load requests for dynamic libraries
+built with
+.SM MH_SPLIT_SEGS
+(split shared libraries).
+
+Split shared libraries reside in a defined contiguous region of address space
+in all dynamic linker runtime processes. This space is backed by named regions
+or sub-maps. These sub-maps are owned by the system and items which are to
+mapped into them must be mapped via the
+.IR load_shared_file (2)
+call. The use of
+sub-maps promotes a high degree of system resource sharing between the
+processes which incorporate and use them. However, some processes require
+either additional or different libraries to be loaded into the shared region.
+While there is some space available within the shared region for alternate and
+new shared libraries, it is inappropriate to use that area for temporary or
+private libraries. Setting the
+.SM DYLD_NEW_LOCAL_SHARED_REGIONS
+flag will cause
+all children of the current process to have their own set of sub-maps. In this
+way the libraries found in the children's submaps will not be caused to be
+present in the submaps shared by the rest of the system.
+
+.SM DYLD_NEW_LOCAL_SHARED_REGIONS
+should be set by anyone wishing to run
+non-standard or temporary split shared libraries by setting an explicit path to
+point to them. i.e. by using the DYLD_LIBRARY_PATH environment variable
+instead of changing the root by executing a
+.IR chroot (2)
+call.
+.TP
+.B DYLD_PRINT_STATISTICS
+Right before the process's main() is called, dyld prints out information about how
+dyld spent its time. Useful for analyzing launch performance.
+.TP
+.B DYLD_IGNORE_PREBINDING { app | all }
+Valid values are "app", "all", and "" (empty). The variable is useful for testing
+how various mixes of prebound and unprebound libraries perform. When set to "all",
+all prebinding is ignored. That is, dyld fixes up any prebound images as if the prebinding
+in it was invalid. When set to "all", just the prebinding information in main
+executables is ignored. When set the nothing, the prebinding in split-seg libraries
+is used, by all other prebinding is ignored.
+.TP
+.B DYLD_PRINT_INITIALIZERS
+Causes dyld to print out a line when running each initializers in every image. Initializers
+run by dyld included constructors for C++ statically allocated objects, functions marked with
+__attribute__((constructor)), and -init functions.
+.TP
+.B DYLD_PRINT_APIS
+Causes dyld to print a line whenever a dyld API is called (e.g. NSAddImage()).
+.TP
+.B DYLD_PRINT_SEGMENTS
+Causes dyld to print out a line containing the name and address range of each mach-o segment
+that dyld maps in.
+.TP
+.B DYLD_PRINT_BINDINGS
+Causes dyld to print a line each time a symbolic name is bound.
+
+
+
+.SH "SEE ALSO"
+libtool(1), ld(1), otool(1)
--- /dev/null
+.TH NSModule 3 "October 6, 2003" "Apple Computer, Inc."
+.SH NAME
+NSModule \- programmatic interface for working with modules and symbols
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+.sp .5
+typedef void * NSModule;
+.sp .5
+extern NSModule NSLinkModule(
+ NSObjectFileImage objectFileImage,
+ const char *moduleName,
+ unsigned long options);
+.sp .5
+extern enum DYLD_BOOL NSUnLinkModule(
+ NSModule module,
+ unsigned long options);
+.sp .5
+extern const char * NSNameOfModule(
+ NSModule m);
+.sp .5
+extern const char * NSLibraryNameForModule(
+ NSModule m);
+.sp 2
+typedef void * NSSymbol;
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolNameDefined(
+ const char *symbolName);
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolNameDefinedWithHint(
+ const char *symbolName
+ const char *libraryNameHint);
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolNameDefinedInImage(
+ const struct mach_header *image,
+ const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupAndBindSymbol(
+ const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupAndBindSymbolWithHint(
+ const char *symbolName
+ const char *libraryNameHint);
+.sp .5
+extern NSSymbol NSLookupSymbolInModule(
+ NSModule module,
+ const char *symbolName);
+.sp .5
+extern NSSymbol NSLookupSymbolInImage(
+ const struct mach_header *image,
+ const char *symbolName,
+ unsigned long options);
+.sp .5
+extern const char * NSNameOfSymbol(
+ NSSymbol symbol);
+.sp .5
+extern void * NSAddressOfSymbol(
+ NSSymbol symbol);
+.sp .5
+extern NSModule NSModuleForSymbol(
+ NSSymbol symbol);
+.sp .5
+extern enum DYLD_BOOL NSAddLibrary(
+ const char *pathName);
+.sp .5
+extern enum DYLD_BOOL NSAddLibraryWithSearching(
+ const char *pathName);
+.sp .5
+extern const struct mach_header * NSAddImage(
+ const char *image_name,
+ unsigned long options);
+.sp .5
+extern long NSVersionOfRunTimeLibrary(
+ const char *libraryName);
+.sp .5
+extern long NSVersionOfLinkTimeLibrary(
+ const char *libraryName);
+.sp .5
+extern int _NSGetExecutablePath(
+ char *buf,
+ unsigned long *bufsize)
+.sp 2
+extern void NSInstallLinkEditErrorHandlers(
+ NSLinkEditErrorHandlers *handlers);
+.sp .5
+extern void NSLinkEditError(
+ NSLinkEditErrors *c,
+ int *errorNumber,
+ const char **fileName,
+ const char **errorString);
+.if
+.SH "FUTURE SYNOPSIS"
+.nf
+.PP
+extern NSModule NSReplaceModule(
+ NSModule moduleToReplace,
+ NSObjectFileImage newObjectFileImage,
+ unsigned long options);
+.fi
+.PP
+These routines are the programmatic interface for working with modules and
+symbols in a program. A program is composed of a set of images, an executable,
+plugins, and dynamic shared libraries. An image which is an executable or a
+plugin is composed of one module containing a collection of symbols. A dynamic
+shared library is composed of one or more modules with each of those modules
+containing a separate collection of symbols. If a symbol is used from a module
+then all the symbols from that module are used.
+.PP
+When a program is executed it selectively binds the symbols it needs from the
+modules in the dynamic libraries that are loaded. Normally a program is
+staticly linked against a set of dynamic shared libraries when it is built.
+So when the program is executed the dynamic linker will automaticly load those
+dynamic shared libraries.
+.PP
+A program may programmatically load plugins after it starts executing and that
+is done with two sets of API's. The first is the API's of
+.IR NSObjectFileImage (3)
+and the second is
+.I NSLinkModule.
+Unlike modules in the dynamic libraries when a plugin is loaded it is not
+selectively bound to but always bound into the program.
+.PP
+.I NSLinkModule
+links the specified object file image into the program and returns the module
+handle for it.
+Currently the implementation is limited to only Mach-O MH_BUNDLE types which
+are used for plugins.
+A module name is specified when a module is linked so that later
+.I NSNameOfModule
+can be used with the module handle and to do things like report errors.
+If you want
+.IR gdb (1)
+to be able to debug your module, when calling
+.I NSLinkModule
+you should pass the image path as the module name.
+When a module is linked, all libraries referenced by the module are added to
+the list of libraries to be searched.
+The parameter,
+.I options,
+can have a set of options or'ed together. The options for
+.I NSLinkModule
+are as follows:
+.TP
+.B NSLINKMODULE_OPTION_NONE
+This specifies no options. With this the global symbols from the module are
+made part of the global symbol table of the program. If any errors occur the
+handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.TP
+.B NSLINKMODULE_OPTION_BINDNOW
+This option causes the dynamic link editor to bind all undefined references for
+the loaded module and not allow references to be bound as needed. This affects
+all the references in the module and all of the dependent references.
+.TP
+.B NSLINKMODULE_OPTION_PRIVATE
+With this option the global symbols from the module are not made part of
+the global symbol table of the program. The global symbols of the
+module can then be looked up using
+.I NSLookupSymbolInModule.
+.TP
+.B NSLINKMODULE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while binding this module it is automaticly
+unloaded and
+.SM NULL
+is returned as the module handle. To get the error information for the module
+that failed to load the routine
+.I NSLinkEditError
+is then used. It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.TP
+.B NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES
+With this option the module init routines are not called. This is only useful
+to the fix-and-continue implementation.
+.TP
+.B NSLINKMODULE_OPTION_TRAILING_PHYS_NAME
+With this option the parameter,
+.I moduleName
+is assumed to be a string with the logical name of the image with the physical
+name of the object file tailing after the NULL character of the logical name.
+This is only useful to the zero-link implementation.
+.PP
+.I NSUnLinkModule
+unlinks the specified module handle from the program. Currently the
+implementation is limited to only allow modules linked with
+.I NSLinkModule
+to be unlinked. The parameter,
+.I options,
+can have a set of options or'ed together. The options for
+.I NSUnLinkModule
+are as follows:
+.TP
+.B NSUNLINKMODULE_OPTION_NONE
+This specifies no options. With this the module is unlinked from the program
+and the memory for the module is deallocated. If any errors occur the
+handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.TP
+.B NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED
+With this option the memory for the module is not deallocated allowing pointers
+into the module to still be valid.
+.TP
+.B NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
+With this option any lazy references (direct function calls) to symbols defined
+in the module are reset to be bound on first call again and not cause any
+undefined symbol errors. Currently this is only implemented for the PowerPC
+architecture.
+.PP
+.I NSNameOfModule
+is passed a module handle and returns the name of the module. If the module
+handle is invalid
+.SM NULL
+is returned.
+.PP
+.I NSLibraryNameForModule
+is passed a module handle and returns the name of the library the module is in
+if any. If the module handle is for a module that is not in a library (in the
+executable or a plugin) or the module handle is invalid
+.SM NULL
+is returned.
+.PP
+.I NSIsSymbolNameDefined
+is passed a global symbol name (global 'C' symbols names are preceded with an
+underbar '\_') and returns
+.SM TRUE
+or
+.SM FALSE
+based on if the symbol is defined in the program's global symbol table.
+If the symbol is not defined no error occurs.
+.PP
+.I NSIsSymbolNameDefinedWithHint
+is the same as
+.I NSIsSymbolNameDefined
+but the
+.I libraryNameHint
+parameter provides a hint as to where to start the lookup in a prebound
+program. The
+.I libraryNameHint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I NSIsSymbolNameDefinedInImage
+is passed a pointer to the mach_header of a mach_header structure of a
+dynamic library being used by the program and a symbol name. This returns
+.SM TRUE
+or FALSE
+based on if the symbol is defined in the specified image or one of the image's
+sub-frameworks or sub-umbrellas.
+If the program was built with the
+.IR ld (1)
+.B \-force_flat_namespace
+flag or executed with the environment variable
+.SM DYLD_FORCE_FLAT_NAMESPACE
+set and the pointer to a mach_header structure is not of a bundle loaded with
+the
+.B NSLINKMODULE_OPTION_PRIVATE
+option of
+.IR NSLinkModule (3)
+then the pointer to a mach_header is ignored and the symbol is looked up in
+all the images using the first definition if found.
+.PP
+The image handle parameter for
+.I NSLookupSymbolInImage
+and
+.I NSIsSymbolNameDefinedInImage
+is a pointer to a read-only mach header structure of a dynamic library being
+used by the program. Besides the
+.IR NSAddImage (3)
+routine the pointer to a mach header can also be obtained by using a link editor
+defined symbol as in <mach-o/ldsym.h> and described on the
+.IR ld (1)
+man page.
+Also the
+.IR dyld (3)
+routine
+.IR _dyld_get_image_header (3)
+and the mach_header pointer arguments to the call back routines called from
+.IR _dyld_register_func_for_add_image (3)
+routines can also be used.
+.PP
+.I NSLookupAndBindSymbol
+is passed a global symbol name and looks up and binds the symbol into the
+program.
+It returns an NSSymbol for the symbol. If any errors occur the handlers
+installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+.PP
+.I NSLookupAndBindSymbolWithHint
+is the same as
+.I NSLookupAndBindSymbol
+but the
+.I libraryNameHint
+parameter provides a hint as to where to start the lookup in a prebound
+program. The
+.I libraryNameHint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I NSLookupSymbolInModule
+is passed a symbol name and a module handle and looks up the symbol in that
+module. Currently this is only implemented for module handles returned with
+.I NSLinkModule.
+If the symbol is found an NSSymbol for the symbol is returned otherwise
+.SM NULL
+is returned and no error occurs.
+.PP
+.I NSLookupSymbolInImage
+is passed a pointer to a mach_header structure of a dynamic library being used
+by the program and a symbol name. It returns an NSSymbol for the symbol for
+defined in the specified image or the image's sub-frameworks or sub-umbrellas.
+If the program was built with the
+.IR ld (1)
+.B \-force_flat_namespace
+flag or executed with the environment variable
+.SM DYLD_FORCE_FLAT_NAMESPACE
+set and the pointer to a mach_header structure is not of a bundle loaded with
+the
+.B NSLINKMODULE_OPTION_PRIVATE
+option of
+.IR NSLinkModule (3)
+then the pointer to a mach_header is ignored and the symbol is looked up in
+all the images using the first definition found.
+If the option
+.SM NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+is not used if any errors occur the handlers installed with
+.I NSInstallLinkEditErrorHandlers
+are called or the default action is taken if there are no handlers.
+The options of
+.I NSLookupSymbolInImage
+are as follows:
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND
+Just bind the non-lazy symbols of module that defines the
+.I symbolName
+and let all lazy symbols in the module be bound on first call. This should be
+used in the normal case for a trusted module expected to bind without any errors
+like a module in a system supplied library.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW
+Bind all the non-lazy and lazy symbols of module that defines the
+.I symbolName
+and let all dependent symbols in the needed libraries be bound as needed. This
+would be used for a module that might not be expected bind without errors but
+links against only system supplied libraries which are expected to bind without
+any errors.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY
+Bind all the symbols of the module that defines the
+.I symbolName
+and all the dependent symbols of all needed libraries. This should only be
+used for things like signal handlers and linkedit error handlers that can't
+bind other symbols when executing to handle the signal or error.
+.TP
+.B NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while binding the module that defines the
+.I symbolName
+then the module is automaticly unloaded and
+.SM NULL
+is returned as the NSSymbol. To get the error information for why the module
+that failed to bind the routine
+.I NSLinkEditError
+is then used. It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.PP
+.I NSNameOfSymbol
+is passed an NSSymbol and returns the name of the symbol.
+.PP
+.I NSAddressOfSymbol
+is passed an NSSymbol and returns the address of the symbol.
+.PP
+.I NSModuleForSymbol
+is passed an NSSymbol and returns the NSModule that symbol is defined in.
+.PP
+.I NSAddLibrary
+is passed the file name of a dynamic shared library to be added to the search
+list. If it is successful it returns
+.SM TRUE
+else it returns
+.SM FALSE.
+.PP
+.I NSAddLibraryWithSearching
+is passed the file name of a dynamic shared library to be added to the search
+list the file name passed will be effected by the various
+.SM DYLD
+environment variables as if this library were linked into the program. If it
+is successful it returns
+.SM TRUE
+else it returns
+.SM FALSE.
+.PP
+.I NSAddImage
+is passed the file name of a dynamic shared library to be added to the search
+list of the program if not already loaded. It returns a pointer to the
+mach_header structure of the dynamic library being used by the program.
+For best performance of this routine if the library is expected to be already
+loaded by the program the
+.I image_name
+should be a full path name and the same as the name recorded by the program.
+If it is a symlink then an
+.IR open (2)
+and an
+.IR fstat (2)
+are needed to determine it is the same file as one already loaded.
+.PP
+If the dynamic shared library has not already been loaded it along with all the
+needed dependent libraries are loaded. With the options parameter
+.SM NSADDIMAGE_OPTION_NONE
+then any error in loading will cause the linkEdit error handler set by
+.IR NSInstallLinkEditErrorHandlers (3)
+to be called or the default action of printing the error and exiting to be
+taken. The other options of
+.I NSAddImage
+are as follows:
+.TP
+.B NSADDIMAGE_OPTION_RETURN_ON_ERROR
+With this option if errors occur while loading this library it is automatically
+unloaded and
+.SM NULL
+is returned. To get the error information for the library that failed to load
+the routine
+.I NSLinkEditError
+is then used. It has the same parameters as the link edit error handler (see
+below) except all the parameters are pointers in which the information is
+returned indirectly.
+.TP
+.B NSADDIMAGE_OPTION_WITH_SEARCHING
+With this option the
+.I image_name
+passed for the library and all its dependents will be effected by the various
+.SM DYLD
+environment variables as if this library were linked into the program.
+.TP
+.B NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+With this option if the
+.I image_name
+passed for the library has not already been loaded it is not loaded. Only if
+it has been loaded the pointer to the mach_header will not be
+.SM NULL.
+.TP
+.B NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME
+When this option is specified if a later load of a dependent dynamic library
+with a file system path is needed by an image that matches the install name of
+the dynamic library loaded with this option, then the dynamic library loaded
+with the call to NSAddImage() is used in place of the dependent dynamic library.
+.PP
+.I NSVersionOfRunTimeLibrary
+is passed the install name of a dynamic shared library and returns
+current_version number of the library the program is using or \-1 if the
+program is not using that library.
+.PP
+.I NSVersionOfLinkTimeLibrary
+is passed the install name of a dynamic shared library and returns the
+current_version number of the library the executable program was built
+with or \-1 if the program was not built with that library.
+.PP
+.I _NSGetExecutablePath
+copies the path of the executable into the buffer and
+returns 0 if the path was successfully copied in the provided buffer. If the
+buffer is not large enough, \-1 is returned and the expected buffer size is
+copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
+the executable not a "real path" to the executable. That is the path may be
+a symbolic link and not the real file. And with deep directories the total
+bufsize needed could be more than MAXPATHLEN.
+.SH ERROR HANDLING
+.PP
+.I NSInstallLinkEditErrorHandlers
+is passed a pointer to a NSLinkEditErrorHandlers which contains three function
+pointers to be used for handling dynamic link errors. The prototypes for these
+functions are given in the following typedef:
+.RS
+.nf
+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;
+.fi
+.RE
+.PP
+The first two functions allow the programmer to direct the link edit processing
+of undefined symbols and multiply defined symbols.
+The third function allows the programmer to catch all other link editor
+errors.
+.PP
+The state when one of the user error functions gets called will be such that no
+module will be partially loaded (except in the case of resource errors like out
+of memory and other relocation errors).
+However, with undefined symbol errors those modules referencing undefined
+symbols will be partially bound, and use of such modules can and will crash the
+program.
+.PP
+Great care should be taken when implementing these functions, as the program is
+running in a state that will crash if it uses an unbound symbol.
+To be safe, these functions should only rely on other things in the same module
+or in the executable.
+.PP
+If the user does not supply these functions, the default will be to write an
+error message on to file descriptor 2 (usually stderr) and exit the program
+(except for the
+.I linkEdit
+error handler when the
+.I NSLinkEditErrors
+is NSLinkEditWarningError, then the default is to do nothing).
+.PP
+The specified undefined handler may make calls to any of the runtime loading
+functions to add modules based on the undefined symbol name.
+After dealing with this symbol name successfully (by doing a runtime loading
+operation to resolve the undefined reference) the handler simply returns.
+If more symbol's names remain undefined the handler will be called repeatedly
+with an undefined symbol name.
+If the handler can't deal with the symbol it should not return (put up a panel,
+abort, etc) and cause the program to exit.
+Or it can remove itself as the undefined handler and return which will cause
+the default action of printing the undefined symbol names and exiting.
+.PP
+The specified multiply defined symbol handler is called during the process of
+runtime linking and thus it may not call any of the runtime loading functions
+as only one set of linking operations can be performed in the task at a time.
+The only programmatic functions that can be called from a multiply defined
+symbol handler are
+.I NSNameOfSymbol,
+.I NSNameOfModule
+and
+.I NSLibraryNameForModule
+(provided they are linked into the program before the handler is called).
+This handler returns the module handle for the symbol that is to be used for
+further link editing, either the
+.I oldModule
+or the
+.I newModule.
+It may also record one of the module handles to later take action after the
+runtime linking process has completed (for example later unlink the module).
+The dynamic link editor updates the references to the symbol if the handler
+specifies the new symbol is to be used.
+The references which are updated are those that the compiler system generated
+as indirect references. Initialized data and references that were created at
+runtime are not effected.
+.PP
+The specified
+.I linkEdit
+error handler is called for all other runtime linking errors.
+These other runtime linking errors are either warnings or fatal errors.
+If the user's link edit error handler function returns
+for a fatal error it will cause the program to exit.
+There is small set of major error classes which have specific error numbers.
+These numbers are be passed in the parameter
+.I errorClass.
+These major error classes include:
+.RS
+.nf
+typedef enum {
+ NSLinkEditFileAccessError,
+ NSLinkEditFileFormatError,
+ NSLinkEditMachResourceError,
+ NSLinkEditUnixResourceError,
+ NSLinkEditOtherError,
+ NSLinkEditWarningError,
+ NSLinkEditMultiplyDefinedError,
+ NSLinkEditUndefinedError
+} NSLinkEditErrors;
+.fi
+.RE
+.PP
+For the error class NSLinkEditUnixResourceError the
+.I errorNumber
+parameter will be an
+.I errno
+value (see
+.IR intro (2)).
+For the error class NSLinkEditMachResourceError the
+.I errorNumber
+parameter will be a
+.I kern_return_t
+value.
+For the error class NSLinkEditOtherError the
+.I errorNumber
+parameter will be a one of the following values:
+.RS
+.nf
+typedef enum {
+ NSOtherErrorRelocation,
+ NSOtherErrorLazyBind,
+ NSOtherErrorIndrLoop,
+ NSOtherErrorLazyInit,
+ NSOtherErrorInvalidArgs
+} NSOtherErrorNumbers;
+.fi
+.RE
+.PP
+For all errors, an attempt to pass an error string will be made.
+In some cases such as resource errors, it may not be possible to return a
+string.
+In those cases the
+.I errorString
+parameter will be
+.sm NULL.
+.PP
+For file access errors and file format errors, an attempt to return a file name
+will also be passed, and if that is not possible the
+.I filename
+parameter will be
+.sm NULL.
+.SH ALSO SEE
+NSObjectFileImage(3), dyld(3)
--- /dev/null
+.TH NSObjectFileImage 3 "March 14, 2003" "Apple Computer, Inc."
+.SH NAME
+NSObjectFileImage \- programmatic interface for working with Mach-O files
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(
+ const char *pathName,
+ NSObjectFileImage *objectFileImage);
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(
+ void *address,
+ unsigned long size,
+ NSObjectFileImage *objectFileImage);
+.sp .5
+extern NSObjectFileImageReturnCode NSCreateCoreFileImageFromFile(
+ const char *pathName,
+ NSObjectFileImage *objectFileImage);
+.sp .5
+extern enum DYLD_BOOL NSDestroyObjectFileImage(
+ NSObjectFileImage objectFileImage);
+.sp .5
+extern unsigned long NSSymbolDefinitionCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+.sp .5
+extern const char * NSSymbolDefinitionNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long ordinal);
+.sp .5
+extern unsigned long NSSymbolReferenceCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+.sp .5
+extern const char * NSSymbolReferenceNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long ordinal,
+ enum DYLD_BOOL *tentative_definition); /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL NSIsSymbolDefinedInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *symbolName);
+.sp .5
+extern void * NSGetSectionDataInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *segmentName,
+ const char *sectionName,
+ unsigned long* size); /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL NSHasModInitObjectFileImage(
+ NSObjectFileImage objectFileImage);
+.fi
+.SH DESCRIPTION
+.PP
+These routines are the programmatic interface for working with Mach-O files.
+They bring the Mach-O file into memory and the API allows the file to
+be inspected or loaded into the program. On creation of an object file image
+it is checked to insure it is a valid format and it is compatible with the host
+machine's cpu architecture.
+.PP
+.I NSCreateObjectFileImageFromFile
+takes the parameter
+.I pathName
+as the path name to the file name in the file system and creates and returns
+an NSObjectFileImage. Currently only
+.SM MH_BUNDLE
+files can be used with
+.I NSCreateObjectFileImageFromFile
+which can then be loaded into the program using
+.IR NSLinkModule (3).
+If the file is valid an NSObjectFileImage is returned and the return code is
+NSObjectFileImageSuccess.
+.I NSCreateObjectFileImageFromMemory
+does the same as
+.I NSCreateObjectFileImageFromFile
+but takes two parameters
+.I address
+and
+.I size
+for the Mach-O file that is in memory.
+.PP
+.I NSCreateCoreFileImageFromFile
+takes the parameter
+.I pathName
+as the path name to a core file in the file system and creates and returns
+an NSObjectFileImage. This NSObjectFileImage can then can be loaded into a
+task with
+.IR _dyld_debug_task_from_core (3)
+to determine what libraries were loaded and which modules were linked.
+.PP
+.I NSSymbolDefinitionCountInObjectFileImage
+returns the number of symbol definitions in the NSObjectFileImage.
+.PP
+.I NSSymbolDefinitionNameInObjectFileImage
+returns the name of the i'th symbol definitions in the NSObjectFileImage.
+The 'C' string returned should not be freed. If the ordinal specified is
+outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will be
+returned.
+.PP
+.I NSSymbolReferenceCountInObjectFileImage
+returns the number of references to undefined symbols the NSObjectFileImage.
+.PP
+.I NSSymbolReferenceNameInObjectFileImage
+returns the name of the i'th undefined symbol in the NSObjectFileImage.
+The 'C' string returned should not be freed. If the ordinal specified is
+outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
+returned.
+.PP
+.I NSIsSymbolDefinedInObjectFileImage
+returns TRUE if the specified symbol name has a definition in the
+NSObjectFileImage.
+.PP
+.I NSGetSectionDataInObjectFileImage
+returns the address of the data for the named section in the named segment in
+the NSObjectFileImage. If the parameter size is not NULL, the size of the
+section is returned in size. If the section cannot be found or a zerofill
+section, NULL is returned and the size returned is zero.
+.PP
+.I NSHasModInitObjectFileImage
+returns TRUE if the NSObjectFileImage has any module initialization routines
+and FALSE otherwise.
+
+.SH RETURN CODES
+The API's that create NSObjectFileImage's return an NSObjectFileImageReturnCode
+with the following possible values:
+.TP
+.B NSObjectFileImageSuccess
+Indicates the API was successful and it returned a valid NSObjectFileImage for
+the host machine's cpu architecture.
+.TP
+.B NSObjectFileImageFailure
+Indicates the API failed and no NSObjectFileImage was returned. If this is
+returned an error message is printed on stderr as to the reason for the
+failure.
+.TP
+.B NSObjectFileImageInappropriateFile
+Indicates the API failed because the file passed to it was not an appropriate
+type of object file.
+.TP
+.B NSObjectFileImageArch
+Indicates the API failed because the host machine's cpu architecture could not
+be found in the file.
+.TP
+.B NSObjectFileImageFormat
+Indicates the API failed because the Mach-O format was malformed. If this is
+returned an error message is printed on stderr as to the format error.
+.TP
+.B NSObjectFileImageAccess
+Indicates the API failed because the file could not be accessed.
+.SH ALSO SEE
+NSModule(3), dyld(3)
--- /dev/null
+.TH NSObjectFileImage 3 "July 9, 2003" "Apple Computer, Inc."
+.SH NAME
+NSObjectFileImage_priv \- programmatic interface for working with Mach-O files
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld_priv.h>
+.sp .5
+extern enum DYLD_BOOL
+NSFindSectionAndOffsetInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long imageOffset,
+ const char** segmentName, /* can be NULL */
+ const char** sectionName, /* can be NULL */
+ unsigned long* sectionOffset) /* can be NULL */
+.sp .5
+extern enum DYLD_BOOL
+NSHasModInitObjectFileImage(
+ NSObjectFileImage objectFileImage);
+.fi
+.SH DESCRIPTION
+.PP
+These routines are the programmatic interface for working with Mach-O files.
+They bring the Mach-O file into memory and the API allows the file to
+be inspected or loaded into the program. On creation of an object file image
+it is checked to insure it is a valid format and it is compatible with the host
+machine's cpu architecture.
+.PP
+.PP
+.I NSFindSectionAndOffsetInObjectFileImage
+is supplied an imageOffset into an ObjectFileImage and returns
+via parameters the segment/section name and offset into that section of
+that imageOffset. It returns FALSE if the imageOffset is not
+in any section, otherwise TRUE. You can used the resulting sectionOffset to
+index into the data returned by NSGetSectionDataInObjectFileImage.
+.PP
+.I NSHasModInitObjectFileImage
+returns TRUE if the NSObjectFileImage has any module initialization routines
+and FALSE otherwise.
+
+.SH ALSO SEE
+NSObjectFileImage(3), NSModule(3), dyld(3)
--- /dev/null
+.Dd September 24, 2004
+.Os
+.Dt DLADDR 3
+.Sh NAME
+.Nm dladdr
+.Nd find the image containing a given address
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft int
+.Fn dladdr "const void* addr" "Dl_info* info"
+.Sh DESCRIPTION
+The
+.Fn dladdr
+function
+queries dyld (the dynamic linker) for information about the image
+containing the address
+.Fa addr .
+The information is returned in the structure specified by
+.Fa info .
+The structure contains at least the following members:
+.Bl -tag -width "XXXconst char *dli_fname"
+.It Li "const char* dli_fname"
+The pathname of the shared object containing the address.
+.It Li "void* dli_fbase"
+The base address (mach_header) at which the image is mapped into the
+address space of the calling process.
+.It Li "const char* dli_sname"
+The name of the nearest run-time symbol with a value less than or
+equal to
+.Fa addr .
+.It Li "void* dli_saddr"
+The value of the symbol returned in
+.Li dli_sname .
+.El
+.Pp
+The
+.Fn dladdr
+function
+is available only in dynamically linked programs.
+.Sh ERRORS
+If an image containing
+.Fa addr
+cannot be found,
+.Fn dladdr
+returns 0.
+On success, a non-zero value is returned.
+.Pp
+If the image containing
+.Fa addr
+is found, but no nearest symbol was found,
+the dli_sname and dli_saddr fields are set to NULL.
+.Sh SEE ALSO
+.Xr dyld 3 ,
+.Xr dlopen 3
+.Sh HISTORY
+The
+.Fn dladdr
+function first appeared in the Solaris operating system.
+.Sh AUTHORS
+Mac OS X 10.3 incorporated the dlcompat package written by Jorge Acereda <jacereda@users.sourceforge.net>
+and Peter O'Gorman <ogorman@users.sourceforge.net>.
+.Pp
+In Mac OS X 10.4, dlopen was rewritten to be a native part of dyld.
+.Pp
+This man page was borrowed from FreeBSD and modified.
+.Sh BUGS
+This implementation is almost bug-compatible with the Solaris
+implementation. The following bugs are present:
+.Bl -bullet
+.It
+Returning 0 as an indication of failure goes against long-standing
+Unix tradition.
+.El
--- /dev/null
+.Dd Sept 25, 2004
+.Dt DLCLOSE 3
+.Sh NAME
+.Nm dlclose
+.Nd close a dynamic library or bundle
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft int
+.Fn dlclose "void* handle"
+.Sh DESCRIPTION
+.Fn dlclose
+releases a reference to the dynamic library or bundle referenced by
+.Fa handle .
+If the reference count drops to 0, the bundle is removed from the
+address space, and
+.Fa handle
+is rendered invalid.
+Just before removing a dynamic library or bundle in this way, any
+termination routines in it are called.
+.Fa handle
+is the value returned by a previous call to dlopen.
+.Sh RETURN VALUES
+If
+.Fn dlclose
+is successful, it returns a value of 0.
+Otherwise it returns -1, and sets an error string that can be
+retrived with
+.Fn dlerror .
+.Pp
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr NSModule 3
+.Xr NSObjectFileImage 3
+.Xr ld 1
+.Xr cc 1
--- /dev/null
+.Dd Sept 25, 2004
+.Dt DLERROR 3
+.Sh NAME
+.Nm dlerror
+.Nd get diagnostic information
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft const char*
+.Fn dlerror "void"
+.Sh DESCRIPTION
+.Fn dlerror
+returns a null-terminated character string describing the last error that
+occurred on this thread during a call to
+.Fn dlopen ,
+.Fn dlsym ,
+or
+.Fn dlclose .
+If no such error has occurred,
+.Fn dlerror
+returns a null pointer.
+At each call to
+.Fn dlerror ,
+the error indication is reset. Thus in the case of two calls
+to
+.Fn dlerror ,
+where the second call follows the first immediately, the second call
+will always return a null pointer.
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlclose 3
+.Xr dlsym 3
+.Xr dyld 3
--- /dev/null
+.Dd February 8, 2005
+.Os
+.Dt DLOPEN 3
+.Sh NAME
+.Nm dlopen
+.Nd load and link a dynamic library or bundle
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void*
+.Fn dlopen "const char* path" "int mode"
+.Sh DESCRIPTION
+.Fn dlopen
+examines the mach-o file specified by
+.Fa path .
+If the file is compatible with the current process and has not already been
+loaded into the current process, it is loaded and linked. After being linked,
+if it contains any initializer functions, they are called, before
+.Fn dlopen
+returns.
+.Fn dlopen
+can load dynamic libraries and bundles. It returns a handle that can
+be used with
+.Fn dlsym
+and
+.Fn dlclose .
+A second call to
+.Fn dlopen
+with the same path will return the same handle, but the internal reference
+count for the handle will be incremented. Therefore all
+.Fn dlopen
+calls should be balanced with a
+.Fn dlclose
+call.
+.Pp
+If a null pointer is passed in
+.Fa path ,
+.Fn dlopen
+returns a handle equivalent to RTLD_DEFAULT.
+.Pp
+.Fa mode
+contains options to
+.Fn dlopen .
+It must contain one or more of the following values, possibly ORed together:
+.Pp
+.Bl -tag -width RTLD_LAZYX
+.It Dv RTLD_LAZY
+Each external function reference is bound the first time the function is called.
+.It Dv RTLD_NOW
+All external function references are bound immediately during the call to
+.Fn dlopen .
+.El
+.Pp
+.Dv RTLD_LAZY
+is normally preferred, for reasons of efficiency.
+However,
+.Dv RTLD_NOW
+is useful to ensure that any undefined symbols are discovered during the
+call to
+.Fn dlopen .
+If neither
+RTLD_LAZY nor RTLD_NOW is specified, the default is RTLD_LAZY.
+.Pp
+One of the following flags may be ORed into the
+.Fa mode
+argument:
+.Bl -tag -width RTLD_GLOBALX
+.It Dv RTLD_GLOBAL
+Symbols exported from this image (dynamic library or bundle) will be available to any
+images build with -flat_namespace option to
+.Xr ld 1
+or to calls to
+.Fn dlsym
+when using a special handle.
+.It Dv RTLD_LOCAL
+Symbols exported from this image (dynamic library or bundle) are generally hidden
+and only availble to
+.Fn dlsym
+when directly using the handle returned by this call to
+.Fn dlopen .
+If neither
+RTLD_GLOBAL nor RTLD_LOCAL is specified, the default is RTLD_GLOBAL.
+.El
+.Sh SEARCHING
+.Fn dlopen
+uses a series of steps to find a compatible mach-o file. The first compatible file found is used.
+.Pp
+1) If the directory specified by
+.Fa path
+does not contain a slash '/' (i.e. it is a leaf name) then the environment variable LD_LIBRARY_PATH is
+used. LD_LIBRARY_PATH should be a colon seperated list of directories.
+.Fn dlopen
+searches each directory, in the order specified, for the leaf name
+.Fa path .
+.Pp
+2) If DYLD_LIBRARY_PATH is set, then those directories are searched, in order,
+with the leaf name of
+.Fa path .
+.Pp
+3) If DYLD_FALLBACK_LIBRARY_PATH is set, then those directories are searched, in order
+with the leaf name of
+.Fa path .
+If DYLD_FALLBACK_LIBRARY_PATH is not set, then the following directories are searched: $HOME/lib, /usr/local/lib, /usr/lib
+.Pp
+4) Lastly,
+.Fa path
+is tried as-is as a regular file path. That means it might resolve relative to the current working directory.
+.Pp
+Note: There are no configuration files to control dlopen searching.
+.Pp
+Note: Mac OS X uses "fat" files to combine 32-bit and 64-bit libraries. This means there are no separate 32-bit and 64-bit search paths.
+.Pp
+.Sh RETURN VALUES
+If
+.Fn dlopen
+fails, it returns a null pointer, and sets an error condition which may be interrogated with
+.Fn dlerror .
+.Sh AUTHORS
+Mac OS X 10.3 incorporated the dlcompat package written by Jorge Acereda <jacereda@users.sourceforge.net>
+and Peter O'Gorman <ogorman@users.sourceforge.net>.
+.Pp
+In Mac OS X 10.4, dlopen was rewritten to be a native part of dyld.
+.Pp
+.Sh SEE ALSO
+.Xr dlclose 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr ld 1
--- /dev/null
+.Dd Sept 25, 2004
+.Dt DLSYM 3
+.Sh NAME
+.Nm dlsym
+.Nd get address of a symbol
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void*
+.Fn dlsym "void* handle" "const char* symbol"
+.Sh DESCRIPTION
+.Fn dlsym
+returns the address of the code or data location
+specified by the null-terminated character string
+.Fa symbol .
+Which libraries and bundles are searched depends on the
+.Fa handle
+parameter.
+.Pp
+If
+.Fn dlsym
+is called with a
+.Fa handle ,
+returned by
+.Fn dlopen
+then only that image and any libraries it depends on are searched for
+.Fa symbol .
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_DEFAULT ,
+then every mach-o image in the process is searched in the order they were loaded.
+This can be a costly search and should be avoided.
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_NEXT ,
+then the search for the symbol is limited to the images which were loaded
+after the one issuing the call to
+.Fn dlsym .
+.Pp
+.Sh RETURN VALUES
+The
+.Fn dlsym
+function
+returns a null pointer if the symbol cannot be found, and sets an error
+condition which may be queried with
+.Fn dlerror .
+.Pp
+.Sh NOTES
+Unlike other dyld API's, the symbol name passed to
+.Fn dlsym
+must NOT be prepended with an underscore.
+.Sh SEE ALSO
+.Xr dlopen 3
+.Xr dlsym 3
+.Xr dlerror 3
+.Xr dyld 3
+.Xr NSModule 3
+.Xr NSObjectFileImage 3
+.Xr ld 1
+.Xr cc 1
--- /dev/null
+.TH DYLD 3 "January 15, 2005" "Apple Computer, Inc."
+.SH NAME
+dyld \- low level programatic interface to the dynamic link editor
+.SH SYNOPSIS
+.nf
+.PP
+#include <mach-o/dyld.h>
+bool _dyld_present(void);
+.sp .5
+uint32_t _dyld_image_count(void);
+.sp .5
+const struct mach_header *_dyld_get_image_header(
+ uint32_t image_index);
+.sp .5
+intptr_t _dyld_get_image_vmaddr_slide(
+ uint32_t image_index);
+.sp .5
+const char *_dyld_get_image_name(
+ uint32_t image_index);
+.sp .5
+void _dyld_lookup_and_bind(
+ const char *symbol_name,
+ void **address,
+ NSModule *module);
+.sp .5
+void _dyld_lookup_and_bind_with_hint(
+ const char *symbol_name,
+ const char *library_name_hint,
+ void **address,
+ NSModule *module);
+.sp .5
+void _dyld_lookup_and_bind_fully(
+ const char *symbol_name,
+ void **address,
+ NSModule *module);
+.sp .5
+bool _dyld_bind_fully_image_containing_address(
+ const void *address);
+.sp .5
+bool _dyld_image_containing_address(
+ const void* address);
+.sp .5
+const struct mach_header * _dyld_get_image_header_containing_address(
+ const void* address);
+.sp .5
+bool _dyld_launched_prebound(void);
+.sp .5
+bool _dyld_all_twolevel_modules_prebound(void);
+.sp .5
+int _dyld_func_lookup(
+ const char *dyld_func_name,
+ void **address);
+.sp .5
+extern void _dyld_bind_objc_module(
+ const void *objc_module);
+.sp .5
+extern void _dyld_get_objc_module_sect_for_module(
+ NSModule module,
+ void **objc_module,
+ size_t *size);
+.sp .5
+extern void _dyld_lookup_and_bind_objc(
+ const char *symbol_name,
+ void **address,
+ NSModule *module);
+.sp .5
+extern void _dyld_moninit(
+ void (*monaddition)(char *lowpc, char *highpc));
+.sp .5
+
+extern void _dyld_register_func_for_add_image(
+ void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+.sp .5
+extern void _dyld_register_func_for_remove_image(
+ void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+.sp .5
+extern void _dyld_register_func_for_link_module(
+ void (*func)(NSModule module));
+.fi
+.SH DESCRIPTION
+These routines are the low level programatic interface to the dynamic link
+editor.
+.PP
+.I _dyld_present returns non-zero if the dynamic linker is being used in the
+program and zero otherwise. If this returns zero this rest of these functions
+should not be called and most likely crash the program if called.
+.PP
+.I _dyld_image_count
+returns the current number of images mapped in by the dynamic link editor.
+.PP
+.I _dyld_get_image_header
+returns the mach header of the image indexed by image_index. If image_index is
+out of range NULL is returned.
+.PP
+.I _dyld_get_image_vmaddr_slide
+returns the virtural memory address slide amount of the image indexed by
+.I image_index.
+If image_index is out of range zero is returned.
+.PP
+.I _dyld_get_image_name
+returns the name of the image indexed by
+.I image_index.
+If image_index is out of range NULL is returned.
+.PP
+.I _dyld_lookup_and_bind
+looks up the
+.I symbol_name
+and binds it into the program. It indirectly returns the
+.I address
+and and a pointer to the
+.I module
+that defined the symbol.
+.PP
+.I _dyld_lookup_and_bind_with_hint
+is the same as
+.I _dyld_lookup_and_bind
+but the
+.I library_name_hint
+parameter provides a hint as to where to start the lookup in a prebound
+program. The
+.I library_name_hint
+parameter is matched up with the actual library install names with
+.IR strstr (3).
+.PP
+.I _dyld_lookup_and_bind_fully
+looks up the
+.I symbol_name
+and binds it and all of its references into the program. It indirectly returns
+the
+.I address
+and and a pointer to the
+.I module
+that defined the symbol.
+.PP
+.I _dyld_bind_fully_image_containing_address
+fully binds the image containing the specified address. It returns TRUE if the
+address is contained in a loaded image and FALSE otherwise.
+.PP
+.I _dyld_image_containing_address
+It returns TRUE if the address is contained in an image dyld loaded and FALSE
+otherwise.
+.PP
+.I _dyld_get_image_header_containing_address
+It returns a pointer to the mach header of the image if the address is contained
+in an image dyld loaded and NULL otherwise.
+.PP
+.I _dyld_launched_prebound
+returns TRUE if the program was launched using the prebound state and FALSE
+otherwise.
+.PP
+.I_dyld_all_twolevel_modules_prebound(void);
+returns TRUE if all the libraries currently in use by the program are being used
+as two-level namespace libraries, are prebound and have all their modules bound.
+Otherwise it returns FALSE.
+.PP
+.I _dyld_func_lookup
+is passed a name,
+.I dyld_func_name,
+of a dynamic link editor function and returns the
+.I address
+of the function indirectly. It returns non-zero if the function is found
+and zero otherwise.
+.PP
+.I _dyld_bind_objc_module
+is passed a pointer to something in an (__OBJC,__module) section and causes the
+module that is associated with that address to be bound.
+.PP
+.I _dyld_get_objc_module_sect_for_module
+is passed a module and sets a pointer to the (__OBJC,__module) section and its
+size for the specified module.
+.PP
+.I _dyld_lookup_and_bind_objc()
+is the same as _dyld_lookup_and_bind() but does not update the symbol pointers
+if the symbol is in a bound module. The reason for this is that an objc symbol
+like
+.I .objc_class_name_Object
+is never used by a symbol pointer. Since this is done a lot by the objc
+runtime and updating symbol pointers is not cheep it should not be done.
+.PP
+.I _dyld_moninit
+is called from the profiling runtime routine
+.IR moninit(3)
+to cause the dyld loaded code to be profiled. It is passed a pointer to the
+the profiling runtime routine
+.IR monaddtion(3)
+to be called after an image had been mapped in.
+.PP
+.I _dyld_register_func_for_add_image
+registers the specified function to be called when a new image is added
+(a bundle or a dynamic shared library) to the program. When this function is
+first registered it is called for once for each image that is currently part of
+the program.
+.PP
+.I _dyld_register_func_for_remove_image
+registers the specified function to be called when an image is removed
+(a bundle or a dynamic shared library) from the program.
+.I _dyld_register_func_for_link_module
+registers the specified function to be called when a module is bound into the
+program. When this function is first registered it is called for once for each
+module that is currently bound into the program.
--- /dev/null
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 39;
+ objects = {
+ EF799FE7070D27BB00F78484 = {
+ children = (
+ EF799FE8070D27BB00F78484,
+ EF799FEA070D27BB00F78484,
+ );
+ isa = PBXGroup;
+ name = man;
+ path = doc/man;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FE8070D27BB00F78484 = {
+ children = (
+ EF799FE9070D27BB00F78484,
+ );
+ isa = PBXGroup;
+ name = man1;
+ path = doc/man/man1;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FE9070D27BB00F78484 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = text.man;
+ name = dyld.1;
+ path = doc/man/man1/dyld.1;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FEA070D27BB00F78484 = {
+ children = (
+ EF799FEB070D27BB00F78484,
+ EF799FEC070D27BB00F78484,
+ EF799FED070D27BB00F78484,
+ EF799FEE070D27BB00F78484,
+ EF799FEF070D27BB00F78484,
+ EF799FF0070D27BB00F78484,
+ EF799FF1070D27BB00F78484,
+ EF799FF2070D27BB00F78484,
+ EF799FF3070D27BB00F78484,
+ );
+ isa = PBXGroup;
+ name = man3;
+ path = doc/man/man3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FEB070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dladdr.3;
+ path = doc/man/man3/dladdr.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FEC070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dlclose.3;
+ path = doc/man/man3/dlclose.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FED070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dlerror.3;
+ path = doc/man/man3/dlerror.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FEE070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dlopen.3;
+ path = doc/man/man3/dlopen.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FEF070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dlsym.3;
+ path = doc/man/man3/dlsym.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FF0070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = dyld.3;
+ path = doc/man/man3/dyld.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FF1070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = NSModule.3;
+ path = doc/man/man3/NSModule.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FF2070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = NSObjectFileImage.3;
+ path = doc/man/man3/NSObjectFileImage.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF799FF3070D27BB00F78484 = {
+ explicitFileType = text.man;
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ name = NSObjectFileImage_priv.3;
+ path = doc/man/man3/NSObjectFileImage_priv.3;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ EF79A010070D293E00F78484 = {
+ fileRef = EF799FE9070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A011070D295200F78484 = {
+ fileRef = EF799FEB070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A012070D295200F78484 = {
+ fileRef = EF799FEC070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A013070D295200F78484 = {
+ fileRef = EF799FED070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A014070D295200F78484 = {
+ fileRef = EF799FEE070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A015070D295200F78484 = {
+ fileRef = EF799FEF070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A016070D295200F78484 = {
+ fileRef = EF799FF0070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A017070D295200F78484 = {
+ fileRef = EF799FF1070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A018070D295200F78484 = {
+ fileRef = EF799FF2070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ EF79A019070D295200F78484 = {
+ fileRef = EF799FF3070D27BB00F78484;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+//EF0
+//EF1
+//EF2
+//EF3
+//EF4
+//F90
+//F91
+//F92
+//F93
+//F94
+ F906E2230639E96400B13DB2 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dyld_debug.c;
+ path = src/dyld_debug.c;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F906E2240639E96400B13DB2 = {
+ fileRef = F906E2230639E96400B13DB2;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F913FAD90630A8AE00B7AE9D = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyldAPIsInLibSystem.cpp;
+ path = src/dyldAPIsInLibSystem.cpp;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F913FADA0630A8AE00B7AE9D = {
+ fileRef = F913FAD90630A8AE00B7AE9D;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F921D3160703769A000D1056 = {
+ compilerSpec = com.apple.compilers.gcc.3_5;
+ fileType = sourcecode.c;
+ isEditable = 1;
+ isa = PBXBuildRule;
+ outputFiles = (
+ );
+ };
+ F921D317070376A6000D1056 = {
+ compilerSpec = com.apple.compilers.gcc.3_5;
+ fileType = sourcecode.c;
+ isEditable = 1;
+ isa = PBXBuildRule;
+ outputFiles = (
+ );
+ };
+ F921D318070376B0000D1056 = {
+ compilerSpec = com.apple.compilers.gcc.3_5;
+ fileType = sourcecode.asm;
+ isEditable = 1;
+ isa = PBXBuildRule;
+ outputFiles = (
+ );
+ };
+ F921D31E070376F1000D1056 = {
+ compilerSpec = com.apple.compilers.gcc.3_5;
+ fileType = sourcecode.cpp;
+ isEditable = 1;
+ isa = PBXBuildRule;
+ outputFiles = (
+ );
+ };
+ F939F219078F1A2100AC144F = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyld_debug.h;
+ path = "include/mach-o/dyld_debug.h";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F939F21A078F1A2100AC144F = {
+ fileRef = F939F219078F1A2100AC144F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F939F21B078F1A2C00AC144F = {
+ fileRef = F939F219078F1A2100AC144F;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F93AA9A30630AE1E00301D9F = {
+ fileRef = F9ED4CE80630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F93AA9A40630AE1E00301D9F = {
+ fileRef = F9ED4CE90630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F93AA9A50630AE1E00301D9F = {
+ fileRef = F9ED4CEA0630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F93AA9B30630AE8200301D9F = {
+ buildActionMask = 8;
+ dstPath = "/usr/include/mach-o";
+ dstSubfolderSpec = 0;
+ files = (
+ F939F21B078F1A2C00AC144F,
+ F93AA9A50630AE1E00301D9F,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ F93AA9B60630AEB100301D9F = {
+ buildActionMask = 8;
+ dstPath = "/usr/local/include/mach-o";
+ dstSubfolderSpec = 0;
+ files = (
+ F93AA9A30630AE1E00301D9F,
+ F93AA9A40630AE1E00301D9F,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ F93AA9C20630AF0700301D9F = {
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man1;
+ dstSubfolderSpec = 0;
+ files = (
+ EF79A010070D293E00F78484,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ F93AA9C60630AF1F00301D9F = {
+ buildActionMask = 8;
+ dstPath = /usr/share/man/man3;
+ dstSubfolderSpec = 0;
+ files = (
+ EF79A011070D295200F78484,
+ EF79A012070D295200F78484,
+ EF79A013070D295200F78484,
+ EF79A014070D295200F78484,
+ EF79A015070D295200F78484,
+ EF79A016070D295200F78484,
+ EF79A017070D295200F78484,
+ EF79A018070D295200F78484,
+ EF79A019070D295200F78484,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ F9574C4906C94DA700142BFA = {
+ compilerSpec = com.apple.compilers.gcc.3_5;
+ fileType = sourcecode.c;
+ isEditable = 1;
+ isa = PBXBuildRule;
+ outputFiles = (
+ );
+ };
+ F9574CB206C95C0D00142BFA = {
+ buildActionMask = 8;
+ dstPath = /usr/include;
+ dstSubfolderSpec = 0;
+ files = (
+ F9574CB306C95C1B00142BFA,
+ );
+ isa = PBXCopyFilesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 1;
+ };
+ F9574CB306C95C1B00142BFA = {
+ fileRef = F99EE6AE06B48D4200BF1992;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F99EE6AE06B48D4200BF1992 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dlfcn.h;
+ path = include/dlfcn.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F99EE6AF06B48D4200BF1992 = {
+ fileRef = F99EE6AE06B48D4200BF1992;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9B01E3D0739ABDE00CF981B = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.exports;
+ name = dyld.exp;
+ path = src/dyld.exp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9B01E3E0739ABDE00CF981B = {
+ fileRef = F9B01E3D0739ABDE00CF981B;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9CA205D06CBF578000BA084 = {
+ buildActionMask = 8;
+ files = (
+ );
+ inputPaths = (
+ "${DSTROOT}/usr/local/lib/system/ldyldapis.a",
+ );
+ isa = PBXShellScriptBuildPhase;
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 1;
+ shellPath = /bin/sh;
+ shellScript = "cd ${DSTROOT}/usr/local/lib/system\nln -s libdyldapis.a libdyldapis_profile.a\nln -s libdyldapis.a libdyldapis_debug.a\n";
+ };
+ F9ED4C870630A72200DF4E74 = {
+ children = (
+ F9ED4CBB0630A7AA00DF4E74,
+ F9ED4CC30630A7BE00DF4E74,
+ F9ED4CBE0630A7B100DF4E74,
+ F9ED4C990630A76000DF4E74,
+ );
+ isa = PBXGroup;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9ED4C890630A72300DF4E74 = {
+ buildSettings = {
+ COPY_PHASE_STRIP = NO;
+ DEAD_CODE_STRIPPING = NO;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ };
+ isa = PBXBuildStyle;
+ name = Development;
+ };
+ F9ED4C8A0630A72300DF4E74 = {
+ buildSettings = {
+ COPY_PHASE_STRIP = YES;
+ GCC_ENABLE_CPP_RTTI = NO;
+ };
+ isa = PBXBuildStyle;
+ name = Deployment;
+ };
+ F9ED4C8B0630A72300DF4E74 = {
+ buildSettings = {
+ };
+ buildStyles = (
+ F9ED4C890630A72300DF4E74,
+ F9ED4C8A0630A72300DF4E74,
+ );
+ hasScannedForEncodings = 1;
+ isa = PBXProject;
+ mainGroup = F9ED4C870630A72200DF4E74;
+ productRefGroup = F9ED4C990630A76000DF4E74;
+ projectDirPath = "";
+ targets = (
+ F9ED4C920630A73900DF4E74,
+ F9ED4C970630A76000DF4E74,
+ F9ED4C9E0630A76B00DF4E74,
+ );
+ };
+ F9ED4C920630A73900DF4E74 = {
+ buildPhases = (
+ );
+ buildSettings = {
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = all;
+ SECTORDER_FLAGS = "";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ F9ED4CA70630A78A00DF4E74,
+ F9ED4CA90630A78A00DF4E74,
+ );
+ isa = PBXAggregateTarget;
+ name = all;
+ productName = all;
+ };
+ F9ED4C950630A76000DF4E74 = {
+ buildActionMask = 2147483647;
+ files = (
+ F9ED4CDF0630A7F100DF4E74,
+ F9ED4CD60630A7F100DF4E74,
+ F9ED4CD70630A7F100DF4E74,
+ F9ED4CD80630A7F100DF4E74,
+ F9ED4CD90630A7F100DF4E74,
+ F9ED4CDA0630A7F100DF4E74,
+ F9ED4CDB0630A7F100DF4E74,
+ F9ED4CDE0630A7F100DF4E74,
+ F9ED4CE00630A7F100DF4E74,
+ F9ED4CE10630A7F100DF4E74,
+ F9ED4CE20630A7F100DF4E74,
+ F9ED4CE30630A7F100DF4E74,
+ F9ED4CE40630A7F100DF4E74,
+ F9ED4CE50630A7F100DF4E74,
+ F9ED4CEB0630A80600DF4E74,
+ F9ED4CEC0630A80600DF4E74,
+ F9ED4CED0630A80600DF4E74,
+ F99EE6AF06B48D4200BF1992,
+ F9B01E3E0739ABDE00CF981B,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9ED4C960630A76000DF4E74 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9ED4C970630A76000DF4E74 = {
+ buildPhases = (
+ F9ED4C950630A76000DF4E74,
+ F9ED4C960630A76000DF4E74,
+ );
+ buildRules = (
+ F921D318070376B0000D1056,
+ F921D317070376A6000D1056,
+ F921D3160703769A000D1056,
+ );
+ buildSettings = {
+ ARCHS = ppc;
+ CURRENT_PROJECT_VERSION = "$(RC_ProjectSourceVersion)";
+ DEAD_CODE_STRIPPING = YES;
+ EXPORTED_SYMBOLS_FILE = "";
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_ENABLE_CPP_RTTI = NO;
+ GCC_MODEL_TUNING = G4;
+ GCC_OPTIMIZATION_LEVEL = 3;
+ GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+ HEADER_SEARCH_PATHS = ./include;
+ INSTALL_PATH = /usr/lib;
+ LIBRARY_SEARCH_PATHS = "";
+ MACOSX_DEPLOYMENT_TARGET = 10.4;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "-v -seg1addr 8fe00000 -exported_symbols_list src/dyld.exp -nostdlib -lstdc++ /usr/local/lib/system/libc.a -lgcc -Wl,-e,__dyld_start -Wl,-dylinker -Wl,-dylinker_install_name,/usr/lib/dyld";
+ OTHER_REZFLAGS = "";
+ PER_ARCH_CFLAGS_ppc = "";
+ PER_ARCH_CFLAGS_ppc64 = "-msoft-float";
+ PREBINDING = NO;
+ PRODUCT_NAME = dyld;
+ STRIPFLAGS = "-S";
+ UNSTRIPPED_PRODUCT = NO;
+ VALID_ARCHS = "ppc ppc64 i386";
+ VERSIONING_SYSTEM = "apple-generic";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = dyld;
+ productName = dyld;
+ productReference = F9ED4C980630A76000DF4E74;
+ productType = "com.apple.product-type.tool";
+ };
+ F9ED4C980630A76000DF4E74 = {
+ explicitFileType = "compiled.mach-o.executable";
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = dyld;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ F9ED4C990630A76000DF4E74 = {
+ children = (
+ F9ED4C980630A76000DF4E74,
+ F9ED4C9F0630A76B00DF4E74,
+ );
+ isa = PBXGroup;
+ name = Products;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9ED4C9B0630A76B00DF4E74 = {
+ buildActionMask = 2147483647;
+ files = (
+ F9FE429C06C82066001D8CE5,
+ F939F21A078F1A2100AC144F,
+ );
+ isa = PBXHeadersBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9ED4C9C0630A76B00DF4E74 = {
+ buildActionMask = 2147483647;
+ files = (
+ F9F256360639DBCC00A7427D,
+ F9F256370639DBCC00A7427D,
+ F913FADA0630A8AE00B7AE9D,
+ F906E2240639E96400B13DB2,
+ );
+ isa = PBXSourcesBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9ED4C9D0630A76B00DF4E74 = {
+ buildActionMask = 2147483647;
+ files = (
+ );
+ isa = PBXFrameworksBuildPhase;
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F9ED4C9E0630A76B00DF4E74 = {
+ buildPhases = (
+ F9ED4C9C0630A76B00DF4E74,
+ F9ED4C9B0630A76B00DF4E74,
+ F93AA9B30630AE8200301D9F,
+ F9574CB206C95C0D00142BFA,
+ F93AA9B60630AEB100301D9F,
+ F93AA9C20630AF0700301D9F,
+ F93AA9C60630AF1F00301D9F,
+ F9CA205D06CBF578000BA084,
+ F9ED4C9D0630A76B00DF4E74,
+ );
+ buildRules = (
+ F921D31E070376F1000D1056,
+ F9574C4906C94DA700142BFA,
+ );
+ buildSettings = {
+ ARCHS = ppc;
+ GCC_ENABLE_CPP_EXCEPTIONS = NO;
+ HEADER_SEARCH_PATHS = ./include;
+ INSTALL_PATH = /usr/local/lib/system;
+ LIBRARY_STYLE = STATIC;
+ OTHER_CFLAGS = "";
+ OTHER_LDFLAGS = "";
+ OTHER_REZFLAGS = "";
+ PRODUCT_NAME = dyldapis;
+ SECTORDER_FLAGS = "";
+ VALID_ARCHS = "ppc ppc64 i386";
+ WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas";
+ };
+ dependencies = (
+ );
+ isa = PBXNativeTarget;
+ name = libdyld;
+ productName = libdyld;
+ productReference = F9ED4C9F0630A76B00DF4E74;
+ productType = "com.apple.product-type.library.static";
+ };
+ F9ED4C9F0630A76B00DF4E74 = {
+ explicitFileType = archive.ar;
+ includeInIndex = 0;
+ isa = PBXFileReference;
+ path = libdyldapis.a;
+ refType = 3;
+ sourceTree = BUILT_PRODUCTS_DIR;
+ };
+ F9ED4CA60630A78A00DF4E74 = {
+ containerPortal = F9ED4C8B0630A72300DF4E74;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = F9ED4C970630A76000DF4E74;
+ remoteInfo = dyld;
+ };
+ F9ED4CA70630A78A00DF4E74 = {
+ isa = PBXTargetDependency;
+ target = F9ED4C970630A76000DF4E74;
+ targetProxy = F9ED4CA60630A78A00DF4E74;
+ };
+ F9ED4CA80630A78A00DF4E74 = {
+ containerPortal = F9ED4C8B0630A72300DF4E74;
+ isa = PBXContainerItemProxy;
+ proxyType = 1;
+ remoteGlobalIDString = F9ED4C9E0630A76B00DF4E74;
+ remoteInfo = libdyld;
+ };
+ F9ED4CA90630A78A00DF4E74 = {
+ isa = PBXTargetDependency;
+ target = F9ED4C9E0630A76B00DF4E74;
+ targetProxy = F9ED4CA80630A78A00DF4E74;
+ };
+ F9ED4CBB0630A7AA00DF4E74 = {
+ children = (
+ F9ED4CC60630A7F100DF4E74,
+ F9ED4CC70630A7F100DF4E74,
+ F9ED4CC80630A7F100DF4E74,
+ F9FE429B06C82066001D8CE5,
+ F9ED4CC90630A7F100DF4E74,
+ F9ED4CCA0630A7F100DF4E74,
+ F913FAD90630A8AE00B7AE9D,
+ F9ED4CCB0630A7F100DF4E74,
+ F9ED4CCC0630A7F100DF4E74,
+ F9ED4CCD0630A7F100DF4E74,
+ F9ED4CCE0630A7F100DF4E74,
+ F9ED4CCF0630A7F100DF4E74,
+ F9ED4CD00630A7F100DF4E74,
+ F9ED4CD10630A7F100DF4E74,
+ F9ED4CD20630A7F100DF4E74,
+ F9ED4CD30630A7F100DF4E74,
+ F9ED4CD40630A7F100DF4E74,
+ F9ED4CD50630A7F100DF4E74,
+ F9B01E3D0739ABDE00CF981B,
+ F906E2230639E96400B13DB2,
+ );
+ isa = PBXGroup;
+ name = src;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9ED4CBE0630A7B100DF4E74 = {
+ children = (
+ F9ED4CE80630A80600DF4E74,
+ F9ED4CE90630A80600DF4E74,
+ F939F219078F1A2100AC144F,
+ F9ED4CEA0630A80600DF4E74,
+ F99EE6AE06B48D4200BF1992,
+ );
+ isa = PBXGroup;
+ name = include;
+ path = "";
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9ED4CC30630A7BE00DF4E74 = {
+ children = (
+ EF799FE7070D27BB00F78484,
+ );
+ isa = PBXGroup;
+ name = doc;
+ path = "";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CC60630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyld_gdb.cpp;
+ path = src/dyld_gdb.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CC70630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyld.cpp;
+ path = src/dyld.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CC80630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyld.h;
+ path = src/dyld.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CC90630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyldAPIs.cpp;
+ path = src/dyldAPIs.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCA0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = dyldExceptions.c;
+ path = src/dyldExceptions.c;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCB0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyldInitialization.cpp;
+ path = src/dyldInitialization.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCC0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyldLock.cpp;
+ path = src/dyldLock.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCD0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyldLock.h;
+ path = src/dyldLock.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCE0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = dyldNew.cpp;
+ path = src/dyldNew.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CCF0630A7F100DF4E74 = {
+ fileEncoding = 30;
+ indentWidth = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.asm;
+ name = dyldStartup.s;
+ path = src/dyldStartup.s;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ tabWidth = 8;
+ usesTabs = 1;
+ };
+ F9ED4CD00630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.c;
+ name = glue.c;
+ path = src/glue.c;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CD10630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = ImageLoader.cpp;
+ path = src/ImageLoader.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CD20630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = ImageLoader.h;
+ path = src/ImageLoader.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CD30630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.cpp.cpp;
+ name = ImageLoaderMachO.cpp;
+ path = src/ImageLoaderMachO.cpp;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CD40630A7F100DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = ImageLoaderMachO.h;
+ path = src/ImageLoaderMachO.h;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CD50630A7F100DF4E74 = {
+ fileEncoding = 30;
+ indentWidth = 4;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.asm;
+ name = stub_binding_helper.s;
+ path = src/stub_binding_helper.s;
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ tabWidth = 8;
+ usesTabs = 1;
+ };
+ F9ED4CD60630A7F100DF4E74 = {
+ fileRef = F9ED4CC60630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CD70630A7F100DF4E74 = {
+ fileRef = F9ED4CC70630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CD80630A7F100DF4E74 = {
+ fileRef = F9ED4CC80630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CD90630A7F100DF4E74 = {
+ fileRef = F9ED4CC90630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CDA0630A7F100DF4E74 = {
+ fileRef = F9ED4CCA0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CDB0630A7F100DF4E74 = {
+ fileRef = F9ED4CCB0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CDE0630A7F100DF4E74 = {
+ fileRef = F9ED4CCE0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CDF0630A7F100DF4E74 = {
+ fileRef = F9ED4CCF0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE00630A7F100DF4E74 = {
+ fileRef = F9ED4CD00630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE10630A7F100DF4E74 = {
+ fileRef = F9ED4CD10630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE20630A7F100DF4E74 = {
+ fileRef = F9ED4CD20630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE30630A7F100DF4E74 = {
+ fileRef = F9ED4CD30630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE40630A7F100DF4E74 = {
+ fileRef = F9ED4CD40630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE50630A7F100DF4E74 = {
+ fileRef = F9ED4CD50630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CE80630A80600DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyld_gdb.h;
+ path = "include/mach-o/dyld_gdb.h";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CE90630A80600DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyld_priv.h;
+ path = "include/mach-o/dyld_priv.h";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CEA0630A80600DF4E74 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyld.h;
+ path = "include/mach-o/dyld.h";
+ refType = 2;
+ sourceTree = SOURCE_ROOT;
+ };
+ F9ED4CEB0630A80600DF4E74 = {
+ fileRef = F9ED4CE80630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CEC0630A80600DF4E74 = {
+ fileRef = F9ED4CE90630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9ED4CED0630A80600DF4E74 = {
+ fileRef = F9ED4CEA0630A80600DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9F256360639DBCC00A7427D = {
+ fileRef = F9ED4CCC0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9F256370639DBCC00A7427D = {
+ fileRef = F9ED4CCD0630A7F100DF4E74;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ F9FE429B06C82066001D8CE5 = {
+ fileEncoding = 30;
+ isa = PBXFileReference;
+ lastKnownFileType = sourcecode.c.h;
+ name = dyldLibSystemThreadHelpers.h;
+ path = src/dyldLibSystemThreadHelpers.h;
+ refType = 4;
+ sourceTree = "<group>";
+ };
+ F9FE429C06C82066001D8CE5 = {
+ fileRef = F9FE429B06C82066001D8CE5;
+ isa = PBXBuildFile;
+ settings = {
+ };
+ };
+ };
+ rootObject = F9ED4C8B0630A72300DF4E74;
+}
--- /dev/null
+/*
+ * Copyright (c) 2004-2005 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@
+ */
+
+/*
+ Based on the dlcompat work done by:
+ Jorge Acereda <jacereda@users.sourceforge.net> &
+ Peter O'Gorman <ogorman@users.sourceforge.net>
+*/
+
+#ifndef _DLFCN_H_
+#define _DLFCN_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <sys/cdefs.h>
+
+#ifndef _POSIX_C_SOURCE
+/*
+ * Structure filled in by dladdr().
+ */
+typedef struct dl_info {
+ const char *dli_fname; /* Pathname of shared object */
+ void *dli_fbase; /* Base address of shared object */
+ const char *dli_sname; /* Name of nearest symbol */
+ void *dli_saddr; /* Address of nearest symbol */
+} Dl_info;
+
+extern int dladdr(const void *, Dl_info *);
+#endif /* not POSIX */
+
+extern int dlclose(void * __handle);
+extern char * dlerror(void);
+extern void * dlopen(const char * __path, int __mode);
+extern void * dlsym(void * __handle, const char * __symbol);
+
+#define RTLD_LAZY 0x1
+#define RTLD_NOW 0x2
+#define RTLD_LOCAL 0x4
+#define RTLD_GLOBAL 0x8
+
+#ifndef _POSIX_C_SOURCE
+#define RTLD_NOLOAD 0x10
+#define RTLD_NODELETE 0x80
+
+/*
+ * Special handle arguments for dlsym().
+ */
+#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */
+#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */
+#endif /* not POSIX */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DLFCN_H_ */
--- /dev/null
+/*
+ * Copyright (c) 1999-2005 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 */
+
+#include <stddef.h>
+#include <stdint.h>
+#if __cplusplus
+ /* C++ has bool type built in */
+#else
+ #include <stdbool.h>
+#endif
+#include <mach-o/loader.h>
+#include <AvailabilityMacros.h>
+
+#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 struct __NSObjectFileImage* 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);
+extern NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(
+ const void *address,
+ size_t size,
+ NSObjectFileImage *objectFileImage);
+extern 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 uint32_t NSSymbolDefinitionCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+extern const char * NSSymbolDefinitionNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ uint32_t ordinal);
+extern uint32_t NSSymbolReferenceCountInObjectFileImage(
+ NSObjectFileImage objectFileImage);
+extern const char * NSSymbolReferenceNameInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ uint32_t ordinal,
+ 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 bool NSIsSymbolDefinedInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void * NSGetSectionDataInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ const char *segmentName,
+ const char *sectionName,
+ size_t *size); /* can be NULL */
+/* SPI first appeared in Mac OS X 10.3 */
+extern bool NSHasModInitObjectFileImage(
+ NSObjectFileImage objectFileImage)
+ AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+/* module API */
+typedef struct __NSModule* 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,
+ uint32_t 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 bool NSUnLinkModule(
+ NSModule module,
+ uint32_t 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,
+ uint32_t options);
+
+/* symbol API */
+typedef struct __NSSymbol* NSSymbol;
+extern bool NSIsSymbolNameDefined(
+ const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSIsSymbolNameDefinedWithHint(
+ const char *symbolName,
+ const char *libraryNameHint) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSIsSymbolNameDefinedInImage(
+ const struct mach_header *image,
+ const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupAndBindSymbol(
+ const char *symbolName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupAndBindSymbolWithHint(
+ const char *symbolName,
+ const char *libraryNameHint) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern NSSymbol NSLookupSymbolInModule(
+ NSModule module,
+ const char *symbolName);
+extern NSSymbol NSLookupSymbolInImage(
+ const struct mach_header *image,
+ const char *symbolName,
+ uint32_t 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(
+ const NSLinkEditErrorHandlers *handlers);
+
+/* other API */
+extern bool NSAddLibrary(
+ const char *pathName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern bool NSAddLibraryWithSearching(
+ const char *pathName) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern const struct mach_header * NSAddImage(
+ const char *image_name,
+ uint32_t 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 int32_t NSVersionOfRunTimeLibrary(
+ const char *libraryName);
+extern int32_t NSVersionOfLinkTimeLibrary(
+ const char *libraryName);
+extern int _NSGetExecutablePath( /* SPI first appeared in Mac OS X 10.2 */
+ char *buf,
+ uint32_t *bufsize);
+
+/*
+ * The low level _dyld_... API.
+ * (used by the objective-C runtime primarily)
+ */
+extern bool _dyld_present(
+ void);
+
+extern uint32_t _dyld_image_count(
+ void);
+extern const struct mach_header * _dyld_get_image_header(
+ uint32_t image_index);
+extern intptr_t _dyld_get_image_vmaddr_slide(
+ uint32_t image_index);
+extern const char * _dyld_get_image_name(
+ uint32_t image_index);
+
+extern void _dyld_register_func_for_add_image(
+ void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide));
+extern void _dyld_register_func_for_remove_image(
+ void (*func)(const struct mach_header *mh, intptr_t 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,
+ size_t *size);
+extern void _dyld_bind_objc_module(
+ const void *objc_module);
+extern bool _dyld_bind_fully_image_containing_address(
+ const void *address);
+extern bool _dyld_image_containing_address(
+ const void* address);
+/* SPI first appeared in Mac OS X 10.3 */
+extern const struct mach_header * _dyld_get_image_header_containing_address(
+ const void* address)
+ AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER;
+
+extern void _dyld_moninit(
+ void (*monaddition)(char *lowpc, char *highpc));
+extern bool _dyld_launched_prebound(
+ void);
+/* SPI first appeared in Mac OS X 10.3 */
+extern 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,
+ void **address,
+ NSModule* module) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void _dyld_lookup_and_bind_with_hint(
+ const char *symbol_name,
+ const char *library_name_hint,
+ void **address,
+ NSModule* module) AVAILABLE_MAC_OS_X_VERSION_10_1_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+extern void _dyld_lookup_and_bind_objc(
+ const char *symbol_name,
+ void **address,
+ NSModule* module);
+extern void _dyld_lookup_and_bind_fully(
+ const char *symbol_name,
+ void **address,
+ NSModule* module);
+
+extern int _dyld_func_lookup(
+ const char *dyld_func_name,
+ void **address);
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_DYLD_H_ */
--- /dev/null
+/*
+ * 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 _DYLD_DEBUG_
+#define _DYLD_DEBUG_
+
+#include <mach/mach.h>
+#ifndef DYLD_BUILD /* do not include this when building dyld itself */
+#include <mach-o/dyld.h>
+#endif /* !defined(DYLD_BUILD) */
+
+#include <AvailabilityMacros.h>
+
+/*
+ * The dyld debugging API is deprecated as of Mac OS X 10.4
+ */
+enum dyld_debug_return {
+ DYLD_SUCCESS,
+ DYLD_INCONSISTENT_DATA,
+ DYLD_INVALID_ARGUMENTS,
+ DYLD_FAILURE
+};
+
+struct dyld_debug_module {
+ struct mach_header *header;
+ unsigned long vmaddr_slide;
+ unsigned long module_index;
+};
+
+enum dyld_event_type {
+ DYLD_IMAGE_ADDED,
+ DYLD_MODULE_BOUND,
+ DYLD_MODULE_REMOVED,
+ DYLD_MODULE_REPLACED,
+ DYLD_PAST_EVENTS_END,
+ DYLD_IMAGE_REMOVED
+};
+
+struct dyld_event {
+ enum dyld_event_type type;
+ struct dyld_debug_module arg[2];
+};
+
+extern enum dyld_debug_return _dyld_debug_defining_module(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ char *name,
+ struct dyld_debug_module *module) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_is_module_bound(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ struct dyld_debug_module module,
+ boolean_t *bound) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_bind_module(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ struct dyld_debug_module module) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_module_name(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ struct dyld_debug_module module,
+ char **image_name,
+ unsigned long *image_nameCnt,
+ char **module_name,
+ unsigned long *module_nameCnt) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+extern enum dyld_debug_return _dyld_debug_subscribe_to_events(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ void (*dyld_event_routine)(struct dyld_event event)) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * _dyld_debug_add_event_subscriber() uses the mig interface functions below
+ * to dispatch the dyld event messages from the subscriber port specified.
+ */
+extern enum dyld_debug_return _dyld_debug_add_event_subscriber(
+ mach_port_t target_task,
+ unsigned long send_timeout,
+ unsigned long rcv_timeout,
+ boolean_t inconsistent_data_ok,
+ mach_port_t subscriber) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * These structures should be produced by mig(1) from the mig generated files
+ * but they are not. These are really only needed so the correct size of the
+ * request and reply messages can be allocated.
+ */
+struct _dyld_event_message_request {
+#ifdef __MACH30__
+ mach_msg_header_t head;
+ NDR_record_t NDR;
+ struct dyld_event event;
+ mach_msg_trailer_t trailer;
+#else
+ msg_header_t head;
+ msg_type_t eventType;
+ struct dyld_event event;
+#endif
+};
+struct _dyld_event_message_reply {
+#ifdef __MACH30__
+ mach_msg_header_t head;
+ NDR_record_t NDR;
+ struct dyld_event event;
+#else
+ msg_header_t head;
+ msg_type_t RetCodeType;
+ kern_return_t RetCode;
+#endif
+};
+#ifndef mig_internal
+/*
+ * _dyld_event_server() is the mig generated routine to dispatch dyld event
+ * messages.
+ */
+extern boolean_t _dyld_event_server(
+#ifdef __MACH30__
+ mach_msg_header_t *request,
+ mach_msg_header_t *reply);
+#else
+ struct _dyld_event_message_request *request,
+ struct _dyld_event_message_reply *reply);
+#endif
+#endif /* mig_internal */
+
+#ifndef SHLIB
+/*
+ * _dyld_event_server_callback() is the routine called by _dyld_event_server()
+ * that must be written by users of _dyld_event_server().
+ */
+extern
+#ifdef __MACH30__
+kern_return_t
+#else
+void
+#endif
+_dyld_event_server_callback(
+#ifdef __MACH30__
+ mach_port_t subscriber,
+#else
+ port_t subscriber,
+#endif
+ struct dyld_event event);
+#endif /* SHLIB */
+
+/*
+ * This is the state of the target task while we are sending a message to it.
+ */
+struct _dyld_debug_task_state {
+ mach_port_t debug_port;
+ mach_port_t debug_thread;
+ unsigned int debug_thread_resume_count;
+ unsigned int task_resume_count;
+ mach_port_t *threads;
+ unsigned int thread_count;
+};
+
+/*
+ * _dyld_debug_make_runnable() is called before sending messages to the
+ * dynamic link editor. Basically it assures that the debugging
+ * thread is the only runnable thread in the task to receive the
+ * message. It also assures that the debugging thread is indeed
+ * runnable if it was suspended. The function will make sure each
+ * thread in the remote task is suspended and resumed the same number
+ * of times, so in the end the suspend count of each individual thread
+ * is the same.
+ */
+extern enum dyld_debug_return _dyld_debug_make_runnable(
+ mach_port_t target_task,
+ struct _dyld_debug_task_state *state) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * _dyld_debug_restore_runnable() is called after sending messages to the
+ * dynamic link editor. It undoes what _dyld_debug_make_runnable() did to the
+ * task and put it back the way it was.
+ */
+extern enum dyld_debug_return _dyld_debug_restore_runnable(
+ mach_port_t target_task,
+ struct _dyld_debug_task_state *state) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+/*
+ * To provide more detailed information when the APIs of the dyld debug
+ * interfaces fail (return DYLD_FAILURE) the following structure is filled in.
+ * After it is filled in the function registered with
+ * set_dyld_debug_error_func() is called with a pointer to that struct.
+ *
+ * The local_error field is a unique number for each possible error condition
+ * in the source code in that makes up the dyld debug APIs. The source file
+ * and line number in the cctools libdyld directory where the dyld debug APIs
+ * are implemented are set into the file_name and line_number fields. The
+ * field dyld_debug_return is filled in with that would be returned by the
+ * API (usually DYLD_FAILURE). The other fields will be zero or filled in by
+ * the error code from the mach system call, or UNIX system call that failed.
+ */
+struct dyld_debug_error_data {
+ enum dyld_debug_return dyld_debug_return;
+ kern_return_t mach_error;
+ int dyld_debug_errno;
+ unsigned long local_error;
+ char *file_name;
+ unsigned long line_number;
+};
+
+extern void _dyld_debug_set_error_func(
+ void (*func)(struct dyld_debug_error_data *e)) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+#ifndef DYLD_BUILD /* do not include this when building dyld itself */
+
+extern enum dyld_debug_return _dyld_debug_task_from_core(
+ NSObjectFileImage coreFileImage,
+ mach_port_t *core_task) AVAILABLE_MAC_OS_X_VERSION_10_0_AND_LATER_BUT_DEPRECATED_IN_MAC_OS_X_VERSION_10_4;
+
+#endif /* !defined(DYLD_BUILD) */
+
+#endif /* _DYLD_DEBUG_ */
--- /dev/null
+/*
+ * 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 _DYLD_GDB_
+#define _DYLD_GDB_
+/*
+ * This file describes the interface between gdb and dyld created for
+ * MacOS X GM. Prior to MacOS X GM gdb used the dyld_debug interfaces
+ * described in <mach-o/dyld_debug.h>.
+ */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#define OLD_GDB_DYLD_INTERFACE __ppc__ || __i386__
+
+#if OLD_GDB_DYLD_INTERFACE
+/*
+ * gdb_dyld_version is the version of gdb interface that dyld is currently
+ * exporting. For the interface described in this header file gdb_dyld_version
+ * is 2. As the gdb/dyld interface changes this number will be incremented and
+ * comments will be added as to what are the are changes for the various
+ * versions.
+ */
+extern unsigned int gdb_dyld_version;
+
+/*
+ * gdb_dyld_state_changed is the internal dyld routine called by dyld to notify
+ * gdb that the state of the data structures has changed. gdb is expected to
+ * put a break point on this routine and re-read the internal dyld data
+ * structures below when this break point is hit.
+ */
+extern void gdb_dyld_state_changed(void);
+
+/*
+ * gdb looks directly at parts of two of dyld's internal data structures. The
+ * list of object file images and the list of library images. The parts of
+ * these structures that gdb looks at will not change unless the value of
+ * gdb_dyld_version changes. The size of these structures and the other fields
+ * that gdb does not look at may change.
+ *
+ * struct object_images {
+ * struct object_image images[NOBJECT_IMAGES];
+ * unsigned long nimages;
+ * struct object_images *next_images;
+ * ...
+ * };
+ *
+ * struct library_images {
+ * struct library_image images[NLIBRARY_IMAGES];
+ * unsigned long nimages;
+ * struct library_images *next_images;
+ * ...
+ * };
+ *
+ * Both the object_image structure and the library_image structure
+ * start with a structure containing the following fields:
+ *
+ * struct image {
+ * char *physical_name; physical image name (file name)
+ * unsigned long vmaddr_slide; the slide from the staticly linked address
+ * struct mach_header *mh; address of the mach header of the image
+ * unsigned long valid; TRUE if this is struct is valid
+ * char *name; image name for reporting errors
+ * ...
+ * };
+ *
+ * In gdb_dyld_version 1 the first field was "name". In gdb_dyld_version 2 the
+ * first field was changed to "physical_name" and a new fifth field "name" was
+ * added. These two fields are set to the same values except in the case of
+ * zero-link. In zero-link the NSLinkModule() option
+ * NSLINKMODULE_OPTION_TRAILING_PHYS_NAME is used and then the physical_name is
+ * the file name of the module zero-link loaded that is part of the logical
+ * image "name".
+ */
+
+/* object_images is the global object_images structure */
+
+/* the number of gdb_object_image structures present per bucket */
+extern unsigned int gdb_nobject_images;
+
+/* the size of each gdb_object_image structure */
+extern unsigned int gdb_object_image_size;
+
+/* library_images is the global library_images structure */
+
+/* the number of gdb_library_image structures present per bucket */
+extern unsigned int gdb_nlibrary_images;
+
+/* the size of each gdb_library_image structure */
+extern unsigned int gdb_library_image_size;
+
+#endif /* OLD_GDB_DYLD_INTERFACE */
+
+
+/*
+ * Beginning in Mac OS X 10.4, there is a new mechanism for dyld to notify gdb and other about new images.
+ *
+ *
+ */
+
+enum dyld_image_mode { dyld_image_adding=0, dyld_image_removing=1 };
+
+struct dyld_image_info {
+ const struct mach_header* imageLoadAddress; /* base address image is mapped into */
+ const char* imageFilePath; /* path dyld used to load the image */
+ uintptr_t imageFileModDate; /* time_t of image file */
+ /* if stat().st_mtime of imageFilePath does not match imageFileModDate, */
+ /* then file has been modified since dyld loaded it */
+};
+
+
+typedef void (*dyld_image_notifier)(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
+
+/*
+ * gdb looks for the symbol "_dyld_all_image_infos" in dyld. It contains the fields below.
+ *
+ * For a snap shot of what images are currently loaded, the infoArray fields contain a pointer
+ * to an array of all images. If infoArray is NULL, it means it is being modified, come back later.
+ *
+ * To be notified of changes, gdb sets a break point on the notification field. The function
+ * it points to is called by dyld with an array of information about what images have been added
+ * (dyld_image_adding) or are about to be removed (dyld_image_removing).
+ *
+ * The notification is called after infoArray is updated. This means that if gdb attaches to a process
+ * and infoArray is NULL, gdb can set a break point on notification and let the proccess continue to
+ * run until the break point. Then gdb can inspect the full infoArray.
+ */
+ struct dyld_all_image_infos {
+ uint32_t version; /* == 1 in Mac OS X 10.4 */
+ uint32_t infoArrayCount;
+ const struct dyld_image_info* infoArray;
+ dyld_image_notifier notification;
+ bool processDetachedFromSharedRegion;
+};
+extern struct dyld_all_image_infos dyld_all_image_infos;
+
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _DYLD_GDB_ */
--- /dev/null
+/*
+ * 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 _MACH_O_DYLD_PRIV_H_
+#define _MACH_O_DYLD_PRIV_H_
+
+
+#include <mach-o/dyld.h>
+
+#if __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+/*
+ * Given an imageOffset into an ObjectFileImage, returns
+ * the segment/section name and offset into that section of
+ * that imageOffset. Returns FALSE if the imageOffset is not
+ * in any section. You can used the resulting sectionOffset to
+ * index into the data returned by NSGetSectionDataInObjectFileImage.
+ *
+ * First appeared in Mac OS X 10.3
+ *
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool
+NSFindSectionAndOffsetInObjectFileImage(
+ NSObjectFileImage objectFileImage,
+ unsigned long imageOffset,
+ const char** segmentName, /* can be NULL */
+ const char** sectionName, /* can be NULL */
+ unsigned long* sectionOffset); /* can be NULL */
+
+
+
+
+#if __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* _MACH_O_DYLD_PRIV_H_ */
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __STDC_LIMIT_MACROS
+#include <stdint.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <mach/mach.h>
+#include <mach-o/fat.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#include "ImageLoader.h"
+
+
+uint32_t ImageLoader::fgImagesWithUsedPrebinding = 0;
+uint32_t ImageLoader::fgTotalRebaseFixups = 0;
+uint32_t ImageLoader::fgTotalBindFixups = 0;
+uint32_t ImageLoader::fgTotalLazyBindFixups = 0;
+uint32_t ImageLoader::fgTotalPossibleLazyBindFixups = 0;
+uint64_t ImageLoader::fgTotalLoadLibrariesTime;
+uint64_t ImageLoader::fgTotalRebaseTime;
+uint64_t ImageLoader::fgTotalBindTime;
+uint64_t ImageLoader::fgTotalNotifyTime;
+uint64_t ImageLoader::fgTotalInitTime;
+uintptr_t ImageLoader::fgNextSplitSegAddress = 0x90000000;
+uintptr_t Segment::fgNextNonSplitSegAddress = 0x8FE00000;
+
+
+
+__attribute__((noreturn))
+void throwf(const char* format, ...)
+{
+ va_list list;
+ char* p;
+ va_start(list, format);
+ vasprintf(&p, format, list);
+ va_end(list);
+
+ const char* t = p;
+ throw t;
+}
+
+void ImageLoader::init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate)
+{
+ fPathHash = 0;
+ fPath = NULL;
+ if ( path != NULL )
+ this->setPath(path);
+ fLogicalPath = NULL;
+ fDevice = device;
+ fInode = inode;
+ fLastModified = modDate;
+ fOffsetInFatFile = offsetInFat;
+ //fSegments = NULL;
+ fLibraries = NULL;
+ fLibrariesCount = 0;
+ fReferenceCount = 0;
+ fAllLibraryChecksumsAndLoadAddressesMatch = false;
+ fLeaveMapped = false;
+ fHideSymbols = false;
+ fMatchByInstallName = false;
+ fLibrariesLoaded = false;
+ fBased = false;
+ fBoundAllNonLazy = false;
+ fBoundAllLazy = false;
+ fAnnounced = false;
+ fInitialized = false;
+ fNextAddImageIndex = 0;
+}
+
+
+ImageLoader::ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info)
+{
+ init(path, offsetInFat, info.st_dev, info.st_ino, info.st_mtime);
+}
+
+ImageLoader::ImageLoader(const char* moduleName)
+{
+ init(moduleName, 0, 0, 0, 0);
+}
+
+
+ImageLoader::~ImageLoader()
+{
+ // need to read up on STL and see if this is right way to destruct vector contents
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ delete seg;
+ }
+ if ( fPath != NULL )
+ delete [] fPath;
+ if ( fLogicalPath != NULL )
+ delete [] fLogicalPath;
+}
+
+
+void ImageLoader::setPath(const char* path)
+{
+ if ( fPath != NULL ) {
+ // if duplicate path, do nothing
+ if ( strcmp(path, fPath) == 0 )
+ return;
+ delete [] fPath;
+ }
+ fPath = new char[strlen(path)+1];
+ strcpy((char*)fPath, path);
+ fPathHash = hash(fPath);
+}
+
+void ImageLoader::setLogicalPath(const char* path)
+{
+ if ( fPath == NULL ) {
+ // no physical path set yet, so use this path as physical
+ this->setPath(path);
+ }
+ else if ( strcmp(path, fPath) == 0 ) {
+ // do not set logical path because it is the same as the physical path
+ fLogicalPath = NULL;
+ }
+ else {
+ fLogicalPath = new char[strlen(path)+1];
+ strcpy((char*)fLogicalPath, path);
+ }
+}
+
+const char* ImageLoader::getLogicalPath() const
+{
+ if ( fLogicalPath != NULL )
+ return fLogicalPath;
+ else
+ return fPath;
+}
+
+uint32_t ImageLoader::hash(const char* path)
+{
+ // this does not need to be a great hash
+ // it is just used to reduce the number of strcmp() calls
+ // of existing images when loading a new image
+ uint32_t h = 0;
+ for (const char* s=path; *s != '\0'; ++s)
+ h = h*5 + *s;
+ return h;
+}
+
+bool ImageLoader::matchInstallPath() const
+{
+ return fMatchByInstallName;
+}
+
+void ImageLoader::setMatchInstallPath(bool match)
+{
+ fMatchByInstallName = match;
+}
+
+bool ImageLoader::statMatch(const struct stat& stat_buf) const
+{
+ return ( (this->fDevice == stat_buf.st_dev) && (this->fInode == stat_buf.st_ino) );
+}
+
+const char* ImageLoader::getShortName() const
+{
+ // try to return leaf name
+ if ( fPath != NULL ) {
+ const char* s = strrchr(fPath, '/');
+ if ( s != NULL )
+ return &s[1];
+ }
+ return fPath;
+}
+
+uint64_t ImageLoader::getOffsetInFatFile() const
+{
+ return fOffsetInFatFile;
+}
+
+void ImageLoader::setLeaveMapped()
+{
+ fLeaveMapped = true;
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ fSegments[i]->setUnMapWhenDestructed(false);
+ }
+}
+
+void ImageLoader::setHideExports(bool hide)
+{
+ fHideSymbols = hide;
+}
+
+bool ImageLoader::hasHiddenExports() const
+{
+ return fHideSymbols;
+}
+
+bool ImageLoader::isLinked() const
+{
+ return fBoundAllNonLazy;
+}
+
+time_t ImageLoader::lastModified()
+{
+ return fLastModified;
+}
+
+bool ImageLoader::containsAddress(const void* addr) const
+{
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ const uint8_t* start = (const uint8_t*)seg->getActualLoadAddress();
+ const uint8_t* end = start + seg->getSize();
+ if ( (start <= addr) && (addr < end) && !seg->unaccessible() )
+ return true;
+ }
+ return false;
+}
+
+void ImageLoader::addMappedRegions(RegionsVector& regions) const
+{
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ MappedRegion region;
+ region.address = seg->getActualLoadAddress();
+ region.size = seg->getSize();
+ regions.push_back(region);
+ }
+}
+
+
+void ImageLoader::incrementReferenceCount()
+{
+ ++fReferenceCount;
+}
+
+bool ImageLoader::decrementReferenceCount()
+{
+ return ( --fReferenceCount == 0 );
+}
+
+
+const ImageLoader::Symbol* ImageLoader::resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const
+{
+ const ImageLoader::Symbol* sym;
+ // search self
+ if ( searchSelf ) {
+ sym = this->findExportedSymbol(name, NULL, false, foundIn);
+ if ( sym != NULL )
+ return sym;
+ }
+
+ // search directly dependent libraries
+ for (uint32_t i=0; i < fLibrariesCount; ++i) {
+ ImageLoader* dependentImage = fLibraries[i].image;
+ if ( dependentImage != NULL ) {
+ const ImageLoader::Symbol* sym = dependentImage->findExportedSymbol(name, NULL, false, foundIn);
+ if ( sym != NULL )
+ return sym;
+ }
+ }
+
+ // search indirectly dependent libraries
+ for (uint32_t i=0; i < fLibrariesCount; ++i) {
+ ImageLoader* dependentImage = fLibraries[i].image;
+ if ( dependentImage != NULL ) {
+ const ImageLoader::Symbol* sym = dependentImage->resolveSymbol(name, false, foundIn);
+ if ( sym != NULL )
+ return sym;
+ }
+ }
+
+ return NULL;
+}
+
+
+
+void ImageLoader::link(const LinkContext& context, BindingLaziness bindness, InitializerRunning inits, uint32_t notifyCount)
+{
+ uint64_t t1 = mach_absolute_time();
+ this->recursiveLoadLibraries(context);
+
+ uint64_t t2 = mach_absolute_time();
+ this->recursiveRebase(context);
+
+ uint64_t t3 = mach_absolute_time();
+ this->recursiveBind(context, bindness);
+
+ uint64_t t4 = mach_absolute_time();
+ this->recursiveImageNotification(context, notifyCount);
+
+ if ( (inits == kRunInitializers) || (inits == kDontRunInitializersButTellObjc) ) {
+ std::vector<ImageLoader*> newImages;
+ this->recursiveImageAnnouncement(context, newImages); // build bottom up list images being added
+ context.notifyAdding(newImages); // tell gdb or anyone who cares about these
+ }
+
+ uint64_t t5 = mach_absolute_time();
+ if ( inits == kRunInitializers ) {
+ this->recursiveInitialization(context);
+ uint64_t t6 = mach_absolute_time();
+ fgTotalInitTime += t6 - t5;
+ }
+ fgTotalLoadLibrariesTime += t2 - t1;
+ fgTotalRebaseTime += t3 - t2;
+ fgTotalBindTime += t4 - t3;
+ fgTotalNotifyTime += t5 - t4;
+}
+
+
+// only called pre-main on main executable
+// if crt.c is ever cleaned up, this could go away
+void ImageLoader::runInitializers(const LinkContext& context)
+{
+ std::vector<ImageLoader*> newImages;
+ this->recursiveImageAnnouncement(context, newImages); // build bottom up list images being added
+ context.notifyAdding(newImages); // tell gdb or anyone who cares about these
+
+ this->recursiveInitialization(context);
+}
+
+// called inside _dyld_register_func_for_add_image()
+void ImageLoader::runNotification(const LinkContext& context, uint32_t notifyCount)
+{
+ this->recursiveImageNotification(context, notifyCount);
+}
+
+
+intptr_t ImageLoader::assignSegmentAddresses(const LinkContext& context)
+{
+ // preflight and calculate slide if needed
+ const unsigned int segmentCount = fSegments.size();
+ intptr_t slide = 0;
+ if ( this->segmentsCanSlide() && this->segmentsMustSlideTogether() ) {
+ bool needsToSlide = false;
+ uintptr_t lowAddr = UINTPTR_MAX;
+ uintptr_t highAddr = 0;
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ const uintptr_t segLow = seg->getPreferredLoadAddress();
+ const uintptr_t segHigh = segLow + seg->getSize();
+ if ( segLow < lowAddr )
+ lowAddr = segLow;
+ if ( segHigh > highAddr )
+ highAddr = segHigh;
+
+ if ( context.slideAndPackDylibs || !seg->hasPreferredLoadAddress() || !Segment::reserveAddressRange(seg->getPreferredLoadAddress(), seg->getSize()) )
+ needsToSlide = true;
+ }
+ if ( needsToSlide ) {
+ // find a chunk of address space to hold all segments
+ uintptr_t addr = Segment::reserveAnAddressRange(highAddr-lowAddr, context);
+ slide = addr - lowAddr;
+ }
+ }
+ else if ( ! this->segmentsCanSlide() ) {
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ if ( strcmp(seg->getName(), "__PAGEZERO") == 0 )
+ continue;
+ if ( !Segment::reserveAddressRange(seg->getPreferredLoadAddress(), seg->getSize()) )
+ throw "can't map";
+ }
+ }
+ else {
+ // mach-o does not support independently sliding segments
+ }
+ return slide;
+}
+
+
+void ImageLoader::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+ if ( context.verboseMapping )
+ fprintf(stderr, "dyld: Mapping %s\n", this->getPath());
+ // find address range for image
+ intptr_t slide = this->assignSegmentAddresses(context);
+ // map in all segments
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ seg->map(fd, offsetInFat, slide, context);
+ }
+ // update slide to reflect load location
+ this->setSlide(slide);
+
+ // now that it is mapped and slide is set, mark that we should unmap it when done
+ for(unsigned int i=0; i < segmentCount; ++i){
+ fSegments[i]->setUnMapWhenDestructed(true);
+ }
+}
+
+void ImageLoader::mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context)
+{
+ if ( context.verboseMapping )
+ fprintf(stderr, "dyld: Mapping memory %p\n", memoryImage);
+ // find address range for image
+ intptr_t slide = this->assignSegmentAddresses(context);
+ // map in all segments
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ seg->map(memoryImage, slide, context);
+ }
+ // update slide to reflect load location
+ this->setSlide(slide);
+ // set R/W permissions on all segments at slide location
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ seg->setPermissions();
+ }
+}
+
+bool ImageLoader::allDependentLibrariesAsWhenPreBound() const
+{
+ return fAllLibraryChecksumsAndLoadAddressesMatch;
+}
+
+
+void ImageLoader::recursiveLoadLibraries(const LinkContext& context)
+{
+ if ( ! fLibrariesLoaded ) {
+ // break cycles
+ fLibrariesLoaded = true;
+
+ // get list of libraries this image needs
+ fLibrariesCount = this->doGetDependentLibraryCount();
+ fLibraries = new DependentLibrary[fLibrariesCount];
+ this->doGetDependentLibraries(fLibraries);
+
+ // try to load each
+ bool canUsePrelinkingInfo = true;
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& requiredLib = fLibraries[i];
+ try {
+ requiredLib.image = context.loadLibrary(requiredLib.name, true, this->getPath(), NULL);
+ if ( requiredLib.image == this ) {
+ // found circular reference, perhaps DYLD_LIBARY_PATH is causing this rdar://problem/3684168
+ requiredLib.image = context.loadLibrary(requiredLib.name, false, NULL, NULL);
+ if ( requiredLib.image != this )
+ fprintf(stderr, "dyld: warning DYLD_ setting caused circular dependency in %s\n", this->getPath());
+ }
+ LibraryInfo actualInfo = requiredLib.image->doGetLibraryInfo();
+ requiredLib.checksumMatches = ( actualInfo.checksum == requiredLib.info.checksum );
+ // check found library version is compatible
+ if ( actualInfo.minVersion < requiredLib.info.minVersion ) {
+ throwf("Incompatible library version: %s requires version %d.%d.%d or later, but %s provides version %d.%d.%d",
+ this->getShortName(), requiredLib.info.minVersion >> 16, (requiredLib.info.minVersion >> 8) & 0xff, requiredLib.info.minVersion & 0xff,
+ requiredLib.image->getShortName(), actualInfo.minVersion >> 16, (actualInfo.minVersion >> 8) & 0xff, actualInfo.minVersion & 0xff);
+ }
+ // prebinding for this image disabled if any dependent library changed or slid
+ if ( !requiredLib.checksumMatches || (requiredLib.image->getSlide() != 0) )
+ canUsePrelinkingInfo = false;
+ //if ( context.verbosePrebinding ) {
+ // if ( !requiredLib.checksumMatches )
+ // fprintf(stderr, "dyld: checksum mismatch, (%lld v %lld) for %s referencing %s\n", requiredLib.info.checksum, actualInfo.checksum, this->getPath(), requiredLib.image->getPath());
+ // if ( requiredLib.image->getSlide() != 0 )
+ // fprintf(stderr, "dyld: dependent library slid for %s referencing %s\n", this->getPath(), requiredLib.image->getPath());
+ //}
+ }
+ catch (const char* msg) {
+ //if ( context.verbosePrebinding )
+ // fprintf(stderr, "dyld: exception during processing for %s referencing %s\n", this->getPath(), requiredLib.image->getPath());
+ if ( requiredLib.required ) {
+ const char* formatString = "Library not loaded: %s\n Referenced from: %s\n Reason: %s";
+ const char* referencedFrom = this->getPath();
+ char buf[strlen(requiredLib.name)+strlen(referencedFrom)+strlen(formatString)+strlen(msg)+2];
+ sprintf(buf, formatString, requiredLib.name, referencedFrom, msg);
+ throw strdup(buf); // this is a leak if exception doesn't halt program
+ }
+ // ok if weak library not found
+ requiredLib.image = NULL;
+ canUsePrelinkingInfo = false; // this disables all prebinding, we may want to just slam import vectors for this lib to zero
+ }
+ }
+ fAllLibraryChecksumsAndLoadAddressesMatch = canUsePrelinkingInfo;
+
+ // tell each to load its dependents
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL ) {
+ libInfo.isSubFramework = libInfo.image->isSubframeworkOf(context, this);
+ libInfo.isReExported = libInfo.isSubFramework || this->hasSubLibrary(context, libInfo.image);
+ //if ( libInfo.isReExported )
+ // fprintf(stderr, "%s re-exports %s\n", strrchr(this->getPath(), '/'), strrchr(libInfo.image->getPath(),'/'));
+ libInfo.image->recursiveLoadLibraries(context);
+ }
+ }
+
+ // do deep prebind check
+ if ( fAllLibraryChecksumsAndLoadAddressesMatch ) {
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ const DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL ) {
+ if ( !libInfo.image->allDependentLibrariesAsWhenPreBound() )
+ fAllLibraryChecksumsAndLoadAddressesMatch = false;
+ }
+ }
+ }
+
+ }
+}
+
+void ImageLoader::recursiveRebase(const LinkContext& context)
+{
+ if ( ! fBased ) {
+ // break cycles
+ fBased = true;
+
+ try {
+ // rebase lower level libraries first
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL )
+ libInfo.image->recursiveRebase(context);
+ }
+
+ // rebase this image
+ doRebase(context);
+ }
+ catch (const char* msg) {
+ // this image is not rebased
+ fBased = false;
+ throw msg;
+ }
+ }
+}
+
+
+
+
+void ImageLoader::recursiveBind(const LinkContext& context, BindingLaziness bindness)
+{
+ // normally just non-lazy pointers are bound up front,
+ // but DYLD_BIND_AT_LAUNCH will cause lazy pointers to be bound up from
+ // and some dyld API's bind all lazys at runtime
+ bool nonLazy = false;
+ bool lazy = false;
+ switch( bindness ) {
+ case kNonLazyOnly:
+ nonLazy = true;
+ break;
+ case kLazyAndNonLazy:
+ nonLazy = true;
+ lazy = true;
+ break;
+ case kLazyOnly:
+ case kLazyOnlyNoDependents:
+ lazy = true;
+ break;
+ }
+ const bool doNonLazy = nonLazy && !fBoundAllNonLazy;
+ const bool doLazy = lazy && !fBoundAllLazy;
+ if ( doNonLazy || doLazy ) {
+ // break cycles
+ bool oldBoundAllNonLazy = fBoundAllNonLazy;
+ bool oldBoundAllLazy = fBoundAllLazy;
+ fBoundAllNonLazy = fBoundAllNonLazy || nonLazy;
+ fBoundAllLazy = fBoundAllLazy || lazy;
+
+ try {
+ // bind lower level libraries first
+ if ( bindness != kLazyOnlyNoDependents ) {
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL )
+ libInfo.image->recursiveBind(context, bindness);
+ }
+ }
+ // bind this image
+ if ( doLazy && !doNonLazy )
+ doBind(context, kLazyOnly);
+ else if ( !doLazy && doNonLazy )
+ doBind(context, kNonLazyOnly);
+ else
+ doBind(context, kLazyAndNonLazy);
+ }
+ catch (const char* msg) {
+ // restore state
+ fBoundAllNonLazy = oldBoundAllNonLazy;
+ fBoundAllLazy = oldBoundAllLazy;
+ throw msg;
+ }
+ }
+}
+
+//
+// This is complex because _dyld_register_func_for_add_image() is defined to not only
+// notify you of future image loads, but also of all currently loaded images. Therefore
+// each image needs to track that all add-image-funcs have been notified about it.
+// Since add-image-funcs cannot be removed, each has a unique index and each image
+// records the thru which index notificiation has already been done.
+//
+void ImageLoader::recursiveImageNotification(const LinkContext& context, uint32_t addImageCount)
+{
+ if ( fNextAddImageIndex < addImageCount ) {
+ // break cycles
+ const uint32_t initIndex = fNextAddImageIndex;
+ fNextAddImageIndex = addImageCount;
+
+ // notify all requestors about this image
+ context.imageNotification(this, initIndex);
+
+ // notify about lower level libraries first
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL )
+ libInfo.image->recursiveImageNotification(context, addImageCount);
+ }
+ }
+}
+
+
+void ImageLoader::recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages)
+{
+ if ( ! fAnnounced ) {
+ // break cycles
+ fAnnounced = true;
+
+ // announce lower level libraries first
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL )
+ libInfo.image->recursiveImageAnnouncement(context, newImages);
+ }
+
+ // add to list of images to notify gdb about
+ newImages.push_back(this);
+ //fprintf(stderr, "next size = %d\n", newImages.size());
+
+ // remember that this image wants to be notified about other images
+ if ( this->hasImageNotification() )
+ context.addImageNeedingNotification(this);
+ }
+}
+
+
+
+void ImageLoader::recursiveInitialization(const LinkContext& context)
+{
+ if ( ! fInitialized ) {
+ // break cycles
+ fInitialized = true;
+
+ try {
+ // initialize lower level libraries first
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.image != NULL )
+ libInfo.image->recursiveInitialization(context);
+ }
+
+ // record termination order
+ if ( this->needsTermination() )
+ context.terminationRecorder(this);
+
+ // initialize this image
+ this->doInitialization(context);
+ }
+ catch (const char* msg) {
+ // this image is not initialized
+ fInitialized = false;
+ throw msg;
+ }
+ }
+}
+
+void ImageLoader::reprebindCommit(const LinkContext& context, bool commit)
+{
+ // do nothing on unprebound images
+ if ( ! this->isPrebindable() )
+ return;
+
+ // do nothing if prebinding is up to date
+ if ( this->usablePrebinding(context) )
+ return;
+
+ // make sure we are not replacing a symlink with a file
+ char realFilePath[PATH_MAX];
+ if ( realpath(this->getPath(), realFilePath) == NULL ) {
+ throwf("realpath() failed on %s, errno=%d", this->getPath(), errno);
+ }
+ // recreate temp file name
+ char tempFilePath[PATH_MAX];
+ ImageLoader::addSuffix(realFilePath, "_redoprebinding", tempFilePath);
+
+ if ( commit ) {
+ // all files successfully reprebound, so do swap
+ int result = rename(tempFilePath, realFilePath);
+ if ( result != 0 ) {
+ // if there are two dylibs with the same install path, the second will fail to prebind
+ // because the _redoprebinding temp file is gone. In that case, log and go on.
+ if ( errno == ENOENT )
+ fprintf(stderr, "update_prebinding: temp file missing: %s\n", tempFilePath);
+ else
+ throwf("can't swap temporary re-prebound file: rename(%s,%s) returned errno=%d", tempFilePath, realFilePath, errno);
+ }
+ }
+ else {
+ // something went wrong during prebinding, delete the temp files
+ unlink(tempFilePath);
+ }
+}
+
+void ImageLoader::reprebind(const LinkContext& context, time_t timestamp)
+{
+ // do nothing on unprebound images
+ if ( ! this->isPrebindable() )
+ return;
+
+ // do nothing if prebinding is up to date
+ if ( this->usablePrebinding(context) ) {
+ if ( context.verbosePrebinding )
+ fprintf(stderr, "dyld: no need to re-prebind: %s\n", this->getPath());
+ return;
+ }
+ // make copy of file and map it in
+ char tempFilePath[PATH_MAX];
+ realpath(this->getPath(), tempFilePath);
+ ImageLoader::addSuffix(this->getPath(), "_redoprebinding", tempFilePath);
+ uint8_t* fileToPrebind;
+ uint64_t fileToPrebindSize;
+ this->copyAndMap(tempFilePath, &fileToPrebind, &fileToPrebindSize);
+
+ // do format specific prebinding
+ this->doPrebinding(context, timestamp, fileToPrebind);
+
+ // flush and swap files
+ int result = msync(fileToPrebind, fileToPrebindSize, MS_ASYNC);
+ if ( result != 0 )
+ throw "error syncing re-prebound file";
+ result = munmap(fileToPrebind, fileToPrebindSize);
+ if ( result != 0 )
+ throw "error unmapping re-prebound file";
+
+ // log
+ if ( context.verbosePrebinding )
+ fprintf(stderr, "dyld: re-prebound: %s\n", this->getPath());
+}
+
+void ImageLoader::copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize)
+{
+ // reopen dylib
+ int src = open(this->getPath(), O_RDONLY);
+ if ( src == -1 )
+ throw "can't open image";
+ struct stat stat_buf;
+ if ( fstat(src, &stat_buf) == -1)
+ throw "can't stat image";
+ if ( stat_buf.st_mtime != fLastModified )
+ throw "image file changed since it was loaded";
+
+ // create new file with all same permissions to hold copy of dylib
+ unlink(tempFile);
+ int dst = open(tempFile, O_CREAT | O_RDWR | O_TRUNC, stat_buf.st_mode);
+ if ( dst == -1 )
+ throw "can't create temp image";
+
+ // mark source as "don't cache"
+ (void)fcntl(src, F_NOCACHE, 1);
+ // we want to cache the dst because we are about to map it in and modify it
+
+ // copy permission bits
+ if ( chmod(tempFile, stat_buf.st_mode & 07777) == -1 )
+ throw "can't chmod temp image";
+ if ( chown(tempFile, stat_buf.st_uid, stat_buf.st_gid) == -1)
+ throw "can't chown temp image";
+
+ // copy contents
+ ssize_t len;
+ const uint32_t kBufferSize = 128*1024;
+ static uint8_t* buffer = NULL;
+ if ( buffer == NULL ) {
+ vm_address_t addr = 0;
+ if ( vm_allocate(mach_task_self(), &addr, kBufferSize, true /*find range*/) == KERN_SUCCESS )
+ buffer = (uint8_t*)addr;
+ else
+ throw "can't allcoate copy buffer";
+ }
+ while ( (len = read(src, buffer, kBufferSize)) > 0 ) {
+ write(dst, buffer, len);
+ }
+
+ // map in dst file
+ *fileToPrebindSize = stat_buf.st_size - fOffsetInFatFile; // this may map in too much, but it does not matter
+ *fileToPrebind = (uint8_t*)mmap(NULL, *fileToPrebindSize, PROT_READ | PROT_WRITE, MAP_FILE | MAP_SHARED, dst, fOffsetInFatFile);
+ if ( *fileToPrebind == (uint8_t*)(-1) )
+ throw "can't mmap temp image";
+
+ // closing notes:
+ // ok to close file after mapped in
+ // ok to throw above without closing file because the throw will terminate update_prebinding
+ int result1 = close(dst);
+ int result2 = close(src);
+ if ( (result1 != 0) || (result2 != 0) )
+ throw "can't close file";
+}
+
+
+static void printTime(const char* msg, uint64_t partTime, uint64_t totalTime)
+{
+ static uint64_t sUnitsPerSecond = 0;
+ if ( sUnitsPerSecond == 0 ) {
+ struct mach_timebase_info timeBaseInfo;
+ if ( mach_timebase_info(&timeBaseInfo) == KERN_SUCCESS ) {
+ sUnitsPerSecond = timeBaseInfo.denom;
+ }
+ }
+ if ( partTime < sUnitsPerSecond ) {
+ uint32_t milliSecondsTimeTen = (partTime*10000)/sUnitsPerSecond;
+ uint32_t milliSeconds = milliSecondsTimeTen/10;
+ uint32_t percentTimesTen = (partTime*1000)/totalTime;
+ uint32_t percent = percentTimesTen/10;
+ fprintf(stderr, "%s: %u.%u milliseconds (%u.%u%%)\n", msg, milliSeconds, milliSecondsTimeTen-milliSeconds*10, percent, percentTimesTen-percent*10);
+ }
+ else {
+ uint32_t secondsTimeTen = (partTime*10)/sUnitsPerSecond;
+ uint32_t seconds = secondsTimeTen/100;
+ uint32_t percentTimesTen = (partTime*1000)/totalTime;
+ uint32_t percent = percentTimesTen/10;
+ fprintf(stderr, "%s: %u.%u seconds (%u.%u%%)\n", msg, seconds, secondsTimeTen-seconds*10, percent, percentTimesTen-percent*10);
+ }
+}
+
+static char* commatize(uint64_t in, char* out)
+{
+ char* result = out;
+ char rawNum[30];
+ sprintf(rawNum, "%llu", in);
+ const int rawNumLen = strlen(rawNum);
+ for(int i=0; i < rawNumLen-1; ++i) {
+ *out++ = rawNum[i];
+ if ( ((rawNumLen-i) % 3) == 1 )
+ *out++ = ',';
+ }
+ *out++ = rawNum[rawNumLen-1];
+ *out = '\0';
+ return result;
+}
+
+
+void ImageLoader::printStatistics(unsigned int imageCount)
+{
+ uint64_t totalTime = fgTotalLoadLibrariesTime + fgTotalRebaseTime + fgTotalBindTime + fgTotalNotifyTime + fgTotalInitTime;
+ char commaNum1[40];
+ char commaNum2[40];
+
+ printTime("total time", totalTime, totalTime);
+ fprintf(stderr, "total images loaded: %d (%d used prebinding)\n", imageCount, fgImagesWithUsedPrebinding);
+ printTime("total images loading time", fgTotalLoadLibrariesTime, totalTime);
+ fprintf(stderr, "total rebase fixups: %s\n", commatize(fgTotalRebaseFixups, commaNum1));
+ printTime("total rebase fixups time", fgTotalRebaseFixups, totalTime);
+ fprintf(stderr, "total binding fixups: %s\n", commatize(fgTotalBindFixups, commaNum1));
+ printTime("total binding fixups time", fgTotalBindTime, totalTime);
+ fprintf(stderr, "total bindings lazily fixed up: %s of %s\n", commatize(fgTotalLazyBindFixups, commaNum1), commatize(fgTotalPossibleLazyBindFixups, commaNum2));
+ printTime("total notify time time", fgTotalNotifyTime, totalTime);
+ printTime("total init time time", fgTotalInitTime, totalTime);
+}
+
+
+//
+// copy path and add suffix to result
+//
+// /path/foo.dylib _debug => /path/foo_debug.dylib
+// foo.dylib _debug => foo_debug.dylib
+// foo _debug => foo_debug
+// /path/bar _debug => /path/bar_debug
+// /path/bar.A.dylib _debug => /path/bar.A_debug.dylib
+//
+void ImageLoader::addSuffix(const char* path, const char* suffix, char* result)
+{
+ strcpy(result, path);
+
+ char* start = strrchr(result, '/');
+ if ( start != NULL )
+ start++;
+ else
+ start = result;
+
+ char* dot = strrchr(start, '.');
+ if ( dot != NULL ) {
+ strcpy(dot, suffix);
+ strcat(&dot[strlen(suffix)], &path[dot-result]);
+ }
+ else {
+ strcat(result, suffix);
+ }
+}
+
+
+void Segment::map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context)
+{
+ vm_offset_t fileOffset = this->getFileOffset() + offsetInFatWrapper;
+ vm_size_t size = this->getFileSize();
+ void* requestedLoadAddress = (void*)(this->getPreferredLoadAddress() + slide);
+ int protection = 0;
+ if ( !this->unaccessible() ) {
+ if ( this->executable() )
+ protection |= PROT_EXEC;
+ if ( this->readable() )
+ protection |= PROT_READ;
+ if ( this->writeable() )
+ protection |= PROT_WRITE;
+ }
+ void* loadAddress = mmap(requestedLoadAddress, size, protection, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, fileOffset);
+ if ( loadAddress == ((void*)(-1)) )
+ throwf("mmap() error %d at address=0x%08lX, size=0x%08lX in Segment::map() mapping %s", errno, (uintptr_t)requestedLoadAddress, (uintptr_t)size, this->getImage()->getPath());
+
+ if ( context.verboseMapping )
+ fprintf(stderr, "%18s at %p->%p\n", this->getName(), loadAddress, (char*)loadAddress+this->getFileSize()-1);
+}
+
+void Segment::map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context)
+{
+ vm_address_t loadAddress = this->getPreferredLoadAddress() + slide;
+ vm_address_t srcAddr = (uintptr_t)memoryImage + this->getFileOffset();
+ vm_size_t size = this->getFileSize();
+ kern_return_t r = vm_copy(mach_task_self(), srcAddr, size, loadAddress);
+ if ( r != KERN_SUCCESS )
+ throw "can't map segment";
+
+ if ( context.verboseMapping )
+ fprintf(stderr, "%18s at %p->%p\n", this->getName(), (char*)loadAddress, (char*)loadAddress+this->getFileSize()-1);
+}
+
+void Segment::setPermissions()
+{
+ vm_prot_t protection = 0;
+ if ( !this->unaccessible() ) {
+ if ( this->executable() )
+ protection |= VM_PROT_EXECUTE;
+ if ( this->readable() )
+ protection |= VM_PROT_READ;
+ if ( this->writeable() )
+ protection |= VM_PROT_WRITE;
+ }
+ vm_address_t addr = this->getActualLoadAddress();
+ vm_size_t size = this->getSize();
+ const bool setCurrentPermissions = false;
+ kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, protection);
+ if ( r != KERN_SUCCESS )
+ throw "can't set vm permissions for mapped segment";
+}
+
+void Segment::tempWritable()
+{
+ vm_address_t addr = this->getActualLoadAddress();
+ vm_size_t size = this->getSize();
+ const bool setCurrentPermissions = false;
+ kern_return_t r = vm_protect(mach_task_self(), addr, size, setCurrentPermissions, VM_PROT_WRITE | VM_PROT_READ);
+ if ( r != KERN_SUCCESS )
+ throw "can't set vm permissions for mapped segment";
+}
+
+
+bool Segment::hasTrailingZeroFill()
+{
+ return ( this->writeable() && (this->getSize() > this->getFileSize()) );
+}
+
+
+uintptr_t Segment::reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context)
+{
+ vm_address_t addr = 0;
+ vm_size_t size = length;
+ if ( context.slideAndPackDylibs ) {
+ addr = (fgNextNonSplitSegAddress - length) & (-4096); // page align
+ kern_return_t r = vm_allocate(mach_task_self(), &addr, size, false /*use this range*/);
+ if ( r != KERN_SUCCESS )
+ throw "out of address space";
+ fgNextNonSplitSegAddress = addr;
+ }
+ else {
+ kern_return_t r = vm_allocate(mach_task_self(), &addr, size, true /*find range*/);
+ if ( r != KERN_SUCCESS )
+ throw "out of address space";
+ }
+ return addr;
+}
+
+bool Segment::reserveAddressRange(uintptr_t start, size_t length)
+{
+ vm_address_t addr = start;
+ vm_size_t size = length;
+ kern_return_t r = vm_allocate(mach_task_self(), &addr, size, false /*only this range*/);
+ if ( r != KERN_SUCCESS )
+ return false;
+ return true;
+}
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * 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 __IMAGELOADER__
+#define __IMAGELOADER__
+
+#include <sys/types.h>
+#include <mach/mach_time.h> // struct mach_timebase_info
+#include <stdint.h>
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+
+// utility
+__attribute__((noreturn)) void throwf(const char* format, ...);
+
+//
+// ImageLoader is an abstract base class. To support loading a particular executable
+// file format, you make a concrete subclass of ImageLoader.
+//
+// For each executable file (dynamic shared object) in use, an ImageLoader is instantiated.
+//
+// The ImageLoader base class does the work of linking together images, but it knows nothing
+// about any particular file format.
+//
+//
+class ImageLoader {
+public:
+
+ typedef uint32_t DefinitionFlags;
+ static const DefinitionFlags kNoDefinitionOptions = 0;
+ static const DefinitionFlags kWeakDefinition = 1;
+
+ typedef uint32_t ReferenceFlags;
+ static const ReferenceFlags kNoReferenceOptions = 0;
+ static const ReferenceFlags kWeakReference = 1;
+ static const ReferenceFlags kTentativeDefinition = 2;
+
+
+ enum BindingLaziness { kNonLazyOnly, kLazyAndNonLazy, kLazyOnly, kLazyOnlyNoDependents };
+ enum InitializerRunning { kDontRunInitializers, kRunInitializers, kDontRunInitializersButTellObjc };
+ enum PrebindMode { kUseAllPrebinding, kUseSplitSegPrebinding, kUseAllButAppPredbinding, kUseNoPrebinding };
+ enum BindingOptions { kBindingNone, kBindingLazyPointers, kBindingNeverSetLazyPointers };
+ enum SharedRegionMode { kUseSharedRegion, kUsePrivateSharedRegion, kDontUseSharedRegion };
+
+ struct Symbol; // abstact symbol
+
+ struct MappedRegion {
+ uintptr_t address;
+ size_t size;
+ };
+ typedef std::vector<MappedRegion> RegionsVector;
+
+ struct LinkContext {
+ ImageLoader* (*loadLibrary)(const char* libraryName, bool search, const char* origin, const char* rpath[]);
+ uint32_t (*imageNotification)(ImageLoader* image, uint32_t startIndex);
+ void (*terminationRecorder)(ImageLoader* image);
+ bool (*flatExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
+ bool (*coalescedExportFinder)(const char* name, const Symbol** sym, ImageLoader** image);
+ void (*undefinedHandler)(const char* name);
+ void (*addImageNeedingNotification)(ImageLoader* image);
+ void (*notifyAdding)(std::vector<ImageLoader*>& images);
+ void (*getAllMappedRegions)(RegionsVector&);
+ void * (*bindingHandler)(const char *, const char *, void *);
+ BindingOptions bindingOptions;
+ int argc;
+ const char** argv;
+ const char** envp;
+ const char** apple;
+ ImageLoader* mainExecutable;
+ const char* imageSuffix;
+ PrebindMode prebindUsage;
+ SharedRegionMode sharedRegionMode;
+ bool bindFlat;
+ bool slideAndPackDylibs;
+ bool verboseOpts;
+ bool verboseEnv;
+ bool verboseMapping;
+ bool verboseRebase;
+ bool verboseBind;
+ bool verboseInit;
+ bool verbosePrebinding;
+ bool verboseWarnings;
+ };
+
+ // constructor is protected, but anyone can delete an image
+ virtual ~ImageLoader();
+
+ // link() takes a newly instantiated ImageLoader and does all
+ // fixups needed to make it usable by the process
+ void link(const LinkContext& context, BindingLaziness mode, InitializerRunning inits, uint32_t notifyCount);
+
+ // runInitializers() is normally called in link() but the main executable must
+ // run crt code before initializers
+ void runInitializers(const LinkContext& context);
+
+ // runNotification() is normally called in link() but the main executable must
+ // run crt code before initializers
+ void runNotification(const LinkContext& context, uint32_t notifyCount);
+
+ // used by dyld to see if a requested library is already loaded (might be symlink)
+ bool statMatch(const struct stat& stat_buf) const;
+
+ // get short name of this image
+ const char* getShortName() const;
+
+ // get path used to load this image, not necessarily the "real" path
+ const char* getPath() const { return fPath; }
+
+ uint32_t getPathHash() const { return fPathHash; }
+
+ // get path used to load this image represents (ZeroLink only) which image this .o is part of
+ const char* getLogicalPath() const;
+
+ // get path this image is intended to be placed on disk or NULL if no preferred install location
+ virtual const char* getInstallPath() const = 0;
+
+ // image was loaded with NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME and all clients are looking for install path
+ bool matchInstallPath() const;
+ void setMatchInstallPath(bool);
+
+ // if path was a fat file, offset of image loaded in that fat file
+ uint64_t getOffsetInFatFile() const;
+
+ // mark that this image's exported symbols should be ignored when linking other images (e.g. RTLD_LOCAL)
+ void setHideExports(bool hide = true);
+
+ // check if this image's exported symbols should be ignored when linking other images
+ bool hasHiddenExports() const;
+
+ // checks if this image is already linked into the process
+ bool isLinked() const;
+
+ // even if image is deleted, leave segments mapped in
+ void setLeaveMapped();
+
+ // checks if the specifed address is within one of this image's segments
+ virtual bool containsAddress(const void* addr) const;
+
+ // adds to list of ranges of memory mapped in
+ void addMappedRegions(RegionsVector& regions) const;
+
+ // st_mtime from stat() on file
+ time_t lastModified();
+
+ // image should create prebound version of itself
+ void reprebind(const LinkContext& context, time_t timestamp);
+
+ // if 'commit', the prebound version should be swapped in, otherwise deleted
+ void reprebindCommit(const LinkContext& context, bool commit);
+
+ // only valid for main executables, returns a pointer its entry point
+ virtual void* getMain() const = 0;
+
+ // dyld API's require each image to have an associated mach_header
+ virtual const struct mach_header* machHeader() const = 0;
+
+ // dyld API's require each image to have a slide (actual load address minus preferred load address)
+ virtual uintptr_t getSlide() const = 0;
+
+ // dyld API's require each image to have a slide (actual load address minus preferred load address)
+ virtual const void* getBaseAddress() const = 0;
+
+ // image has exports that participate in runtime coalescing
+ virtual bool hasCoalescedExports() const = 0;
+
+ // search symbol table of definitions in this image for requested name
+ virtual const Symbol* findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const = 0;
+
+ // gets address of implementation (code) of the specified exported symbol
+ virtual uintptr_t getExportedSymbolAddress(const Symbol* sym) const = 0;
+
+ // gets attributes of the specified exported symbol
+ virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const = 0;
+
+ // gets name of the specified exported symbol
+ virtual const char* getExportedSymbolName(const Symbol* sym) const = 0;
+
+ // gets how many symbols are exported by this image
+ virtual uint32_t getExportedSymbolCount() const = 0;
+
+ // gets the i'th exported symbol
+ virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const = 0;
+
+ // find exported symbol as if imported by this image
+ // used by RTLD_NEXT and RTLD_SELF
+ virtual const Symbol* resolveSymbol(const char* name, bool searchSelf, ImageLoader** foundIn) const;
+
+ // gets how many symbols are imported by this image
+ virtual uint32_t getImportedSymbolCount() const = 0;
+
+ // gets the i'th imported symbol
+ virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const = 0;
+
+ // gets attributes of the specified imported symbol
+ virtual ReferenceFlags geImportedSymbolInfo(const Symbol* sym) const = 0;
+
+ // gets name of the specified imported symbol
+ virtual const char* getImportedSymbolName(const Symbol* sym) const = 0;
+
+ // checks if this image is a bundle and can be loaded but not linked
+ virtual bool isBundle() const = 0;
+
+ // checks if this image is a dylib
+ virtual bool isDylib() const = 0;
+
+ // only for main executable
+ virtual bool forceFlat() const = 0;
+
+ // called at runtime when a lazily bound function is first called
+ virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context) = 0;
+
+ // calls termination routines (e.g. C++ static destructors for image)
+ virtual void doTermination(const LinkContext& context) = 0;
+
+ // tell this image about other images
+ virtual void doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]) = 0;
+
+ // return if this image has initialization routines
+ virtual bool needsInitialization() = 0;
+
+ // return if this image has a routine to be called when any image is loaded or unloaded
+ virtual bool hasImageNotification() = 0;
+
+ // return if this image has specified section and set start and length
+ virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length) = 0;
+
+ // given a pointer into an image, find which segment and section it is in
+ virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset) = 0;
+
+ // the image supports being prebound
+ virtual bool isPrebindable() const = 0;
+
+ // the image is prebindable and its prebinding is valid
+ virtual bool usablePrebinding(const LinkContext& context) const = 0;
+
+ // used to implement refernce counting of images
+ void incrementReferenceCount();
+ bool decrementReferenceCount();
+
+ // triggered by DYLD_PRINT_STATISTICS to write info on work done and how fast
+ static void printStatistics(unsigned int imageCount);
+
+ // used with DYLD_IMAGE_SUFFIX
+ static void addSuffix(const char* path, const char* suffix, char* result);
+
+ static uint32_t hash(const char*);
+
+
+ void setPath(const char* path); // only called for images created from memory
+ void setLogicalPath(const char* path);
+
+
+protected:
+ // abstract base class so all constructors protected
+ ImageLoader(const char* path, uint64_t offsetInFat, const struct stat& info);
+ ImageLoader(const char* moduleName);
+ ImageLoader(const ImageLoader&);
+ void operator=(const ImageLoader&);
+
+
+ struct LibraryInfo {
+ uint64_t checksum;
+ uint32_t minVersion;
+ uint32_t maxVersion;
+ };
+
+ struct DependentLibrary {
+ const char* name;
+ ImageLoader* image;
+ LibraryInfo info;
+ bool required;
+ bool checksumMatches;
+ bool isReExported;
+ bool isSubFramework;
+ };
+
+ typedef void (*Initializer)(int argc, const char* argv[], const char* envp[],const char* apple[]);
+ typedef void (*Terminator)(void);
+
+ // To link() an image, its dependent libraries are loaded, it is rebased, bound, and initialized.
+ // These methods do the above, exactly once, and it the right order
+ void recursiveLoadLibraries(const LinkContext& context);
+ void recursiveRebase(const LinkContext& context);
+ void recursiveBind(const LinkContext& context, BindingLaziness bindness);
+ void recursiveImageAnnouncement(const LinkContext& context, std::vector<ImageLoader*>& newImages);
+ void recursiveImageNotification(const LinkContext& context, uint32_t addImageCount);
+ void recursiveInitialization(const LinkContext& context);
+
+ // map any segments this image has into memory and build fSegments
+ // this is called before doGetDependentLibraryCount so if metadata is in segments it is mapped in
+ virtual void instantiateSegments(const uint8_t* fileData) = 0;
+
+ // return how many libraries this image depends on
+ virtual uint32_t doGetDependentLibraryCount() = 0;
+
+ // fill in information about dependent libraries (array length is doGetDependentLibraryCount())
+ virtual void doGetDependentLibraries(DependentLibrary libs[]) = 0;
+
+ // called on images that are libraries, returns info about itself
+ virtual LibraryInfo doGetLibraryInfo() = 0;
+
+ // do any fix ups in this image that depend only on the load address of the image
+ virtual void doRebase(const LinkContext& context) = 0;
+
+ // do any symbolic fix ups in this image
+ virtual void doBind(const LinkContext& context, BindingLaziness bindness) = 0;
+
+ // run any initialization routines in this image
+ virtual void doInitialization(const LinkContext& context) = 0;
+
+ // write prebinding updates to mapped file fileToPrebind
+ virtual void doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind) = 0;
+
+ // return if this image has termination routines
+ virtual bool needsTermination() = 0;
+
+ // support for runtimes in which segments don't have to maintain their relative positions
+ virtual bool segmentsMustSlideTogether() const = 0;
+
+ // built with PIC code and can load at any address
+ virtual bool segmentsCanSlide() const = 0;
+
+ // set how much all segments slide
+ virtual void setSlide(intptr_t slide) = 0;
+
+ // utility routine to map in all segements in fSegments from a file
+ virtual void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+
+ // utility routine to map in all segements in fSegments from a memory image
+ virtual void mapSegments(const void* memoryImage, uint64_t imageLen, const LinkContext& context);
+
+ // returns if all dependent libraries checksum's were as expected and none slide
+ bool allDependentLibrariesAsWhenPreBound() const;
+
+ // in mach-o a child tells it parent to re-export, instead of the other way around...
+ virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const = 0;
+
+ // in mach-o a parent library knows name of sub libraries it re-exports..
+ virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const = 0;
+
+ static uint32_t fgImagesWithUsedPrebinding;
+ static uint32_t fgTotalRebaseFixups;
+ static uint32_t fgTotalBindFixups;
+ static uint32_t fgTotalLazyBindFixups;
+ static uint32_t fgTotalPossibleLazyBindFixups;
+ static uint64_t fgTotalLoadLibrariesTime;
+ static uint64_t fgTotalRebaseTime;
+ static uint64_t fgTotalBindTime;
+ static uint64_t fgTotalNotifyTime;
+ static uint64_t fgTotalInitTime;
+ static uintptr_t fgNextSplitSegAddress;
+ const char* fPath;
+ const char* fLogicalPath; // for ZeroLink - the image which this bundle is part of
+ dev_t fDevice;
+ ino_t fInode;
+ time_t fLastModified;
+ uint64_t fOffsetInFatFile;
+ std::vector<class Segment*> fSegments;
+ DependentLibrary* fLibraries;
+ uint32_t fLibrariesCount;
+ uint32_t fPathHash;
+ uint32_t fReferenceCount;
+ bool fAllLibraryChecksumsAndLoadAddressesMatch;
+ bool fLeaveMapped; // when unloaded, leave image mapped in cause some other code may have pointers into it
+
+
+private:
+ void init(const char* path, uint64_t offsetInFat, dev_t device, ino_t inode, time_t modDate);
+ intptr_t assignSegmentAddresses(const LinkContext& context);
+ void copyAndMap(const char* tempFile, uint8_t** fileToPrebind, uint64_t* fileToPrebindSize);
+
+
+ bool fHideSymbols; // ignore this image's exported symbols when linking other images
+ bool fMatchByInstallName;// look at image's install-path not its load path
+ bool fLibrariesLoaded;
+ bool fBased;
+ bool fBoundAllNonLazy;
+ bool fBoundAllLazy;
+ bool fAnnounced;
+ bool fInitialized;
+ uint16_t fNextAddImageIndex;
+};
+
+
+//
+// Segment is an abstract base class. A segment is a chunk of an executable
+// file that is mapped into memory. Each subclass of ImageLoader typically
+// implements its own concrete subclass of Segment.
+//
+//
+class Segment {
+public:
+ virtual ~Segment() {}
+
+ virtual const ImageLoader* getImage() = 0;
+ virtual const char* getName() = 0;
+ virtual uintptr_t getSize() = 0;
+ virtual uintptr_t getFileSize() = 0;
+ virtual bool hasTrailingZeroFill();
+ virtual uintptr_t getFileOffset() = 0;
+ virtual bool readable() = 0;
+ virtual bool writeable() = 0;
+ virtual bool executable() = 0;
+ virtual bool unaccessible() = 0;
+ virtual bool hasFixUps() = 0;
+ virtual uintptr_t getActualLoadAddress() = 0;
+ virtual uintptr_t getPreferredLoadAddress() = 0;
+ virtual void setUnMapWhenDestructed(bool unmap) = 0;
+
+protected:
+ // abstract base class so all constructors protected
+ Segment() {}
+ Segment(const Segment&);
+ void operator=(const Segment&);
+
+ virtual bool hasPreferredLoadAddress() = 0;
+ //virtual void setActualLoadAddress(uint64_t addr) = 0;
+
+ static bool reserveAddressRange(uintptr_t start, size_t length);
+ static uintptr_t reserveAnAddressRange(size_t length, const ImageLoader::LinkContext& context);
+ static uintptr_t fgNextNonSplitSegAddress;
+
+private:
+ void map(int fd, uint64_t offsetInFatWrapper, intptr_t slide, const ImageLoader::LinkContext& context);
+ void map(const void* memoryImage, intptr_t slide, const ImageLoader::LinkContext& context);
+ void setPermissions();
+ void tempWritable();
+
+ friend class ImageLoader;
+ friend class ImageLoaderMachO;
+};
+
+
+
+#endif
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <mach/shared_memory_server.h>
+#include <mach/mach.h>
+#include <mach/thread_status.h>
+#include <mach-o/loader.h>
+#include <mach-o/reloc.h>
+#include <mach-o/nlist.h>
+#include <sys/sysctl.h>
+#if __ppc__ || __ppc64__
+ #include <mach-o/ppc/reloc.h>
+#endif
+
+#include "ImageLoaderMachO.h"
+#include "mach-o/dyld_gdb.h"
+
+// no header for this yet, rdar://problem/3850825
+extern "C" void sys_icache_invalidate(void *, size_t);
+
+// optimize strcmp for ppc
+#if __ppc__
+ #include <ppc_intrinsics.h>
+#else
+ #define astrcmp(a,b) strcmp(a,b)
+#endif
+
+// relocation_info.r_length field has value 3 for 64-bit executables and value 2 for 32-bit executables
+#if __LP64__
+ #define RELOC_SIZE 3
+ #define LC_SEGMENT_COMMAND LC_SEGMENT_64
+ #define LC_ROUTINES_COMMAND LC_ROUTINES_64
+ struct macho_header : public mach_header_64 {};
+ struct macho_segment_command : public segment_command_64 {};
+ struct macho_section : public section_64 {};
+ struct macho_nlist : public nlist_64 {};
+ struct macho_routines_command : public routines_command_64 {};
+#else
+ #define RELOC_SIZE 2
+ #define LC_SEGMENT_COMMAND LC_SEGMENT
+ #define LC_ROUTINES_COMMAND LC_ROUTINES
+ struct macho_header : public mach_header {};
+ struct macho_segment_command : public segment_command {};
+ struct macho_section : public section {};
+ struct macho_nlist : public nlist {};
+ struct macho_routines_command : public routines_command {};
+#endif
+
+
+uint32_t ImageLoaderMachO::fgHintedBinaryTreeSearchs = 0;
+uint32_t ImageLoaderMachO::fgUnhintedBinaryTreeSearchs = 0;
+
+
+//#define LINKEDIT_USAGE_DEBUG 1
+
+#if LINKEDIT_USAGE_DEBUG
+ #include <set>
+ static std::set<uintptr_t> sLinkEditPageBuckets;
+
+ namespace dyld {
+ extern ImageLoader* findImageContainingAddress(const void* addr);
+ };
+
+ static void noteAccessedLinkEditAddress(const void* addr)
+ {
+ uintptr_t page = ((uintptr_t)addr) & (-4096);
+ sLinkEditPageBuckets.insert(page);
+ fprintf(stderr, "dyld: accessing page 0x%08lX in __LINKEDIT of %s\n", page, dyld::findImageContainingAddress(addr)->getPath());
+ }
+#endif
+
+// only way to share initialization in C++
+void ImageLoaderMachO::init()
+{
+ fMachOData = NULL;
+ fLinkEditBase = NULL;
+ fSymbolTable = NULL;
+ fStrings = NULL;
+ fDynamicInfo = NULL;
+ fSlide = 0;
+ fIsSplitSeg = false;
+ fHasSubLibraries= false;
+ fHasSubUmbrella = false;
+ fDashInit = NULL;
+ fModInitSection = NULL;
+ fModTermSection = NULL;
+ fDATAdyld = NULL;
+ fImageNotifySection = NULL;
+ fTwoLevelHints = NULL;
+ fDylibID = NULL;
+ fReExportThruFramework = NULL;
+ fTextSegmentWithFixups = NULL;
+}
+
+// create image by copying an in-memory mach-o file
+ImageLoaderMachO::ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context)
+ : ImageLoader(moduleName)
+{
+ // clean slate
+ this->init();
+
+ // temporary use this buffer until TEXT is mapped in
+ fMachOData = (const uint8_t*)mh;
+
+ // create segments
+ this->instantiateSegments((const uint8_t*)mh);
+
+ // map segments
+ if ( mh->filetype != MH_EXECUTE )
+ ImageLoader::mapSegments((const void*)mh, len, context);
+
+ // get pointers to interesting things
+ this->parseLoadCmds();
+}
+
+
+// create image by mapping in a mach-o file
+ImageLoaderMachO::ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offsetInFat,
+ uint64_t lenInFat, const struct stat& info, const LinkContext& context)
+ : ImageLoader(path, offsetInFat, info)
+{
+ // clean slate
+ this->init();
+
+ // read load commands
+ const unsigned int dataSize = sizeof(macho_header) + ((macho_header*)firstPage)->sizeofcmds;
+ uint8_t buffer[dataSize];
+ const uint8_t* fileData = firstPage;
+ if ( dataSize > 4096 ) {
+ // only read more if cmds take up more space than first page
+ fileData = buffer;
+ memcpy(buffer, firstPage, 4096);
+ pread(fd, &buffer[4096], dataSize-4096, offsetInFat+4096);
+ }
+
+ // temporary use this buffer until TEXT is mapped in
+ fMachOData = fileData;
+
+ // the meaning of many fields changes in split seg mach-o files
+ fIsSplitSeg = ((((macho_header*)fileData)->flags & MH_SPLIT_SEGS) != 0) && (((macho_header*)fileData)->filetype == MH_DYLIB);
+
+ // create segments
+ this->instantiateSegments(fileData);
+
+ // map segments, except for main executable which is already mapped in by kernel
+ if ( ((macho_header*)fileData)->filetype != MH_EXECUTE )
+ this->mapSegments(fd, offsetInFat, lenInFat, info.st_size, context);
+
+ // get pointers to interesting things
+ this->parseLoadCmds();
+}
+
+
+
+
+void ImageLoaderMachO::instantiateSegments(const uint8_t* fileData)
+{
+ const uint32_t cmd_count = ((macho_header*)fileData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fileData[sizeof(macho_header)];
+
+ // construct Segment object for each LC_SEGMENT cmd and add to list
+ const struct load_command* cmd = cmds;
+ for (unsigned long i = 0; i < cmd_count; ++i) {
+ if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
+ fSegments.push_back(new SegmentMachO((struct macho_segment_command*)cmd, this, fileData));
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+
+
+bool ImageLoaderMachO::segmentsMustSlideTogether() const
+{
+ return true;
+}
+
+bool ImageLoaderMachO::segmentsCanSlide() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->filetype == MH_DYLIB) || (mh->filetype == MH_BUNDLE) );
+}
+
+bool ImageLoaderMachO::isBundle() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( mh->filetype == MH_BUNDLE );
+}
+
+bool ImageLoaderMachO::isDylib() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( mh->filetype == MH_DYLIB );
+}
+
+bool ImageLoaderMachO::forceFlat() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->flags & MH_FORCE_FLAT) != 0 );
+}
+
+bool ImageLoaderMachO::usesTwoLevelNameSpace() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->flags & MH_TWOLEVEL) != 0 );
+}
+
+bool ImageLoaderMachO::isPrebindable() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->flags & MH_PREBOUND) != 0 );
+}
+
+bool ImageLoaderMachO::hasCoalescedExports() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->flags & MH_WEAK_DEFINES) != 0 );
+}
+
+bool ImageLoaderMachO::needsCoalescing() const
+{
+ const macho_header* mh = (macho_header*)fMachOData;
+ return ( (mh->flags & MH_BINDS_TO_WEAK) != 0 );
+}
+
+#if !__LP64__ // split segs not supported for 64-bits
+
+#if 1 // hack until kernel headers and glue are in system
+struct _shared_region_mapping_np {
+ mach_vm_address_t address;
+ mach_vm_size_t size;
+ mach_vm_offset_t file_offset;
+ vm_prot_t max_prot; /* read/write/execute/COW/ZF */
+ vm_prot_t init_prot; /* read/write/execute/COW/ZF */
+};
+struct _shared_region_range_np {
+ mach_vm_address_t address;
+ mach_vm_size_t size;
+};
+
+// Called by dyld.
+// Requests the kernel to map a number of regions from the fd into the
+// shared sections address range (0x90000000-0xAFFFFFFF).
+// If shared_region_make_private_np() has not been called by this process,
+// the file mapped in is seen in the address space of all processes that
+// participate in using the shared region.
+// If shared_region_make_private_np() _has_ been called by this process,
+// the file mapped in is only seen by this process.
+// If the slide parameter is not NULL and then regions cannot be mapped
+// as requested, the kernel will try to map the file in at a different
+// address in the shared region and return the distance slid.
+// If the mapping requesting cannot be fulfilled, returns non-zero.
+static int
+_shared_region_map_file_np(
+ int fd, // file descriptor to map into shared region
+ unsigned int regionCount, // number of entres in array of regions
+ const _shared_region_mapping_np regions[], // the array of regions to map
+ uint64_t* slide) // the amount all regions were slid, NULL means don't attempt to slide
+{
+ //fprintf(stderr, "%s(%i, %u, %8p, %8p)\n", __func__, fd, regionCount, regions, slide);
+ //for ( unsigned int i=0; i < regionCount; ++i) {
+ // fprintf(stderr, "\taddress=0x%08llX, size=0x%08llX\n", regions[i].address, regions[i].size);
+ //}
+ int r = syscall(299, fd, regionCount, regions, slide);
+// if(0 != r)
+// fprintf(stderr, "%s(%i, %u, %8p, %8p) errno=%i (%s)\n", __func__, fd, regionCount, regions, slide, errno, strerror(errno));
+ return r;
+}
+// Called by dyld if shared_region_map_file() fails.
+// Requests the kernel to take this process out of using the shared region.
+// The specified ranges are created as private copies from the shared region for this process.
+static int
+_shared_region_make_private_np(
+ unsigned int rangeCount, // number of entres in array of msrp_range
+ const _shared_region_range_np ranges[]) // the array of shared regions to make private
+{
+ //fprintf(stderr, "%s(%u, %8p)\n", __func__, rangeCount, ranges);
+ int r = syscall(300, rangeCount, ranges);
+// if(0 != r)
+// fprintf(stderr, "%s(%u, %8p) errno=%i (%s)\n", __func__, rangeCount, ranges, errno, strerror(errno));
+ return r;
+}
+#define KERN_SHREG_PRIVATIZABLE 54
+#endif // hack until kernel headers and glue are in system
+
+static uintptr_t sNextAltLoadAddress
+#if __ppc_
+ = 0xC0000000;
+#else
+ = 0;
+#endif
+
+
+static
+bool
+hasSharedRegionMapFile(void)
+{
+ int mib[CTL_MAXNAME];
+ int value = 0;
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_SHREG_PRIVATIZABLE;
+ size = sizeof (int);
+ if (sysctl(mib, 2, &value, &size, NULL, 0) != 0) {
+ value = 0;
+ }
+
+ return 0 != value;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFilePrivateOutside(int fd,
+ uint64_t offsetInFat,
+ uint64_t lenInFat,
+ uint64_t fileLen,
+ const LinkContext& context)
+{
+ const unsigned int segmentCount = fSegments.size();
+ const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+ const unsigned int regionCount = segmentCount+extraZeroFillEntries;
+ _shared_region_mapping_np regions[regionCount];
+ initMappingTable(offsetInFat, regions);
+ int r = -1;
+ // find space somewhere to allocate split seg
+ bool foundRoom = false;
+ vm_size_t biggestDiff = 0;
+ while ( ! foundRoom ) {
+ foundRoom = true;
+ for(unsigned int i=0; i < regionCount; ++i) {
+ vm_address_t addr = sNextAltLoadAddress + regions[i].address - regions[0].address;
+ vm_size_t size = regions[i].size ;
+ r = vm_allocate(mach_task_self(), &addr, size, false /*only this range*/);
+ if ( 0 != r ) {
+ // no room here, deallocate what has succeeded so far
+ for(unsigned int j=0; j < i; ++j) {
+ vm_address_t addr = sNextAltLoadAddress + regions[j].address - regions[0].address;
+ vm_size_t size = regions[j].size ;
+ (void)vm_deallocate(mach_task_self(), addr, size);
+ }
+ sNextAltLoadAddress += 0x00100000; // skip ahead 1MB and try again
+ if ( (sNextAltLoadAddress & 0xF0000000) == 0x90000000 )
+ throw "can't map split seg anywhere";
+ foundRoom = false;
+ break;
+ }
+ vm_size_t high = (regions[i].address + size - regions[0].address) & 0x0FFFFFFF;
+ if ( high > biggestDiff )
+ biggestDiff = high;
+ }
+ }
+
+ // map in each region
+ uintptr_t slide = sNextAltLoadAddress - regions[0].address;
+ this->setSlide(slide);
+ for(unsigned int i=0; i < regionCount; ++i) {
+ if ( (regions[i].init_prot & VM_PROT_ZF) != 0 ) {
+ // do nothing vm_allocate() zero-fills by default
+ }
+ else {
+ void* mmapAddress = (void*)(uintptr_t)(regions[i].address + slide);
+ size_t size = regions[i].size;
+ int protection = 0;
+ if ( regions[i].init_prot & VM_PROT_EXECUTE )
+ protection |= PROT_EXEC;
+ if ( regions[i].init_prot & VM_PROT_READ )
+ protection |= PROT_READ;
+ if ( regions[i].init_prot & VM_PROT_WRITE )
+ protection |= PROT_WRITE;
+ off_t offset = regions[i].file_offset;
+ //fprintf(stderr, "mmap(%p, 0x%08lX, block=0x%08X, %s\n", mmapAddress, size, biggestDiff, fPath);
+ mmapAddress = mmap(mmapAddress, size, protection, MAP_FILE | MAP_FIXED | MAP_PRIVATE, fd, offset);
+ if ( mmapAddress == ((void*)(-1)) )
+ throw "mmap error";
+ }
+ }
+ // set so next maps right after this one
+ sNextAltLoadAddress += biggestDiff;
+ sNextAltLoadAddress = (sNextAltLoadAddress + 4095) & (-4096);
+
+ // logging
+ if ( context.verboseMapping ) {
+ fprintf(stderr, "dyld: Mapping split-seg outside shared region, slid by 0x%08lX %s\n", this->fSlide, this->getPath());
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ const _shared_region_mapping_np* entry = ®ions[entryIndex];
+ if ( (entry->init_prot & VM_PROT_ZF) == 0 )
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+ if ( entryIndex < (regionCount-1) ) {
+ const _shared_region_mapping_np* nextEntry = ®ions[entryIndex+1];
+ if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+ uint64_t segOffset = nextEntry->address - entry->address;
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX (zerofill)\n",
+ seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+ ++entryIndex;
+ }
+ }
+ }
+ }
+
+ return r;
+}
+
+
+void ImageLoaderMachO::mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+ enum SharedRegionState
+ {
+ kSharedRegionStartState = 0,
+ kSharedRegionLoadFileState,
+ kSharedRegionMapFileState,
+ kSharedRegionMapFilePrivateState,
+ kSharedRegionMapFilePrivateOutsideState,
+ };
+ static SharedRegionState sSharedRegionState = kSharedRegionStartState;
+
+ // non-split segment libraries handled by super class
+ if ( !fIsSplitSeg )
+ return ImageLoader::mapSegments(fd, offsetInFat, lenInFat, fileLen, context);
+
+ if ( kSharedRegionStartState == sSharedRegionState ) {
+ if ( hasSharedRegionMapFile() ) {
+ if ( (context.sharedRegionMode == kUsePrivateSharedRegion) || context.slideAndPackDylibs ) {
+ sharedRegionMakePrivate(context);
+ sSharedRegionState = kSharedRegionMapFilePrivateState;
+ }
+ else if ( context.sharedRegionMode == kDontUseSharedRegion ) {
+ sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+ }
+ else {
+ sSharedRegionState = kSharedRegionMapFileState;
+ }
+ }
+ else {
+ sSharedRegionState = kSharedRegionLoadFileState;
+ }
+ }
+
+ if ( kSharedRegionLoadFileState == sSharedRegionState ) {
+ if ( 0 != sharedRegionLoadFile(fd, offsetInFat, lenInFat, fileLen, context) ) {
+ sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+ }
+ }
+ else
+ if ( kSharedRegionMapFileState == sSharedRegionState ) {
+ if ( 0 != sharedRegionMapFile(fd, offsetInFat, lenInFat, fileLen, context) ) {
+ sharedRegionMakePrivate(context);
+ sSharedRegionState = kSharedRegionMapFilePrivateState;
+ }
+ }
+
+ if ( kSharedRegionMapFilePrivateState == sSharedRegionState ) {
+ if ( 0 != sharedRegionMapFilePrivate(fd, offsetInFat, lenInFat, fileLen, context) ) {
+ sSharedRegionState = kSharedRegionMapFilePrivateOutsideState;
+ }
+ }
+
+ if ( kSharedRegionMapFilePrivateOutsideState == sSharedRegionState ) {
+ if ( 0 != sharedRegionMapFilePrivateOutside(fd, offsetInFat, lenInFat, fileLen, context) ) {
+ throw "mapping error";
+ }
+ }
+}
+
+unsigned int
+ImageLoaderMachO::getExtraZeroFillEntriesCount()
+{
+ // calculate mapping entries
+ const unsigned int segmentCount = fSegments.size();
+ unsigned int extraZeroFillEntries = 0;
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ if ( seg->hasTrailingZeroFill() )
+ ++extraZeroFillEntries;
+ }
+
+ return extraZeroFillEntries;
+}
+
+void
+ImageLoaderMachO::initMappingTable(uint64_t offsetInFat,
+ _shared_region_mapping_np *mappingTable)
+{
+ unsigned int segmentCount = fSegments.size();
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+ entry->address = seg->getActualLoadAddress();
+ entry->size = seg->getFileSize();
+ entry->file_offset = seg->getFileOffset() + offsetInFat;
+ entry->init_prot = VM_PROT_NONE;
+ if ( !seg->unaccessible() ) {
+ if ( seg->executable() )
+ entry->init_prot |= VM_PROT_EXECUTE;
+ if ( seg->readable() )
+ entry->init_prot |= VM_PROT_READ;
+ if ( seg->writeable() )
+ entry->init_prot |= VM_PROT_WRITE | VM_PROT_COW;
+ }
+ entry->max_prot = entry->init_prot;
+ if ( seg->hasTrailingZeroFill() ) {
+ _shared_region_mapping_np* zfentry = &mappingTable[++entryIndex];
+ zfentry->address = entry->address + seg->getFileSize();
+ zfentry->size = seg->getSize() - seg->getFileSize();
+ zfentry->file_offset = 0;
+ zfentry->init_prot = entry->init_prot | VM_PROT_COW | VM_PROT_ZF;
+ zfentry->max_prot = zfentry->init_prot;
+ }
+ }
+}
+
+int
+ImageLoaderMachO::sharedRegionMakePrivate(const LinkContext& context)
+{
+ if ( context.verboseMapping )
+ fprintf(stderr, "dyld: making shared regions private\n");
+
+ // shared mapping failed, so make private copy of shared region and try mapping private
+ RegionsVector allRegions;
+ context.getAllMappedRegions(allRegions);
+ std::vector<_shared_region_range_np> splitSegRegions;
+ const unsigned int allRegiontCount = allRegions.size();
+ for(unsigned int i=0; i < allRegiontCount; ++i){
+ MappedRegion region = allRegions[i];
+ uint8_t highByte = region.address >> 28;
+ if ( (highByte == 9) || (highByte == 0xA) ) {
+ _shared_region_range_np splitRegion;
+ splitRegion.address = region.address;
+ splitRegion.size = region.size;
+ splitSegRegions.push_back(splitRegion);
+ }
+ }
+ int result = _shared_region_make_private_np(splitSegRegions.size(), &splitSegRegions[0]);
+ // notify gdb or other lurkers that this process is no longer using the shared region
+ dyld_all_image_infos.processDetachedFromSharedRegion = true;
+ return result;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFile(int fd,
+ uint64_t offsetInFat,
+ uint64_t lenInFat,
+ uint64_t fileLen,
+ const LinkContext& context)
+{
+ // build table of segments to map
+ const unsigned int segmentCount = fSegments.size();
+ const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+ const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+ _shared_region_mapping_np mappingTable[mappingTableCount];
+ initMappingTable(offsetInFat, mappingTable);
+// uint64_t slide;
+ uint64_t *slidep = NULL;
+
+ // try to map it in shared
+ int r = _shared_region_map_file_np(fd, mappingTableCount, mappingTable, slidep);
+ if ( 0 == r ) {
+ if(NULL != slidep && 0 != *slidep) {
+ // update with actual load addresses
+ }
+ if ( context.verboseMapping ) {
+ fprintf(stderr, "dyld: Mapping split-seg shared %s\n", this->getPath());
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ const _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+ if ( (entry->init_prot & VM_PROT_ZF) == 0 )
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+ if ( entryIndex < (mappingTableCount-1) ) {
+ const _shared_region_mapping_np* nextEntry = &mappingTable[entryIndex+1];
+ if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+ uint64_t segOffset = nextEntry->address - entry->address;
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+ ++entryIndex;
+ }
+ }
+ }
+ }
+ }
+ return r;
+}
+
+int
+ImageLoaderMachO::sharedRegionMapFilePrivate(int fd,
+ uint64_t offsetInFat,
+ uint64_t lenInFat,
+ uint64_t fileLen,
+ const LinkContext& context)
+{
+ const unsigned int segmentCount = fSegments.size();
+
+ // adjust base address of segments to pack next to last dylib
+ if ( context.slideAndPackDylibs ) {
+ uintptr_t lowestReadOnly = (uintptr_t)(-1);
+ uintptr_t lowestWritable = (uintptr_t)(-1);
+ for(unsigned int segIndex=0; segIndex < segmentCount; ++segIndex){
+ Segment* seg = fSegments[segIndex];
+ uintptr_t segEnd = seg->getActualLoadAddress();
+ if ( seg->writeable() ) {
+ if ( segEnd < lowestWritable )
+ lowestWritable = segEnd;
+ }
+ else {
+ if ( segEnd < lowestReadOnly )
+ lowestReadOnly = segEnd;
+ }
+ }
+ uintptr_t baseAddress;
+ if ( lowestWritable - 256*1024*1024 < lowestReadOnly )
+ baseAddress = lowestWritable - 256*1024*1024;
+ else
+ baseAddress = lowestReadOnly;
+ // record that we want dylb slid to fgNextSplitSegAddress
+ this->setSlide(fgNextSplitSegAddress - baseAddress);
+ }
+
+ // build table of segments to map
+ const unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+ const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+ _shared_region_mapping_np mappingTable[mappingTableCount];
+ initMappingTable(offsetInFat, mappingTable);
+ uint64_t slide = 0;
+
+ // try map it in privately (don't allow sliding if we pre-calculated the load address to pack dylibs)
+ int r = _shared_region_map_file_np(fd, mappingTableCount, mappingTable, context.slideAndPackDylibs ? NULL : &slide);
+ if ( 0 == r ) {
+ if ( 0 != slide ) {
+ slide = (slide) & (-4096); // round down to page boundary
+ this->setSlide(slide);
+ }
+ if ( context.verboseMapping ) {
+ if ( slide == 0 )
+ fprintf(stderr, "dyld: Mapping split-seg un-shared %s\n", this->getPath());
+ else
+ fprintf(stderr, "dyld: Mapping split-seg un-shared slid by 0x%08llX %s\n", slide, this->getPath());
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ const _shared_region_mapping_np* entry = &mappingTable[entryIndex];
+ if ( (entry->init_prot & VM_PROT_ZF) == 0 )
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+ if ( entryIndex < (mappingTableCount-1) ) {
+ const _shared_region_mapping_np* nextEntry = &mappingTable[entryIndex+1];
+ if ( (nextEntry->init_prot & VM_PROT_ZF) != 0 ) {
+ uint64_t segOffset = nextEntry->address - entry->address;
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX (zerofill)\n",
+ seg->getName(), (uintptr_t)(seg->getActualLoadAddress() + segOffset), (uintptr_t)(seg->getActualLoadAddress() + segOffset + nextEntry->size - 1));
+ ++entryIndex;
+ }
+ }
+ }
+ }
+ if ( context.slideAndPackDylibs ) {
+ // calculate where next split-seg dylib can load
+ uintptr_t largestReadOnly = 0;
+ uintptr_t largestWritable = 0;
+ for (unsigned int segIndex=0; segIndex < segmentCount; ++segIndex) {
+ Segment* seg = fSegments[segIndex];
+ uintptr_t segEnd = seg->getActualLoadAddress()+seg->getSize();
+ segEnd = (segEnd+4095) & (-4096); // page align
+ if ( seg->writeable() ) {
+ if ( segEnd > largestWritable )
+ largestWritable = segEnd;
+ }
+ else {
+ if ( segEnd > largestReadOnly )
+ largestReadOnly = segEnd;
+ }
+ }
+ if ( largestWritable - 256*1024*1024 > largestReadOnly )
+ fgNextSplitSegAddress = largestWritable - 256*1024*1024;
+ else
+ fgNextSplitSegAddress = largestReadOnly;
+ }
+ }
+ if ( context.slideAndPackDylibs && (r != 0) )
+ throw "can't rebase split-seg dylib";
+
+ return r;
+}
+
+
+int
+ImageLoaderMachO::sharedRegionLoadFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context)
+{
+
+ // map in split segment file at random address, then tell kernel to share it
+ void* loadAddress = 0;
+ loadAddress = mmap(NULL, fileLen, PROT_READ, MAP_FILE, fd, 0);
+ if ( loadAddress == ((void*)(-1)) )
+ throw "mmap error";
+
+ // calculate mapping entries
+ const unsigned int segmentCount = fSegments.size();
+ unsigned int extraZeroFillEntries = getExtraZeroFillEntriesCount();
+
+ // build table of segments to map
+ const unsigned int mappingTableCount = segmentCount+extraZeroFillEntries;
+ const uintptr_t baseAddress = fSegments[0]->getPreferredLoadAddress();
+ sf_mapping mappingTable[mappingTableCount];
+ initMappingTable(offsetInFat, mappingTable, baseAddress);
+
+
+ // use load_shared_file() to map all segments at once
+ int flags = 0; // might need to set NEW_LOCAL_SHARED_REGIONS on first use
+ static bool firstTime = true;
+ if ( firstTime ) {
+ // when NEW_LOCAL_SHARED_REGIONS bit is set, this process will get is own shared region
+ // this is used by Xcode to prevent development libraries from polluting the global shared segment
+ if ( context.sharedRegionMode == kUsePrivateSharedRegion )
+ flags |= NEW_LOCAL_SHARED_REGIONS;
+ firstTime = false;
+ }
+
+ caddr_t base_address = (caddr_t)baseAddress;
+ kern_return_t r;
+ r = load_shared_file( (char*)fPath, // path of file to map shared
+ (char*)loadAddress, // beginning of local copy of sharable pages in file
+ fileLen, // end of shareable pages in file
+ &base_address, // beginning of address range to map
+ mappingTableCount, // number of entres in array of sf_mapping
+ mappingTable, // the array of sf_mapping
+ &flags); // in/out flags
+ if ( 0 != r ) {
+ // try again but tell kernel it is ok to slide
+ flags |= ALTERNATE_LOAD_SITE;
+ r = load_shared_file((char*)fPath,(char*)loadAddress, fileLen, &base_address,
+ mappingTableCount, mappingTable, &flags);
+ }
+
+ // unmap file from random address now that they are (hopefully) mapped into the shared region
+ munmap(loadAddress, fileLen);
+
+ if ( 0 == r ) {
+ if ( base_address != (caddr_t)baseAddress )
+ this->setSlide((uintptr_t)base_address - baseAddress);
+ if ( context.verboseMapping ) {
+ if ( base_address != (caddr_t)baseAddress )
+ fprintf(stderr, "dyld: Mapping split-seg load_shared_alt_region %s\n", this->getPath());
+ else
+ fprintf(stderr, "dyld: Mapping split-seg load_shared %s\n", this->getPath());
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ const sf_mapping* entry = &mappingTable[entryIndex];
+ if ( (entry->protection & VM_PROT_ZF) == 0 )
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), seg->getActualLoadAddress(), seg->getActualLoadAddress()+seg->getFileSize()-1);
+ if ( entryIndex < (mappingTableCount-1) ) {
+ const sf_mapping* nextEntry = &mappingTable[entryIndex+1];
+ if ( (nextEntry->protection & VM_PROT_ZF) != 0 ) {
+ fprintf(stderr, "%18s at 0x%08lX->0x%08lX\n",
+ seg->getName(), (uintptr_t)(nextEntry->mapping_offset + base_address), (uintptr_t)(nextEntry->mapping_offset + base_address + nextEntry->size - 1));
+ ++entryIndex;
+ }
+ }
+ }
+ }
+ }
+ return r;
+}
+void
+ImageLoaderMachO::initMappingTable(uint64_t offsetInFat,
+ sf_mapping *mappingTable,
+ uintptr_t baseAddress)
+{
+ unsigned int segmentCount = fSegments.size();
+ for(unsigned int segIndex=0,entryIndex=0; segIndex < segmentCount; ++segIndex, ++entryIndex){
+ Segment* seg = fSegments[segIndex];
+ sf_mapping* entry = &mappingTable[entryIndex];
+ entry->mapping_offset = seg->getPreferredLoadAddress() - baseAddress;
+ entry->size = seg->getFileSize();
+ entry->file_offset = seg->getFileOffset() + offsetInFat;
+ entry->protection = VM_PROT_NONE;
+ if ( !seg->unaccessible() ) {
+ if ( seg->executable() )
+ entry->protection |= VM_PROT_EXECUTE;
+ if ( seg->readable() )
+ entry->protection |= VM_PROT_READ;
+ if ( seg->writeable() )
+ entry->protection |= VM_PROT_WRITE | VM_PROT_COW;
+ }
+
+ entry->cksum = 0;
+ if ( seg->hasTrailingZeroFill() ) {
+ sf_mapping* zfentry = &mappingTable[++entryIndex];
+ zfentry->mapping_offset = entry->mapping_offset + seg->getFileSize();
+ zfentry->size = seg->getSize() - seg->getFileSize();
+ zfentry->file_offset = 0;
+ zfentry->protection = entry->protection | VM_PROT_COW | VM_PROT_ZF;
+ zfentry->cksum = 0;
+ }
+ }
+}
+
+#endif // !__LP64__ split segs not supported for 64-bits
+
+
+void ImageLoaderMachO::setSlide(intptr_t slide)
+{
+ fSlide = slide;
+}
+
+void ImageLoaderMachO::parseLoadCmds()
+{
+ // now that segments are mapped in, get real fMachOData, fLinkEditBase, and fSlide
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ // set up pointer to __LINKEDIT segment
+ if ( strcmp(seg->getName(),"__LINKEDIT") == 0 )
+ fLinkEditBase = (uint8_t*)(seg->getActualLoadAddress() - seg->getFileOffset());
+ // __TEXT segment always starts at beginning of file and contains mach_header and load commands
+ if ( strcmp(seg->getName(),"__TEXT") == 0 ) {
+ if ( seg->hasFixUps() )
+ fTextSegmentWithFixups = (SegmentMachO*)seg;
+ }
+ // some segment always starts at beginning of file and contains mach_header and load commands
+ if ( (seg->getFileOffset() == 0) && (seg->getFileSize() != 0) ) {
+ fMachOData = (uint8_t*)(seg->getActualLoadAddress());
+ }
+ }
+
+ // walk load commands (mapped in at start of __TEXT segment)
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SYMTAB:
+ {
+ const struct symtab_command* symtab = (struct symtab_command*)cmd;
+ fStrings = (const char*)&fLinkEditBase[symtab->stroff];
+ fSymbolTable = (struct macho_nlist*)(&fLinkEditBase[symtab->symoff]);
+ }
+ break;
+ case LC_DYSYMTAB:
+ fDynamicInfo = (struct dysymtab_command*)cmd;
+ break;
+ case LC_SUB_UMBRELLA:
+ fHasSubUmbrella = true;
+ break;
+ case LC_SUB_FRAMEWORK:
+ {
+ const struct sub_framework_command* subf = (struct sub_framework_command*)cmd;
+ fReExportThruFramework = (char*)cmd + subf->umbrella.offset;
+ }
+ break;
+ case LC_SUB_LIBRARY:
+ fHasSubLibraries = true;
+ break;
+ case LC_ROUTINES_COMMAND:
+ fDashInit = (struct macho_routines_command*)cmd;
+ break;
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ const bool isDataSeg = (strcmp(seg->segname, "__DATA") == 0);
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ const uint8_t type = sect->flags & SECTION_TYPE;
+ if ( type == S_MOD_INIT_FUNC_POINTERS )
+ fModInitSection = sect;
+ else if ( type == S_MOD_TERM_FUNC_POINTERS )
+ fModTermSection = sect;
+ else if ( isDataSeg && (strcmp(sect->sectname, "__dyld") == 0) )
+ fDATAdyld = sect;
+ else if ( isDataSeg && (strcmp(sect->sectname, "__image_notify") == 0) )
+ fImageNotifySection = sect;
+ }
+ }
+ break;
+ case LC_TWOLEVEL_HINTS:
+ fTwoLevelHints = (struct twolevel_hints_command*)cmd;
+ break;
+ case LC_ID_DYLIB:
+ {
+ fDylibID = (struct dylib_command*)cmd;
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+
+
+
+const char* ImageLoaderMachO::getInstallPath() const
+{
+ if ( fDylibID != NULL ) {
+ return (char*)fDylibID + fDylibID->dylib.name.offset;
+ }
+ return NULL;
+}
+
+// test if this image is re-exported through parent (the image that loaded this one)
+bool ImageLoaderMachO::isSubframeworkOf(const LinkContext& context, const ImageLoader* parent) const
+{
+ if ( fReExportThruFramework != NULL ) {
+ // need to match LC_SUB_FRAMEWORK string against the leaf name of the install location of parent...
+ const char* parentInstallPath = parent->getInstallPath();
+ if ( parentInstallPath != NULL ) {
+ const char* lastSlash = strrchr(parentInstallPath, '/');
+ if ( lastSlash != NULL ) {
+ if ( strcmp(&lastSlash[1], fReExportThruFramework) == 0 )
+ return true;
+ if ( context.imageSuffix != NULL ) {
+ // when DYLD_IMAGE_SUFFIX is used, lastSlash string needs imageSuffix removed from end
+ char reexportAndSuffix[strlen(context.imageSuffix)+strlen(fReExportThruFramework)+1];
+ strcpy(reexportAndSuffix, fReExportThruFramework);
+ strcat(reexportAndSuffix, context.imageSuffix);
+ if ( strcmp(&lastSlash[1], reexportAndSuffix) == 0 )
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+
+// test if child is re-exported
+bool ImageLoaderMachO::hasSubLibrary(const LinkContext& context, const ImageLoader* child) const
+{
+ if ( fHasSubLibraries ) {
+ // need to match LC_SUB_LIBRARY string against the leaf name (without extension) of the install location of child...
+ const char* childInstallPath = child->getInstallPath();
+ if ( childInstallPath != NULL ) {
+ const char* lastSlash = strrchr(childInstallPath, '/');
+ if ( lastSlash != NULL ) {
+ const char* firstDot = strchr(lastSlash, '.');
+ int len;
+ if ( firstDot == NULL )
+ len = strlen(lastSlash);
+ else
+ len = firstDot-lastSlash-1;
+ char childLeafName[len+1];
+ strncpy(childLeafName, &lastSlash[1], len);
+ childLeafName[len] = '\0';
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SUB_LIBRARY:
+ {
+ const struct sub_library_command* lib = (struct sub_library_command*)cmd;
+ const char* aSubLibName = (char*)cmd + lib->sub_library.offset;
+ if ( strcmp(aSubLibName, childLeafName) == 0 )
+ return true;
+ if ( context.imageSuffix != NULL ) {
+ // when DYLD_IMAGE_SUFFIX is used, childLeafName string needs imageSuffix removed from end
+ char aSubLibNameAndSuffix[strlen(context.imageSuffix)+strlen(aSubLibName)+1];
+ strcpy(aSubLibNameAndSuffix, aSubLibName);
+ strcat(aSubLibNameAndSuffix, context.imageSuffix);
+ if ( strcmp(aSubLibNameAndSuffix, childLeafName) == 0 )
+ return true;
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ }
+ }
+ }
+ if ( fHasSubUmbrella ) {
+ // need to match LC_SUB_UMBRELLA string against the leaf name of install location of child...
+ const char* childInstallPath = child->getInstallPath();
+ if ( childInstallPath != NULL ) {
+ const char* lastSlash = strrchr(childInstallPath, '/');
+ if ( lastSlash != NULL ) {
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SUB_UMBRELLA:
+ {
+ const struct sub_umbrella_command* um = (struct sub_umbrella_command*)cmd;
+ const char* aSubUmbrellaName = (char*)cmd + um->sub_umbrella.offset;
+ if ( strcmp(aSubUmbrellaName, &lastSlash[1]) == 0 )
+ return true;
+ if ( context.imageSuffix != NULL ) {
+ // when DYLD_IMAGE_SUFFIX is used, lastSlash string needs imageSuffix removed from end
+ char umbrellaAndSuffix[strlen(context.imageSuffix)+strlen(aSubUmbrellaName)+1];
+ strcpy(umbrellaAndSuffix, aSubUmbrellaName);
+ strcat(umbrellaAndSuffix, context.imageSuffix);
+ if ( strcmp(umbrellaAndSuffix, &lastSlash[1]) == 0 )
+ return true;
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ }
+ }
+ }
+ return false;
+}
+
+
+void* ImageLoaderMachO::getMain() const
+{
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (unsigned long i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_UNIXTHREAD:
+ {
+ #if __ppc__
+ const ppc_thread_state_t* registers = (ppc_thread_state_t*)(((char*)cmd) + 16);
+ return (void*)registers->srr0;
+ #elif __ppc64__
+ const ppc_thread_state64_t* registers = (ppc_thread_state64_t*)(((char*)cmd) + 16);
+ return (void*)registers->srr0;
+ #elif __i386__
+ const i386_thread_state_t* registers = (i386_thread_state_t*)(((char*)cmd) + 16);
+ return (void*)registers->eip;
+ #else
+ #warning need processor specific code
+ #endif
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ return NULL;
+}
+
+
+uint32_t ImageLoaderMachO::doGetDependentLibraryCount()
+{
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ uint32_t count = 0;
+ const struct load_command* cmd = cmds;
+ for (unsigned long i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_LOAD_DYLIB:
+ case LC_LOAD_WEAK_DYLIB:
+ ++count;
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ return count;
+}
+
+void ImageLoaderMachO::doGetDependentLibraries(DependentLibrary libs[])
+{
+ uint32_t index = 0;
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (unsigned long i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_LOAD_DYLIB:
+ case LC_LOAD_WEAK_DYLIB:
+ {
+ const struct dylib_command* dylib = (struct dylib_command*)cmd;
+ DependentLibrary* lib = &libs[index++];
+ lib->name = (char*)cmd + dylib->dylib.name.offset;
+ //lib->name = strdup((char*)cmd + dylib->dylib.name.offset);
+ lib->image = NULL;
+ lib->info.checksum = dylib->dylib.timestamp;
+ lib->info.minVersion = dylib->dylib.compatibility_version;
+ lib->info.maxVersion = dylib->dylib.current_version;
+ lib->required = (cmd->cmd == LC_LOAD_DYLIB);
+ lib->checksumMatches = false;
+ lib->isReExported = false;
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+ImageLoader::LibraryInfo ImageLoaderMachO::doGetLibraryInfo()
+{
+ LibraryInfo info;
+ if ( fDylibID != NULL ) {
+ info.minVersion = fDylibID->dylib.compatibility_version;
+ info.maxVersion = fDylibID->dylib.current_version;
+ info.checksum = fDylibID->dylib.timestamp;
+ }
+ else {
+ info.minVersion = 0;
+ info.maxVersion = 0;
+ info.checksum = 0;
+ }
+ return info;
+}
+
+
+uintptr_t ImageLoaderMachO::getRelocBase()
+{
+ if ( fIsSplitSeg ) {
+ // in split segment libraries r_address is offset from first writable segment
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i){
+ Segment* seg = fSegments[i];
+ if ( seg->writeable() ) {
+ return seg->getActualLoadAddress();
+ }
+ }
+ }
+
+ // in non-split segment libraries r_address is offset from first segment
+ return fSegments[0]->getActualLoadAddress();
+}
+
+#if __ppc__
+static inline void otherRelocsPPC(uintptr_t* locationToFix, uint8_t relocationType, uint16_t otherHalf, uintptr_t slide)
+{
+ // low 16 bits of 32-bit ppc instructions need fixing
+ struct ppcInstruction { uint16_t opcode; int16_t immediateValue; };
+ ppcInstruction* instruction = (ppcInstruction*)locationToFix;
+ //uint32_t before = *((uint32_t*)locationToFix);
+ switch ( relocationType )
+ {
+ case PPC_RELOC_LO16:
+ instruction->immediateValue = ((otherHalf << 16) | instruction->immediateValue) + slide;
+ break;
+ case PPC_RELOC_HI16:
+ instruction->immediateValue = ((((instruction->immediateValue << 16) | otherHalf) + slide) >> 16);
+ break;
+ case PPC_RELOC_HA16:
+ int16_t signedOtherHalf = (int16_t)(otherHalf & 0xffff);
+ uint32_t temp = (instruction->immediateValue << 16) + signedOtherHalf + slide;
+ if ( (temp & 0x00008000) != 0 )
+ temp += 0x00008000;
+ instruction->immediateValue = temp >> 16;
+ }
+ //uint32_t after = *((uint32_t*)locationToFix);
+ //fprintf(stderr, "dyld: ppc fixup %0p type %d from 0x%08X to 0x%08X\n", locationToFix, relocationType, before, after);
+}
+#endif
+
+void ImageLoaderMachO::doRebase(const LinkContext& context)
+{
+ // if prebound and loaded at prebound address, then no need to rebase
+ // Note: you might think that the check for allDependentLibrariesAsWhenPreBound() is not needed
+ // but it is. If a dependent library changed, this image's lazy pointers into that library
+ // need to be updated (reset back to lazy binding handler). That work is done most easily
+ // here because there is a PPC_RELOC_PB_LA_PTR reloc record for each lazy pointer.
+ if ( this->usablePrebinding(context) && this->usesTwoLevelNameSpace() ) {
+ // skip rebasing cause prebound and prebinding not disabled
+ ++fgImagesWithUsedPrebinding; // bump totals for statistics
+ return;
+ }
+
+ // print why prebinding was not used
+ if ( context.verbosePrebinding ) {
+ if ( !this->isPrebindable() ) {
+ fprintf(stderr, "dyld: image not prebound, so could not use prebinding in %s\n", this->getPath());
+ }
+ else if ( fSlide != 0 ) {
+ fprintf(stderr, "dyld: image slid, so could not use prebinding in %s\n", this->getPath());
+ }
+ else if ( !this->allDependentLibrariesAsWhenPreBound() ) {
+ fprintf(stderr, "dyld: dependent libraries changed, so could not use prebinding in %s\n", this->getPath());
+ }
+ else if ( !this->usesTwoLevelNameSpace() ){
+ fprintf(stderr, "dyld: image uses flat-namespace so, parts of prebinding ignored %s\n", this->getPath());
+ }
+ else {
+ fprintf(stderr, "dyld: environment variable disabled use of prebinding in %s\n", this->getPath());
+ }
+ }
+
+ // if there are __TEXT fixups, temporarily make __TEXT writable
+ if ( fTextSegmentWithFixups != NULL )
+ fTextSegmentWithFixups->tempWritable();
+
+ // cache this value that is used in the following loop
+ register const uintptr_t slide = this->fSlide;
+
+ // loop through all local (internal) relocation records
+ const uintptr_t relocBase = this->getRelocBase();
+ const relocation_info* const relocsStart = (struct relocation_info*)(&fLinkEditBase[fDynamicInfo->locreloff]);
+ const relocation_info* const relocsEnd = &relocsStart[fDynamicInfo->nlocrel];
+ for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+ if ( (reloc->r_address & R_SCATTERED) == 0 ) {
+ if ( reloc->r_symbolnum == R_ABS ) {
+ // ignore absolute relocations
+ }
+ else if (reloc->r_length == RELOC_SIZE) {
+ switch(reloc->r_type) {
+ case GENERIC_RELOC_VANILLA:
+ *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+ break;
+ #if __ppc__
+ case PPC_RELOC_HI16:
+ case PPC_RELOC_LO16:
+ case PPC_RELOC_HA16:
+ // some tools leave object file relocations in linked images
+ otherRelocsPPC((uintptr_t*)(reloc->r_address + relocBase), reloc->r_type, reloc[1].r_address, slide);
+ ++reloc; // these relocations come in pairs, skip next
+ break;
+ #endif
+ default:
+ throw "unknown local relocation type";
+ }
+ }
+ else {
+ throw "bad local relocation length";
+ }
+ }
+ else {
+ const struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+ if (sreloc->r_length == RELOC_SIZE) {
+ uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
+ switch(sreloc->r_type) {
+ case GENERIC_RELOC_VANILLA:
+ *locationToFix += slide;
+ break;
+ #if __ppc__ || __ppc64__
+ case PPC_RELOC_PB_LA_PTR:
+ // should only see these in prebound images, and we got here so prebinding is being ignored
+ *locationToFix = sreloc->r_value + slide;
+ break;
+ #endif
+ #if __ppc__
+ case PPC_RELOC_HI16:
+ case PPC_RELOC_LO16:
+ case PPC_RELOC_HA16:
+ // Metrowerks compiler sometimes leaves object file relocations in linked images???
+ ++reloc; // these relocations come in pairs, get next one
+ otherRelocsPPC(locationToFix, sreloc->r_type, reloc->r_address, slide);
+ break;
+ #endif
+ #if __i386__
+ case GENERIC_RELOC_PB_LA_PTR:
+ // should only see these in prebound images, and we got here so prebinding is being ignored
+ *locationToFix = sreloc->r_value + slide;
+ break;
+ #endif
+ default:
+ throw "unknown local scattered relocation type";
+ }
+ }
+ else {
+ throw "bad local scattered relocation length";
+ }
+ }
+ }
+
+ // if there were __TEXT fixups, restore write protection
+ if ( fTextSegmentWithFixups != NULL ) {
+ fTextSegmentWithFixups->setPermissions();
+ sys_icache_invalidate((void*)fTextSegmentWithFixups->getActualLoadAddress(), fTextSegmentWithFixups->getSize());
+ }
+
+ // update stats
+ fgTotalRebaseFixups += fDynamicInfo->nlocrel;
+}
+
+
+const struct macho_nlist* ImageLoaderMachO::binarySearchWithToc(const char* key, const char stringPool[], const struct macho_nlist symbols[],
+ const struct dylib_table_of_contents toc[], uint32_t symbolCount, uint32_t hintIndex)
+{
+ int32_t high = symbolCount-1;
+ int32_t mid = hintIndex;
+
+ // handle out of range hint
+ if ( mid >= (int32_t)symbolCount ) {
+ mid = symbolCount/2;
+ ++ImageLoaderMachO::fgUnhintedBinaryTreeSearchs;
+ }
+ else {
+ ++ImageLoaderMachO::fgHintedBinaryTreeSearchs;
+ }
+
+ for (int32_t low = 0; low <= high; mid = (low+high)/2) {
+ const uint32_t index = toc[mid].symbol_index;
+ const struct macho_nlist* pivot = &symbols[index];
+ const char* pivotStr = &stringPool[pivot->n_un.n_strx];
+#if LINKEDIT_USAGE_DEBUG
+ noteAccessedLinkEditAddress(&toc[mid]);
+ noteAccessedLinkEditAddress(pivot);
+ noteAccessedLinkEditAddress(pivotStr);
+#endif
+ int cmp = astrcmp(key, pivotStr);
+ if ( cmp == 0 )
+ return pivot;
+ if ( cmp > 0 ) {
+ // key > pivot
+ low = mid + 1;
+ }
+ else {
+ // key < pivot
+ high = mid - 1;
+ }
+ }
+ return NULL;
+}
+
+const struct macho_nlist* ImageLoaderMachO::binarySearch(const char* key, const char stringPool[], const struct macho_nlist symbols[], uint32_t symbolCount)
+{
+ ++ImageLoaderMachO::fgUnhintedBinaryTreeSearchs;
+ const struct macho_nlist* base = symbols;
+ for (uint32_t n = symbolCount; n > 0; n /= 2) {
+ const struct macho_nlist* pivot = &base[n/2];
+ const char* pivotStr = &stringPool[pivot->n_un.n_strx];
+#if LINKEDIT_USAGE_DEBUG
+ noteAccessedLinkEditAddress(pivot);
+ noteAccessedLinkEditAddress(pivotStr);
+#endif
+ int cmp = astrcmp(key, pivotStr);
+ if ( cmp == 0 )
+ return pivot;
+ if ( cmp > 0 ) {
+ // key > pivot
+ // move base to symbol after pivot
+ base = &pivot[1];
+ --n;
+ }
+ else {
+ // key < pivot
+ // keep same base
+ }
+ }
+ return NULL;
+}
+
+const ImageLoader::Symbol* ImageLoaderMachO::findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const
+{
+ const struct macho_nlist* sym = NULL;
+ const struct twolevel_hint* theHint = (struct twolevel_hint*)hint;
+ if ( fDynamicInfo->tocoff == 0 )
+ sym = binarySearch(name, fStrings, &fSymbolTable[fDynamicInfo->iextdefsym], fDynamicInfo->nextdefsym);
+ else {
+ uint32_t start = fDynamicInfo->nextdefsym;
+ if ( theHint != NULL )
+ start = theHint->itoc;
+ if ( (theHint == NULL) || (theHint->isub_image == 0) ) {
+ sym = binarySearchWithToc(name, fStrings, fSymbolTable, (dylib_table_of_contents*)&fLinkEditBase[fDynamicInfo->tocoff],
+ fDynamicInfo->ntoc, start);
+ }
+ }
+ if ( sym != NULL ) {
+ if ( foundIn != NULL )
+ *foundIn = (ImageLoader*)this;
+
+ return (const Symbol*)sym;
+ }
+
+ if ( searchReExports ) {
+ // hint might tell us to try a particular subimage
+ if ( (theHint != NULL) && (theHint->isub_image > 0) && (theHint->isub_image <= fLibrariesCount) ) {
+ // isub_image is an index into a list that is sorted non-rexported images first
+ uint32_t index = 0;
+ ImageLoader* target = NULL;
+ // pass one, only look at sub-frameworks
+ for (uint32_t i=0; i < fLibrariesCount; ++i) {
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.isSubFramework && (libInfo.image != NULL)) {
+ if ( ++index == theHint->isub_image ) {
+ target = libInfo.image;
+ break;
+ }
+ }
+ }
+ if (target != NULL) {
+ // pass two, only look at non-sub-framework-reexports
+ for (uint32_t i=0; i < fLibrariesCount; ++i) {
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( libInfo.isReExported && !libInfo.isSubFramework && (libInfo.image != NULL) ) {
+ if ( ++index == theHint->isub_image ) {
+ target = libInfo.image;
+ break;
+ }
+ }
+ }
+ }
+ if (target != NULL) {
+ const Symbol* result = target->findExportedSymbol(name, NULL, searchReExports, foundIn);
+ if ( result != NULL )
+ return result;
+ }
+ }
+
+ // hint failed, try all sub images
+ // pass one, only look at sub-frameworks
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( (libInfo.image != NULL) && libInfo.isSubFramework ) {
+ const Symbol* result = libInfo.image->findExportedSymbol(name, NULL, searchReExports, foundIn);
+ if ( result != NULL )
+ return result;
+ }
+ }
+ // pass two, only look at non-sub-framework-reexports
+ for(unsigned int i=0; i < fLibrariesCount; ++i){
+ DependentLibrary& libInfo = fLibraries[i];
+ if ( (libInfo.image != NULL) && libInfo.isReExported && !libInfo.isSubFramework ) {
+ const Symbol* result = libInfo.image->findExportedSymbol(name, NULL, searchReExports, foundIn);
+ if ( result != NULL )
+ return result;
+ }
+ }
+ }
+
+ // last change: the hint is wrong (non-zero but actually in this image)
+ if ( (theHint != NULL) && (theHint->isub_image != 0) ) {
+ sym = binarySearchWithToc(name, fStrings, fSymbolTable, (dylib_table_of_contents*)&fLinkEditBase[fDynamicInfo->tocoff],
+ fDynamicInfo->ntoc, fDynamicInfo->nextdefsym);
+ if ( sym != NULL ) {
+ if ( foundIn != NULL )
+ *foundIn = (ImageLoader*)this;
+ return (const Symbol*)sym;
+ }
+ }
+
+ return NULL;
+}
+
+
+uintptr_t ImageLoaderMachO::getExportedSymbolAddress(const Symbol* sym) const
+{
+ const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+ return nlistSym->n_value + fSlide;
+}
+
+ImageLoader::DefinitionFlags ImageLoaderMachO::getExportedSymbolInfo(const Symbol* sym) const
+{
+ const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+ if ( (nlistSym->n_desc & N_WEAK_DEF) != 0 )
+ return kWeakDefinition;
+ return kNoDefinitionOptions;
+}
+
+const char* ImageLoaderMachO::getExportedSymbolName(const Symbol* sym) const
+{
+ const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+ return &fStrings[nlistSym->n_un.n_strx];
+}
+
+uint32_t ImageLoaderMachO::getExportedSymbolCount() const
+{
+ return fDynamicInfo->nextdefsym;
+}
+
+
+const ImageLoader::Symbol* ImageLoaderMachO::getIndexedExportedSymbol(uint32_t index) const
+{
+ if ( index < fDynamicInfo->nextdefsym ) {
+ const struct macho_nlist* sym = &fSymbolTable[fDynamicInfo->iextdefsym + index];
+ return (const ImageLoader::Symbol*)sym;
+ }
+ return NULL;
+}
+
+
+uint32_t ImageLoaderMachO::getImportedSymbolCount() const
+{
+ return fDynamicInfo->nundefsym;
+}
+
+
+const ImageLoader::Symbol* ImageLoaderMachO::getIndexedImportedSymbol(uint32_t index) const
+{
+ if ( index < fDynamicInfo->nundefsym ) {
+ const struct macho_nlist* sym = &fSymbolTable[fDynamicInfo->iundefsym + index];
+ return (const ImageLoader::Symbol*)sym;
+ }
+ return NULL;
+}
+
+
+ImageLoader::ReferenceFlags ImageLoaderMachO::geImportedSymbolInfo(const ImageLoader::Symbol* sym) const
+{
+ const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+ ImageLoader::ReferenceFlags flags = kNoReferenceOptions;
+ if ( ((nlistSym->n_type & N_TYPE) == N_UNDF) && (nlistSym->n_value != 0) )
+ flags |= ImageLoader::kTentativeDefinition;
+ if ( (nlistSym->n_desc & N_WEAK_REF) != 0 )
+ flags |= ImageLoader::kWeakReference;
+ return flags;
+}
+
+
+const char* ImageLoaderMachO::getImportedSymbolName(const ImageLoader::Symbol* sym) const
+{
+ const struct macho_nlist* nlistSym = (const struct macho_nlist*)sym;
+ return &fStrings[nlistSym->n_un.n_strx];
+}
+
+
+bool ImageLoaderMachO::getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length)
+{
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ if ( (strcmp(sect->segname, segmentName) == 0) && (strcmp(sect->sectname, sectionName) == 0) ) {
+ *start = (uintptr_t*)(sect->addr + fSlide);
+ *length = sect->size;
+ return true;
+ }
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ return false;
+}
+
+
+bool ImageLoaderMachO::findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset)
+{
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ const uintptr_t unslidInteriorAddress = (uintptr_t)imageInterior - this->getSlide();
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ if ( (unslidInteriorAddress >= seg->vmaddr) && (unslidInteriorAddress < (seg->vmaddr+seg->vmsize)) ) {
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ if ((sect->addr <= unslidInteriorAddress) && (unslidInteriorAddress < (sect->addr+sect->size))) {
+ if ( segmentName != NULL )
+ *segmentName = sect->segname;
+ if ( sectionName != NULL )
+ *sectionName = sect->sectname;
+ if ( sectionOffset != NULL )
+ *sectionOffset = unslidInteriorAddress - sect->addr;
+ return true;
+ }
+ }
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ return false;
+}
+
+
+bool ImageLoaderMachO::symbolRequiresCoalescing(const struct macho_nlist* symbol)
+{
+ // if a define and weak ==> coalesced
+ if ( ((symbol->n_type & N_TYPE) == N_SECT) && ((symbol->n_desc & N_WEAK_DEF) != 0) )
+ return true;
+ // if an undefine and not referencing a weak symbol ==> coalesced
+ if ( ((symbol->n_type & N_TYPE) != N_SECT) && ((symbol->n_desc & N_REF_TO_WEAK) != 0) )
+ return true;
+
+ // regular symbol
+ return false;
+}
+
+
+static void __attribute__((noreturn)) throwSymbolNotFound(const char* symbol, const char* referencedFrom, const char* expectedIn)
+{
+ const char* formatString = "Symbol not found: %s\n Referenced from: %s\n Expected in: %s\n";
+ char buf[strlen(symbol)+strlen(referencedFrom)+strlen(expectedIn)+strlen(formatString)];
+ sprintf(buf, formatString, symbol, referencedFrom, expectedIn);
+ throw strdup(buf); // this is a leak if exception doesn't halt program
+}
+
+uintptr_t ImageLoaderMachO::resolveUndefined(const LinkContext& context, const struct macho_nlist* undefinedSymbol, bool twoLevel, ImageLoader** foundIn)
+{
+ const char* symbolName = &fStrings[undefinedSymbol->n_un.n_strx];
+
+ if ( context.bindFlat || !twoLevel ) {
+ // flat lookup
+ const Symbol* sym;
+ if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+ return (*foundIn)->getExportedSymbolAddress(sym);
+ // if a bundle is loaded privately the above will not find its exports
+ if ( this->isBundle() && this->hasHiddenExports() ) {
+ // look in self for needed symbol
+ sym = this->findExportedSymbol(symbolName, NULL, false, foundIn);
+ if ( sym != NULL )
+ return (*foundIn)->getExportedSymbolAddress(sym);
+ }
+ if ( ((undefinedSymbol->n_type & N_PEXT) != 0) || ((undefinedSymbol->n_type & N_TYPE) == N_SECT) ) {
+ // could be a multi-module private_extern internal reference
+ // the static linker squirrels away the target address in n_value
+ uintptr_t addr = undefinedSymbol->n_value + this->fSlide;
+ *foundIn = this;
+ return addr;
+ }
+ if ( (undefinedSymbol->n_desc & N_WEAK_REF) != 0 ) {
+ // definition can't be found anywhere
+ // if reference is weak_import, then it is ok, just return 0
+ return 0;
+ }
+ throwSymbolNotFound(symbolName, this->getPath(), "flat namespace");
+ }
+ else {
+ // symbol requires searching images with coalesced symbols
+ if ( this->needsCoalescing() && symbolRequiresCoalescing(undefinedSymbol) ) {
+ const Symbol* sym;
+ if ( context.coalescedExportFinder(symbolName, &sym, foundIn) )
+ return (*foundIn)->getExportedSymbolAddress(sym);
+ //throwSymbolNotFound(symbolName, this->getPath(), "coalesced namespace");
+ //fprintf(stderr, "dyld: coalesced symbol %s not found in any coalesced image, falling back to two-level lookup", symbolName);
+ }
+
+ // two level lookup
+ void* hint = NULL;
+ ImageLoader* target = NULL;
+ uint8_t ord = GET_LIBRARY_ORDINAL(undefinedSymbol->n_desc);
+ if ( ord == EXECUTABLE_ORDINAL ) {
+ target = context.mainExecutable;
+ }
+ else if ( ord == SELF_LIBRARY_ORDINAL ) {
+ target = this;
+ }
+ else if ( ord == DYNAMIC_LOOKUP_ORDINAL ) {
+ // rnielsen: HACKHACK
+ // flat lookup
+ const Symbol* sym;
+ if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+ return (*foundIn)->getExportedSymbolAddress(sym);
+ // no image has exports this symbol
+ // either report error or hope ZeroLink can just-in-time load an image
+ context.undefinedHandler(symbolName);
+ // try looking again
+ if ( context.flatExportFinder(symbolName, &sym, foundIn) )
+ return (*foundIn)->getExportedSymbolAddress(sym);
+
+ throwSymbolNotFound(symbolName, this->getPath(), "dynamic lookup");
+ }
+ else if ( ord <= fLibrariesCount ) {
+ DependentLibrary& libInfo = fLibraries[ord-1];
+ target = libInfo.image;
+ if ( (target == NULL) && (((undefinedSymbol->n_desc & N_WEAK_REF) != 0) || !libInfo.required) ) {
+ // if target library not loaded and reference is weak or library is weak return 0
+ return 0;
+ }
+ }
+ else {
+ throw "corrupt binary, library ordinal too big";
+ }
+
+ if ( target == NULL ) {
+ fprintf(stderr, "resolveUndefined(%s) in %s\n", symbolName, this->getPath());
+ throw "symbol not found";
+ }
+
+ // interpret hint
+ if ( fTwoLevelHints != NULL ) {
+ uint32_t symIndex = undefinedSymbol - fSymbolTable;
+ int32_t undefinedIndex = symIndex - fDynamicInfo->iundefsym;
+ if ( (undefinedIndex >= 0) && ((uint32_t)undefinedIndex < fDynamicInfo->nundefsym) ) {
+ const struct twolevel_hint* hints = (struct twolevel_hint*)(&fLinkEditBase[fTwoLevelHints->offset]);
+ const struct twolevel_hint* theHint = &hints[undefinedIndex];
+ hint = (void*)theHint;
+ }
+ }
+
+ const Symbol* sym = target->findExportedSymbol(symbolName, hint, true, foundIn);
+ if ( sym!= NULL ) {
+ return (*foundIn)->getExportedSymbolAddress(sym);
+ }
+ else if ( (undefinedSymbol->n_type & N_PEXT) != 0 ) {
+ // don't know why the static linker did not eliminate the internal reference to a private extern definition
+ *foundIn = this;
+ return undefinedSymbol->n_value + fSlide;
+ }
+ else if ( (undefinedSymbol->n_desc & N_WEAK_REF) != 0 ) {
+ // if definition not found and reference is weak return 0
+ return 0;
+ }
+
+ // nowhere to be found
+ throwSymbolNotFound(symbolName, this->getPath(), target->getPath());
+ }
+}
+
+void ImageLoaderMachO::doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols)
+{
+ const uintptr_t relocBase = this->getRelocBase();
+ const bool twoLevel = this->usesTwoLevelNameSpace();
+ const bool prebound = this->isPrebindable();
+
+ // if there are __TEXT fixups, temporarily make __TEXT writable
+ if ( fTextSegmentWithFixups != NULL )
+ fTextSegmentWithFixups->tempWritable();
+
+ // cache last lookup
+ const struct macho_nlist* lastUndefinedSymbol = 0;
+ uintptr_t symbolAddr = 0;
+ ImageLoader* image = NULL;
+
+ // loop through all external relocation records and bind each
+ const relocation_info* const relocsStart = (struct relocation_info*)(&fLinkEditBase[fDynamicInfo->extreloff]);
+ const relocation_info* const relocsEnd = &relocsStart[fDynamicInfo->nextrel];
+ for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+ if (reloc->r_length == RELOC_SIZE) {
+ switch(reloc->r_type) {
+ case GENERIC_RELOC_VANILLA:
+ {
+ const struct macho_nlist* undefinedSymbol = &fSymbolTable[reloc->r_symbolnum];
+ // if only processing coalesced symbols and this one does not require coalesceing, skip to next
+ if ( onlyCoalescedSymbols && !symbolRequiresCoalescing(undefinedSymbol) )
+ continue;
+ uintptr_t* location = ((uintptr_t*)(reloc->r_address + relocBase));
+ uintptr_t value = *location;
+ if ( prebound ) {
+ // we are doing relocations, so prebinding was not usable
+ // in a prebound executable, the n_value field is set to the address where the symbol was found when prebound
+ // so, subtracting that gives the initial displacement which we need to add to the newly found symbol address
+ // if mach-o relocation structs had an "addend" field this would not be necessary.
+ value -= undefinedSymbol->n_value;
+ }
+ // if undefinedSymbol is same as last time, then symbolAddr and image will resolve to the same too
+ if ( undefinedSymbol != lastUndefinedSymbol ) {
+ symbolAddr = this->resolveUndefined(context, undefinedSymbol, twoLevel, &image);
+ lastUndefinedSymbol = undefinedSymbol;
+ }
+ if ( context.verboseBind ) {
+ const char *path = NULL;
+ if(NULL != image) {
+ path = image->getShortName();
+ }
+ if(0 == value) {
+ fprintf(stderr, "dyld: bind: %s:0x%08lx = %s:%s, *0x%08lx = 0x%08lx\n",
+ this->getShortName(), (uintptr_t)location,
+ path, &fStrings[undefinedSymbol->n_un.n_strx], (uintptr_t)location, symbolAddr);
+ }
+ else {
+ fprintf(stderr, "dyld: bind: %s:0x%08lx = %s:%s, *0x%08lx = 0x%08lx + %ld\n",
+ this->getShortName(), (uintptr_t)location,
+ path, &fStrings[undefinedSymbol->n_un.n_strx], (uintptr_t)location, symbolAddr, value);
+ }
+ }
+ value += symbolAddr;
+ *location = value;
+ }
+ break;
+ default:
+ throw "unknown external relocation type";
+ }
+ }
+ else {
+ throw "bad external relocation length";
+ }
+ }
+
+ // if there were __TEXT fixups, restore write protection
+ if ( fTextSegmentWithFixups != NULL ) {
+ fTextSegmentWithFixups->setPermissions();
+ sys_icache_invalidate((void*)fTextSegmentWithFixups->getActualLoadAddress(), fTextSegmentWithFixups->getSize());
+ }
+
+ // update stats
+ fgTotalBindFixups += fDynamicInfo->nextrel;
+}
+
+const mach_header* ImageLoaderMachO::machHeader() const
+{
+ return (mach_header*)fMachOData;
+}
+
+uintptr_t ImageLoaderMachO::getSlide() const
+{
+ return fSlide;
+}
+
+// hmm. maybe this should be up in ImageLoader??
+const void* ImageLoaderMachO::getBaseAddress() const
+{
+ Segment* seg = fSegments[0];
+ return (const void*)seg->getActualLoadAddress();
+}
+
+
+uintptr_t ImageLoaderMachO::doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context)
+{
+ // scan for all non-lazy-pointer sections
+ const bool twoLevel = this->usesTwoLevelNameSpace();
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ const uint32_t* const indirectTable = (uint32_t*)&fLinkEditBase[fDynamicInfo->indirectsymoff];
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ const uint8_t type = sect->flags & SECTION_TYPE;
+ if ( type == S_LAZY_SYMBOL_POINTERS ) {
+ const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+ uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
+ if ( (lazyPointer >= symbolPointers) && (lazyPointer < &symbolPointers[pointerCount]) ) {
+ const uint32_t indirectTableOffset = sect->reserved1;
+ const uint32_t lazyIndex = lazyPointer - symbolPointers;
+ uint32_t symbolIndex = indirectTable[indirectTableOffset + lazyIndex];
+ if ( symbolIndex != INDIRECT_SYMBOL_ABS && symbolIndex != INDIRECT_SYMBOL_LOCAL ) {
+ ImageLoader *image = NULL;
+ const char *path = NULL;
+ uintptr_t symbolAddr = this->resolveUndefined(context, &fSymbolTable[symbolIndex], twoLevel, &image);
+ if ( context.verboseBind ) {
+ if(NULL == path && NULL != image) {
+ path = image->getShortName();
+ }
+ fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+ this->getShortName(), &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], "lazy_ptr",
+ path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (uintptr_t)&symbolPointers[lazyIndex], symbolAddr);
+ }
+ if ( NULL != context.bindingHandler ) {
+ if(NULL == path && NULL != image) {
+ path = image->getPath();
+ }
+ symbolAddr = (uintptr_t)context.bindingHandler(path, &fStrings[fSymbolTable[symbolIndex].n_un.n_strx], (void *)symbolAddr);
+ }
+ symbolPointers[lazyIndex] = symbolAddr;
+ // update stats
+ fgTotalLazyBindFixups++;
+ return symbolPointers[lazyIndex];
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+ throw "lazy pointer not found";
+}
+
+
+
+void ImageLoaderMachO::doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols)
+{
+ // scan for all non-lazy-pointer sections
+ const bool twoLevel = this->usesTwoLevelNameSpace();
+ const uint32_t cmd_count = ((macho_header*)fMachOData)->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fMachOData[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ const uint32_t* const indirectTable = (uint32_t*)&fLinkEditBase[fDynamicInfo->indirectsymoff];
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ const uint8_t type = sect->flags & SECTION_TYPE;
+ const uint32_t pointerCount = sect->size / sizeof(uintptr_t);
+ if ( type == S_NON_LAZY_SYMBOL_POINTERS ) {
+ if ( (bindness == kLazyOnly) || (bindness == kLazyOnlyNoDependents) )
+ continue;
+ }
+ else if ( type == S_LAZY_SYMBOL_POINTERS ) {
+ // process each symbol pointer in this section
+ fgTotalPossibleLazyBindFixups += pointerCount;
+ if ( bindness == kNonLazyOnly )
+ continue;
+ }
+ else {
+ continue;
+ }
+ const uint32_t indirectTableOffset = sect->reserved1;
+ uintptr_t* const symbolPointers = (uintptr_t*)(sect->addr + fSlide);
+ for (uint32_t j=0; j < pointerCount; ++j) {
+ uint32_t symbolIndex = indirectTable[indirectTableOffset + j];
+ if ( symbolIndex == INDIRECT_SYMBOL_LOCAL) {
+ symbolPointers[j] += this->fSlide;
+ }
+ else if ( symbolIndex == INDIRECT_SYMBOL_ABS) {
+ // do nothing since already has absolute address
+ }
+ else {
+ const struct macho_nlist* sym = &fSymbolTable[symbolIndex];
+ if ( symbolIndex == 0 ) {
+ // This could be rdar://problem/3534709
+ if ( ((const macho_header*)fMachOData)->filetype == MH_EXECUTE ) {
+ static bool alreadyWarned = false;
+ if ( (sym->n_type & N_TYPE) != N_UNDF ) {
+ // The indirect table parallels the (non)lazy pointer sections. For
+ // instance, to find info about the fifth lazy pointer you look at the
+ // fifth entry in the indirect table. (try otool -Iv on a file).
+ // The entry in the indirect table contains an index into the symbol table.
+
+ // The bug in ld caused the entry in the indirect table to be zero
+ // (instead of a magic value that means a local symbol). So, if the
+ // symbolIndex == 0, we may be encountering the bug, or 0 may be a valid
+ // symbol table index. The check I put in place is to see if the zero'th
+ // symbol table entry is an import entry (usually it is a local symbol
+ // definition).
+ if ( context.verboseWarnings && !alreadyWarned ) {
+ fprintf(stderr, "dyld: malformed executable '%s', skipping indirect symbol to %s\n",
+ this->getPath(), &fStrings[sym->n_un.n_strx]);
+ alreadyWarned = true;
+ }
+ continue;
+ }
+ }
+ }
+ ImageLoader *image = NULL;
+ // if only processing coalesced symbols and this one does not require coalesceing, skip to next
+ if ( onlyCoalescedSymbols && !symbolRequiresCoalescing(sym) )
+ continue;
+ uintptr_t symbolAddr;
+ symbolAddr = resolveUndefined(context, sym, twoLevel, &image);
+ if ( context.verboseBind ) {
+ const char *path = NULL;
+ if(NULL != image) {
+ path = image->getShortName();
+ }
+ const char *typeName;
+ if ( type == S_LAZY_SYMBOL_POINTERS ) {
+ typeName = "lazy_ptr";
+ }
+ else {
+ typeName = "non_lazy_ptr";
+ }
+ fprintf(stderr, "dyld: bind: %s:%s$%s = %s:%s, *0x%08lx = 0x%08lx\n",
+ this->getShortName(), &fStrings[sym->n_un.n_strx], typeName,
+ path, &fStrings[sym->n_un.n_strx], (uintptr_t)&symbolPointers[j], symbolAddr);
+ }
+ symbolPointers[j] = symbolAddr;
+ }
+ }
+ // update stats
+ fgTotalBindFixups += pointerCount;
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+/*
+ * The address of these symbols are written in to the (__DATA,__dyld) section
+ * at the following offsets:
+ * at offset 0 stub_binding_helper_interface
+ * at offset 4 _dyld_func_lookup
+ * at offset 8 start_debug_thread
+ * The 'C' types (if any) for these symbols are ignored here and all are
+ * declared as longs so the assignment of their address in to the section will
+ * not require a cast. stub_binding_helper_interface is really a label in the
+ * assembly code interface for the stub binding. It does not have a meaningful
+ * 'C' type. _dyld_func_lookup is the routine in dyld_libfuncs.c.
+ * start_debug_thread is the routine in debug.c.
+ *
+ * For ppc the image's stub_binding_binding_helper is read from:
+ * at offset 20 the image's stub_binding_binding_helper address
+ * and saved into to the image structure.
+ */
+struct DATAdyld {
+ void* dyldLazyBinder; // filled in at launch by dyld to point into dyld to &stub_binding_helper_interface
+ void* dyldFuncLookup; // filled in at launch by dyld to point into dyld to &_dyld_func_lookup
+ void* startDebugThread; // debugger interface ???
+ void* debugPort; // debugger interface ???
+ void* debugThread; // debugger interface ???
+ void* stubBindHelper; // filled in at static link time to point to stub helper in image
+ void* coreDebug; // ???
+};
+
+// These are defined in dyldStartup.s
+extern "C" void stub_binding_helper();
+extern "C" bool dyld_func_lookup(const char* name, uintptr_t* address);
+
+
+void ImageLoaderMachO::setupLazyPointerHandler()
+{
+ if ( fDATAdyld != NULL ) {
+ struct DATAdyld* dd = (struct DATAdyld*)(fDATAdyld->addr + fSlide);
+ if ( fDATAdyld->size > offsetof(DATAdyld, dyldLazyBinder) ) {
+ if ( dd->dyldLazyBinder != (void*)&stub_binding_helper )
+ dd->dyldLazyBinder = (void*)&stub_binding_helper;
+ }
+ if ( fDATAdyld->size > offsetof(DATAdyld, dyldFuncLookup) ) {
+ if ( dd->dyldFuncLookup != (void*)&dyld_func_lookup )
+ dd->dyldFuncLookup = (void*)&dyld_func_lookup;
+ }
+ //if ( fDATAdyld->size > offsetof(DATAdyld, startDebugThread) )
+ // dd->startDebugThread = &start_debug_thread;
+#ifdef __ppc__
+ //if ( fDATAdyld->size > offsetof(DATAdyld, stubBindHelper) )
+ // save = dd->stubBindHelper;
+#endif
+ }
+}
+
+bool ImageLoaderMachO::usablePrebinding(const LinkContext& context) const
+{
+ // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
+ if ( this->isPrebindable() && this->allDependentLibrariesAsWhenPreBound() && (this->getSlide() == 0) ) {
+ // allow environment variables to disable prebinding
+ if ( context.bindFlat )
+ return false;
+ switch ( context.prebindUsage ) {
+ case kUseAllPrebinding:
+ return true;
+ case kUseSplitSegPrebinding:
+ return this->fIsSplitSeg;
+ case kUseAllButAppPredbinding:
+ return (this != context.mainExecutable);
+ case kUseNoPrebinding:
+ return false;
+ }
+ }
+ return false;
+}
+
+void ImageLoaderMachO::doBind(const LinkContext& context, BindingLaziness bindness)
+{
+ // set dyld entry points in image
+ this->setupLazyPointerHandler();
+
+ // if prebound and loaded at prebound address, and all libraries are same as when this was prebound, then no need to bind
+ // note: flat-namespace binaries need to be imports rebound (even if correctly prebound)
+ if ( this->usablePrebinding(context) && this->usesTwoLevelNameSpace() ) {
+ // if image has coalesced symbols, then these need to be rebound
+ if ( this->needsCoalescing() ) {
+ this->doBindExternalRelocations(context, true);
+ this->doBindIndirectSymbolPointers(context, kLazyAndNonLazy, true);
+ }
+ // skip binding because prebound and prebinding not disabled
+ return;
+ }
+
+ // values bound by name are stored two different ways in mach-o
+ switch (bindness) {
+ case kNonLazyOnly:
+ case kLazyAndNonLazy:
+ // external relocations are used for data initialized to external symbols
+ this->doBindExternalRelocations(context, false);
+ break;
+ case kLazyOnly:
+ case kLazyOnlyNoDependents:
+ break;
+ }
+ // "indirect symbols" are used for code references to external symbols
+ this->doBindIndirectSymbolPointers(context, bindness, false);
+}
+
+
+
+void ImageLoaderMachO::doImageInit(const LinkContext& context)
+{
+ if ( fDashInit != NULL ) {
+ Initializer func = (Initializer)(fDashInit->init_address + fSlide);
+ if ( context.verboseInit )
+ fprintf(stderr, "dyld: calling -init function 0x%p in %s\n", func, this->getPath());
+ func(context.argc, context.argv, context.envp, context.apple);
+ }
+}
+
+void ImageLoaderMachO::doModInitFunctions(const LinkContext& context)
+{
+ if ( fModInitSection != NULL ) {
+ Initializer* inits = (Initializer*)(fModInitSection->addr + fSlide);
+ const uint32_t count = fModInitSection->size / sizeof(uintptr_t);
+ for (uint32_t i=0; i < count; ++i) {
+ Initializer func = inits[i];
+ if ( context.verboseInit )
+ fprintf(stderr, "dyld: calling initializer function %p in %s\n", func, this->getPath());
+ func(context.argc, context.argv, context.envp, context.apple);
+ }
+ }
+}
+
+
+void ImageLoaderMachO::doInitialization(const LinkContext& context)
+{
+ // mach-o has -init and static initializers
+ doImageInit(context);
+ doModInitFunctions(context);
+}
+
+bool ImageLoaderMachO::needsInitialization()
+{
+ return ( (fDashInit != NULL) || (fModInitSection != NULL) );
+}
+
+
+bool ImageLoaderMachO::needsTermination()
+{
+ return ( fModTermSection != NULL );
+}
+
+bool ImageLoaderMachO::hasImageNotification()
+{
+ return ( fImageNotifySection != NULL );
+}
+
+
+void ImageLoaderMachO::doTermination(const LinkContext& context)
+{
+ if ( fModTermSection != NULL ) {
+ Terminator* terms = (Terminator*)(fModTermSection->addr + fSlide);
+ const uint32_t count = fModTermSection->size / sizeof(uintptr_t);
+ for (uint32_t i=count; i > 0; --i) {
+ Terminator func = terms[i-1];
+ if ( context.verboseInit )
+ fprintf(stderr, "dyld: calling terminaton function %p in %s\n", func, this->getPath());
+ func();
+ }
+ }
+}
+
+void ImageLoaderMachO::doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[])
+{
+ if ( fImageNotifySection != NULL ) {
+ dyld_image_notifier* notes = (dyld_image_notifier*)(fImageNotifySection->addr + fSlide);
+ const uint32_t count = fImageNotifySection->size / sizeof(uintptr_t);
+ for (uint32_t i=count; i > 0; --i) {
+ dyld_image_notifier func = notes[i-1];
+ func(mode, infoCount, info);
+ }
+ }
+}
+
+void ImageLoaderMachO::printStatistics(unsigned int imageCount)
+{
+ ImageLoader::printStatistics(imageCount);
+ fprintf(stderr, "total hinted binary tree searches: %d\n", fgHintedBinaryTreeSearchs);
+ fprintf(stderr, "total unhinted binary tree searches: %d\n", fgUnhintedBinaryTreeSearchs);
+
+#if LINKEDIT_USAGE_DEBUG
+ fprintf(stderr, "linkedit pages accessed (%lu):\n", sLinkEditPageBuckets.size());
+#endif
+}
+
+void ImageLoaderMachO::doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind)
+{
+ // update __DATA segment
+ this->applyPrebindingToDATA(fileToPrebind);
+
+ // update load commands
+ this->applyPrebindingToLoadCommands(context, fileToPrebind, timestamp);
+
+ // update symbol table
+ this->applyPrebindingToLinkEdit(context, fileToPrebind);
+}
+
+void ImageLoaderMachO::applyPrebindingToDATA(uint8_t* fileToPrebind)
+{
+ const unsigned int segmentCount = fSegments.size();
+ for(unsigned int i=0; i < segmentCount; ++i) {
+ SegmentMachO* seg = (SegmentMachO*)fSegments[i];
+ if ( seg->writeable() ) {
+ memcpy(&fileToPrebind[seg->fFileOffset], (void*)seg->getActualLoadAddress(), seg->fFileSize);
+ }
+ }
+}
+
+void ImageLoaderMachO::applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp)
+{
+ macho_header* mh = (macho_header*)fileToPrebind;
+ const uint32_t cmd_count = mh->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fileToPrebind[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_LOAD_DYLIB:
+ case LC_LOAD_WEAK_DYLIB:
+ {
+ // update each dylib load command with the timestamp of the target dylib
+ struct dylib_command* dylib = (struct dylib_command*)cmd;
+ const char* name = (char*)cmd + dylib->dylib.name.offset;
+ for (const DependentLibrary* dl=fLibraries; dl < &fLibraries[fLibrariesCount]; dl++) {
+ if (strcmp(dl->name, name) == 0 ) {
+ // found matching DependentLibrary for this load command
+ ImageLoaderMachO* targetImage = (ImageLoaderMachO*)(dl->image); // !!! assume only mach-o images are prebound
+ if ( ! targetImage->isPrebindable() )
+ throw "dependent dylib is not prebound";
+ // if the target is currently being re-prebound then its timestamp will be the same as this one
+ if ( ! targetImage->usablePrebinding(context) ) {
+ dylib->dylib.timestamp = timestamp;
+ }
+ else {
+ // otherwise dependent library is already correctly prebound, so use its checksum
+ dylib->dylib.timestamp = targetImage->doGetLibraryInfo().checksum;
+ }
+ break;
+ }
+ }
+ }
+ break;
+ case LC_ID_DYLIB:
+ {
+ // update the ID of this library with the new timestamp
+ struct dylib_command* dylib = (struct dylib_command*)cmd;
+ dylib->dylib.timestamp = timestamp;
+ }
+ break;
+ case LC_SEGMENT_COMMAND:
+ // if dylib was rebased, update segment commands
+ if ( fSlide != 0 ) {
+ struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ seg->vmaddr += fSlide;
+ struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ sect->addr += fSlide;
+ }
+ }
+ break;
+ case LC_ROUTINES_COMMAND:
+ // if dylib was rebased, update -init command
+ if ( fSlide != 0 ) {
+ struct macho_routines_command* routines = (struct macho_routines_command*)cmd;
+ routines->init_address += fSlide;
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+void ImageLoaderMachO::applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind)
+{
+ // In prebound images, the n_value of the symbol table entry for is the prebound address
+ // This is needed when prebinding can't be used, to back solve for any possible addend in non-lazy pointers
+ const char* stringPool = NULL;
+ struct macho_nlist* symbolTable = NULL;
+ const struct dysymtab_command* dysymtab = NULL;
+
+ // get symbol table info
+ macho_header* mh = (macho_header*)fileToPrebind;
+ const uint32_t cmd_count = mh->ncmds;
+ const struct load_command* const cmds = (struct load_command*)&fileToPrebind[sizeof(macho_header)];
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SYMTAB:
+ {
+ const struct symtab_command* symtab = (struct symtab_command*)cmd;
+ stringPool = (const char*)&fileToPrebind[symtab->stroff];
+ symbolTable = (struct macho_nlist*)(&fileToPrebind[symtab->symoff]);
+ }
+ break;
+ case LC_DYSYMTAB:
+ dysymtab = (struct dysymtab_command*)cmd;
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+
+ // walk all imports and re-resolve their n_value (needed incase prebinding is invalid)
+ struct macho_nlist* lastImport = &symbolTable[dysymtab->iundefsym+dysymtab->nundefsym];
+ for (struct macho_nlist* entry = &symbolTable[dysymtab->iundefsym]; entry < lastImport; ++entry) {
+ ImageLoader* dummy;
+ entry->n_value = this->resolveUndefined(context, entry, this->usesTwoLevelNameSpace(), &dummy);
+ }
+
+ // walk all exports and slide their n_value
+ struct macho_nlist* lastExport = &symbolTable[dysymtab->iextdefsym+dysymtab->nextdefsym];
+ for (struct macho_nlist* entry = &symbolTable[dysymtab->iextdefsym]; entry < lastExport; ++entry) {
+ entry->n_value += fSlide;
+ }
+
+ // walk all local symbols and slide their n_value
+ struct macho_nlist* lastLocal = &symbolTable[dysymtab->ilocalsym+dysymtab->nlocalsym];
+ for (struct macho_nlist* entry = &symbolTable[dysymtab->ilocalsym]; entry < lastLocal; ++entry) {
+ if ( (entry->n_type & N_TYPE) == N_SECT )
+ entry->n_value += fSlide;
+ }
+
+ // walk all local relocations and reset every PPC_RELOC_PB_LA_PTR r_value
+ relocation_info* const relocsStart = (struct relocation_info*)(&fileToPrebind[dysymtab->locreloff]);
+ relocation_info* const relocsEnd = &relocsStart[dysymtab->nlocrel];
+ for (relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+ if ( (reloc->r_address & R_SCATTERED) != 0 ) {
+ struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+ if (sreloc->r_length == RELOC_SIZE) {
+ switch(sreloc->r_type) {
+ #if __ppc__ || __ppc64__
+ case PPC_RELOC_PB_LA_PTR:
+ #elif __i386__
+ case GENERIC_RELOC_PB_LA_PTR:
+ #else
+ #error unknown architecture
+ #endif
+ sreloc->r_value += fSlide;
+ break;
+ }
+ }
+ }
+ }
+
+}
+
+
+SegmentMachO::SegmentMachO(const struct macho_segment_command* cmd, ImageLoaderMachO* image, const uint8_t* fileData)
+ : fImage(image), fSize(cmd->vmsize), fFileSize(cmd->filesize), fFileOffset(cmd->fileoff), fPreferredLoadAddress(cmd->vmaddr),
+ fVMProtection(cmd->initprot), fHasFixUps(false), fUnMapOnDestruction(false)
+{
+ strncpy(fName, cmd->segname, 16);
+ fName[16] = '\0';
+ // scan sections for fix-up bit
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)cmd + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[cmd->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ if ( (sect->flags & (S_ATTR_EXT_RELOC | S_ATTR_LOC_RELOC)) != 0 )
+ fHasFixUps = true;
+ }
+}
+
+SegmentMachO::~SegmentMachO()
+{
+ if ( fUnMapOnDestruction ) {
+ //fprintf(stderr, "unmapping segment %s at 0x%08lX\n", getName(), getActualLoadAddress());
+ munmap((void*)(this->getActualLoadAddress()), this->getSize());
+ }
+}
+
+const ImageLoader* SegmentMachO::getImage()
+{
+ return fImage;
+}
+
+const char* SegmentMachO::getName()
+{
+ return fName;
+}
+
+uintptr_t SegmentMachO::getSize()
+{
+ return fSize;
+}
+
+uintptr_t SegmentMachO::getFileSize()
+{
+ return fFileSize;
+}
+
+uintptr_t SegmentMachO::getFileOffset()
+{
+ return fFileOffset;
+}
+
+bool SegmentMachO::readable()
+{
+ return ( (fVMProtection & VM_PROT_READ) != 0);
+}
+
+bool SegmentMachO::writeable()
+{
+ return ((fVMProtection & VM_PROT_WRITE) != 0);
+}
+
+bool SegmentMachO::executable()
+{
+ return ((fVMProtection & VM_PROT_EXECUTE) != 0);
+}
+
+bool SegmentMachO::unaccessible()
+{
+ return (fVMProtection == 0);
+}
+
+bool SegmentMachO::hasFixUps()
+{
+ return fHasFixUps;
+}
+
+uintptr_t SegmentMachO::getActualLoadAddress()
+{
+ return fPreferredLoadAddress + fImage->fSlide;
+}
+
+uintptr_t SegmentMachO::getPreferredLoadAddress()
+{
+ return fPreferredLoadAddress;
+}
+
+bool SegmentMachO::hasPreferredLoadAddress()
+{
+ return (fPreferredLoadAddress != 0);
+}
+
+void SegmentMachO::setUnMapWhenDestructed(bool unmap)
+{
+ fUnMapOnDestruction = unmap;
+}
+
+static uint32_t *buildCRCTable(void)
+{
+ uint32_t *table = new uint32_t[256];
+ uint32_t p = 0xedb88320UL; // standard CRC-32 polynomial
+
+ for (unsigned int i = 0; i < 256; i++) {
+ uint32_t c = i;
+ for (unsigned int j = 0; j < 8; j++) {
+ if ( c & 1 ) c = p ^ (c >> 1);
+ else c = c >> 1;
+ }
+ table[i] = c;
+ }
+
+ return table;
+}
+
+uint32_t SegmentMachO::crc32()
+{
+ if ( !readable() ) return 0;
+
+ static uint32_t *crcTable = NULL;
+ if ( !crcTable ) crcTable = buildCRCTable();
+
+ uint32_t crc = ~(uint32_t)0;
+ uint8_t *p = (uint8_t *)getActualLoadAddress();
+ uint8_t *end = p + getSize();
+ while ( p < end ) {
+ crc = crcTable[(crc & 0xff) ^ (*p++)] ^ (crc >> 8);
+ }
+ return crc ^ ~(uint32_t)0;
+}
+
+
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __IMAGELOADERMACHO__
+#define __IMAGELOADERMACHO__
+
+#include <stdint.h>
+
+#include "ImageLoader.h"
+
+struct sf_mapping;
+struct _shared_region_mapping_np;
+
+//
+// ImageLoaderMachO is the concrete subclass of ImageLoader which loads mach-o format files.
+// The class is written to be 64-bit clean and support both 32-bit and 64-bit executables in
+// mach-o.
+//
+//
+class ImageLoaderMachO : public ImageLoader {
+public:
+ ImageLoaderMachO(const char* path, int fd, const uint8_t firstPage[4096], uint64_t offset, uint64_t len, const struct stat& info, const LinkContext& context);
+ ImageLoaderMachO(const char* moduleName, const struct mach_header* mh, uint64_t len, const LinkContext& context);
+ virtual ~ImageLoaderMachO() {}
+
+ const char* getInstallPath() const;
+ virtual void* getMain() const;
+ virtual const struct mach_header* machHeader() const;
+ virtual uintptr_t getSlide() const;
+ virtual const void* getBaseAddress() const;
+ virtual bool hasCoalescedExports() const;
+ virtual const Symbol* findExportedSymbol(const char* name, const void* hint, bool searchReExports, ImageLoader** foundIn) const;
+ virtual uintptr_t getExportedSymbolAddress(const Symbol* sym) const;
+ virtual DefinitionFlags getExportedSymbolInfo(const Symbol* sym) const;
+ virtual const char* getExportedSymbolName(const Symbol* sym) const;
+ virtual uint32_t getExportedSymbolCount() const;
+ virtual const Symbol* getIndexedExportedSymbol(uint32_t index) const;
+ virtual uint32_t getImportedSymbolCount() const;
+ virtual const Symbol* getIndexedImportedSymbol(uint32_t index) const;
+ virtual ReferenceFlags geImportedSymbolInfo(const Symbol* sym) const;
+ virtual const char* getImportedSymbolName(const Symbol* sym) const;
+ virtual bool isBundle() const;
+ virtual bool isDylib() const;
+ virtual bool forceFlat() const;
+ virtual uintptr_t doBindLazySymbol(uintptr_t* lazyPointer, const LinkContext& context);
+ virtual void doTermination(const LinkContext& context);
+ virtual void doNotification(enum dyld_image_mode mode, uint32_t infoCount, const struct dyld_image_info info[]);
+ virtual bool needsInitialization();
+ virtual bool hasImageNotification();
+ virtual bool getSectionContent(const char* segmentName, const char* sectionName, void** start, size_t* length);
+ virtual bool findSection(const void* imageInterior, const char** segmentName, const char** sectionName, size_t* sectionOffset);
+ virtual bool usablePrebinding(const LinkContext& context) const;
+
+
+ static void printStatistics(unsigned int imageCount);
+
+protected:
+ ImageLoaderMachO(const ImageLoaderMachO&);
+ void operator=(const ImageLoaderMachO&);
+
+ virtual uint32_t doGetDependentLibraryCount();
+ virtual void doGetDependentLibraries(DependentLibrary libs[]);
+ virtual LibraryInfo doGetLibraryInfo();
+ virtual void doRebase(const LinkContext& context);
+ virtual void doBind(const LinkContext& context, BindingLaziness bindness);
+ virtual void doInitialization(const LinkContext& context);
+ virtual void doPrebinding(const LinkContext& context, time_t timestamp, uint8_t* fileToPrebind);
+ virtual bool needsTermination();
+ virtual void instantiateSegments(const uint8_t* fileData);
+ virtual bool segmentsMustSlideTogether() const;
+ virtual bool segmentsCanSlide() const;
+ virtual void setSlide(intptr_t slide);
+ virtual bool usesTwoLevelNameSpace() const;
+ virtual bool isSubframeworkOf(const LinkContext& context, const ImageLoader* image) const;
+ virtual bool hasSubLibrary(const LinkContext& context, const ImageLoader* child) const;
+ virtual bool isPrebindable() const;
+
+#if !__LP64__ // split segs not supported for 64-bits
+ virtual void mapSegments(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+#endif
+
+private:
+ friend class SegmentMachO;
+
+ void init();
+ void parseLoadCmds();
+ void doBindIndirectSymbolPointers(const LinkContext& context, BindingLaziness bindness, bool onlyCoalescedSymbols);
+ void doBindExternalRelocations(const LinkContext& context, bool onlyCoalescedSymbols);
+ uintptr_t resolveUndefined(const LinkContext& context, const struct macho_nlist* symbol, bool twoLevel, ImageLoader **foundIn);
+ uintptr_t getRelocBase();
+ void doImageInit(const LinkContext& context);
+ void doModInitFunctions(const LinkContext& context);
+ void setupLazyPointerHandler();
+ void applyPrebindingToDATA(uint8_t* fileToPrebind);
+ void applyPrebindingToLoadCommands(const LinkContext& context, uint8_t* fileToPrebind, time_t timestamp);
+ void applyPrebindingToLinkEdit(const LinkContext& context, uint8_t* fileToPrebind);
+#if !__LP64__ // split segs not supported for 64-bits
+ unsigned int getExtraZeroFillEntriesCount();
+ int sharedRegionLoadFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+ int sharedRegionMapFile(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+ int sharedRegionMakePrivate(const LinkContext& context);
+ int sharedRegionMapFilePrivate(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+ int sharedRegionMapFilePrivateOutside(int fd, uint64_t offsetInFat, uint64_t lenInFat, uint64_t fileLen, const LinkContext& context);
+ void initMappingTable(uint64_t offsetInFat, sf_mapping *mappingTable, uintptr_t baseAddress);
+ void initMappingTable(uint64_t offsetInFat, _shared_region_mapping_np *mappingTable);
+#endif
+ bool needsCoalescing() const;
+
+ static bool symbolRequiresCoalescing(const struct macho_nlist* symbol);
+ static uintptr_t bindLazySymbol(const mach_header*, uintptr_t* lazyPointer);
+ static const struct macho_nlist* binarySearch(const char* key, const char stringPool[], const struct macho_nlist symbols[], uint32_t symbolCount);
+ static const struct macho_nlist* binarySearchWithToc(const char* key, const char stringPool[], const struct macho_nlist symbols[],
+ const struct dylib_table_of_contents toc[], uint32_t symbolCount, uint32_t hintIndex);
+
+ const uint8_t* fMachOData;
+ const uint8_t* fLinkEditBase; // add any internal "offset" to this to get actual address
+ const struct macho_nlist* fSymbolTable;
+ const char* fStrings;
+ const struct dysymtab_command* fDynamicInfo;
+ uintptr_t fSlide;
+ bool fIsSplitSeg;
+ bool fHasSubLibraries;
+ bool fHasSubUmbrella;
+ bool fTextSegmentHasFixups;
+ const struct macho_routines_command* fDashInit;
+ const struct macho_section* fModInitSection;
+ const struct macho_section* fModTermSection;
+ const struct macho_section* fDATAdyld;
+ const struct macho_section* fImageNotifySection;
+ const struct twolevel_hints_command* fTwoLevelHints;
+ const struct dylib_command* fDylibID;
+ const char* fReExportThruFramework;
+ SegmentMachO* fTextSegmentWithFixups; // NULL unless __TEXT segment has fixups
+
+ static uint32_t fgHintedBinaryTreeSearchs;
+ static uint32_t fgUnhintedBinaryTreeSearchs;
+};
+
+
+class SegmentMachO : public Segment
+{
+public:
+ SegmentMachO(const struct macho_segment_command* cmd, ImageLoaderMachO*, const uint8_t* fileData);
+ virtual ~SegmentMachO();
+
+ virtual const ImageLoader* getImage();
+ virtual const char* getName();
+ virtual uintptr_t getSize();
+ virtual uintptr_t getFileSize();
+ virtual uintptr_t getFileOffset();
+ virtual bool readable();
+ virtual bool writeable();
+ virtual bool executable();
+ virtual bool unaccessible();
+ virtual bool hasFixUps();
+ virtual uintptr_t getActualLoadAddress();
+ virtual uintptr_t getPreferredLoadAddress();
+ virtual void setUnMapWhenDestructed(bool unmap);
+ virtual uint32_t crc32();
+
+protected:
+ virtual bool hasPreferredLoadAddress();
+
+private:
+ SegmentMachO(const SegmentMachO&);
+ void operator=(const SegmentMachO&);
+
+ friend class ImageLoaderMachO;
+
+
+ ImageLoaderMachO* const fImage;
+ char fName[18];
+ const uintptr_t fSize;
+ const uintptr_t fFileSize;
+ const uintptr_t fFileOffset;
+ const uintptr_t fPreferredLoadAddress;
+ const uint16_t fVMProtection;
+ bool fHasFixUps;
+ bool fUnMapOnDestruction;
+};
+
+
+#endif // __IMAGELOADERMACHO__
+
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stdint.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/param.h>
+#include <mach/mach_time.h> // mach_absolute_time()
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <mach-o/fat.h>
+#include <mach-o/loader.h>
+#include <libkern/OSByteOrder.h>
+#include <mach/mach.h>
+#include <sys/sysctl.h>
+
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+#include "dyld.h"
+#include "ImageLoader.h"
+#include "ImageLoaderMachO.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+
+#define CPU_TYPE_MASK 0x00FFFFFF /* complement of CPU_ARCH_MASK */
+
+
+/* implemented in dyld_gdb.cpp */
+void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[]);
+void removeImageFromAllImages(const mach_header* mh);
+#if OLD_GDB_DYLD_INTERFACE
+void addImageForgdb(const mach_header* mh, uintptr_t slide, const char* physicalPath, const char* logicalPath);
+void removeImageForgdb(const struct mach_header* mh);
+#endif
+
+// magic so CrashReporter logs message
+extern "C" {
+ char error_string[1024];
+}
+
+
+//
+// The file contains the core of dyld used to get a process to main().
+// The API's that dyld supports are implemented in dyldAPIs.cpp.
+//
+//
+//
+//
+//
+
+
+namespace dyld {
+
+
+//
+// state of all environment variables dyld uses
+//
+struct EnvironmentVariables {
+ const char* const * DYLD_FRAMEWORK_PATH;
+ const char* const * DYLD_FALLBACK_FRAMEWORK_PATH;
+ const char* const * DYLD_LIBRARY_PATH;
+ const char* const * DYLD_FALLBACK_LIBRARY_PATH;
+ const char* const * DYLD_ROOT_PATH;
+ const char* const * DYLD_INSERT_LIBRARIES;
+ const char* const * LD_LIBRARY_PATH; // for unix conformance
+ bool DYLD_PRINT_LIBRARIES;
+ bool DYLD_PRINT_LIBRARIES_POST_LAUNCH;
+ bool DYLD_BIND_AT_LAUNCH;
+ bool DYLD_PRINT_STATISTICS;
+ bool DYLD_PRINT_OPTS;
+ bool DYLD_PRINT_ENV;
+ // DYLD_IMAGE_SUFFIX ==> gLinkContext.imageSuffix
+ // DYLD_PRINT_OPTS ==> gLinkContext.verboseOpts
+ // DYLD_PRINT_ENV ==> gLinkContext.verboseEnv
+ // DYLD_FORCE_FLAT_NAMESPACE ==> gLinkContext.bindFlat
+ // DYLD_PRINT_INITIALIZERS ==> gLinkContext.verboseInit
+ // DYLD_PRINT_SEGMENTS ==> gLinkContext.verboseMapping
+ // DYLD_PRINT_BINDINGS ==> gLinkContext.verboseBind
+ // DYLD_PRINT_REBASINGS ==> gLinkContext.verboseRebase
+ // DYLD_PRINT_APIS ==> gLogAPIs
+ // DYLD_IGNORE_PREBINDING ==> gLinkContext.prebindUsage
+ // DYLD_PREBIND_DEBUG ==> gLinkContext.verbosePrebinding
+ // DYLD_NEW_LOCAL_SHARED_REGIONS ==> gLinkContext.sharedRegionMode
+ // DYLD_SHARED_REGION ==> gLinkContext.sharedRegionMode
+ // DYLD_SLIDE_AND_PACK_DYLIBS ==> gLinkContext.slideAndPackDylibs
+ // DYLD_PRINT_WARNINGS ==> gLinkContext.verboseWarnings
+};
+
+// all global state
+static const char* sExecPath = NULL;
+static const struct mach_header* sMainExecutableMachHeader = NULL;
+static cpu_type_t sHostCPU;
+static cpu_subtype_t sHostCPUsubtype;
+static ImageLoader* sMainExecutable = NULL;
+static std::vector<ImageLoader*> sAllImages;
+static std::vector<ImageLoader*> sImageRoots;
+static std::vector<ImageLoader*> sImageFilesNeedingTermination;
+static std::vector<ImageLoader*> sImagesToNotifyAboutOtherImages;
+static std::vector<ImageCallback> sAddImageCallbacks;
+static std::vector<ImageCallback> sRemoveImageCallbacks;
+static ImageLoader* sLastImageByAddressCache;
+static EnvironmentVariables sEnv;
+static const char* sFrameworkFallbackPaths[] = { "$HOME/Library/Frameworks", "/Library/Frameworks", "/Network/Library/Frameworks", "/System/Library/Frameworks", NULL };
+static const char* sLibraryFallbackPaths[] = { "$HOME/lib", "/usr/local/lib", "/usr/lib", NULL };
+static BundleNotificationCallBack sBundleNotifier = NULL;
+static BundleLocatorCallBack sBundleLocation = NULL;
+static UndefinedHandler sUndefinedHandler = NULL;
+ImageLoader::LinkContext gLinkContext;
+bool gLogAPIs = false;
+const struct ThreadingHelpers* gThreadHelpers = NULL;
+
+
+
+// utility class to assure files are closed when an exception is thrown
+class FileOpener {
+public:
+ FileOpener(const char* path);
+ ~FileOpener();
+ int getFileDescriptor() { return fd; }
+private:
+ int fd;
+};
+
+FileOpener::FileOpener(const char* path)
+{
+ fd = open(path, O_RDONLY, 0);
+}
+
+FileOpener::~FileOpener()
+{
+ close(fd);
+}
+
+
+
+// Objective-C installs an addImage hook to dyld to get notified about new images
+// The callback needs to be run after the image is rebased and bound, but before its initializers are called
+static uint32_t imageNotification(ImageLoader* image, uint32_t startIndex)
+{
+ // tell all register add image handlers about this
+ const uint32_t callbackCount = sAddImageCallbacks.size();
+ for (uint32_t i=startIndex; i < callbackCount; ++i) {
+ ImageCallback cb = sAddImageCallbacks[i];
+ //fprintf(stderr, "dyld: calling add-image-callback[%d]=%p for %s\n", i, cb, image->getPath());
+ (cb)(image->machHeader(), image->getSlide());
+ }
+ return callbackCount;
+}
+
+
+
+// notify gdb et al about these new images
+static void notifyAdding(std::vector<ImageLoader*>& images)
+{
+ // build array
+ unsigned int len = images.size();
+ if ( len != 0 ) {
+ dyld_image_info infos[len];
+ for (unsigned int i=0; i < len; ++i) {
+ dyld_image_info* p = &infos[i];
+ ImageLoader* image = images[i];
+ p->imageLoadAddress = image->machHeader();
+ p->imageFilePath = image->getPath();
+ p->imageFileModDate = image->lastModified();
+ //fprintf(stderr, "notifying objc about %s\n", image->getPath());
+ }
+
+ // tell gdb
+ addImagesToAllImages(len, infos);
+
+ // tell all interested images (after gdb, so you can debug anything the notification does)
+ for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
+ (*it)->doNotification(dyld_image_adding, len, infos);
+ }
+ }
+}
+
+
+
+// In order for register_func_for_add_image() callbacks to to be called bottom up,
+// we need to maintain a list of root images. The main executable is usally the
+// first root. Any images dynamically added are also roots (unless already loaded).
+// If DYLD_INSERT_LIBRARIES is used, those libraries are first.
+static void addRootImage(ImageLoader* image)
+{
+ //fprintf(stderr, "addRootImage(%p, %s)\n", image, image->getPath());
+ // add to list of roots
+ sImageRoots.push_back(image);
+}
+
+// Objective-C will contain a __DATA/__image_notify section which contains pointers to a function to call
+// whenever any new image is loaded.
+static void addImageNeedingNotification(ImageLoader* image)
+{
+ sImagesToNotifyAboutOtherImages.push_back(image);
+}
+
+static void addImage(ImageLoader* image)
+{
+ // add to master list
+ sAllImages.push_back(image);
+
+ if ( sEnv.DYLD_PRINT_LIBRARIES || (sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH && (sMainExecutable!=NULL) && sMainExecutable->isLinked()) ) {
+ uint64_t offset = image->getOffsetInFatFile();
+ if ( offset == 0 )
+ fprintf(stderr, "dyld: loaded: %s\n", image->getPath());
+ else
+ fprintf(stderr, "dyld: loaded: %s, cpu-sub-type: %d\n", image->getPath(), image->machHeader()->cpusubtype);
+ }
+
+#if OLD_GDB_DYLD_INTERFACE
+ // let gdb find out about this
+ addImageForgdb(image->machHeader(), image->getSlide(), image->getPath(), image->getLogicalPath());
+#endif
+}
+
+void removeImage(ImageLoader* image)
+{
+ // flush find-by-address cache
+ if ( sLastImageByAddressCache == image )
+ sLastImageByAddressCache = NULL;
+
+ // if in termination list, pull it out and run terminator
+ for (std::vector<ImageLoader*>::iterator it=sImageFilesNeedingTermination.begin(); it != sImageFilesNeedingTermination.end(); it++) {
+ if ( *it == image ) {
+ sImageFilesNeedingTermination.erase(it);
+ image->doTermination(gLinkContext);
+ break;
+ }
+ }
+
+ // tell all register add image handlers about this
+ // do this before removing image from internal data structures so that the callback can querey dyld about the image
+ for (std::vector<ImageCallback>::iterator it=sRemoveImageCallbacks.begin(); it != sRemoveImageCallbacks.end(); it++) {
+ (*it)(image->machHeader(), image->getSlide());
+ }
+
+ // remove from master list
+ for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+ if ( *it == image ) {
+ sAllImages.erase(it);
+ break;
+ }
+ }
+
+ // if in announcement list, pull it out
+ for (std::vector<ImageLoader*>::iterator it=sImagesToNotifyAboutOtherImages.begin(); it != sImagesToNotifyAboutOtherImages.end(); it++) {
+ if ( *it == image ) {
+ sImagesToNotifyAboutOtherImages.erase(it);
+ break;
+ }
+ }
+
+ // if in root list, pull it out
+ for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+ if ( *it == image ) {
+ sImageRoots.erase(it);
+ break;
+ }
+ }
+
+ // tell gdb, new way
+ removeImageFromAllImages(image->machHeader());
+
+#if OLD_GDB_DYLD_INTERFACE
+ // tell gdb, old way
+ removeImageForgdb(image->machHeader());
+ gdb_dyld_state_changed();
+#endif
+}
+
+
+static void terminationRecorder(ImageLoader* image)
+{
+ sImageFilesNeedingTermination.push_back(image);
+}
+
+const char* getExecutablePath()
+{
+ return sExecPath;
+}
+
+
+void initializeMainExecutable()
+{
+ const int rootCount = sImageRoots.size();
+ for(int i=0; i < rootCount; ++i) {
+ ImageLoader* image = sImageRoots[i];
+ //fprintf(stderr, "initializeMainExecutable: image = %p\n", image);
+ image->runInitializers(gLinkContext);
+ }
+/*
+ // this does not work???
+ for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+ ImageLoader* image = *it;
+ fprintf(stderr, "initializeMainExecutable: image = %p\n", image);
+ // don't know why vector sometimes starts with NULL element???
+ if ( image != NULL )
+ image->runInitializers(gLinkContext);
+ }
+*/
+ if ( sEnv.DYLD_PRINT_STATISTICS )
+ ImageLoaderMachO::printStatistics(sAllImages.size());
+}
+
+bool mainExecutablePrebound()
+{
+ return sMainExecutable->usablePrebinding(gLinkContext);
+}
+
+ImageLoader* mainExecutable()
+{
+ return sMainExecutable;
+}
+
+
+void runTerminators()
+{
+ const unsigned int imageCount = sImageFilesNeedingTermination.size();
+ for(unsigned int i=imageCount; i > 0; --i){
+ ImageLoader* image = sImageFilesNeedingTermination[i-1];
+ image->doTermination(gLinkContext);
+ }
+ sImageFilesNeedingTermination.clear();
+}
+
+
+//
+// Turns a colon separated list of strings
+// into a NULL terminated array of string
+// pointers.
+//
+static const char** parseColonList(const char* list)
+{
+ if ( list[0] == '\0' )
+ return NULL;
+
+ int colonCount = 0;
+ for(const char* s=list; *s != '\0'; ++s) {
+ if (*s == ':')
+ ++colonCount;
+ }
+
+ int index = 0;
+ const char* start = list;
+ char** result = new char*[colonCount+2];
+ for(const char* s=list; *s != '\0'; ++s) {
+ if (*s == ':') {
+ int len = s-start;
+ char* str = new char[len+1];
+ strncpy(str, start, len);
+ str[len] = '\0';
+ start = &s[1];
+ result[index++] = str;
+ }
+ }
+ int len = strlen(start);
+ char* str = new char[len+1];
+ strcpy(str, start);
+ result[index++] = str;
+ result[index] = NULL;
+
+ return (const char**)result;
+}
+
+/*
+ * Library path searching is not done for setuid programs
+ * which are not run by the real user. Futher the
+ * evironment varaible for the library path is cleared so
+ * that if this program executes a non-set uid program this
+ * part of the evironment will not be passed along so that
+ * that program also will not have it's libraries searched
+ * for.
+ */
+ static bool riskyUser()
+ {
+ static bool checked = false;
+ static bool risky = false;
+ if ( !checked ) {
+ risky = ( getuid() != 0 && (getuid() != geteuid() || getgid() != getegid()) );
+ checked = true;
+ }
+ return risky;
+ }
+
+
+static bool disableIfBadUser(char* rhs)
+{
+ bool didDisable = false;
+ if ( riskyUser() ) {
+ *rhs ='\0';
+ didDisable = true;
+ }
+ return didDisable;
+}
+
+static void paths_expand_roots(const char **paths, const char *key, const char *val)
+{
+// assert(val != NULL);
+// assert(paths != NULL);
+ if(NULL != key) {
+ size_t keyLen = strlen(key);
+ for(int i=0; paths[i] != NULL; ++i) {
+ if ( strncmp(paths[i], key, keyLen) == 0 ) {
+ char* newPath = new char[strlen(val) + (strlen(paths[i]) - keyLen) + 1];
+ strcpy(newPath, val);
+ strcat(newPath, &paths[i][keyLen]);
+ paths[i] = newPath;
+ }
+ }
+ }
+ return;
+}
+
+static void removePathWithPrefix(const char* paths[], const char* prefix)
+{
+ size_t prefixLen = strlen(prefix);
+ for(int s=0,d=0; (paths[d] != NULL) && (paths[s] != NULL); ++s, ++d) {
+ if ( strncmp(paths[s], prefix, prefixLen) == 0 )
+ ++s;
+ paths[d] = paths[s];
+ }
+}
+
+#if 0
+static void paths_dump(const char **paths)
+{
+// assert(paths != NULL);
+ const char **strs = paths;
+ while(*strs != NULL)
+ {
+ fprintf(stderr, "\"%s\"\n", *strs);
+ strs++;
+ }
+ return;
+}
+#endif
+
+static void printOptions(const char* argv[])
+{
+ uint32_t i = 0;
+ while ( NULL != argv[i] ) {
+ fprintf(stderr, "opt[%i] = \"%s\"\n", i, argv[i]);
+ i++;
+ }
+}
+
+static void printEnvironmentVariables(const char* envp[])
+{
+ while ( NULL != *envp ) {
+ fprintf(stderr, "%s\n", *envp);
+ envp++;
+ }
+}
+
+
+
+void processDyldEnvironmentVarible(const char* key, const char* value)
+{
+ if ( strcmp(key, "DYLD_FRAMEWORK_PATH") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ sEnv.DYLD_FRAMEWORK_PATH = parseColonList(value);
+ }
+ else if ( strcmp(key, "DYLD_FALLBACK_FRAMEWORK_PATH") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = parseColonList(value);
+ }
+ else if ( strcmp(key, "DYLD_LIBRARY_PATH") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ sEnv.DYLD_LIBRARY_PATH = parseColonList(value);
+ }
+ else if ( strcmp(key, "DYLD_FALLBACK_LIBRARY_PATH") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = parseColonList(value);
+ }
+ else if ( (strcmp(key, "DYLD_ROOT_PATH") == 0) || (strcmp(key, "DYLD_PATHS_ROOT") == 0) ) {
+ if ( !disableIfBadUser((char*)value) ) {
+ if ( strcmp(value, "/") != 0 ) {
+ sEnv.DYLD_ROOT_PATH = parseColonList(value);
+ for (int i=0; sEnv.DYLD_ROOT_PATH[i] != NULL; ++i) {
+ if ( sEnv.DYLD_ROOT_PATH[i][0] != '/' ) {
+ fprintf(stderr, "dyld: warning DYLD_ROOT_PATH not used because it contains a non-absolute path");
+ sEnv.DYLD_ROOT_PATH = NULL;
+ }
+ }
+ }
+ }
+ }
+ else if ( strcmp(key, "DYLD_IMAGE_SUFFIX") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ gLinkContext.imageSuffix = value;
+ }
+ else if ( strcmp(key, "DYLD_INSERT_LIBRARIES") == 0 ) {
+ if ( !disableIfBadUser((char*)value) )
+ sEnv.DYLD_INSERT_LIBRARIES = parseColonList(value);
+ }
+ else if ( strcmp(key, "DYLD_DEBUG_TRACE") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_DEBUG_TRACE not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_ERROR_PRINT") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_ERROR_PRINT not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_PRINT_OPTS") == 0 ) {
+ sEnv.DYLD_PRINT_OPTS = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_ENV") == 0 ) {
+ sEnv.DYLD_PRINT_ENV = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_LIBRARIES") == 0 ) {
+ sEnv.DYLD_PRINT_LIBRARIES = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_LIBRARIES_POST_LAUNCH") == 0 ) {
+ sEnv.DYLD_PRINT_LIBRARIES_POST_LAUNCH = true;
+ }
+ else if ( strcmp(key, "DYLD_TRACE") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_TRACE not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_EBADEXEC_ONLY") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_EBADEXEC_ONLY not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_BIND_AT_LAUNCH") == 0 ) {
+ sEnv.DYLD_BIND_AT_LAUNCH = true;
+ }
+ else if ( strcmp(key, "DYLD_FORCE_FLAT_NAMESPACE") == 0 ) {
+ gLinkContext.bindFlat = true;
+ }
+ else if ( strcmp(key, "DYLD_DEAD_LOCK_HANG") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_DEAD_LOCK_HANG not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_ABORT_MULTIPLE_INITS") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_ABORT_MULTIPLE_INITS not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_NEW_LOCAL_SHARED_REGIONS") == 0 ) {
+ gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
+ }
+ else if ( strcmp(key, "DYLD_SLIDE_AND_PACK_DYLIBS") == 0 ) {
+ gLinkContext.slideAndPackDylibs = true;
+ }
+ else if ( strcmp(key, "DYLD_NO_FIX_PREBINDING") == 0 ) {
+ // since the new dyld never runs fix_prebinding, no need to warn if someone does not want it run
+ //fprintf(stderr, "dyld: warning DYLD_NO_FIX_PREBINDING not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_PREBIND_DEBUG") == 0 ) {
+ gLinkContext.verbosePrebinding = true;
+ }
+ else if ( strcmp(key, "DYLD_HINTS_DEBUG") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_HINTS_DEBUG not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_SAMPLE_DEBUG") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_SAMPLE_DEBUG not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_EXECUTABLE_PATH_DEBUG") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_EXECUTABLE_PATH_DEBUG not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_TWO_LEVEL_DEBUG") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_TWO_LEVEL_DEBUG not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_LAZY_INITIALIZERS") == 0 ) {
+ fprintf(stderr, "dyld: warning DYLD_LAZY_INITIALIZERS not supported\n");
+ }
+ else if ( strcmp(key, "DYLD_PRINT_INITIALIZERS") == 0 ) {
+ gLinkContext.verboseInit = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_STATISTICS") == 0 ) {
+ sEnv.DYLD_PRINT_STATISTICS = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_SEGMENTS") == 0 ) {
+ gLinkContext.verboseMapping = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_BINDINGS") == 0 ) {
+ gLinkContext.verboseBind = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_REBASINGS") == 0 ) {
+ gLinkContext.verboseRebase = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_APIS") == 0 ) {
+ gLogAPIs = true;
+ }
+ else if ( strcmp(key, "DYLD_PRINT_WARNINGS") == 0 ) {
+ gLinkContext.verboseWarnings = true;
+ }
+ else if ( strcmp(key, "DYLD_SHARED_REGION") == 0 ) {
+ if ( strcmp(value, "private") == 0 ) {
+ gLinkContext.sharedRegionMode = ImageLoader::kUsePrivateSharedRegion;
+ }
+ else if ( strcmp(value, "avoid") == 0 ) {
+ gLinkContext.sharedRegionMode = ImageLoader::kDontUseSharedRegion;
+ }
+ else if ( strcmp(value, "use") == 0 ) {
+ gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
+ }
+ else if ( value[0] == '\0' ) {
+ gLinkContext.sharedRegionMode = ImageLoader::kUseSharedRegion;
+ }
+ else {
+ fprintf(stderr, "dyld: warning unknown option to DYLD_SHARED_REGION. Valid options are: use, private, avoid\n");
+ }
+ }
+ else if ( strcmp(key, "DYLD_IGNORE_PREBINDING") == 0 ) {
+ if ( strcmp(value, "all") == 0 ) {
+ gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
+ }
+ else if ( strcmp(value, "app") == 0 ) {
+ gLinkContext.prebindUsage = ImageLoader::kUseAllButAppPredbinding;
+ }
+ else if ( strcmp(value, "nonsplit") == 0 ) {
+ gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
+ }
+ else if ( value[0] == '\0' ) {
+ gLinkContext.prebindUsage = ImageLoader::kUseSplitSegPrebinding;
+ }
+ else {
+ fprintf(stderr, "dyld: warning unknown option to DYLD_IGNORE_PREBINDING. Valid options are: all, app, nonsplit\n");
+ }
+ }
+ else {
+ fprintf(stderr, "dyld: warning, unknown environment variable: %s\n", key);
+ }
+}
+
+static void checkEnvironmentVariables(const char* envp[])
+{
+ const char* home = NULL;
+ const char** p;
+ for(p = envp; *p != NULL; p++) {
+ const char* keyEqualsValue = *p;
+ if ( strncmp(keyEqualsValue, "DYLD_", 5) == 0 ) {
+ const char* equals = strchr(keyEqualsValue, '=');
+ if ( equals != NULL ) {
+ const char* value = &equals[1];
+ const int keyLen = equals-keyEqualsValue;
+ char key[keyLen];
+ strncpy(key, keyEqualsValue, keyLen);
+ key[keyLen] = '\0';
+ processDyldEnvironmentVarible(key, value);
+ }
+ }
+ else if ( strncmp(keyEqualsValue, "HOME=", 5) == 0 ) {
+ home = &keyEqualsValue[5];
+ }
+ else if ( strncmp(keyEqualsValue, "LD_LIBRARY_PATH=", 16) == 0 ) {
+ const char* path = &keyEqualsValue[16];
+ if ( !disableIfBadUser((char*)path) )
+ sEnv.LD_LIBRARY_PATH = parseColonList(path);
+ }
+ }
+
+ // default value for DYLD_FALLBACK_FRAMEWORK_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_FRAMEWORK_PATH == NULL ) {
+ const char** paths = sFrameworkFallbackPaths;
+ if ( home != NULL ) {
+ if ( riskyUser() )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
+ }
+ sEnv.DYLD_FALLBACK_FRAMEWORK_PATH = paths;
+ }
+
+ // default value for DYLD_FALLBACK_LIBRARY_PATH, if not set in environment
+ if ( sEnv.DYLD_FALLBACK_LIBRARY_PATH == NULL ) {
+ const char** paths = sLibraryFallbackPaths;
+ if ( home != NULL ) {
+ if ( riskyUser() )
+ removePathWithPrefix(paths, "$HOME");
+ else
+ paths_expand_roots(paths, "$HOME", home);
+ }
+ sEnv.DYLD_FALLBACK_LIBRARY_PATH = paths;
+ }
+}
+
+
+static void getHostInfo()
+{
+#if 0
+ struct host_basic_info info;
+ mach_msg_type_number_t count = HOST_BASIC_INFO_COUNT;
+ mach_port_t hostPort = mach_host_self();
+ kern_return_t result = host_info(hostPort, HOST_BASIC_INFO, (host_info_t)&info, &count);
+ mach_port_deallocate(mach_task_self(), hostPort);
+ if ( result != KERN_SUCCESS )
+ throw "host_info() failed";
+
+ sHostCPU = info.cpu_type;
+ sHostCPUsubtype = info.cpu_subtype;
+#endif
+
+ size_t valSize = sizeof(sHostCPU);
+ if (sysctlbyname ("hw.cputype", &sHostCPU, &valSize, NULL, 0) != 0)
+ throw "sysctlbyname(hw.cputype) failed";
+ valSize = sizeof(sHostCPUsubtype);
+ if (sysctlbyname ("hw.cpusubtype", &sHostCPUsubtype, &valSize, NULL, 0) != 0)
+ throw "sysctlbyname(hw.cpusubtype) failed";
+}
+
+bool validImage(ImageLoader* possibleImage)
+{
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
+ if ( possibleImage == sAllImages[i] ) {
+ return true;
+ }
+ }
+ return false;
+}
+
+uint32_t getImageCount()
+{
+ return sAllImages.size();
+}
+
+ImageLoader* getIndexedImage(unsigned int index)
+{
+ if ( index < sAllImages.size() )
+ return sAllImages[index];
+ else
+ return NULL;
+}
+
+ImageLoader* findImageByMachHeader(const struct mach_header* target)
+{
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
+ ImageLoader* anImage = sAllImages[i];
+ if ( anImage->machHeader() == target )
+ return anImage;
+ }
+ return NULL;
+}
+
+
+ImageLoader* findImageContainingAddress(const void* addr)
+{
+#if FIND_STATS
+ static int cacheHit = 0;
+ static int cacheMiss = 0;
+ static int cacheNotMacho = 0;
+ if ( ((cacheHit+cacheMiss+cacheNotMacho) % 100) == 0 )
+ fprintf(stderr, "findImageContainingAddress(): cache hit = %d, miss = %d, unknown = %d\n", cacheHit, cacheMiss, cacheNotMacho);
+#endif
+ // first look in image where last address was found rdar://problem/3685517
+ if ( (sLastImageByAddressCache != NULL) && sLastImageByAddressCache->containsAddress(addr) ) {
+#if FIND_STATS
+ ++cacheHit;
+#endif
+ return sLastImageByAddressCache;
+ }
+ // do exhastive search
+ // todo: consider maintaining a list sorted by address ranges and do a binary search on that
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
+ ImageLoader* anImage = sAllImages[i];
+ if ( anImage->containsAddress(addr) ) {
+ sLastImageByAddressCache = anImage;
+#if FIND_STATS
+ ++cacheMiss;
+#endif
+ return anImage;
+ }
+ }
+#if FIND_STATS
+ ++cacheNotMacho;
+#endif
+ return NULL;
+}
+
+
+void forEachImageDo( void (*callback)(ImageLoader*, void* userData), void* userData)
+{
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i) {
+ ImageLoader* anImage = sAllImages[i];
+ (*callback)(anImage, userData);
+ }
+}
+
+ImageLoader* findLoadedImage(const struct stat& stat_buf)
+{
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
+ ImageLoader* anImage = sAllImages[i];
+ if ( anImage->statMatch(stat_buf) )
+ return anImage;
+ }
+ return NULL;
+}
+
+// based on ANSI-C strstr()
+static const char* strrstr(const char* str, const char* sub)
+{
+ const int sublen = strlen(sub);
+ for(const char* p = &str[strlen(str)]; p != str; --p) {
+ if ( strncmp(p, sub, sublen) == 0 )
+ return p;
+ }
+ return NULL;
+}
+
+
+//
+// Find framework path
+//
+// /path/foo.framework/foo => foo.framework/foo
+// /path/foo.framework/Versions/A/foo => foo.framework/Versions/A/foo
+// /path/foo.framework/Frameworks/bar.framework/bar => bar.framework/bar
+// /path/foo.framework/Libraries/bar.dylb => NULL
+// /path/foo.framework/bar => NULL
+//
+// Returns NULL if not a framework path
+//
+static const char* getFrameworkPartialPath(const char* path)
+{
+ const char* dirDot = strrstr(path, ".framework/");
+ if ( dirDot != NULL ) {
+ const char* dirStart = dirDot;
+ for ( ; dirStart >= path; --dirStart) {
+ if ( (*dirStart == '/') || (dirStart == path) ) {
+ const char* frameworkStart = &dirStart[1];
+ if ( dirStart == path )
+ --frameworkStart;
+ int len = dirDot - frameworkStart;
+ char framework[len+1];
+ strncpy(framework, frameworkStart, len);
+ framework[len] = '\0';
+ const char* leaf = strrchr(path, '/');
+ if ( leaf != NULL ) {
+ if ( strcmp(framework, &leaf[1]) == 0 ) {
+ return frameworkStart;
+ }
+ if ( gLinkContext.imageSuffix != NULL ) {
+ // some debug frameworks have install names that end in _debug
+ if ( strncmp(framework, &leaf[1], len) == 0 ) {
+ if ( strcmp( gLinkContext.imageSuffix, &leaf[len+1]) == 0 )
+ return frameworkStart;
+ }
+ }
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+static const char* getLibraryLeafName(const char* path)
+{
+ const char* start = strrchr(path, '/');
+ if ( start != NULL )
+ return &start[1];
+ else
+ return path;
+}
+
+
+
+const cpu_subtype_t CPU_SUBTYPE_END_OF_LIST = -1;
+
+
+//
+// A fat file may contain multiple sub-images for the same CPU type.
+// In that case, dyld picks which sub-image to use by scanning a table
+// of preferred cpu-sub-types for the running cpu.
+//
+// There is one row in the table for each cpu-sub-type on which dyld might run.
+// The first entry in a row is that cpu-sub-type. It is followed by all
+// cpu-sub-types that can run on that cpu, if preferred order. Each row ends with
+// a "SUBTYPE_ALL" (to denote that images written to run on any cpu-sub-type are usable),
+// followed by one or more CPU_SUBTYPE_END_OF_LIST to pad out this row.
+//
+
+
+//
+// 32-bit PowerPC sub-type lists
+//
+const int kPPC_RowCount = 4;
+static const cpu_subtype_t kPPC32[kPPC_RowCount][6] = {
+ // G5 can run any code
+ { CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
+
+ // G4 can run all but G5 code
+ { CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
+ { CPU_SUBTYPE_POWERPC_7400, CPU_SUBTYPE_POWERPC_7450, CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST },
+
+ // G3 cannot run G4 or G5 code
+ { CPU_SUBTYPE_POWERPC_750, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST, CPU_SUBTYPE_END_OF_LIST }
+};
+
+
+//
+// 64-bit PowerPC sub-type lists
+//
+const int kPPC64_RowCount = 1;
+static const cpu_subtype_t kPPC64[kPPC64_RowCount][3] = {
+ // G5 can run any 64-bit code
+ { CPU_SUBTYPE_POWERPC_970, CPU_SUBTYPE_POWERPC_ALL, CPU_SUBTYPE_END_OF_LIST },
+};
+
+
+
+//
+// 32-bit x86 sub-type lists
+//
+// TO-DO
+
+
+
+// scan the tables above to find the cpu-sub-type-list for this machine
+static const cpu_subtype_t* findCPUSubtypeList(cpu_type_t cpu, cpu_subtype_t subtype)
+{
+ switch (cpu) {
+ case CPU_TYPE_POWERPC:
+ for (int i=0; i < kPPC_RowCount ; ++i) {
+ if ( kPPC32[i][0] == subtype )
+ return kPPC32[i];
+ }
+ break;
+ case CPU_TYPE_POWERPC64:
+ for (int i=0; i < kPPC64_RowCount ; ++i) {
+ if ( kPPC64[i][0] == subtype )
+ return kPPC64[i];
+ }
+ break;
+ case CPU_TYPE_I386:
+ // To do
+ break;
+ }
+ return NULL;
+}
+
+
+
+
+// scan fat table-of-contents for best most preferred subtype
+static bool fatFindBestFromOrderedList(cpu_type_t cpu, const cpu_subtype_t list[], const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+ const fat_arch* const archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+ for (uint32_t subTypeIndex=0; list[subTypeIndex] != CPU_SUBTYPE_END_OF_LIST; ++subTypeIndex) {
+ for(uint32_t fatIndex=0; fatIndex < OSSwapBigToHostInt32(fh->nfat_arch); ++fatIndex) {
+ if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[fatIndex].cputype) == cpu)
+ && (list[subTypeIndex] == archs[fatIndex].cpusubtype) ) {
+ *offset = OSSwapBigToHostInt32(archs[fatIndex].offset);
+ *len = OSSwapBigToHostInt32(archs[fatIndex].size);
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+// scan fat table-of-contents for exact match of cpu and cpu-sub-type
+static bool fatFindExactMatch(cpu_type_t cpu, cpu_subtype_t subtype, const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+ const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+ for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+ if ( ((cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu)
+ && ((cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == subtype) ) {
+ *offset = OSSwapBigToHostInt32(archs[i].offset);
+ *len = OSSwapBigToHostInt32(archs[i].size);
+ return true;
+ }
+ }
+ return false;
+}
+
+// scan fat table-of-contents for image with matching cpu-type and runs-on-all-sub-types
+static bool fatFindRunsOnAllCPUs(cpu_type_t cpu, const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+ const fat_arch* archs = (fat_arch*)(((char*)fh)+sizeof(fat_header));
+ for(uint32_t i=0; i < OSSwapBigToHostInt32(fh->nfat_arch); ++i) {
+ if ( (cpu_type_t)OSSwapBigToHostInt32(archs[i].cputype) == cpu) {
+ switch (cpu) {
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_POWERPC_ALL ) {
+ *offset = OSSwapBigToHostInt32(archs[i].offset);
+ *len = OSSwapBigToHostInt32(archs[i].size);
+ return true;
+ }
+ break;
+ case CPU_TYPE_I386:
+ if ( (cpu_subtype_t)OSSwapBigToHostInt32(archs[i].cpusubtype) == CPU_SUBTYPE_I386_ALL ) {
+ *offset = OSSwapBigToHostInt32(archs[i].offset);
+ *len = OSSwapBigToHostInt32(archs[i].size);
+ return true;
+ }
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+//
+// A fat file may contain multiple sub-images for the same cpu-type,
+// each optimized for a different cpu-sub-type (e.g G3 or G5).
+// This routine picks the optimal sub-image.
+//
+static bool fatFindBest(const fat_header* fh, uint64_t* offset, uint64_t* len)
+{
+ // assume all dylibs loaded must have same cpu type as main executable
+ const cpu_type_t cpu = sMainExecutableMachHeader->cputype;
+
+ // We only know the subtype to use if the main executable cpu type matches the host
+ if ( (cpu & CPU_TYPE_MASK) == sHostCPU ) {
+ // get preference ordered list of subtypes
+ const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(cpu, sHostCPUsubtype);
+
+ // use ordered list to find best sub-image in fat file
+ if ( subTypePreferenceList != NULL )
+ return fatFindBestFromOrderedList(cpu, subTypePreferenceList, fh, offset, len);
+
+ // if running cpu is not in list, try for an exact match
+ if ( fatFindExactMatch(cpu, sHostCPUsubtype, fh, offset, len) )
+ return true;
+ }
+
+ // running on an uknown cpu, can only load generic code
+ return fatFindRunsOnAllCPUs(cpu, fh, offset, len);
+}
+
+
+
+//
+// This is used to validate if a non-fat (aka thin or raw) mach-o file can be used
+// on the current processor. It is deemed compatible if any of the following are true:
+// 1) mach_header subtype is in list of compatible subtypes for running processor
+// 2) mach_header subtype is same as running processor subtype
+// 3) mach_header subtype runs on all processor variants
+//
+//
+bool isCompatibleMachO(const uint8_t* firstPage)
+{
+ const mach_header* mh = (mach_header*)firstPage;
+ if ( mh->magic == sMainExecutableMachHeader->magic ) {
+ if ( mh->cputype == sMainExecutableMachHeader->cputype ) {
+ if ( (mh->cputype & CPU_TYPE_MASK) == sHostCPU ) {
+ // get preference ordered list of subtypes that this machine can use
+ const cpu_subtype_t* subTypePreferenceList = findCPUSubtypeList(mh->cputype, sHostCPUsubtype);
+ if ( subTypePreferenceList != NULL ) {
+ // if image's subtype is in the list, it is compatible
+ for (const cpu_subtype_t* p = subTypePreferenceList; *p != CPU_SUBTYPE_END_OF_LIST; ++p) {
+ if ( *p == mh->cpusubtype )
+ return true;
+ }
+ // have list and not in list, so not compatible
+ throw "incompatible cpu-subtype";
+ }
+ // unknown cpu sub-type, but if exact match for current subtype then ok to use
+ if ( mh->cpusubtype == sHostCPUsubtype )
+ return true;
+ }
+
+ // cpu unknown, so don't know if subtype is compatible
+ // only load _ALL variant
+ switch (mh->cputype) {
+ case CPU_TYPE_POWERPC:
+ case CPU_TYPE_POWERPC64:
+ if ( mh->cpusubtype == CPU_SUBTYPE_POWERPC_ALL )
+ return true;
+ break;
+ case CPU_TYPE_I386:
+ if ( mh->cpusubtype == CPU_SUBTYPE_I386_ALL )
+ return true;
+ break;
+ }
+ }
+ }
+ return false;
+}
+
+
+// The kernel maps in main executable before dyld gets control. We need to
+// make an ImageLoader* for the already mapped in main executable.
+static ImageLoader* instantiateFromLoadedImage(const struct mach_header* mh, const char* path)
+{
+ // try mach-o loader
+ if ( isCompatibleMachO((const uint8_t*)mh) ) {
+ ImageLoader* image = new ImageLoaderMachO(path, mh, 0, gLinkContext);
+ addImage(image);
+ return image;
+ }
+
+ return NULL;
+}
+
+
+
+
+// map in file and instantiate an ImageLoader
+static ImageLoader* loadPhase6(int fd, struct stat& stat_buf, const char* path, const LoadContext& context)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ uint64_t fileOffset = 0;
+ uint64_t fileLength = stat_buf.st_size;
+#if __ppc64__
+ if ( *((uint32_t*)((char*)(&stat_buf)+0x60)) == 0xFEFEFEFE )
+ fileLength = *((uint64_t*)((char*)(&stat_buf)+0x30)); // HACK work around for kernel stat bug rdar://problem/3845883
+#endif
+
+ // validate it is a file (not directory)
+ if ( (stat_buf.st_mode & S_IFMT) != S_IFREG )
+ throw "not a file";
+
+ // min file is 4K
+ if ( fileLength < 4096 ) {
+ throw "file to short";
+ }
+
+ uint8_t firstPage[4096];
+ pread(fd, firstPage, 4096,0);
+
+ // if fat wrapper, find usable sub-file
+ const fat_header* fileStartAsFat = (fat_header*)firstPage;
+ if ( fileStartAsFat->magic == OSSwapBigToHostInt32(FAT_MAGIC) ) {
+ if ( fatFindBest(fileStartAsFat, &fileOffset, &fileLength) ) {
+ pread(fd, firstPage, 4096, fileOffset);
+ }
+ else {
+ throw "no matching architecture in fat wrapper";
+ }
+ }
+
+ // try mach-o loader
+ if ( isCompatibleMachO(firstPage) ) {
+ char realFilePath[PATH_MAX];
+ if ( gLinkContext.slideAndPackDylibs ) {
+ // when prebinding, we always want to track the real path of images
+ if ( realpath(path, realFilePath) != NULL )
+ path = realFilePath;
+ }
+
+ // instantiate an image
+ ImageLoader* image = new ImageLoaderMachO(path, fd, firstPage, fileOffset, fileLength, stat_buf, gLinkContext);
+
+ // now sanity check that this loaded image does not have the same install path as any existing image
+ const char* loadedImageInstallPath = image->getInstallPath();
+ if ( image->isDylib() && (loadedImageInstallPath != NULL) && (loadedImageInstallPath[0] == '/') ) {
+ for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+ ImageLoader* anImage = *it;
+ const char* installPath = anImage->getInstallPath();
+ if ( installPath != NULL) {
+ if ( strcmp(loadedImageInstallPath, installPath) == 0 ) {
+ //fprintf(stderr, "duplicate(%s) => %p\n", installPath, anImage);
+ delete image;
+ return anImage;
+ }
+ }
+ }
+ }
+
+ // some API's restrict what they can load
+ if ( context.mustBeBundle && !image->isBundle() )
+ throw "not a bundle";
+ if ( context.mustBeDylib && !image->isDylib() )
+ throw "not a dylib";
+
+ // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
+ if ( ! image->isBundle() )
+ addImage(image);
+
+ return image;
+ }
+
+ // try other file formats...
+
+ throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
+ firstPage[0], firstPage[1], firstPage[2], firstPage[3], firstPage[4], firstPage[5], firstPage[6],firstPage[7]);
+}
+
+
+// try to open file
+static ImageLoader* loadPhase5open(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stdout, "%s(%s)\n", __func__, path);
+ ImageLoader* image = NULL;
+
+ // open file (automagically closed when this function exits)
+ FileOpener file(path);
+
+ //fprintf(stderr, "open(%s) => %d\n", path, file.getFileDescriptor() );
+
+ if ( file.getFileDescriptor() == -1 )
+ return NULL;
+
+ struct stat stat_buf;
+#if __ppc64__
+ memset(&stat_buf, 254, sizeof(struct stat)); // hack until rdar://problem/3845883 is fixed
+#endif
+ if ( fstat(file.getFileDescriptor(), &stat_buf) == -1)
+ throw "stat error";
+
+ // in case image was renamed or found via symlinks, check for inode match
+ image = findLoadedImage(stat_buf);
+ if ( image != NULL )
+ return image;
+
+ // needed to implement NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED
+ if ( context.dontLoad )
+ return NULL;
+
+ try {
+ return loadPhase6(file.getFileDescriptor(), stat_buf, path, context);
+ }
+ catch (const char* msg) {
+ char* newMsg = new char[strlen(msg) + strlen(path) + 8];
+ sprintf(newMsg, "%s: %s", path, msg);
+ exceptions->push_back(newMsg);
+ return NULL;
+ }
+}
+
+// look for path match with existing loaded images
+static ImageLoader* loadPhase5check(const char* path, const LoadContext& context)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ // search path against load-path and install-path of all already loaded images
+ uint32_t hash = ImageLoader::hash(path);
+ for (std::vector<ImageLoader*>::iterator it=sAllImages.begin(); it != sAllImages.end(); it++) {
+ ImageLoader* anImage = *it;
+ // check has first to cut down on strcmp calls
+ if ( anImage->getPathHash() == hash )
+ if ( strcmp(path, anImage->getPath()) == 0 ) {
+ // if we are looking for a dylib don't return something else
+ if ( !context.mustBeDylib || anImage->isDylib() )
+ return anImage;
+ }
+ if ( context.matchByInstallName || anImage->matchInstallPath() ) {
+ const char* installPath = anImage->getInstallPath();
+ if ( installPath != NULL) {
+ if ( strcmp(path, installPath) == 0 ) {
+ // if we are looking for a dylib don't return something else
+ if ( !context.mustBeDylib || anImage->isDylib() )
+ return anImage;
+ }
+ }
+ }
+ }
+
+ //fprintf(stderr, "check(%s) => NULL\n", path);
+ return NULL;
+}
+
+
+// open or check existing
+static ImageLoader* loadPhase5(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ if ( exceptions != NULL )
+ return loadPhase5open(path, context, exceptions);
+ else
+ return loadPhase5check(path, context);
+}
+
+// try with and without image suffix
+static ImageLoader* loadPhase4(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ ImageLoader* image = NULL;
+ if ( gLinkContext.imageSuffix != NULL ) {
+ char pathWithSuffix[strlen(path)+strlen( gLinkContext.imageSuffix)+2];
+ ImageLoader::addSuffix(path, gLinkContext.imageSuffix, pathWithSuffix);
+ image = loadPhase5(pathWithSuffix, context, exceptions);
+ }
+ if ( image == NULL )
+ image = loadPhase5(path, context, exceptions);
+ return image;
+}
+
+
+// expand @ variables
+static ImageLoader* loadPhase3(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ ImageLoader* image = NULL;
+ if ( strncmp(path, "@executable_path/", 17) == 0 ) {
+ // handle @executable_path path prefix
+ const char* executablePath = sExecPath;
+ char newPath[strlen(executablePath) + strlen(path)];
+ strcpy(newPath, executablePath);
+ char* addPoint = strrchr(newPath,'/');
+ if ( addPoint != NULL )
+ strcpy(&addPoint[1], &path[17]);
+ else
+ strcpy(newPath, &path[17]);
+ image = loadPhase4(newPath, context, exceptions);
+ if ( image != NULL )
+ return image;
+
+ // perhaps main executable path is a sym link, find realpath and retry
+ char resolvedPath[PATH_MAX];
+ if ( realpath(sExecPath, resolvedPath) != NULL ) {
+ char newRealPath[strlen(resolvedPath) + strlen(path)];
+ strcpy(newRealPath, resolvedPath);
+ char* addPoint = strrchr(newRealPath,'/');
+ if ( addPoint != NULL )
+ strcpy(&addPoint[1], &path[17]);
+ else
+ strcpy(newRealPath, &path[17]);
+ image = loadPhase4(newRealPath, context, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+ }
+ else if ( (strncmp(path, "@loader_path/", 13) == 0) && (context.origin != NULL) ) {
+ // handle @loader_path path prefix
+ char newPath[strlen(context.origin) + strlen(path)];
+ strcpy(newPath, context.origin);
+ char* addPoint = strrchr(newPath,'/');
+ if ( addPoint != NULL )
+ strcpy(&addPoint[1], &path[13]);
+ else
+ strcpy(newPath, &path[13]);
+ image = loadPhase4(newPath, context, exceptions);
+ if ( image != NULL )
+ return image;
+
+ // perhaps loader path is a sym link, find realpath and retry
+ char resolvedPath[PATH_MAX];
+ if ( realpath(context.origin, resolvedPath) != NULL ) {
+ char newRealPath[strlen(resolvedPath) + strlen(path)];
+ strcpy(newRealPath, resolvedPath);
+ char* addPoint = strrchr(newRealPath,'/');
+ if ( addPoint != NULL )
+ strcpy(&addPoint[1], &path[13]);
+ else
+ strcpy(newRealPath, &path[13]);
+ image = loadPhase4(newRealPath, context, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+ }
+
+ return loadPhase4(path, context, exceptions);
+}
+
+
+// try search paths
+static ImageLoader* loadPhase2(const char* path, const LoadContext& context,
+ const char* const frameworkPaths[], const char* const libraryPaths[],
+ std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ ImageLoader* image = NULL;
+ const char* frameworkPartialPath = getFrameworkPartialPath(path);
+ if ( frameworkPaths != NULL ) {
+ if ( frameworkPartialPath != NULL ) {
+ const int frameworkPartialPathLen = strlen(frameworkPartialPath);
+ for(const char* const* fp = frameworkPaths; *fp != NULL; ++fp) {
+ char npath[strlen(*fp)+frameworkPartialPathLen+8];
+ strcpy(npath, *fp);
+ strcat(npath, "/");
+ strcat(npath, frameworkPartialPath);
+ //fprintf(stderr, "dyld: fallback framework path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, npath);
+ image = loadPhase4(npath, context, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+ }
+ }
+ if ( libraryPaths != NULL ) {
+ const char* libraryLeafName = getLibraryLeafName(path);
+ const int libraryLeafNameLen = strlen(libraryLeafName);
+ for(const char* const* lp = libraryPaths; *lp != NULL; ++lp) {
+ char libpath[strlen(*lp)+libraryLeafNameLen+8];
+ strcpy(libpath, *lp);
+ strcat(libpath, "/");
+ strcat(libpath, libraryLeafName);
+ //fprintf(stderr, "dyld: fallback library path used: %s() -> loadPhase4(\"%s\", ...)\n", __func__, libpath);
+ image = loadPhase4(libpath, context, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+ }
+ return NULL;
+}
+
+// try search overrides and fallbacks
+static ImageLoader* loadPhase1(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ ImageLoader* image = NULL;
+
+ // handle LD_LIBRARY_PATH environment variables that force searching
+ if ( context.useLdLibraryPath && (sEnv.LD_LIBRARY_PATH != NULL) ) {
+ image = loadPhase2(path, context, NULL, sEnv.LD_LIBRARY_PATH, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+
+ // handle DYLD_ environment variables that force searching
+ if ( context.useSearchPaths && ((sEnv.DYLD_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_LIBRARY_PATH != NULL)) ) {
+ image = loadPhase2(path, context, sEnv.DYLD_FRAMEWORK_PATH, sEnv.DYLD_LIBRARY_PATH, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+
+ // try raw path
+ image = loadPhase3(path, context, exceptions);
+ if ( image != NULL )
+ return image;
+
+ // try fallback paths
+ if ( (sEnv.DYLD_FALLBACK_FRAMEWORK_PATH != NULL) || (sEnv.DYLD_FALLBACK_LIBRARY_PATH != NULL) ) {
+ image = loadPhase2(path, context, sEnv.DYLD_FALLBACK_FRAMEWORK_PATH, sEnv.DYLD_FALLBACK_LIBRARY_PATH, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+
+ return NULL;
+}
+
+// try root substitutions
+static ImageLoader* loadPhase0(const char* path, const LoadContext& context, std::vector<const char*>* exceptions)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+
+ // handle DYLD_ROOT_PATH which forces absolute paths to use a new root
+ if ( (sEnv.DYLD_ROOT_PATH != NULL) && (path[0] == '/') ) {
+ for(const char* const* rootPath = sEnv.DYLD_ROOT_PATH ; *rootPath != NULL; ++rootPath) {
+ char newPath[strlen(*rootPath) + strlen(path)+2];
+ strcpy(newPath, *rootPath);
+ strcat(newPath, path);
+ ImageLoader* image = loadPhase1(newPath, context, exceptions);
+ if ( image != NULL )
+ return image;
+ }
+ }
+
+ // try raw path
+ return loadPhase1(path, context, exceptions);
+}
+
+//
+// Given all the DYLD_ environment variables, the general case for loading libraries
+// is that any given path expands into a list of possible locations to load. We
+// also must take care to ensure two copies of the "same" library are never loaded.
+//
+// The algorithm used here is that there is a separate function for each "phase" of the
+// path expansion. Each phase function calls the next phase with each possible expansion
+// of that phase. The result is the last phase is called with all possible paths.
+//
+// To catch duplicates the algorithm is run twice. The first time, the last phase checks
+// the path against all loaded images. The second time, the last phase calls open() on
+// the path. Either time, if an image is found, the phases all unwind without checking
+// for other paths.
+//
+ImageLoader* load(const char* path, const LoadContext& context)
+{
+ //fprintf(stderr, "%s(%s)\n", __func__ , path);
+ char realPath[PATH_MAX];
+ // when DYLD_IMAGE_SUFFIX is in used, do a realpath(), otherwise a load of "Foo.framework/Foo" will not match
+ if ( context.useSearchPaths && ( gLinkContext.imageSuffix != NULL) ) {
+ if ( realpath(path, realPath) != NULL )
+ path = realPath;
+ }
+
+ // try all path permutations and check against existing loaded images
+ ImageLoader* image = loadPhase0(path, context, NULL);
+ if ( image != NULL )
+ return image;
+
+ // try all path permutations and try open() until first sucesss
+ std::vector<const char*> exceptions;
+ image = loadPhase0(path, context, &exceptions);
+ if ( image != NULL )
+ return image;
+ else if ( context.dontLoad )
+ return NULL;
+ else if ( exceptions.size() == 0 )
+ throw "image not found";
+ else {
+ const char* msgStart = "no suitable image found. Did find:";
+ const char* delim = "\n\t";
+ size_t allsizes = strlen(msgStart)+8;
+ for (unsigned int i=0; i < exceptions.size(); ++i)
+ allsizes += (strlen(exceptions[i]) + strlen(delim));
+ char* fullMsg = new char[allsizes];
+ strcpy(fullMsg, msgStart);
+ for (unsigned int i=0; i < exceptions.size(); ++i) {
+ strcat(fullMsg, delim);
+ strcat(fullMsg, exceptions[i]);
+ }
+ throw (const char*)fullMsg;
+ }
+}
+
+
+
+
+// create when NSLinkModule is called for a second time on a bundle
+ImageLoader* cloneImage(ImageLoader* image)
+{
+ const uint64_t offsetInFat = image->getOffsetInFatFile();
+
+ // open file (automagically closed when this function exits)
+ FileOpener file(image->getPath());
+
+ struct stat stat_buf;
+#if __ppc64__
+ memset(&stat_buf, 254, sizeof(struct stat)); // hack until rdar://problem/3845883 is fixed
+#endif
+ if ( fstat(file.getFileDescriptor(), &stat_buf) == -1)
+ throw "stat error";
+
+ // read first page of file
+ uint8_t firstPage[4096];
+ pread(file.getFileDescriptor(), firstPage, 4096, offsetInFat);
+
+ // fat length is only used for sanity checking, since this image was already loaded once, just use upper bound
+ uint64_t lenInFat = stat_buf.st_size - offsetInFat;
+
+ // try mach-o loader
+ if ( isCompatibleMachO(firstPage) ) {
+ ImageLoader* clone = new ImageLoaderMachO(image->getPath(), file.getFileDescriptor(), firstPage, offsetInFat, lenInFat, stat_buf, gLinkContext);
+ // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
+ if ( ! image->isBundle() )
+ addImage(clone);
+ return clone;
+ }
+
+ // try other file formats...
+ throw "can't clone image";
+}
+
+
+ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName)
+{
+ // try mach-o each loader
+ if ( isCompatibleMachO(mem) ) {
+ ImageLoader* image = new ImageLoaderMachO(moduleName, (mach_header*)mem, len, gLinkContext);
+ // don't add bundles to global list, they can be loaded but not linked. When linked it will be added to list
+ if ( ! image->isBundle() )
+ addImage(image);
+ return image;
+ }
+
+ // try other file formats...
+
+ throwf("unknown file type, first eight bytes: 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X 0x%02X",
+ mem[0], mem[1], mem[2], mem[3], mem[4], mem[5], mem[6],mem[7]);
+}
+
+
+void registerAddCallback(ImageCallback func)
+{
+ // now add to list to get notified when any more images are added
+ sAddImageCallbacks.push_back(func);
+
+ // call callback with all existing images, starting at roots
+ const int rootCount = sImageRoots.size();
+ for(int i=0; i < rootCount; ++i) {
+ ImageLoader* image = sImageRoots[i];
+ image->runNotification(gLinkContext, sAddImageCallbacks.size());
+ }
+
+// for (std::vector<ImageLoader*>::iterator it=sImageRoots.begin(); it != sImageRoots.end(); it++) {
+// ImageLoader* image = *it;
+// image->runNotification(gLinkContext, sAddImageCallbacks.size());
+// }
+}
+
+void registerRemoveCallback(ImageCallback func)
+{
+ sRemoveImageCallbacks.push_back(func);
+}
+
+void clearErrorMessage()
+{
+ error_string[0] = '\0';
+}
+
+void setErrorMessage(const char* message)
+{
+ // save off error message in global buffer for CrashReporter to find
+ strncpy(error_string, message, sizeof(error_string)-1);
+ error_string[sizeof(error_string)-1] = '\0';
+}
+
+const char* getErrorMessage()
+{
+ return error_string;
+}
+
+void halt(const char* message)
+{
+ fprintf(stderr, "dyld: %s\n", message);
+ setErrorMessage(message);
+ strncpy(error_string, message, sizeof(error_string)-1);
+ error_string[sizeof(error_string)-1] = '\0';
+
+#if __ppc__ || __ppc64__
+ __asm__ ("trap");
+#elif __i386__
+ __asm__ ("int3");
+#else
+ #error unknown architecture
+#endif
+ abort(); // needed to suppress warning that noreturn function returns
+}
+
+
+uintptr_t bindLazySymbol(const mach_header* mh, uintptr_t* lazyPointer)
+{
+ uintptr_t result = 0;
+ // acquire read-lock on dyld's data structures
+#if 0 // rdar://problem/3811777 turn off locking until deadlock is resolved
+ if ( gThreadHelpers != NULL )
+ (*gThreadHelpers->lockForReading)();
+#endif
+ // lookup and bind lazy pointer and get target address
+ try {
+ // note, target should always be mach-o, because only mach-o lazy handler wired up to this
+ ImageLoader* target = dyld::findImageByMachHeader(mh);
+ if ( target == NULL )
+ throw "image not found for lazy pointer";
+ result = target->doBindLazySymbol(lazyPointer, gLinkContext);
+ }
+ catch (const char* message) {
+ fprintf(stderr, "dyld: lazy symbol binding failed: %s\n", message);
+ halt(message);
+ }
+ // release read-lock on dyld's data structures
+#if 0
+ if ( gThreadHelpers != NULL )
+ (*gThreadHelpers->unlockForReading)();
+#endif
+ // return target address to glue which jumps to it with real parameters restored
+ return result;
+}
+
+
+// SPI used by ZeroLink to lazy load bundles
+void registerZeroLinkHandlers(BundleNotificationCallBack notify, BundleLocatorCallBack locate)
+{
+ sBundleNotifier = notify;
+ sBundleLocation = locate;
+}
+
+void registerUndefinedHandler(UndefinedHandler handler)
+{
+ sUndefinedHandler = handler;
+}
+
+static void undefinedHandler(const char* symboName)
+{
+ if ( sUndefinedHandler != NULL ) {
+ (*sUndefinedHandler)(symboName);
+ }
+}
+
+static bool findExportedSymbol(const char* name, bool onlyInCoalesced, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+ // try ZeroLink short cut to finding bundle which exports this symbol
+ if ( sBundleLocation != NULL ) {
+ ImageLoader* zlImage = (*sBundleLocation)(name);
+ if ( zlImage == ((ImageLoader*)(-1)) ) {
+ // -1 is magic value that request symbol is in a bundle not yet linked into process
+ // try calling handler to link in that symbol
+ undefinedHandler(name);
+ // call locator again
+ zlImage = (*sBundleLocation)(name);
+ }
+ // if still not found, then ZeroLink has no idea where to find it
+ if ( zlImage == ((ImageLoader*)(-1)) )
+ return false;
+ if ( zlImage != NULL ) {
+ // ZeroLink cache knows where the symbol is
+ *sym = zlImage->findExportedSymbol(name, NULL, false, image);
+ if ( *sym != NULL ) {
+ *image = zlImage;
+ return true;
+ }
+ }
+ else {
+ // ZeroLink says it is in some bundle already loaded, but not linked, walk them all
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
+ ImageLoader* anImage = sAllImages[i];
+ if ( anImage->isBundle() && !anImage->hasHiddenExports() ) {
+ //fprintf(stderr, "dyld: search for %s in %s\n", name, anImage->getPath());
+ *sym = anImage->findExportedSymbol(name, NULL, false, image);
+ if ( *sym != NULL ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+
+ // search all images in order
+ ImageLoader* firstWeakImage = NULL;
+ const ImageLoader::Symbol* firstWeakSym = NULL;
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
+ ImageLoader* anImage = sAllImages[i];
+ if ( ! anImage->hasHiddenExports() && (!onlyInCoalesced || anImage->hasCoalescedExports()) ) {
+ *sym = anImage->findExportedSymbol(name, NULL, false, image);
+ if ( *sym != NULL ) {
+ // if weak definition found, record first one found
+ if ( ((*image)->getExportedSymbolInfo(*sym) & ImageLoader::kWeakDefinition) != 0 ) {
+ if ( firstWeakImage == NULL ) {
+ firstWeakImage = *image;
+ firstWeakSym = *sym;
+ }
+ }
+ else {
+ // found non-weak, so immediately return with it
+ return true;
+ }
+ }
+ }
+ }
+ if ( firstWeakSym != NULL ) {
+ // found a weak definition, but no non-weak, so return first weak found
+ *sym = firstWeakSym;
+ *image = firstWeakImage;
+ return true;
+ }
+
+ return false;
+}
+
+bool flatFindExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+ return findExportedSymbol(name, false, sym, image);
+}
+
+bool findCoalescedExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+ return findExportedSymbol(name, true, sym, image);
+}
+
+
+bool flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, ImageLoader** image)
+{
+ // search all images in order
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
+ ImageLoader* anImage = sAllImages[i];
+ // only look at images whose paths contain the hint string (NULL hint string is wildcard)
+ if ( ! anImage->isBundle() && ((librarySubstring==NULL) || (strstr(anImage->getPath(), librarySubstring) != NULL)) ) {
+ *sym = anImage->findExportedSymbol(name, NULL, false, image);
+ if ( *sym != NULL ) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+static void getMappedRegions(ImageLoader::RegionsVector& regions)
+{
+ const unsigned int imageCount = sAllImages.size();
+ for(unsigned int i=0; i < imageCount; ++i){
+ ImageLoader* anImage = sAllImages[i];
+ anImage->addMappedRegions(regions);
+ }
+}
+
+
+static ImageLoader* libraryLocator(const char* libraryName, bool search, const char* origin, const char* rpath[])
+{
+ dyld::LoadContext context;
+ context.useSearchPaths = search;
+ context.useLdLibraryPath = false;
+ context.dontLoad = false;
+ context.mustBeBundle = false;
+ context.mustBeDylib = true;
+ context.matchByInstallName = false;
+ context.origin = origin;
+ context.rpath = rpath;
+ return load(libraryName, context);
+}
+
+
+static void setContext(int argc, const char* argv[], const char* envp[], const char* apple[])
+{
+ gLinkContext.loadLibrary = &libraryLocator;
+ gLinkContext.imageNotification = &imageNotification;
+ gLinkContext.terminationRecorder = &terminationRecorder;
+ gLinkContext.flatExportFinder = &flatFindExportedSymbol;
+ gLinkContext.coalescedExportFinder = &findCoalescedExportedSymbol;
+ gLinkContext.undefinedHandler = &undefinedHandler;
+ gLinkContext.addImageNeedingNotification = &addImageNeedingNotification;
+ gLinkContext.notifyAdding = ¬ifyAdding;
+ gLinkContext.getAllMappedRegions = &getMappedRegions;
+ gLinkContext.bindingHandler = NULL;
+ gLinkContext.bindingOptions = ImageLoader::kBindingNone;
+ gLinkContext.mainExecutable = sMainExecutable;
+ gLinkContext.argc = argc;
+ gLinkContext.argv = argv;
+ gLinkContext.envp = envp;
+ gLinkContext.apple = apple;
+}
+
+
+
+void link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader::InitializerRunning runInitializers)
+{
+ // add to list of known images. This did not happen at creation time for bundles
+ if ( image->isBundle() )
+ addImage(image);
+
+ // we detect root images as those not linked in yet
+ if ( !image->isLinked() )
+ addRootImage(image);
+
+ // notify ZeroLink of new image with concat of logical and physical name
+ if ( sBundleNotifier != NULL && image->isBundle() ) {
+ const int logicalLen = strlen(image->getLogicalPath());
+ char logAndPhys[strlen(image->getPath())+logicalLen+2];
+ strcpy(logAndPhys, image->getLogicalPath());
+ strcpy(&logAndPhys[logicalLen+1], image->getPath());
+ (*sBundleNotifier)(logAndPhys, image);
+ }
+
+ // process images
+ image->link(gLinkContext, bindness, runInitializers, sAddImageCallbacks.size());
+
+#if OLD_GDB_DYLD_INTERFACE
+ // notify gdb that loaded libraries have changed
+ gdb_dyld_state_changed();
+#endif
+}
+
+
+//
+// Entry point for dyld. The kernel loads dyld and jumps to __dyld_start which
+// sets up some registers and call this function.
+//
+// Returns address of main() in target program which __dyld_start jumps to
+//
+uintptr_t
+_main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[])
+{
+ // Pickup the pointer to the exec path.
+ const char* executable = apple[0];
+ if ( executable[0] == '/' ) {
+ // have full path, use it
+ sExecPath = executable;
+ }
+ else {
+ // have relative path, use cwd to make absolute
+ char cwdbuff[MAXPATHLEN];
+ if ( getcwd(cwdbuff, MAXPATHLEN) != NULL ) {
+ // maybe use static buffer to avoid calling malloc so early...
+ char* s = new char[strlen(cwdbuff) + strlen(executable) + 2];
+ strcpy(s, cwdbuff);
+ strcat(s, "/");
+ strcat(s, executable);
+ sExecPath = s;
+ }
+ }
+ uintptr_t result = 0;
+ sMainExecutableMachHeader = mainExecutableMH;
+ checkEnvironmentVariables(envp);
+ if ( sEnv.DYLD_PRINT_OPTS )
+ printOptions(argv);
+ if ( sEnv.DYLD_PRINT_ENV )
+ printEnvironmentVariables(envp);
+ getHostInfo();
+ setContext(argc, argv, envp, apple);
+ ImageLoader::BindingLaziness bindness = sEnv.DYLD_BIND_AT_LAUNCH ? ImageLoader::kLazyAndNonLazy : ImageLoader::kNonLazyOnly;
+
+ // load any inserted libraries before loading the main executable so that they are first in flat namespace
+ int insertLibrariesCount = 0;
+ if ( sEnv.DYLD_INSERT_LIBRARIES != NULL ) {
+ for (const char* const* lib = sEnv.DYLD_INSERT_LIBRARIES; *lib != NULL; ++lib) {
+ insertLibrariesCount++;
+ }
+ }
+ ImageLoader* insertedImages[insertLibrariesCount];
+ if ( insertLibrariesCount > 0 ) {
+ for (int i=0; i < insertLibrariesCount; ++i) {
+ try {
+ LoadContext context;
+ context.useSearchPaths = false;
+ context.useLdLibraryPath = false;
+ context.dontLoad = false;
+ context.mustBeBundle = false;
+ context.mustBeDylib = true;
+ context.matchByInstallName = false;
+ context.origin = NULL; // can't use @loader_path with DYLD_INSERT_LIBRARIES
+ context.rpath = NULL;
+ insertedImages[i] = load(sEnv.DYLD_INSERT_LIBRARIES[i], context);
+ }
+ catch (...) {
+ char buf[strlen(sEnv.DYLD_INSERT_LIBRARIES[i])+50];
+ sprintf(buf, "could not load inserted library: %s\n", sEnv.DYLD_INSERT_LIBRARIES[i]);
+ insertedImages[i] = NULL;
+ halt(buf);
+ }
+ }
+ }
+
+ // load and link main executable
+ try {
+ sMainExecutable = instantiateFromLoadedImage(mainExecutableMH, sExecPath);
+ gLinkContext.mainExecutable = sMainExecutable;
+ if ( sMainExecutable->forceFlat() ) {
+ gLinkContext.bindFlat = true;
+ gLinkContext.prebindUsage = ImageLoader::kUseNoPrebinding;
+ }
+ link(sMainExecutable, bindness, ImageLoader::kDontRunInitializers);
+ result = (uintptr_t)sMainExecutable->getMain();
+ }
+ catch(const char* message) {
+ halt(message);
+ }
+ catch(...) {
+ fprintf(stderr, "dyld: launch failed\n");
+ }
+
+ // Link in any inserted libraries.
+ // Do this after link main executable so any extra libraries pulled in by inserted libraries are at end of flat namespace
+ if ( insertLibrariesCount > 0 ) {
+ for (int i=0; i < insertLibrariesCount; ++i) {
+ try {
+ if ( insertedImages[i] != NULL )
+ link(insertedImages[i], bindness, ImageLoader::kDontRunInitializers);
+ }
+ catch (const char* message) {
+ char buf[strlen(sEnv.DYLD_INSERT_LIBRARIES[i])+50+strlen(message)];
+ sprintf(buf, "could not link inserted library: %s\n%s\n", sEnv.DYLD_INSERT_LIBRARIES[i], message);
+ halt(buf);
+ }
+ }
+ }
+
+ return result;
+}
+
+
+
+
+}; // namespace
+
+
+
--- /dev/null
+#
+# Copyright (c) 2004-2005 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@
+#
+
+#
+# Only the following symbols should be "global".
+# gdb and vmutils lookup these symbols in dyld in order to determine what images the process is using
+#
+
+# Mac OS X 10.4 way to discover a process's images
+_dyld_all_image_infos
+
+# CrashReporter uses this to get message as to why dyld terminated the process
+_error_string
+
+# Used by various tools to see build number of dyld
+_dyldVersionString
+_dyldVersionNumber
+
+# Entry points into dyld needed by loaded every image
+_stub_binding_helper
+_dyld_func_lookup
+
+# Old symbols left for compatibility
+_gdb_dyld_version
+_gdb_dyld_state_changed
+_gdb_nobject_images
+_gdb_object_image_size
+_gdb_nlibrary_images
+_gdb_library_image_size
+_object_images
+_library_images
+_send_event
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stdint.h>
+
+#include "ImageLoader.h"
+
+
+
+//
+// dyld functions available when implementing dyld API's
+//
+//
+namespace dyld {
+
+ struct LoadContext
+ {
+ bool useSearchPaths;
+ bool useLdLibraryPath;
+ bool matchByInstallName;
+ bool dontLoad;
+ bool mustBeBundle;
+ bool mustBeDylib;
+ const char* origin; // path for expanding @loader_path
+ const char** rpath; // future support of -rpath
+ };
+
+
+
+ typedef void (*ImageCallback)(const struct mach_header* mh, intptr_t slide);
+ typedef void (*BundleNotificationCallBack)(const char* imageName, ImageLoader* image);
+ typedef ImageLoader* (*BundleLocatorCallBack)(const char* symbolName);
+ typedef void (*UndefinedHandler)(const char* symbolName);
+
+
+ extern ImageLoader::LinkContext gLinkContext;
+ extern bool gLogAPIs;
+ extern const struct ThreadingHelpers* gThreadHelpers;
+
+
+ extern void registerAddCallback(ImageCallback func);
+ extern void registerRemoveCallback(ImageCallback func);
+ extern void registerZeroLinkHandlers(BundleNotificationCallBack, BundleLocatorCallBack);
+ extern void registerUndefinedHandler(UndefinedHandler);
+ extern void initializeMainExecutable();
+ extern void link(ImageLoader* image, ImageLoader::BindingLaziness bindness, ImageLoader::InitializerRunning runInitializers);
+ extern void runTerminators();
+ extern const char* getExecutablePath();
+ extern bool validImage(ImageLoader*);
+ extern ImageLoader* getIndexedImage(uint32_t index);
+ extern uint32_t getImageCount();
+ extern ImageLoader* findImageByMachHeader(const struct mach_header* target);
+ extern ImageLoader* findImageContainingAddress(const void* addr);
+ extern ImageLoader* findImageByName(const char* path);
+ extern ImageLoader* findLoadedImageByInstallPath(const char* path);
+ extern bool flatFindExportedSymbol(const char* name, const ImageLoader::Symbol** sym, ImageLoader** image);
+ extern bool flatFindExportedSymbolWithHint(const char* name, const char* librarySubstring, const ImageLoader::Symbol** sym, ImageLoader** image);
+ extern ImageLoader* load(const char* path, const LoadContext& context);
+ extern ImageLoader* loadFromMemory(const uint8_t* mem, uint64_t len, const char* moduleName);
+ extern void removeImage(ImageLoader* image);
+ extern ImageLoader* cloneImage(ImageLoader* image);
+ extern void forEachImageDo( void (*)(ImageLoader*, void*), void*);
+ extern uintptr_t _main(const struct mach_header* mainExecutableMH, int argc, const char* argv[], const char* envp[], const char* apple[]);
+ extern void halt(const char* message) __attribute__((noreturn));
+ extern void setErrorMessage(const char* msg);
+ extern const char* getErrorMessage();
+ extern void clearErrorMessage();
+ extern bool mainExecutablePrebound();
+ extern ImageLoader* mainExecutable();
+ extern void processDyldEnvironmentVarible(const char* key, const char* value);
+
+};
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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@
+ */
+
+//
+// This file implements that API's in <mach-o/dyld.h>
+//
+//
+
+
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <sys/time.h>
+
+extern "C" mach_port_name_t task_self_trap(void); // can't include <System/mach/mach_traps.h> because it is missing extern C
+
+#include "mach-o/dyld_gdb.h"
+#include "mach-o/dyld.h"
+#include "mach-o/dyld_priv.h"
+#include "dlfcn.h"
+
+#include "ImageLoader.h"
+#include "dyld.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+static char sLastErrorFilePath[1024];
+static NSLinkEditErrors sLastErrorFileCode;
+static int sLastErrorNo;
+
+
+// In 10.3.x and earlier all the NSObjectFileImage API's were implemeneted in libSystem.dylib
+// Beginning in 10.4 the NSObjectFileImage API's are implemented in dyld and libSystem just forwards
+// This conditional keeps support for old libSystem's which needed some help implementing the API's
+#define OLD_LIBSYSTEM_SUPPORT 1
+
+
+// The following functions have no prototype in any header. They are special cases
+// where _dyld_func_lookup() is used directly.
+static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit);
+static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options);
+static void _dyld_register_binding_handler(void * (*)(const char *, const char *, void *), ImageLoader::BindingOptions);
+static void _dyld_fork_prepare();
+static void _dyld_fork_parent();
+static void _dyld_fork_child();
+static void _dyld_fork_child_final();
+static void _dyld_make_delayed_module_initializer_calls();
+static void _dyld_mod_term_funcs();
+static bool NSMakePrivateModulePublic(NSModule module);
+static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header);
+static void registerThreadHelpers(const dyld::ThreadingHelpers*);
+static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags);
+static const struct dyld_all_image_infos* _dyld_get_all_image_infos();
+
+// The following functions are dyld API's, but since dyld links with a static copy of libc.a
+// the public name cannot be used.
+static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module);
+static bool client_NSIsSymbolNameDefined(const char* symbolName);
+
+
+static void unimplemented()
+{
+ dyld::halt("unimplemented dyld function\n");
+}
+
+struct dyld_func {
+ const char* name;
+ void* implementation;
+};
+
+static struct dyld_func dyld_funcs[] = {
+ {"__dyld_image_count", (void*)_dyld_image_count },
+ {"__dyld_get_image_header", (void*)_dyld_get_image_header },
+ {"__dyld_get_image_vmaddr_slide", (void*)_dyld_get_image_vmaddr_slide },
+ {"__dyld_get_image_name", (void*)_dyld_get_image_name },
+ {"__dyld_lookup_and_bind", (void*)client_dyld_lookup_and_bind },
+ {"__dyld_lookup_and_bind_with_hint", (void*)_dyld_lookup_and_bind_with_hint },
+ {"__dyld_lookup_and_bind_objc", (void*)unimplemented },
+ {"__dyld_lookup_and_bind_fully", (void*)_dyld_lookup_and_bind_fully },
+ {"__dyld_install_handlers", (void*)_dyld_install_handlers },
+ {"__dyld_link_edit_error", (void*)NSLinkEditError },
+#if OLD_LIBSYSTEM_SUPPORT
+ {"__dyld_link_module", (void*)_dyld_link_module },
+#endif
+ {"__dyld_unlink_module", (void*)NSUnLinkModule },
+ {"__dyld_register_func_for_add_image", (void*)_dyld_register_func_for_add_image },
+ {"__dyld_register_func_for_remove_image", (void*)_dyld_register_func_for_remove_image },
+ {"__dyld_register_func_for_link_module", (void*)unimplemented },
+ {"__dyld_register_func_for_unlink_module", (void*)unimplemented },
+ {"__dyld_register_func_for_replace_module", (void*)unimplemented },
+ {"__dyld_get_objc_module_sect_for_module", (void*)unimplemented },
+ {"__dyld_bind_objc_module", (void*)_dyld_bind_objc_module },
+ {"__dyld_bind_fully_image_containing_address", (void*)_dyld_bind_fully_image_containing_address },
+ {"__dyld_image_containing_address", (void*)_dyld_image_containing_address },
+ {"__dyld_get_image_header_containing_address", (void*)_dyld_get_image_header_containing_address },
+ {"__dyld_moninit", (void*)_dyld_moninit },
+ {"__dyld_register_binding_handler", (void*)_dyld_register_binding_handler },
+ {"__dyld_fork_prepare", (void*)_dyld_fork_prepare },
+ {"__dyld_fork_parent", (void*)_dyld_fork_parent },
+ {"__dyld_fork_child", (void*)_dyld_fork_child },
+ {"__dyld_fork_child_final", (void*)_dyld_fork_child_final },
+ {"__dyld_fork_mach_init", (void*)unimplemented },
+ {"__dyld_make_delayed_module_initializer_calls",(void*)_dyld_make_delayed_module_initializer_calls },
+ {"__dyld_NSNameOfSymbol", (void*)NSNameOfSymbol },
+ {"__dyld_NSAddressOfSymbol", (void*)NSAddressOfSymbol },
+ {"__dyld_NSModuleForSymbol", (void*)NSModuleForSymbol },
+ {"__dyld_NSLookupAndBindSymbol", (void*)NSLookupAndBindSymbol },
+ {"__dyld_NSLookupAndBindSymbolWithHint", (void*)NSLookupAndBindSymbolWithHint },
+ {"__dyld_NSLookupSymbolInModule", (void*)NSLookupSymbolInModule},
+ {"__dyld_NSLookupSymbolInImage", (void*)NSLookupSymbolInImage},
+ {"__dyld_NSMakePrivateModulePublic", (void*)NSMakePrivateModulePublic},
+ {"__dyld_NSIsSymbolNameDefined", (void*)client_NSIsSymbolNameDefined},
+ {"__dyld_NSIsSymbolNameDefinedWithHint", (void*)NSIsSymbolNameDefinedWithHint },
+ {"__dyld_NSIsSymbolNameDefinedInImage", (void*)NSIsSymbolNameDefinedInImage},
+ {"__dyld_NSNameOfModule", (void*)NSNameOfModule },
+ {"__dyld_NSLibraryNameForModule", (void*)NSLibraryNameForModule },
+ {"__dyld_NSAddLibrary", (void*)NSAddLibrary },
+ {"__dyld_NSAddLibraryWithSearching", (void*)NSAddLibraryWithSearching },
+ {"__dyld_NSAddImage", (void*)NSAddImage },
+ {"__dyld__NSGetExecutablePath", (void*)_NSGetExecutablePath },
+ {"__dyld_launched_prebound", (void*)_dyld_launched_prebound },
+ {"__dyld_all_twolevel_modules_prebound", (void*)_dyld_all_twolevel_modules_prebound },
+ {"__dyld_call_module_initializers_for_dylib", (void*)_dyld_call_module_initializers_for_dylib },
+ {"__dyld_mod_term_funcs", (void*)_dyld_mod_term_funcs },
+ {"__dyld_install_link_edit_symbol_handlers", (void*)dyld::registerZeroLinkHandlers },
+ {"__dyld_NSCreateObjectFileImageFromFile", (void*)NSCreateObjectFileImageFromFile },
+ {"__dyld_NSCreateObjectFileImageFromMemory", (void*)NSCreateObjectFileImageFromMemory },
+ {"__dyld_NSCreateCoreFileImageFromFile", (void*)unimplemented },
+ {"__dyld_NSDestroyObjectFileImage", (void*)NSDestroyObjectFileImage },
+ {"__dyld_NSLinkModule", (void*)NSLinkModule },
+ {"__dyld_NSHasModInitObjectFileImage", (void*)NSHasModInitObjectFileImage },
+ {"__dyld_NSSymbolDefinitionCountInObjectFileImage", (void*)NSSymbolDefinitionCountInObjectFileImage },
+ {"__dyld_NSSymbolDefinitionNameInObjectFileImage", (void*)NSSymbolDefinitionNameInObjectFileImage },
+ {"__dyld_NSIsSymbolDefinedInObjectFileImage", (void*)NSIsSymbolDefinedInObjectFileImage },
+ {"__dyld_NSSymbolReferenceNameInObjectFileImage", (void*)NSSymbolReferenceNameInObjectFileImage },
+ {"__dyld_NSSymbolReferenceCountInObjectFileImage", (void*)NSSymbolReferenceCountInObjectFileImage },
+ {"__dyld_NSGetSectionDataInObjectFileImage", (void*)NSGetSectionDataInObjectFileImage },
+ {"__dyld_NSFindSectionAndOffsetInObjectFileImage", (void*)NSFindSectionAndOffsetInObjectFileImage },
+ {"__dyld_register_thread_helpers", (void*)registerThreadHelpers },
+ {"__dyld_dladdr", (void*)dladdr },
+ {"__dyld_dlclose", (void*)dlclose },
+ {"__dyld_dlerror", (void*)dlerror },
+ {"__dyld_dlopen", (void*)dlopen },
+ {"__dyld_dlsym", (void*)dlsym },
+ {"__dyld_update_prebinding", (void*)_dyld_update_prebinding },
+ {"__dyld_get_all_image_infos", (void*)_dyld_get_all_image_infos },
+ {NULL, 0}
+};
+
+
+
+// dyld's abstract type NSSymbol is implemented as const ImageLoader::Symbol*
+inline NSSymbol SymbolToNSSymbol(const ImageLoader::Symbol* sym)
+{
+ return (NSSymbol)sym;
+}
+inline const ImageLoader::Symbol* NSSymbolToSymbol(NSSymbol sym)
+{
+ return (const ImageLoader::Symbol*)sym;
+}
+
+// dyld's abstract type NSModule is implemented as ImageLoader*
+inline NSModule ImageLoaderToNSModule(ImageLoader* image)
+{
+ return (NSModule)image;
+}
+inline ImageLoader* NSModuleToImageLoader(NSModule module)
+{
+ ImageLoader* image = (ImageLoader*)module;
+ if ( dyld::validImage(image) )
+ return image;
+ return NULL;
+}
+
+// actual definition for opaque type
+struct __NSObjectFileImage
+{
+ ImageLoader* image;
+ const void* imageBaseAddress; // not used with OFI created from files
+ size_t imageLength; // not used with OFI created from files
+};
+static std::vector<NSObjectFileImage> sObjectFileImages;
+
+
+
+//
+// __NSObjectFileImage are deleted in NSDestroyObjectFileImage()
+// The contained image is delete in one of two places:
+// NSUnLinkModule deletes the image if there is no __NSObjectFileImage with a reference to it
+// NSDestroyObjectFileImage deletes the image if image is not in list of valid images
+//
+
+
+static void dyldAPIhalt(const char* apiName, const char* errorMsg)
+{
+ fprintf(stderr, "dyld: %s() error\n", apiName);
+ dyld::halt(errorMsg);
+}
+
+
+
+static void setLastError(NSLinkEditErrors code, int errnum, const char* file, const char* message)
+{
+ dyld::setErrorMessage(message);
+ strncpy(sLastErrorFilePath, file, 1024);
+ sLastErrorFilePath[1023] = '\0';
+ sLastErrorFileCode = code;
+ sLastErrorNo = errnum;
+}
+
+
+/*
+ *_dyld_NSGetExecutablePath is the dyld side of _NSGetExecutablePath which
+ * copies the path of the executable into the buffer and returns 0 if the path
+ * was successfully copied in the provided buffer. If the buffer is not large
+ * enough, -1 is returned and the expected buffer size is copied in *bufsize.
+ * Note that _NSGetExecutablePath will return "a path" to the executable not a
+ * "real path" to the executable. That is the path may be a symbolic link and
+ * not the real file. And with deep directories the total bufsize needed could
+ * be more than MAXPATHLEN.
+ */
+int _NSGetExecutablePath(char* buf, uint32_t *bufsize)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(...)\n", __func__);
+ const char* exePath = dyld::getExecutablePath();
+ if(*bufsize < strlen(exePath) + 1){
+ *bufsize = strlen(exePath) + 1;
+ return -1;
+ }
+ strcpy(buf, exePath);
+ return 0;
+}
+
+
+//
+// _dyld_call_module_initializers_for_dylib() is the dyld side of
+// __initialize_Cplusplus() which is in dylib1.o.
+// It is intended to only be called inside -init rouintes.
+// -init routines are called before module initializers (what C++
+// initializers use). Calling __initialize_Cplusplus() in a -init
+// routine causes the module initializers for an image to be called
+// which then allows C++ to be used inside a -init routine
+//
+static void _dyld_call_module_initializers_for_dylib(const struct mach_header* mh_dylib_header)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "__initialize_Cplusplus()\n");
+
+ // for now, do nothing...
+}
+
+
+void _dyld_lookup_and_bind_fully(const char* symbolName, void** address, NSModule* module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", %p, %p)\n", __func__, symbolName, address, module);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ dyld::clearErrorMessage();
+ if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+ try {
+ dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+ if ( address != NULL)
+ *address = (void*)image->getExportedSymbolAddress(sym);
+ if ( module != NULL)
+ *module = ImageLoaderToNSModule(image);
+ }
+ catch (const char* msg) {
+ dyldAPIhalt(__func__, msg);
+ }
+ }
+ else {
+ // on failure to find symbol return NULLs
+ if ( address != NULL)
+ *address = NULL;
+ if ( module != NULL)
+ *module = NULL;
+ }
+}
+
+// Note: This cannot have public name because dyld is built with a static copy of libc.a
+// which calls dyld_lookup_and_bind() and expects to find dyld's symbols not host process
+static void client_dyld_lookup_and_bind(const char* symbolName, void** address, NSModule* module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "_dyld_lookup_and_bind(\"%s\", %p, %p)\n", symbolName, address, module);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+ if ( address != NULL)
+ *address = (void*)image->getExportedSymbolAddress(sym);
+ if ( module != NULL)
+ *module = ImageLoaderToNSModule(image);
+ }
+ else {
+ // on failure to find symbol return NULLs
+ if ( address != NULL)
+ *address = NULL;
+ if ( module != NULL)
+ *module = NULL;
+ }
+}
+
+void _dyld_lookup_and_bind_with_hint(const char* symbolName, const char* library_name_hint, void** address, NSModule* module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", \"%s\", %p, %p)\n", __func__, symbolName, library_name_hint, address, module);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ // Look for library whose path contains the hint. If that fails search everywhere
+ if ( dyld::flatFindExportedSymbolWithHint(symbolName, library_name_hint, &sym, &image)
+ || dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+ if ( address != NULL)
+ *address = (void*)image->getExportedSymbolAddress(sym);
+ if ( module != NULL)
+ *module = ImageLoaderToNSModule(image);
+ }
+ else {
+ // on failure to find symbol return NULLs
+ if ( address != NULL)
+ *address = NULL;
+ if ( module != NULL)
+ *module = NULL;
+ }
+}
+
+
+NSSymbol NSLookupAndBindSymbol(const char *symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\")\n", __func__, symbolName);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ if ( dyld::flatFindExportedSymbol(symbolName, &sym, &image) ) {
+ return SymbolToNSSymbol(sym);
+ }
+ // return NULL on failure
+ return NULL;
+}
+
+NSSymbol NSLookupAndBindSymbolWithHint(const char* symbolName, const char* libraryNameHint)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
+ if ( ! found ) {
+ // hint failed, do slow search of all images
+ found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+ }
+ if ( found )
+ return SymbolToNSSymbol(sym);
+
+ // return NULL on failure and log
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", \"%s\") => NULL \n", __func__, symbolName, libraryNameHint);
+ return NULL;
+}
+
+uint32_t _dyld_image_count(void)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ return dyld::getImageCount();
+}
+
+const struct mach_header* _dyld_get_image_header(uint32_t image_index)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%u)\n", __func__, image_index);
+ ImageLoader* image = dyld::getIndexedImage(image_index);
+ if ( image != NULL )
+ return (struct mach_header*)image->machHeader();
+ else
+ return NULL;
+}
+
+
+static __attribute__((noinline))
+const struct mach_header* addImage(const char* path, bool search, bool dontLoad, bool matchInstallName, bool abortOnError)
+{
+ ImageLoader* image = NULL;
+ try {
+ dyld::clearErrorMessage();
+ void* callerAddress = __builtin_return_address(2); // note layers: 2: real client, 1: libSystem glue, 0: dyld API
+ ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+ dyld::LoadContext context;
+ context.useSearchPaths = search;
+ context.useLdLibraryPath = false;
+ context.matchByInstallName = matchInstallName;
+ context.dontLoad = dontLoad;
+ context.mustBeBundle = false;
+ context.mustBeDylib = true;
+ context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+ context.rpath = NULL; // support not yet implemented
+
+ image = load(path, context);
+ if ( image != NULL ) {
+ if ( context.matchByInstallName )
+ image->setMatchInstallPath(true);
+ dyld::link(image, ImageLoader::kNonLazyOnly, ImageLoader::kRunInitializers);
+ return image->machHeader();
+ }
+ }
+ catch (const char* msg) {
+ if ( abortOnError) {
+ char pathMsg[strlen(msg)+strlen(path)+4];
+ strcpy(pathMsg, msg);
+ strcat(pathMsg, " ");
+ strcat(pathMsg, path);
+ dyldAPIhalt("NSAddImage", pathMsg);
+ }
+ // not halting, so set error state for NSLinkEditError to find
+ setLastError(NSLinkEditOtherError, 0, path, msg);
+ }
+ return NULL;
+}
+
+const struct mach_header* NSAddImage(const char* path, uint32_t options)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", 0x%08X)\n", __func__, path, options);
+ const bool dontLoad = ( (options & NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED) != 0 );
+ const bool search = ( (options & NSADDIMAGE_OPTION_WITH_SEARCHING) != 0 );
+ const bool matchInstallName = ( (options & NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME) != 0 );
+ const bool abortOnError = ( (options & NSADDIMAGE_OPTION_RETURN_ON_ERROR) == 0 );
+ return addImage(path, search, dontLoad, matchInstallName, abortOnError);
+}
+
+bool NSAddLibrary(const char* path)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\")\n", __func__, path);
+ return (addImage(path, false, false, false, false) != NULL);
+}
+
+bool NSAddLibraryWithSearching(const char* path)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\")\n", __func__, path);
+ return (addImage(path, true, false, false, false) != NULL);
+}
+
+
+
+//#define NSADDIMAGE_OPTION_NONE 0x0
+//#define NSADDIMAGE_OPTION_RETURN_ON_ERROR 0x1
+//#define NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME 0x8
+
+bool NSIsSymbolNameDefinedInImage(const struct mach_header* mh, const char* symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)mh, symbolName);
+ ImageLoader* image = dyld::findImageByMachHeader(mh);
+ if ( image != NULL ) {
+ if ( image->findExportedSymbol(symbolName, NULL, true, NULL) != NULL)
+ return true;
+ }
+ return false;
+}
+
+NSSymbol NSLookupSymbolInImage(const struct mach_header* mh, const char* symbolName, uint32_t options)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, mh, symbolName, options);
+ const ImageLoader::Symbol* symbol = NULL;
+ dyld::clearErrorMessage();
+ ImageLoader* image = dyld::findImageByMachHeader(mh);
+ if ( image != NULL ) {
+ try {
+ if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_FULLY ) {
+ dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+ }
+ else if ( options & NSLOOKUPSYMBOLINIMAGE_OPTION_BIND_NOW ) {
+ dyld::link(image, ImageLoader::kLazyOnlyNoDependents, ImageLoader::kDontRunInitializers);
+ }
+ }
+ catch (const char* msg) {
+ if ( (options & NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR) == 0 ) {
+ dyldAPIhalt(__func__, msg);
+ }
+ }
+ symbol = image->findExportedSymbol(symbolName, NULL, true, NULL);
+ }
+ if ( dyld::gLogAPIs && (symbol == NULL) )
+ fprintf(stderr, "%s(%p, \"%s\", 0x%08X) ==> NULL\n", __func__, mh, symbolName, options);
+ return SymbolToNSSymbol(symbol);
+}
+
+
+// Note: This cannot have public name because dyld is built with a static copy of libc.a
+// which calls NSIsSymbolNameDefined() and expects to find dyld's symbols not host process
+static bool client_NSIsSymbolNameDefined(const char* symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "NSIsSymbolNameDefined(\"%s\")\n", symbolName);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ return dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+}
+
+bool NSIsSymbolNameDefinedWithHint(const char* symbolName, const char* libraryNameHint)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", \"%s\")\n", __func__, symbolName, libraryNameHint);
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+ bool found = dyld::flatFindExportedSymbolWithHint(symbolName, libraryNameHint, &sym, &image);
+ if ( ! found ) {
+ // hint failed, do slow search of all images
+ found = dyld::flatFindExportedSymbol(symbolName, &sym, &image);
+ }
+ if ( !found && dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", \"%s\") => false \n", __func__, symbolName, libraryNameHint);
+ return found;
+}
+
+const char* NSNameOfSymbol(NSSymbol symbol)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+ const char* result = NULL;
+ ImageLoader* image = dyld::findImageContainingAddress(symbol);
+ if ( image != NULL )
+ result = image->getExportedSymbolName(NSSymbolToSymbol(symbol));
+ return result;
+}
+
+void* NSAddressOfSymbol(NSSymbol symbol)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+ void* result = NULL;
+ ImageLoader* image = dyld::findImageContainingAddress(symbol);
+ if ( image != NULL )
+ result = (void*)image->getExportedSymbolAddress(NSSymbolToSymbol(symbol));
+ return result;
+}
+
+NSModule NSModuleForSymbol(NSSymbol symbol)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, (void *)symbol);
+ NSModule result = NULL;
+ ImageLoader* image = dyld::findImageContainingAddress(symbol);
+ if ( image != NULL )
+ result = ImageLoaderToNSModule(image);
+ return result;
+}
+
+
+intptr_t _dyld_get_image_vmaddr_slide(uint32_t image_index)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%u)\n", __func__, image_index);
+ ImageLoader* image = dyld::getIndexedImage(image_index);
+ if ( image != NULL )
+ return image->getSlide();
+ else
+ return 0;
+}
+
+const char* _dyld_get_image_name(uint32_t image_index)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%u)\n", __func__, image_index);
+ ImageLoader* image = dyld::getIndexedImage(image_index);
+ if ( image != NULL )
+ return image->getLogicalPath();
+ else
+ return NULL;
+}
+
+
+
+bool _dyld_all_twolevel_modules_prebound(void)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ return FALSE; // fixme
+}
+
+void _dyld_bind_objc_module(const void *objc_module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objc_module);
+ // do nothing, with new dyld everything already bound
+}
+
+
+bool _dyld_bind_fully_image_containing_address(const void* address)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, address);
+ dyld::clearErrorMessage();
+ ImageLoader* image = dyld::findImageContainingAddress(address);
+ if ( image != NULL ) {
+ try {
+ dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
+ return true;
+ }
+ catch (const char* msg) {
+ dyldAPIhalt(__func__, msg);
+ }
+ }
+ return false;
+}
+
+bool _dyld_image_containing_address(const void* address)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, address);
+ ImageLoader *imageLoader = dyld::findImageContainingAddress(address);
+ return (NULL != imageLoader);
+}
+
+static NSObjectFileImage createObjectImageFile(ImageLoader* image, const void* address = NULL, size_t len=0)
+{
+ NSObjectFileImage result = new __NSObjectFileImage();
+ result->image = image;
+ result->imageBaseAddress = address;
+ result->imageLength = len;
+ sObjectFileImages.push_back(result);
+ return result;
+}
+
+NSObjectFileImageReturnCode NSCreateObjectFileImageFromFile(const char* pathName, NSObjectFileImage *objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(\"%s\", ...)\n", __func__, pathName);
+ try {
+ void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+ ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+
+ dyld::LoadContext context;
+ context.useSearchPaths = false;
+ context.useLdLibraryPath = false;
+ context.matchByInstallName = false;
+ context.dontLoad = false;
+ context.mustBeBundle = true;
+ context.mustBeDylib = false;
+ context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+ context.rpath = NULL; // support not yet implemented
+
+ ImageLoader* image = dyld::load(pathName, context);
+ // Note: We DO NOT link the image! NSLinkModule will do that
+ if ( image != NULL ) {
+ if ( !image->isBundle() ) {
+ // the image must have been already loaded (since context.mustBeBundle will prevent it from being loaded)
+ return NSObjectFileImageInappropriateFile;
+ }
+ *objectFileImage = createObjectImageFile(image);
+ return NSObjectFileImageSuccess;
+ }
+ }
+ catch (const char* msg) {
+ //fprintf(stderr, "dyld: NSCreateObjectFileImageFromFile() error: %s\n", msg);
+ return NSObjectFileImageInappropriateFile;
+ }
+ return NSObjectFileImageFailure;
+}
+
+
+NSObjectFileImageReturnCode NSCreateObjectFileImageFromMemory(const void* address, size_t size, NSObjectFileImage *objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, %lu, %p)\n", __func__, address, size, objectFileImage);
+
+ try {
+ ImageLoader* image = dyld::loadFromMemory((const uint8_t*)address, size, NULL);
+ if ( ! image->isBundle() ) {
+ // this API can only be used with bundles...
+ delete image;
+ return NSObjectFileImageInappropriateFile;
+ }
+ // Note: We DO NOT link the image! NSLinkModule will do that
+ if ( image != NULL ) {
+ *objectFileImage = createObjectImageFile(image, address, size);
+ return NSObjectFileImageSuccess;
+ }
+ }
+ catch (const char* msg) {
+ fprintf(stderr, "dyld: NSCreateObjectFileImageFromMemory() error: %s\n", msg);
+ }
+ return NSObjectFileImageFailure;
+}
+
+static bool validOFI(NSObjectFileImage objectFileImage)
+{
+ const int ofiCount = sObjectFileImages.size();
+ for (int i=0; i < ofiCount; ++i) {
+ if ( sObjectFileImages[i] == objectFileImage )
+ return true;
+ }
+ return false;
+}
+
+bool NSDestroyObjectFileImage(NSObjectFileImage objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+
+ if ( validOFI(objectFileImage) ) {
+ // if the image has never been linked or has been unlinked, the image is not in the list of valid images
+ // and we should delete it
+ bool linkedImage = dyld::validImage(objectFileImage->image);
+ if ( ! linkedImage )
+ delete objectFileImage->image;
+
+ // remove from list of ofi's
+ for (std::vector<NSObjectFileImage>::iterator it=sObjectFileImages.begin(); it != sObjectFileImages.end(); it++) {
+ if ( *it == objectFileImage ) {
+ sObjectFileImages.erase(it);
+ break;
+ }
+ }
+
+ // if object was created from a memory, release that memory
+ // NOTE: this is the way dyld has always done this. NSCreateObjectFileImageFromMemory() hands over ownership of the memory to dyld
+ if ( objectFileImage->imageBaseAddress != NULL ) {
+ vm_deallocate(mach_task_self(), (vm_address_t)objectFileImage->imageBaseAddress, objectFileImage->imageLength);
+ }
+
+ // free ofi object
+ delete objectFileImage;
+
+ return true;
+ }
+ return false;
+}
+
+bool NSHasModInitObjectFileImage(NSObjectFileImage objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+ return objectFileImage->image->needsInitialization();
+}
+
+uint32_t NSSymbolDefinitionCountInObjectFileImage(NSObjectFileImage objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+ return objectFileImage->image->getExportedSymbolCount();
+}
+
+const char* NSSymbolDefinitionNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
+ const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedExportedSymbol(ordinal);
+ return objectFileImage->image->getExportedSymbolName(sym);
+}
+
+uint32_t NSSymbolReferenceCountInObjectFileImage(NSObjectFileImage objectFileImage)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+ return objectFileImage->image->getImportedSymbolCount();
+}
+
+const char * NSSymbolReferenceNameInObjectFileImage(NSObjectFileImage objectFileImage, uint32_t ordinal,
+ bool* tentative_definition)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p,%d)\n", __func__, objectFileImage, ordinal);
+ const ImageLoader::Symbol* sym = objectFileImage->image->getIndexedImportedSymbol(ordinal);
+ if ( tentative_definition != NULL ) {
+ ImageLoader::ReferenceFlags flags = objectFileImage->image->geImportedSymbolInfo(sym);
+ if ( (flags & ImageLoader::kTentativeDefinition) != 0 )
+ *tentative_definition = true;
+ else
+ *tentative_definition = false;
+ }
+ return objectFileImage->image->getImportedSymbolName(sym);
+}
+
+void* NSGetSectionDataInObjectFileImage(NSObjectFileImage objectFileImage,
+ const char* segmentName, const char* sectionName, unsigned long* size)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p,%s, %s)\n", __func__, objectFileImage, segmentName, sectionName);
+
+ void* start;
+ size_t length;
+ if ( objectFileImage->image->getSectionContent(segmentName, sectionName, &start, &length) ) {
+ if ( size != NULL )
+ *size = length;
+ return start;
+ }
+ return NULL;
+}
+
+
+
+bool NSIsSymbolDefinedInObjectFileImage(NSObjectFileImage objectFileImage, const char* symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p,%s)\n", __func__, objectFileImage, symbolName);
+ const ImageLoader::Symbol* sym = objectFileImage->image->findExportedSymbol(symbolName, NULL, true, NULL);
+ return ( sym != NULL );
+}
+
+/*
+ * Given an imageOffset into an ObjectFileImage, returns
+ * the segment/section name and offset into that section of
+ * that imageOffset. Returns FALSE if the imageOffset is not
+ * in any section. You can used the resulting sectionOffset to
+ * index into the data returned by NSGetSectionDataInObjectFileImage.
+ *
+ * First appeared in Mac OS X 10.3
+ *
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool
+NSFindSectionAndOffsetInObjectFileImage(NSObjectFileImage objectFileImage,
+ unsigned long imageOffset,
+ const char** segmentName, /* can be NULL */
+ const char** sectionName, /* can be NULL */
+ unsigned long* sectionOffset) /* can be NULL */
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, objectFileImage);
+
+ return objectFileImage->image->findSection((char*)(objectFileImage->image->getBaseAddress())+imageOffset, segmentName, sectionName, sectionOffset);
+}
+
+
+
+NSModule NSLinkModule(NSObjectFileImage objectFileImage, const char* moduleName, uint32_t options)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", __func__, objectFileImage, moduleName, options);
+
+ dyld::clearErrorMessage();
+ try {
+ // NSLinkModule allows a bundle to be link multpile times
+ // each link causes the bundle to be copied to a new address
+ if ( objectFileImage->image->isLinked() ) {
+ // already linked, so clone a new one and link it
+#if 0
+ fprintf(stderr, "dyld: warning: %s(0x%08X, \"%s\", 0x%08X) called more than once for 0x%08X\n",
+ __func__, objectFileImage, moduleName, options, objectFileImage);
+#endif
+ objectFileImage->image = dyld::cloneImage(objectFileImage->image);
+ }
+
+ // if this ofi was made with NSCreateObjectFileImageFromFile() then physical path is already set
+ // if this ofi was create with NSCreateObjectFileImageFromMemory() then the phyiscal path should be set if supplied
+ if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 ) {
+ if ( objectFileImage->imageBaseAddress != NULL ) {
+ const char* physEnd = &moduleName[strlen(moduleName)+1];
+ objectFileImage->image->setPath(physEnd);
+ }
+ }
+
+ // set moduleName as the name anyone calling _dyld_get_image_name() will see
+ objectFileImage->image->setLogicalPath(moduleName);
+
+ // support private bundles
+ if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
+ objectFileImage->image->setHideExports();
+
+ // set up linking options
+ ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
+ if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
+ bindness = ImageLoader::kLazyAndNonLazy;
+ ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
+ if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
+ runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
+
+ // load libraries, rebase, bind, to make this image usable
+ dyld::link(objectFileImage->image, bindness, runInitializers);
+
+ return ImageLoaderToNSModule(objectFileImage->image);
+ }
+ catch (const char* msg) {
+ if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
+ dyldAPIhalt(__func__, msg);
+ // not halting, so set error state for NSLinkEditError to find
+ dyld::removeImage(objectFileImage->image);
+ setLastError(NSLinkEditOtherError, 0, moduleName, msg);
+ return NULL;
+ }
+}
+
+#if OLD_LIBSYSTEM_SUPPORT
+// This is for compatibility with old libSystems (libdyld.a) which process ObjectFileImages outside dyld
+static NSModule _dyld_link_module(NSObjectFileImage object_addr, size_t object_size, const char* moduleName, uint32_t options)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, \"%s\", 0x%08X)\n", "NSLinkModule", object_addr, moduleName, options); // note name/args translation
+ ImageLoader* image = NULL;
+ dyld::clearErrorMessage();
+ try {
+ const char* imageName = moduleName;
+ if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
+ imageName = &moduleName[strlen(moduleName)+1];
+
+ image = dyld::loadFromMemory((const uint8_t*)object_addr, object_size, imageName);
+
+ if ( (options & NSLINKMODULE_OPTION_TRAILING_PHYS_NAME) != 0 )
+ image->setLogicalPath(moduleName);
+
+ if ( image != NULL ) {
+ // support private bundles
+ if ( (options & NSLINKMODULE_OPTION_PRIVATE) != 0 )
+ image->setHideExports();
+
+ // set up linking options
+ ImageLoader::BindingLaziness bindness = ImageLoader::kNonLazyOnly;
+ if ( (options & NSLINKMODULE_OPTION_BINDNOW) != 0 )
+ bindness = ImageLoader::kLazyAndNonLazy;
+ ImageLoader::InitializerRunning runInitializers = ImageLoader::kRunInitializers;
+ if ( (options & NSLINKMODULE_OPTION_DONT_CALL_MOD_INIT_ROUTINES) != 0 )
+ runInitializers = ImageLoader::kDontRunInitializersButTellObjc;
+
+ // load libraries, rebase, bind, to make this image usable
+ dyld::link(image, bindness, runInitializers);
+ }
+ }
+ catch (const char* msg) {
+ if ( (options & NSLINKMODULE_OPTION_RETURN_ON_ERROR) == 0 )
+ dyldAPIhalt("NSLinkModule", msg);
+ // not halting, so set error state for NSLinkEditError to find
+ setLastError(NSLinkEditOtherError, 0, moduleName, msg);
+ // if image was created for this bundle, destroy it
+ if ( image != NULL ) {
+ dyld::removeImage(image);
+ delete image;
+ }
+ image = NULL;
+ }
+ return ImageLoaderToNSModule(image);
+}
+#endif
+
+NSSymbol NSLookupSymbolInModule(NSModule module, const char* symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, \"%s\")\n", __func__, (void *)module, symbolName);
+ ImageLoader* image = NSModuleToImageLoader(module);
+ if ( image == NULL )
+ return NULL;
+ return SymbolToNSSymbol(image->findExportedSymbol(symbolName, NULL, false, NULL));
+}
+
+const char* NSNameOfModule(NSModule module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, module);
+ ImageLoader* image = NSModuleToImageLoader(module);
+ if ( image == NULL )
+ return NULL;
+ return image->getPath();
+}
+
+const char* NSLibraryNameForModule(NSModule module)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, module);
+ ImageLoader* image = NSModuleToImageLoader(module);
+ if ( image == NULL )
+ return NULL;
+ return image->getPath();
+}
+
+bool NSUnLinkModule(NSModule module, uint32_t options)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, 0x%08X)\n", __func__, module, options);
+ if ( module == NULL )
+ return false;
+ ImageLoader* image = NSModuleToImageLoader(module);
+ if ( image == NULL )
+ return false;
+ dyld::removeImage(image);
+
+ if ( (options & NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) != 0 )
+ image->setLeaveMapped();
+
+ // TODO: NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES
+
+ // Only delete image if there is no ofi referencing it
+ // That means the ofi was destroyed after linking, so no one is left to delete this image
+ const int ofiCount = sObjectFileImages.size();
+ bool found = false;
+ for (int i=0; i < ofiCount; ++i) {
+ NSObjectFileImage ofi = sObjectFileImages[i];
+ if ( ofi->image == image )
+ found = true;
+ }
+ if ( !found )
+ delete image;
+
+ return true;
+}
+
+// internal name and parameters do not match public name and parameters...
+static void _dyld_install_handlers(void* undefined, void* multiple, void* linkEdit)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "NSLinkEditErrorHandlers()\n");
+
+ dyld::registerUndefinedHandler((dyld::UndefinedHandler)undefined);
+ // no support for multiple or linkedit handlers
+}
+
+const struct mach_header * _dyld_get_image_header_containing_address(const void* address)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, address);
+ ImageLoader* image = dyld::findImageContainingAddress(address);
+ if ( image != NULL )
+ return image->machHeader();
+ return NULL;
+}
+
+
+void _dyld_register_func_for_add_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
+ dyld::registerAddCallback(func);
+}
+
+void _dyld_register_func_for_remove_image(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, (void *)func);
+ dyld::registerRemoveCallback(func);
+}
+
+// called by atexit() function installed by crt
+static void _dyld_mod_term_funcs()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ dyld::runTerminators();
+}
+
+// called by crt before main
+static void _dyld_make_delayed_module_initializer_calls()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ dyld::initializeMainExecutable();
+}
+
+
+void NSLinkEditError(NSLinkEditErrors* c, int* errorNumber, const char** fileName, const char** errorString)
+{
+ // FIXME FIXME
+ *c = sLastErrorFileCode;
+ *errorNumber = sLastErrorNo;
+ *fileName = sLastErrorFilePath;
+ *errorString = dyld::getErrorMessage();
+}
+
+static void _dyld_register_binding_handler(void * (*bindingHandler)(const char *, const char *, void *), ImageLoader::BindingOptions bindingOptions)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ dyld::gLinkContext.bindingHandler = bindingHandler;
+ dyld::gLinkContext.bindingOptions = bindingOptions;
+}
+
+// Call by fork() in libSystem before the kernel trap is done
+static void _dyld_fork_prepare()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the parent side
+static void _dyld_fork_parent()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the child side
+static void _dyld_fork_child()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+ // The implementation of fork() in libSystem knows to reset the variable mach_task_self_
+ // in libSystem for the child of a fork. But dyld is built with a static copy
+ // of libc.a and has its own copy of mach_task_self_ which we reset here.
+ //
+ // In mach_init.h mach_task_self() is #defined to mach_task_self_ and
+ // in mach_init() mach_task_self_ is initialized to task_self_trap().
+ //
+ extern mach_port_t mach_task_self_;
+ mach_task_self_ = task_self_trap();
+}
+
+// Call by fork() in libSystem after the kernel trap is done on the child side after
+// other libSystem child side fixups are done
+static void _dyld_fork_child_final()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+}
+
+
+typedef void (*MonitorProc)(char *lowpc, char *highpc);
+
+static void monInitCallback(ImageLoader* image, void* userData)
+{
+ MonitorProc proc = (MonitorProc)userData;
+ void* start;
+ size_t length;
+ if ( image->getSectionContent("__TEXT", "__text", &start, &length) ) {
+ proc((char*)start, (char*)start+length);
+ }
+}
+
+//
+// _dyld_moninit is called from profiling runtime routine moninit().
+// dyld calls back with the range of each __TEXT/__text section in every
+// linked image.
+//
+void _dyld_moninit(MonitorProc proc)
+{
+ dyld::forEachImageDo(&monInitCallback, (void*)proc);
+}
+
+// returns true if prebinding was used in main executable
+bool _dyld_launched_prebound()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+
+ // ¥¥¥Êif we deprecate prebinding, we may want to consider always returning true or false here
+ return dyld::mainExecutablePrebound();
+}
+
+
+//
+// _dyld_NSMakePrivateModulePublic() is the dyld side of the hack
+// NSMakePrivateModulePublic() needed for the dlopen() to turn it's
+// RTLD_LOCAL handles into RTLD_GLOBAL. It just simply turns off the private
+// flag on the image for this module. If the module was found and it was
+// private then everything worked and TRUE is returned else FALSE is returned.
+//
+static bool NSMakePrivateModulePublic(NSModule module)
+{
+ ImageLoader* image = NSModuleToImageLoader(module);
+ if ( image != NULL ) {
+ if ( image->hasHiddenExports() ) {
+ image->setHideExports(false);
+ return true;
+ }
+ }
+ return false;
+}
+
+
+
+bool lookupDyldFunction(const char* name, uintptr_t* address)
+{
+ for (const dyld_func* p = dyld_funcs; p->name != NULL; ++p) {
+ if ( strcmp(p->name, name) == 0 ) {
+ if( p->implementation == unimplemented )
+ fprintf(stderr, "unimplemented dyld function: %s\n", p->name);
+ *address = (uintptr_t)p->implementation;
+ return true;
+ }
+ }
+ *address = 0;
+ return false;
+}
+
+
+static void registerThreadHelpers(const dyld::ThreadingHelpers* helpers)
+{
+ // We need to make sure libSystem's lazy pointer's are bound
+ // before installing thred helpers.
+ // The reason for this is that if accessing the lock requires
+ // a lazy pointer to be bound (and it does when multi-module
+ // libSystem) is not prebound, the lazy handler will be
+ // invoked which tries to acquire the lock again...an infinite
+ // loop.
+ ImageLoader* image = dyld::findImageContainingAddress(helpers);
+ dyld::link(image, ImageLoader::kLazyOnly, ImageLoader::kDontRunInitializers);
+
+ dyld::gThreadHelpers = helpers;
+}
+
+
+static void dlerrorClear()
+{
+ if ( dyld::gThreadHelpers != NULL ) {
+ char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
+ buffer[0] = '\0';
+ }
+}
+
+static void dlerrorSet(const char* msg)
+{
+ if ( dyld::gThreadHelpers != NULL ) {
+ char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(strlen(msg)+1);
+ strcpy(buffer, msg);
+ }
+}
+
+
+
+void* dlopen(const char* path, int mode)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%s, 0x%08X)\n", __func__, path, mode);
+
+ dlerrorClear();
+
+ // passing NULL for path means return magic object
+ if ( path == NULL ) {
+ return RTLD_DEFAULT;
+ }
+
+ try {
+ void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+ ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+
+ ImageLoader* image = NULL;
+ dyld::LoadContext context;
+ context.useSearchPaths = true;
+ context.useLdLibraryPath= (strchr(path, '/') == NULL); // a leafname implies should search
+ context.matchByInstallName = true;
+ context.dontLoad = ( (mode & RTLD_NOLOAD) != 0 );
+ context.mustBeBundle = false;
+ context.mustBeDylib = false;
+ context.origin = callerImage != NULL ? callerImage->getPath() : NULL; // caller's image's path
+ context.rpath = NULL; // support not yet implemented
+
+ image = load(path, context);
+ if ( image != NULL ) {
+ image->incrementReferenceCount();
+ if ( ! image->isLinked() ) {
+ ImageLoader::BindingLaziness bindiness = ImageLoader::kNonLazyOnly;
+ if ( (mode & RTLD_NOW) != 0 )
+ bindiness = ImageLoader::kLazyAndNonLazy;
+ dyld::link(image, bindiness, ImageLoader::kRunInitializers);
+ // only hide exports if image is not already in use
+ if ( (mode & RTLD_LOCAL) != 0 )
+ image->setHideExports(true);
+ }
+ // RTLD_NODELETE means don't unmap image even after dlclosed. This is what dlcompat did on Mac OS X 10.3
+ // On other *nix OS's, it means dlclose() should do nothing, but the handle should be invalidated.
+ // The subtle differences are:
+ // 1) if the image has any termination routines, whether they are run during dlclose or when the process terminates
+ // 2) If someone does a supsequent dlopen() on the same image, whether the same address should be used.
+ if ( (mode & RTLD_NODELETE) != 0 )
+ image->setLeaveMapped();
+ return image;
+ }
+ }
+ catch (const char* msg) {
+ const char* format = "dlopen(%s, %d): %s";
+ char temp[strlen(format)+strlen(path)+strlen(msg)+10];
+ sprintf(temp, format, path, mode, msg);
+ dlerrorSet(temp);
+ }
+ return NULL;
+}
+
+int dlclose(void* handle)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p)\n", __func__, handle);
+
+ ImageLoader* image = (ImageLoader*)handle;
+ if ( dyld::validImage(image) ) {
+ if ( image->decrementReferenceCount() ) {
+ // for now, only bundles can be unloaded
+ // to unload dylibs we would need to track all direct and indirect uses
+ if ( image->isBundle() ) {
+ dyld::removeImage(image);
+ delete image;
+ }
+ }
+ dlerrorClear();
+ return 0;
+ }
+ else {
+ dlerrorSet("invalid handle passed to dlclose()");
+ return -1;
+ }
+}
+
+
+
+int dladdr(const void* address, Dl_info* info)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, %p)\n", __func__, address, info);
+
+ ImageLoader* image = dyld::findImageContainingAddress(address);
+ if ( image != NULL ) {
+ info->dli_fname = image->getLogicalPath();
+ info->dli_fbase = (void*)image->machHeader();
+ // find closest exported symbol in the image
+ const uint32_t exportCount = image->getExportedSymbolCount();
+ const ImageLoader::Symbol* bestSym = NULL;
+ const void* bestAddr = 0;
+ for(uint32_t i=0; i < exportCount; ++i) {
+ const ImageLoader::Symbol* sym = image->getIndexedExportedSymbol(i);
+ const void* symAddr = (void*)image->getExportedSymbolAddress(sym);
+ if ( (symAddr <= address) && (bestAddr < symAddr) ) {
+ bestSym = sym;
+ bestAddr = symAddr;
+ }
+ }
+ if ( bestSym != NULL ) {
+ info->dli_sname = image->getExportedSymbolName(bestSym) + 1; // strip off leading underscore
+ info->dli_saddr = (void*)bestAddr;
+ }
+ else {
+ info->dli_sname = NULL;
+ info->dli_saddr = NULL;
+ }
+ return 1; // success
+ }
+ return 0; // failure
+}
+
+
+char* dlerror()
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+
+ if ( dyld::gThreadHelpers != NULL ) {
+ char* buffer = (*dyld::gThreadHelpers->getThreadBufferFor_dlerror)(1);
+ // if no error set, return NULL
+ if ( buffer[0] != '\0' )
+ return buffer;
+ }
+ return NULL;
+}
+
+void* dlsym(void* handle, const char* symbolName)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s(%p, %s)\n", __func__, handle, symbolName);
+
+ dlerrorClear();
+
+ ImageLoader* image;
+ const ImageLoader::Symbol* sym;
+
+ // dlsym() assumes symbolName passed in is same as in C source code
+ // dyld assumes all symbol names have an underscore prefix
+ char underscoredName[strlen(symbolName)+2];
+ underscoredName[0] = '_';
+ strcpy(&underscoredName[1], symbolName);
+
+ // magic "search all" handle
+ if ( handle == RTLD_DEFAULT ) {
+ if ( dyld::flatFindExportedSymbol(underscoredName, &sym, &image) ) {
+ return (void*)image->getExportedSymbolAddress(sym);
+ }
+ const char* format = "dlsym(RTLD_DEFAULT, %s): symbol not found";
+ char temp[strlen(format)+strlen(symbolName)+2];
+ sprintf(temp, format, symbolName);
+ dlerrorSet(temp);
+ return NULL;
+ }
+
+ // magic "search what I would see" handle
+ if ( handle == RTLD_NEXT ) {
+ void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+ ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+ sym = callerImage->resolveSymbol(underscoredName, false, &image);
+ if ( sym != NULL ) {
+ return (void*)image->getExportedSymbolAddress(sym);
+ }
+ const char* format = "dlsym(RTLD_NEXT, %s): symbol not found";
+ char temp[strlen(format)+strlen(symbolName)+2];
+ sprintf(temp, format, symbolName);
+ dlerrorSet(temp);
+ return NULL;
+ }
+#ifdef RTLD_SELF
+ // magic "search me, then what I would see" handle
+ if ( handle == RTLD_SELF ) {
+ void* callerAddress = __builtin_return_address(1); // note layers: 1: real client, 0: libSystem glue
+ ImageLoader* callerImage = dyld::findImageContainingAddress(callerAddress);
+ sym = callerImage->findExportedSymbol(underscoredName, NULL, false, &image); // search first in calling image
+ if ( sym != NULL ) {
+ return (void*)image->getExportedSymbolAddress(sym);
+ }
+ sym = callerImage->resolveSymbol(underscoredName, false, &image); // search what calling image links against
+ if ( sym != NULL ) {
+ return (void*)image->getExportedSymbolAddress(sym);
+ }
+ const char* format = "dlsym(RTLD_SELF, %s): symbol not found";
+ char temp[strlen(format)+strlen(symbolName)+2];
+ sprintf(temp, format, symbolName);
+ dlerrorSet(temp);
+ return NULL;
+ }
+#endif
+ // real handle
+ image = (ImageLoader*)handle;
+ if ( dyld::validImage(image) ) {
+ ImageLoader* foundIn;
+ sym = image->findExportedSymbol(underscoredName, NULL, true, &foundIn);
+ if ( sym != NULL ) {
+ return (void*)(foundIn->getExportedSymbolAddress(sym));
+ }
+ sym = image->resolveSymbol(underscoredName, false, &image);// search what image links against
+ if ( sym != NULL ) {
+ return (void*)image->getExportedSymbolAddress(sym);
+ }
+ const char* format = "dlsym(%p, %s): symbol not found";
+ char temp[strlen(format)+strlen(symbolName)+20];
+ sprintf(temp, format, handle, symbolName);
+ dlerrorSet(temp);
+ }
+ else {
+ dlerrorSet("invalid handle passed to dlsym()");
+ }
+ return NULL;
+}
+
+
+#define UPDATE_PREBINDING_DRY_RUN 0x00000001
+#define UPDATE_PREBINDING_PROGRESS 0x00000002
+
+//
+// SPI called only by update_prebinding tool to redo prebinding in all prebound files specified
+// There must be no dylibs loaded when this fnction is called.
+//
+__attribute__((noreturn))
+static void _dyld_update_prebinding(int pathCount, const char* paths[], uint32_t flags)
+{
+ if ( dyld::gLogAPIs )
+ fprintf(stderr, "%s()\n", __func__);
+
+ // list of requested dylibs actually loaded
+ std::vector<ImageLoader*> preboundImages;
+
+ try {
+ // verify no dylibs loaded
+ if ( dyld::getImageCount() != 1 )
+ throw "_dyld_update_prebinding cannot be called with dylib already loaded";
+
+ const uint32_t max_allowed_link_errors = 10;
+ uint32_t link_error_count = 0;
+
+ // load and link each dylib
+ for (int i=0; i < pathCount; ++i) {
+ dyld::LoadContext context;
+ context.useSearchPaths = false;
+ context.matchByInstallName = true;
+ context.dontLoad = false;
+ context.mustBeBundle = false;
+ context.mustBeDylib = true;
+ context.origin = NULL; // @loader_path not allowed in prebinding list
+ context.rpath = NULL; // support not yet implemented
+
+ ImageLoader* image = NULL;
+ try {
+ image = dyld::load(paths[i], context);
+ // bind lazy and non-lazy symbols, but don't run initializers
+ // this may bring in other dylibs later in the list or missing from list, but that is ok
+ dyld::link(image, ImageLoader::kLazyAndNonLazy, ImageLoader::kDontRunInitializers);
+ // recored images we successfully loaded
+ preboundImages.push_back(image);
+ }
+ catch (const char* msg) {
+ if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) ) {
+ const char *stage;
+ if ( image == NULL ) // load exception
+ stage = "load";
+ else // link exception
+ stage = "link";
+ fprintf(stderr, "update_prebinding: warning: could not %s %s: %s\n", stage, paths[i], msg);
+ }
+ if ( image != NULL )
+ link_error_count++;
+ if ( link_error_count > max_allowed_link_errors )
+ throw;
+ }
+ }
+
+ // find missing images
+ uint32_t loadedImageCount = dyld::getImageCount();
+ if ( loadedImageCount > (preboundImages.size()+1) ) {
+ if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+ fprintf(stderr, "update_prebinding: warning: the following dylibs were loaded but will not have their prebinding updated because they are not in the list of paths to reprebind\n");
+ for (uint32_t i=1; i < loadedImageCount; ++i) {
+ ImageLoader* target = dyld::getIndexedImage(i);
+ bool found = false;
+ for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+ if ( *it == target ) {
+ found = true;
+ break;
+ }
+ }
+ if ( !found )
+ if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+ fprintf(stderr, " %s\n", target->getPath());
+ }
+ }
+
+ // warn about unprebound files in the list
+ bool unpreboundWarned = false;
+ for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+ if ( ! (*it)->isPrebindable() && (*it != dyld::mainExecutable()) ) {
+ if ( ! unpreboundWarned ) {
+ if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+ fprintf(stderr, "update_prebinding: warning: the following dylibs were specified but were not built prebound\n");
+ unpreboundWarned = true;
+ }
+ if ( dyld::gLinkContext.verbosePrebinding || (UPDATE_PREBINDING_DRY_RUN & flags) )
+ fprintf(stderr, " %s\n", (*it)->getPath());
+ }
+ }
+
+ if(UPDATE_PREBINDING_DRY_RUN & flags) {
+ fprintf(stderr, "update_prebinding: dry-run: no changes were made to the filesystem.\n");
+ }
+ else {
+ uint32_t imageCount = preboundImages.size();
+ uint32_t imageNumber = 1;
+ // tell each image to write itself out re-prebound
+ struct timeval currentTime = { 0 , 0 };
+ gettimeofday(¤tTime, NULL);
+ time_t timestamp = currentTime.tv_sec;
+ for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+ (*it)->reprebind(dyld::gLinkContext, timestamp);
+ if(UPDATE_PREBINDING_PROGRESS & flags) {
+ fprintf(stdout, "update_prebinding: progress: %3u/%u\n", imageNumber, imageCount);
+ fflush(stdout);
+ imageNumber++;
+ }
+ }
+
+ // tell file system to flush all dirty buffers to disk
+ // after this sync, all the _redoprebinding files will be on disk
+ sync();
+
+ // now commit (swap file) for each re-prebound image
+ // this only updates directories, since the files have already been flushed by previous sync()
+ for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+ (*it)->reprebindCommit(dyld::gLinkContext, true);
+ }
+
+ // tell file system to flush all dirty buffers to disk
+ // this should flush out all directory changes caused by the file swapping
+ sync();
+ }
+ }
+ catch (const char* msg) {
+ // delete temp files
+ try {
+ for (std::vector<ImageLoader*>::iterator it=preboundImages.begin(); it != preboundImages.end(); it++) {
+ (*it)->reprebindCommit(dyld::gLinkContext, false);
+ }
+ }
+ catch (const char* commitMsg) {
+ fprintf(stderr, "update_prebinding: error: %s\n", commitMsg);
+ }
+ fprintf(stderr, "update_prebinding: error: %s\n", msg);
+ exit(1);
+ }
+ exit(0);
+}
+
+
+
+static const struct dyld_all_image_infos* _dyld_get_all_image_infos()
+{
+ return &dyld_all_image_infos;
+}
+
+
+
+
+
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stddef.h>
+#include <string.h>
+#include <crt_externs.h>
+
+#include "mach-o/dyld.h"
+#include "mach-o/dyld_priv.h"
+
+#include "dyldLock.h"
+
+/*
+ * names_match() takes an install_name from an LC_LOAD_DYLIB command and a
+ * libraryName (which is -lx or -framework Foo argument passed to the static
+ * link editor for the same library) and determines if they match. This depends
+ * on conventional use of names including major versioning.
+ */
+static
+bool
+names_match(
+char *install_name,
+const char* libraryName)
+{
+ char *basename;
+ unsigned long n;
+
+ /*
+ * Conventional install names have these forms:
+ * /System/Library/Frameworks/AppKit.framework/Versions/A/Appkit
+ * /Local/Library/Frameworks/AppKit.framework/Appkit
+ * /lib/libsys_s.A.dylib
+ * /usr/lib/libsys_s.dylib
+ */
+ basename = strrchr(install_name, '/');
+ if(basename == NULL)
+ basename = install_name;
+ else
+ basename++;
+
+ /*
+ * By checking the base name matching the library name we take care
+ * of the -framework cases.
+ */
+ if(strcmp(basename, libraryName) == 0)
+ return(TRUE);
+
+ /*
+ * Now check the base name for "lib" if so proceed to check for the
+ * -lx case dealing with a possible .X.dylib and a .dylib extension.
+ */
+ if(strncmp(basename, "lib", 3) ==0){
+ n = strlen(libraryName);
+ if(strncmp(basename+3, libraryName, n) == 0){
+ if(strncmp(basename+3+n, ".dylib", 6) == 0)
+ return(TRUE);
+ if(basename[3+n] == '.' &&
+ basename[3+n+1] != '\0' &&
+ strncmp(basename+3+n+2, ".dylib", 6) == 0)
+ return(TRUE);
+ }
+ }
+ return(FALSE);
+}
+
+void NSInstallLinkEditErrorHandlers(
+const NSLinkEditErrorHandlers* handlers)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(
+ void (*undefined)(const char* symbol_name),
+ NSModule (*multiple)(NSSymbol s, NSModule old, NSModule newhandler),
+ void (*linkEdit)(NSLinkEditErrors c, int errorNumber,
+ const char* fileName, const char* errorString)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_install_handlers", (void**)&p);
+ p(handlers->undefined, handlers->multiple, handlers->linkEdit);
+}
+
+const char*
+NSNameOfModule(
+NSModule module)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static const char* (*p)(NSModule module) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSNameOfModule", (void**)&p);
+ return(p(module));
+}
+
+const char*
+NSLibraryNameForModule(
+NSModule module)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static const char* (*p)(NSModule module) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLibraryNameForModule", (void**)&p);
+ return(p(module));
+}
+
+bool
+NSIsSymbolNameDefined(
+const char* symbolName)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(const char* symbolName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSIsSymbolNameDefined", (void**)&p);
+ return(p(symbolName));
+}
+
+bool
+NSIsSymbolNameDefinedWithHint(
+const char* symbolName,
+const char* libraryNameHint)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(const char* symbolName,
+ const char* libraryNameHint) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedWithHint", (void**)&p);
+ return(p(symbolName, libraryNameHint));
+}
+
+bool
+NSIsSymbolNameDefinedInImage(
+const struct mach_header *image,
+const char* symbolName)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(const struct mach_header *image,
+ const char* symbolName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSIsSymbolNameDefinedInImage", (void**)&p);
+ return(p(image, symbolName));
+}
+
+NSSymbol
+NSLookupAndBindSymbol(
+const char* symbolName)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSSymbol (*p)(const char* symbolName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLookupAndBindSymbol", (void**)&p);
+ return(p(symbolName));
+}
+
+NSSymbol
+NSLookupAndBindSymbolWithHint(
+const char* symbolName,
+const char* libraryNameHint)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSSymbol (*p)(const char* symbolName,
+ const char* libraryNameHint) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLookupAndBindSymbolWithHint", (void**)&p);
+ return(p(symbolName, libraryNameHint));
+}
+
+NSSymbol
+NSLookupSymbolInModule(
+NSModule module,
+const char* symbolName)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static NSSymbol (*p)(NSModule module, const char* symbolName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLookupSymbolInModule", (void**)&p);
+ return(p(module, symbolName));
+}
+
+NSSymbol
+NSLookupSymbolInImage(
+const struct mach_header *image,
+const char* symbolName,
+uint32_t options)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static NSSymbol (*p)(const struct mach_header *image,
+ const char* symbolName,
+ uint32_t options) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLookupSymbolInImage", (void**)&p);
+ return(p(image, symbolName, options));
+}
+
+const char*
+NSNameOfSymbol(
+NSSymbol symbol)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static char * (*p)(NSSymbol symbol) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSNameOfSymbol",(void**)&p);
+ return(p(symbol));
+}
+
+void *
+NSAddressOfSymbol(
+NSSymbol symbol)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void * (*p)(NSSymbol symbol) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSAddressOfSymbol", (void**)&p);
+ return(p(symbol));
+}
+
+NSModule
+NSModuleForSymbol(
+NSSymbol symbol)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static NSModule (*p)(NSSymbol symbol) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSModuleForSymbol", (void**)&p);
+ return(p(symbol));
+}
+
+bool
+NSAddLibrary(
+const char* pathName)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static bool (*p)(const char* pathName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSAddLibrary", (void**)&p);
+ return(p(pathName));
+}
+
+bool
+NSAddLibraryWithSearching(
+const char* pathName)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static bool (*p)(const char* pathName) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSAddLibraryWithSearching", (void**)&p);
+ return(p(pathName));
+}
+
+const struct mach_header *
+NSAddImage(
+const char* image_name,
+uint32_t options)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static const struct mach_header * (*p)(const char* image_name,
+ uint32_t options) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSAddImage", (void**)&p);
+ return(p(image_name, options));
+}
+
+/*
+ * This routine returns the current version of the named shared library the
+ * executable it was built with. The libraryName parameter is the same as the
+ * -lx or -framework Foo argument passed to the static link editor when building
+ * the executable (with -lx it would be "x" and with -framework Foo it would be
+ * "Foo"). If this the executable was not built against the specified library
+ * it returns -1. It should be noted that if this only returns the value the
+ * current version of the named shared library the executable was built with
+ * and not a list of current versions that dependent libraries and bundles the
+ * program is using were built with.
+ */
+int32_t
+NSVersionOfLinkTimeLibrary(
+const char* libraryName)
+{
+ unsigned long i;
+ struct load_command *load_commands, *lc;
+ struct dylib_command *dl;
+ char *install_name;
+#ifndef __OPENSTEP__
+ static struct mach_header *mh = NULL;
+ if(mh == NULL)
+ mh = _NSGetMachExecuteHeader();
+#else /* defined(__OPENSTEP__) */
+#ifdef __DYNAMIC__
+ static struct mach_header *mh = NULL;
+ if(mh == NULL)
+ _dyld_lookup_and_bind("__mh_execute_header", &mh, NULL);
+#else
+ struct mach_header *mh;
+ mh = (struct mach_header *)&_mh_execute_header;
+#endif
+#endif /* __OPENSTEP__ */
+ load_commands = (struct load_command *)
+ ((char *)mh + sizeof(struct mach_header));
+ lc = load_commands;
+ for(i = 0; i < mh->ncmds; i++){
+ if(lc->cmd == LC_LOAD_DYLIB){
+ dl = (struct dylib_command *)lc;
+ install_name = (char *)dl + dl->dylib.name.offset;
+ if(names_match(install_name, libraryName) == TRUE)
+ return(dl->dylib.current_version);
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ return(-1);
+}
+
+/*
+ * This routine returns the current version of the named shared library the
+ * program it is running against. The libraryName parameter is the same as
+ * would be static link editor using the -lx or -framework Foo flags (with -lx
+ * it would be "x" and with -framework Foo it would be "Foo"). If the program
+ * is not using the specified library it returns -1.
+ */
+int32_t
+NSVersionOfRunTimeLibrary(
+const char* libraryName)
+{
+ unsigned long i, j, n;
+ char *install_name;
+ struct load_command *load_commands, *lc;
+ struct dylib_command *dl;
+ const struct mach_header *mh;
+
+ n = _dyld_image_count();
+ for(i = 0; i < n; i++){
+ mh = _dyld_get_image_header(i);
+ if(mh->filetype != MH_DYLIB)
+ continue;
+ load_commands = (struct load_command *)
+ ((char *)mh + sizeof(struct mach_header));
+ lc = load_commands;
+ for(j = 0; j < mh->ncmds; j++){
+ if(lc->cmd == LC_ID_DYLIB){
+ dl = (struct dylib_command *)lc;
+ install_name = (char *)dl + dl->dylib.name.offset;
+ if(names_match(install_name, libraryName) == TRUE)
+ return(dl->dylib.current_version);
+ }
+ lc = (struct load_command *)((char *)lc + lc->cmdsize);
+ }
+ }
+ return(-1);
+}
+
+/*
+ * NSCreateObjectFileImageFromFile() creates an NSObjectFileImage for the
+ * specified file name if the file is a correct Mach-O file that can be loaded
+ * with NSloadModule(). For return codes of NSObjectFileImageFailure and
+ * NSObjectFileImageFormat an error message is printed to stderr. All
+ * other codes cause no printing.
+ */
+NSObjectFileImageReturnCode
+NSCreateObjectFileImageFromFile(
+const char* pathName,
+NSObjectFileImage *objectFileImage)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromFile", (void**)&p);
+ return p(pathName, objectFileImage);
+}
+
+
+/*
+ * NSCreateObjectFileImageFromMemory() creates an NSObjectFileImage for the
+ * object file mapped into memory at address of size length if the object file
+ * is a correct Mach-O file that can be loaded with NSloadModule(). For return
+ * codes of NSObjectFileImageFailure and NSObjectFileImageFormat an error
+ * message is printed to stderr. All other codes cause no printing.
+ */
+NSObjectFileImageReturnCode
+NSCreateObjectFileImageFromMemory(
+const void* address,
+size_t size,
+NSObjectFileImage *objectFileImage)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSObjectFileImageReturnCode (*p)(const void*, size_t, NSObjectFileImage*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSCreateObjectFileImageFromMemory", (void**)&p);
+ return p(address, size, objectFileImage);
+}
+
+/*
+ * NSCreateCoreFileImageFromFile() creates an NSObjectFileImage for the
+ * specified core file name if the file is a correct Mach-O core file.
+ * For return codes of NSObjectFileImageFailure and NSObjectFileImageFormat
+ * an error message is printed to stderr. All other codes cause no printing.
+ */
+NSObjectFileImageReturnCode
+NSCreateCoreFileImageFromFile(
+const char* pathName,
+NSObjectFileImage *objectFileImage)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSObjectFileImageReturnCode (*p)(const char*, NSObjectFileImage*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSCreateCoreFileImageFromFile", (void**)&p);
+ return p(pathName, objectFileImage);
+}
+
+bool
+NSDestroyObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static bool (*p)(NSObjectFileImage) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSDestroyObjectFileImage", (void**)&p);
+ return p(objectFileImage);
+}
+
+
+NSModule
+NSLinkModule(
+NSObjectFileImage objectFileImage,
+const char* moduleName,
+uint32_t options)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static NSModule (*p)(NSObjectFileImage, const char*, unsigned long) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSLinkModule", (void**)&p);
+
+ return p(objectFileImage, moduleName, options);
+}
+
+
+/*
+ * NSFindSectionAndOffsetInObjectFileImage() takes the specified imageOffset
+ * into the specified ObjectFileImage and returns the segment/section name and
+ * offset into that section of that imageOffset. Returns FALSE if the
+ * imageOffset is not in any section. You can used the resulting sectionOffset
+ * to index into the data returned by NSGetSectionDataInObjectFileImage.
+ *
+ * SPI: currently only used by ZeroLink to detect +load methods
+ */
+bool
+NSFindSectionAndOffsetInObjectFileImage(
+NSObjectFileImage objectFileImage,
+unsigned long imageOffset,
+const char** segmentName, /* can be NULL */
+const char** sectionName, /* can be NULL */
+unsigned long* sectionOffset) /* can be NULL */
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(NSObjectFileImage, unsigned long, const char**, const char**, unsigned long*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSFindSectionAndOffsetInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage, imageOffset, segmentName, sectionName, sectionOffset);
+}
+
+
+/*
+ * NSSymbolDefinitionCountInObjectFileImage() returns the number of symbol
+ * definitions in the NSObjectFileImage.
+ */
+uint32_t
+NSSymbolDefinitionCountInObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static unsigned long (*p)(NSObjectFileImage) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSSymbolDefinitionCountInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage);
+}
+
+/*
+ * NSSymbolDefinitionNameInObjectFileImage() returns the name of the i'th
+ * symbol definitions in the NSObjectFileImage. If the ordinal specified is
+ * outside the range [0..NSSymbolDefinitionCountInObjectFileImage], NULL will
+ * be returned.
+ */
+const char*
+NSSymbolDefinitionNameInObjectFileImage(
+NSObjectFileImage objectFileImage,
+uint32_t ordinal)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static const char* (*p)(NSObjectFileImage, uint32_t) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSSymbolDefinitionNameInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage, ordinal);
+}
+
+/*
+ * NSSymbolReferenceCountInObjectFileImage() returns the number of references
+ * to undefined symbols the NSObjectFileImage.
+ */
+uint32_t
+NSSymbolReferenceCountInObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static unsigned long (*p)(NSObjectFileImage) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSSymbolReferenceCountInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage);
+}
+
+/*
+ * NSSymbolReferenceNameInObjectFileImage() returns the name of the i'th
+ * undefined symbol in the NSObjectFileImage. If the ordinal specified is
+ * outside the range [0..NSSymbolReferenceCountInObjectFileImage], NULL will be
+ * returned.
+ */
+const char*
+NSSymbolReferenceNameInObjectFileImage(
+NSObjectFileImage objectFileImage,
+uint32_t ordinal,
+bool *tentative_definition) /* can be NULL */
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static const char* (*p)(NSObjectFileImage, uint32_t, bool*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSSymbolReferenceNameInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage, ordinal, tentative_definition);
+}
+
+/*
+ * NSIsSymbolDefinedInObjectFileImage() returns TRUE if the specified symbol
+ * name has a definition in the NSObjectFileImage and FALSE otherwise.
+ */
+bool
+NSIsSymbolDefinedInObjectFileImage(
+NSObjectFileImage objectFileImage,
+const char* symbolName)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(NSObjectFileImage, const char*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSIsSymbolDefinedInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage, symbolName);
+}
+
+/*
+ * NSGetSectionDataInObjectFileImage() returns a pointer to the section contents
+ * in the NSObjectFileImage for the specified segmentName and sectionName if
+ * it exists and it is not a zerofill section. If not it returns NULL. If
+ * the parameter size is not NULL the size of the section is also returned
+ * indirectly through that pointer.
+ */
+void *
+NSGetSectionDataInObjectFileImage(
+NSObjectFileImage objectFileImage,
+const char* segmentName,
+const char* sectionName,
+unsigned long *size) /* can be NULL */
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void* (*p)(NSObjectFileImage, const char*, const char*, unsigned long*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSGetSectionDataInObjectFileImage", (void**)&p);
+
+ return p(objectFileImage, segmentName, sectionName, size);
+}
+
+/*
+ * NSHasModInitObjectFileImage() returns TRUE if the NSObjectFileImage has any
+ * module initialization sections and FALSE it it does not.
+ *
+ * SPI: currently only used by ZeroLink to detect C++ initializers
+ */
+bool
+NSHasModInitObjectFileImage(
+NSObjectFileImage objectFileImage)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(NSObjectFileImage) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_NSHasModInitObjectFileImage", (void**)&p);
+
+ return p(objectFileImage);
+}
+
+void
+NSLinkEditError(
+NSLinkEditErrors *c,
+int *errorNumber,
+const char* *fileName,
+const char* *errorString)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(NSLinkEditErrors *c,
+ int *errorNumber,
+ const char* *fileName,
+ const char* *errorString) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_link_edit_error", (void**)&p);
+ if(p != NULL)
+ p(c, errorNumber, fileName, errorString);
+}
+
+bool
+NSUnLinkModule(
+NSModule module,
+uint32_t options)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static bool (*p)(NSModule module, uint32_t options) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_unlink_module", (void**)&p);
+
+ return p(module, options);
+}
+
+NSModule
+NSReplaceModule(
+NSModule moduleToReplace,
+NSObjectFileImage newObjectFileImage,
+uint32_t options)
+{
+ return(NULL);
+}
+
+/*
+ *_NSGetExecutablePath copies the path of the executable into the buffer and
+ * returns 0 if the path was successfully copied in the provided buffer. If the
+ * buffer is not large enough, -1 is returned and the expected buffer size is
+ * copied in *bufsize. Note that _NSGetExecutablePath will return "a path" to
+ * the executable not a "real path" to the executable. That is the path may be
+ * a symbolic link and not the real file. And with deep directories the total
+ * bufsize needed could be more than MAXPATHLEN.
+ */
+int
+_NSGetExecutablePath(
+char *buf,
+uint32_t *bufsize)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static int (*p)(char *buf, uint32_t *bufsize) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld__NSGetExecutablePath", (void**)&p);
+ return(p(buf, bufsize));
+}
+
+void
+_dyld_lookup_and_bind(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(const char*, void** , NSModule*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_lookup_and_bind", (void**)&p);
+ p(symbol_name, address, module);
+}
+
+void
+_dyld_lookup_and_bind_with_hint(
+const char* symbol_name,
+const char* library_name_hint,
+void** address,
+NSModule* module)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(const char*, const char*, void**, NSModule*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_lookup_and_bind_with_hint", (void**)&p);
+ p(symbol_name, library_name_hint, address, module);
+}
+
+void
+_dyld_lookup_and_bind_objc(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(const char* , void**, NSModule*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_lookup_and_bind_objc", (void**)&p);
+ p(symbol_name, address, module);
+}
+
+void
+_dyld_lookup_and_bind_fully(
+const char* symbol_name,
+void** address,
+NSModule* module)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(const char*, void**, NSModule*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_lookup_and_bind_fully", (void**)&p);
+ p(symbol_name, address, module);
+}
+
+bool
+_dyld_bind_fully_image_containing_address(
+const void* address)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static bool (*p)(const void*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_bind_fully_image_containing_address", (void**)&p);
+ return p(address);
+}
+
+
+/*
+ * _dyld_register_func_for_add_image registers the specified function to be
+ * called when a new image is added (a bundle or a dynamic shared library) to
+ * the program. When this function is first registered it is called for once
+ * for each image that is currently part of the program.
+ */
+void
+_dyld_register_func_for_add_image(
+void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_func_for_add_image", (void**)&p);
+ p(func);
+}
+
+/*
+ * _dyld_register_func_for_remove_image registers the specified function to be
+ * called when an image is removed (a bundle or a dynamic shared library) from
+ * the program.
+ */
+void
+_dyld_register_func_for_remove_image(
+void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide))
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*func)(const struct mach_header *mh, intptr_t vmaddr_slide)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_func_for_remove_image", (void**)&p);
+ p(func);
+}
+
+/*
+ * _dyld_register_func_for_link_module registers the specified function to be
+ * called when a module is bound into the program. When this function is first
+ * registered it is called for once for each module that is currently bound into
+ * the program.
+ */
+void
+_dyld_register_func_for_link_module(
+void (*func)(NSModule module))
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*func)(NSModule module)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_func_for_link_module", (void**)&p);
+ p(func);
+}
+
+/*
+ * _dyld_register_func_for_unlink_module registers the specified function to be
+ * called when a module is unbound from the program.
+ */
+void
+_dyld_register_func_for_unlink_module(
+void (*func)(NSModule module))
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*func)(NSModule module)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_func_for_unlink_module", (void**)&p);
+ p(func);
+}
+
+/*
+ * _dyld_register_func_for_replace_module registers the specified function to be
+ * called when a module is to be replace with another module in the program.
+ */
+void
+_dyld_register_func_for_replace_module(
+void (*func)(NSModule oldmodule, NSModule newmodule))
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*func)(NSModule oldmodule,
+ NSModule newmodule)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_func_for_replace_module", (void**)&p);
+ p(func);
+}
+
+
+/*
+ * _dyld_get_objc_module_sect_for_module is passed a module and sets a
+ * pointer to the (__OBJC,__module) section and its size for the specified
+ * module.
+ */
+void
+_dyld_get_objc_module_sect_for_module(
+NSModule module,
+void **objc_module,
+unsigned long *size)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void (*p)(NSModule module,
+ void **objc_module,
+ unsigned long *size) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_get_objc_module_sect_for_module", (void**)&p);
+ p(module, objc_module, size);
+}
+
+/*
+ * _dyld_bind_objc_module() is passed a pointer to something in an (__OBJC,
+ * __module) section and causes the module that is associated with that address
+ * to be bound.
+ */
+void
+_dyld_bind_objc_module(
+const void* objc_module)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void (*p)(const void *objc_module) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_bind_objc_module", (void**)&p);
+ p(objc_module);
+}
+
+
+#if __DYNAMIC__
+bool
+_dyld_present(
+void)
+{
+ // hmmm, this code is in libSystem.dylib, which is loaded by dyld...
+ return true;
+}
+#endif
+
+uint32_t
+_dyld_image_count(
+void)
+{
+ DYLD_NO_LOCK_THIS_BLOCK;
+ static unsigned long (*p)(void) = NULL;
+
+ if(_dyld_present() == 0)
+ return(0);
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_image_count", (void**)&p);
+ return(p());
+}
+
+const struct mach_header *
+_dyld_get_image_header(
+uint32_t image_index)
+{
+ DYLD_NO_LOCK_THIS_BLOCK;
+ static struct mach_header * (*p)(uint32_t image_index) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_get_image_header", (void**)&p);
+ return(p(image_index));
+}
+
+intptr_t
+_dyld_get_image_vmaddr_slide(
+uint32_t image_index)
+{
+ DYLD_NO_LOCK_THIS_BLOCK;
+ static unsigned long (*p)(uint32_t image_index) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_get_image_vmaddr_slide", (void**)&p);
+ return(p(image_index));
+}
+
+const char*
+_dyld_get_image_name(
+uint32_t image_index)
+{
+ DYLD_NO_LOCK_THIS_BLOCK;
+ static const char* (*p)(uint32_t image_index) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_get_image_name", (void**)&p);
+ return(p(image_index));
+}
+
+bool
+_dyld_image_containing_address(
+const void* address)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(const void*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_image_containing_address", (void**)&p);
+ return(p(address));
+}
+
+const struct mach_header *
+_dyld_get_image_header_containing_address(
+const void* address)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static const struct mach_header * (*p)(const void*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_get_image_header_containing_address", (void**)&p);
+ return p(address);
+}
+
+void _dyld_moninit(
+void (*monaddition)(char *lowpc, char *highpc))
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void (*p)(void (*monaddition)(char *lowpc, char *highpc)) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_moninit", (void**)&p);
+ p(monaddition);
+}
+
+bool _dyld_launched_prebound(
+void)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(void) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_launched_prebound", (void**)&p);
+ return(p());
+}
+
+bool _dyld_all_twolevel_modules_prebound(
+void)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static bool (*p)(void) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_all_twolevel_modules_prebound", (void**)&p);
+ return(p());
+}
+
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+#include "dyldLock.h"
+#include "dyldLibSystemThreadHelpers.h"
+
+// pthread key used to access per-thread dlerror message
+static pthread_key_t dlerrorPerThreadKey;
+
+// data kept per-thread
+struct dlerrorPerThreadData
+{
+ uint32_t sizeAllocated;
+ char message[1];
+};
+
+// function called by dyld to get buffer to store dlerror message
+static char* getPerThreadBufferFor_dlerror(uint32_t sizeRequired)
+{
+ const int size = (sizeRequired < 256) ? 256 : sizeRequired;
+ dlerrorPerThreadData* data = (dlerrorPerThreadData*)pthread_getspecific(dlerrorPerThreadKey);
+ if ( data == NULL ) {
+ //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
+ const int mallocSize = sizeof(dlerrorPerThreadData)+size;
+ data = (dlerrorPerThreadData*)malloc(mallocSize);
+ data->sizeAllocated = size;
+ pthread_setspecific(dlerrorPerThreadKey, data);
+ }
+ else if ( data->sizeAllocated < sizeRequired ) {
+ free(data);
+ //int mallocSize = offsetof(dlerrorPerThreadData, message[size]);
+ const int mallocSize = sizeof(dlerrorPerThreadData)+size;
+ data = (dlerrorPerThreadData*)malloc(mallocSize);
+ data->sizeAllocated = size;
+ pthread_setspecific(dlerrorPerThreadKey, data);
+ }
+ return data->message;
+}
+
+// that table passed to dyld containing thread helpers
+static dyld::ThreadingHelpers sThreadHelpers = { 1, &lockForLazyBinding, &unlockForLazyBinding, &getPerThreadBufferFor_dlerror };
+
+//
+// during initialization of libSystem this routine will run
+// and call dyld, registering the threading helpers.
+//
+//
+static int registerWithDyld()
+{
+ static void (*p)(dyld::ThreadingHelpers*) = NULL;
+
+ // create key and tell pthread package to call free() on any data associated with key if thread dies
+ pthread_key_create(&dlerrorPerThreadKey, &free);
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_register_thread_helpers", (void**)&p);
+ if(p != NULL)
+ p(&sThreadHelpers);
+
+ return 0;
+}
+
+// should be able to use __attribute__((constructor)) on registerWithDyld, but compiler has bug (3679135)
+// instead use initialization of global to force it to run.
+static int hack = registerWithDyld();
+
+
+char* dlerror()
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static char* (*p)() = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_dlerror", (void**)&p);
+ return(p());
+}
+
+int dladdr(const void* addr, Dl_info* info)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static int (*p)(const void* , Dl_info*) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_dladdr", (void**)&p);
+ return(p(addr, info));
+}
+
+int dlclose(void* handle)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static int (*p)(void* handle) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_dlclose", (void**)&p);
+ return(p(handle));
+}
+
+void* dlopen(const char* path, int mode)
+{
+ DYLD_WRITER_LOCK_THIS_BLOCK;
+ static void* (*p)(const char* path, int) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_dlopen", (void**)&p);
+ return(p(path, mode));
+}
+
+void* dlsym(void* handle, const char* symbol)
+{
+ DYLD_READER_LOCK_THIS_BLOCK;
+ static void* (*p)(void* handle, const char* symbol) = NULL;
+
+ if(p == NULL)
+ _dyld_func_lookup("__dyld_dlsym", (void**)&p);
+ return(p(handle, symbol));
+}
+
+
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <mach-o/loader.h>
+
+//
+// BEGIN copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
+//
+#define KEYMGR_API_MAJOR_GCC3 3
+/* ... with these keys. */
+#define KEYMGR_GCC3_LIVE_IMAGE_LIST 301 /* loaded images */
+#define KEYMGR_GCC3_DW2_OBJ_LIST 302 /* Dwarf2 object list */
+#define KEYMGR_EH_GLOBALS_KEY 13
+
+/* Node of KEYMGR_GCC3_LIVE_IMAGE_LIST. Info about each resident image. */
+struct live_images {
+ unsigned long this_size; /* sizeof (live_images) */
+ struct mach_header *mh; /* the image info */
+ unsigned long vm_slide;
+ void (*destructor)(struct live_images *); /* destructor for this */
+ struct live_images *next;
+ unsigned int examined_p;
+ void *fde;
+ void *object_info;
+ unsigned long info[2]; /* Future use. */
+};
+//
+// END copy of code from libgcc.a source file unwind-dw2-fde-darwin.c
+//
+
+
+//
+// dyld is built as stand alone executable with a static copy of libc, libstdc++, and libgcc.
+//
+// In order for C++ exceptions to work within dyld, the C++ exception handling code
+// must be able to find the exception handling frame data inside dyld. The standard
+// exception handling code uses crt and keymgr to keep track of all images and calls
+// getsectdatafromheader("__eh_frame") to find the EH data for each image. We implement
+// our own copy of those functions below to enable exceptions within dyld.
+//
+// Note: This exception handling is completely separate from any user code exception .
+// handling which has its own keymgr (in libSystem).
+//
+
+
+static struct live_images sDyldImage; // zero filled
+static void* sObjectList = NULL;
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+static void* sEHGlobals = NULL;
+#endif
+
+
+// called by dyldStartup.s very early
+void dyld_exceptions_init(struct mach_header *mh, uintptr_t slide)
+{
+ sDyldImage.this_size = sizeof(struct live_images);
+ sDyldImage.mh = mh;
+ sDyldImage.vm_slide = slide;
+}
+
+
+
+// Hack for gcc 3.5's use of keymgr includes accessing __keymgr_global
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+typedef struct Sinfo_Node {
+ uint32_t size; /* Size of this node. */
+ uint16_t major_version; /* API major version. */
+ uint16_t minor_version; /* API minor version. */
+} Tinfo_Node;
+static const Tinfo_Node keymgr_info = { sizeof (Tinfo_Node), KEYMGR_API_MAJOR_GCC3, 0 };
+const Tinfo_Node* __keymgr_global[3] = { NULL, NULL, &keymgr_info };
+#endif
+
+static __attribute__((noreturn))
+void dyld_abort()
+{
+ fprintf(stderr, "internal dyld error\n");
+ abort();
+}
+
+void* _keymgr_get_and_lock_processwide_ptr(unsigned int key)
+{
+ // The C++ exception handling code uses two keys. No other keys should be seen
+ if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
+ return &sDyldImage;
+ }
+ else if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
+ return sObjectList;
+ }
+ dyld_abort();
+}
+
+void _keymgr_set_and_unlock_processwide_ptr(unsigned int key, void* value)
+{
+ // The C++ exception handling code uses just this key. No other keys should be seen
+ if ( key == KEYMGR_GCC3_DW2_OBJ_LIST ) {
+ sObjectList = value;
+ return;
+ }
+ dyld_abort();
+}
+
+void _keymgr_unlock_processwide_ptr(unsigned int key)
+{
+ // The C++ exception handling code uses just this key. No other keys should be seen
+ if ( key == KEYMGR_GCC3_LIVE_IMAGE_LIST ) {
+ return;
+ }
+ dyld_abort();
+}
+
+void* _keymgr_get_per_thread_data(unsigned int key)
+{
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+ // gcc 3.5 and later use this key
+ if ( key == KEYMGR_EH_GLOBALS_KEY )
+ return sEHGlobals;
+#endif
+
+ // used by std::termination which dyld does not use
+ dyld_abort();
+}
+
+void _keymgr_set_per_thread_data(unsigned int key, void *keydata)
+{
+#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ >= 4))
+ // gcc 3.5 and later use this key
+ if ( key == KEYMGR_EH_GLOBALS_KEY ) {
+ sEHGlobals = keydata;
+ return;
+ }
+#endif
+ // used by std::termination which dyld does not use
+ dyld_abort();
+}
+
+#if __LP64__
+ #define LC_SEGMENT_COMMAND LC_SEGMENT_64
+ #define macho_header mach_header_64
+ #define macho_segment_command segment_command_64
+ #define macho_section section_64
+ #define getsectdatafromheader getsectdatafromheader_64
+#else
+ #define LC_SEGMENT_COMMAND LC_SEGMENT
+ #define macho_header mach_header
+ #define macho_segment_command segment_command
+ #define macho_section section
+#endif
+
+// needed by C++ exception handling code to find __eh_frame section
+const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
+{
+ const struct load_command* cmd;
+ unsigned long i;
+
+ cmd = (struct load_command*) ((char *)mh + sizeof(struct macho_header));
+ for(i = 0; i < mh->ncmds; i++) {
+ if ( cmd->cmd == LC_SEGMENT_COMMAND ) {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ if ( strcmp(seg->segname, segname) == 0 ) {
+ const struct macho_section* sect = (struct macho_section*)( (char*)seg + sizeof(struct macho_segment_command) );
+ unsigned long j;
+ for (j = 0; j < seg->nsects; j++) {
+ if ( strcmp(sect[j].sectname, sectname) == 0 ) {
+ *size = sect[j].size;
+ return (void*)(sect[j].addr);
+ }
+ }
+ }
+ }
+ cmd = (struct load_command*)( (char*)cmd + cmd->cmdsize );
+ }
+ return NULL;
+}
+
+
+// Hack for transition of rdar://problem/3933738
+// Can be removed later.
+// Allow C++ runtime to call getsectdatafromheader or getsectdatafromheader_64
+#if __ppc64__
+ #undef getsectdatafromheader
+ const void* getsectdatafromheader(struct mach_header* mh, const char* segname, const char* sectname, unsigned long* size)
+ {
+ return getsectdatafromheader_64(mh, segname, sectname, size);
+ }
+#endif
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stddef.h>
+#include <string.h>
+#include <mach/mach.h>
+#include <mach-o/loader.h>
+#include <mach-o/ldsyms.h>
+#include <mach-o/reloc.h>
+#if __ppc__ || __ppc64__
+ #include <mach-o/ppc/reloc.h>
+#endif
+#include "dyld.h"
+
+#if __LP64__
+ #define macho_header mach_header_64
+ #define LC_SEGMENT_COMMAND LC_SEGMENT_64
+ #define macho_segment_command segment_command_64
+ #define macho_section section_64
+ #define RELOC_SIZE 3
+#else
+ #define macho_header mach_header
+ #define LC_SEGMENT_COMMAND LC_SEGMENT
+ #define macho_segment_command segment_command
+ #define macho_section section
+ #define RELOC_SIZE 2
+#endif
+
+
+//
+// Code to bootstrap dyld into a runnable state
+//
+//
+
+namespace dyldbootstrap {
+
+
+typedef void (*Initializer)(int argc, const char* argv[], const char* envp[], const char* apple[]);
+
+//
+// For a regular executable, the crt code calls dyld to run the executables initializers.
+// For a static executable, crt directly runs the initializers.
+// dyld (should be static) but is a dynamic executable and needs this hack to run its own initializers.
+// We pass argc, argv, etc in case libc.a uses those arguments
+//
+static void runDyldInitializers(const struct macho_header* mh, intptr_t slide, int argc, const char* argv[], const char* envp[], const char* apple[])
+{
+ const uint32_t cmd_count = mh->ncmds;
+ const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ const uint8_t type = sect->flags & SECTION_TYPE;
+ if ( type == S_MOD_INIT_FUNC_POINTERS ){
+ Initializer* inits = (Initializer*)(sect->addr + slide);
+ const uint32_t count = sect->size / sizeof(uintptr_t);
+ for (uint32_t i=0; i < count; ++i) {
+ Initializer func = inits[i];
+ func(argc, argv, envp, apple);
+ }
+ }
+ }
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+}
+
+
+//
+// If the kernel does not load dyld at its preferred address, we need to apply
+// fixups to various initialized parts of the __DATA segment
+//
+static void rebaseDyld(const struct macho_header* mh, intptr_t slide)
+{
+ // get interesting pointers into dyld
+ const uint32_t cmd_count = mh->ncmds;
+ const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+ const struct load_command* cmd = cmds;
+ const struct macho_segment_command* linkEditSeg = NULL;
+ const struct dysymtab_command* dynamicSymbolTable = NULL;
+ const struct macho_section* nonLazySection = NULL;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ if ( strcmp(seg->segname, "__LINKEDIT") == 0 )
+ linkEditSeg = seg;
+ const struct macho_section* const sectionsStart = (struct macho_section*)((char*)seg + sizeof(struct macho_segment_command));
+ const struct macho_section* const sectionsEnd = §ionsStart[seg->nsects];
+ for (const struct macho_section* sect=sectionsStart; sect < sectionsEnd; ++sect) {
+ const uint8_t type = sect->flags & SECTION_TYPE;
+ if ( type == S_NON_LAZY_SYMBOL_POINTERS )
+ nonLazySection = sect;
+ }
+ }
+ break;
+ case LC_DYSYMTAB:
+ dynamicSymbolTable = (struct dysymtab_command *)cmd;
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+
+ // use reloc's to rebase all random data pointers
+ const uintptr_t relocBase = (uintptr_t)mh;
+ const relocation_info* const relocsStart = (struct relocation_info*)(linkEditSeg->vmaddr + slide + dynamicSymbolTable->locreloff - linkEditSeg->fileoff);
+ const relocation_info* const relocsEnd = &relocsStart[dynamicSymbolTable->nlocrel];
+ for (const relocation_info* reloc=relocsStart; reloc < relocsEnd; ++reloc) {
+ if ( (reloc->r_address & R_SCATTERED) == 0 ) {
+ if (reloc->r_length == RELOC_SIZE) {
+ switch(reloc->r_type) {
+ case GENERIC_RELOC_VANILLA:
+ *((uintptr_t*)(reloc->r_address + relocBase)) += slide;
+ break;
+ }
+ }
+ }
+ else {
+ const struct scattered_relocation_info* sreloc = (struct scattered_relocation_info*)reloc;
+ if (sreloc->r_length == RELOC_SIZE) {
+ uintptr_t* locationToFix = (uintptr_t*)(sreloc->r_address + relocBase);
+ switch(sreloc->r_type) {
+ case GENERIC_RELOC_VANILLA:
+ #if __ppc__ || __ppc64__
+ case PPC_RELOC_PB_LA_PTR:
+ #elif __i386__
+ case GENERIC_RELOC_PB_LA_PTR:
+ #endif
+ // Note the use of PB_LA_PTR is unique here. Seems like ld should strip out all lazy pointers
+ // but it does not. But, since all lazy-pointers point within dyld, they can be slid too
+ *locationToFix += slide;
+ break;
+ }
+ }
+ }
+ }
+
+ // rebase non-lazy pointers (which all point internal to dyld, since dyld uses no shared libraries)
+ if ( nonLazySection != NULL ) {
+ const uint32_t pointerCount = nonLazySection->size / sizeof(uintptr_t);
+ uintptr_t* const symbolPointers = (uintptr_t*)(nonLazySection->addr + slide);
+ for (uint32_t j=0; j < pointerCount; ++j) {
+ symbolPointers[j] += slide;
+ }
+ }
+
+
+}
+
+//
+// For some reason the kernel loads dyld with __TEXT and __LINKEDIT writable
+// rdar://problem/3702311
+//
+static void segmentProtectDyld(const struct macho_header* mh, intptr_t slide)
+{
+ const uint32_t cmd_count = mh->ncmds;
+ const struct load_command* const cmds = (struct load_command*)(((char*)mh)+sizeof(macho_header));
+ const struct load_command* cmd = cmds;
+ for (uint32_t i = 0; i < cmd_count; ++i) {
+ switch (cmd->cmd) {
+ case LC_SEGMENT_COMMAND:
+ {
+ const struct macho_segment_command* seg = (struct macho_segment_command*)cmd;
+ vm_address_t addr = seg->vmaddr + slide;
+ vm_size_t size = seg->vmsize;
+ const bool setCurrentPermissions = false;
+ vm_protect(mach_task_self(), addr, size, setCurrentPermissions, seg->initprot);
+ //fprintf(stderr, "dyld: segment %s, 0x%08X -> 0x%08X, set to %d\n", seg->segname, addr, addr+size-1, seg->initprot);
+ }
+ break;
+ }
+ cmd = (const struct load_command*)(((char*)cmd)+cmd->cmdsize);
+ }
+
+}
+
+extern "C" void dyld_exceptions_init(const struct macho_header*, uintptr_t slide); // in dyldExceptions.cpp
+extern "C" void mach_init();
+
+//
+// This is code to bootstrap dyld. This work in normally done for a program by dyld and crt.
+// In dyld we have to do this manually.
+//
+uintptr_t start(const struct mach_header* appsMachHeader, int argc, const char* argv[], intptr_t slide)
+{
+ // _mh_dylinker_header is magic symbol defined by static linker (ld), see <mach-o/ldsyms.h>
+ const struct macho_header* dyldsMachHeader = (const struct macho_header*)(((char*)&_mh_dylinker_header)+slide);
+
+ // if kernel had to slide dyld, we need to fix up load sensitive locations
+ // we have to do this before using any global variables
+ if ( slide != 0 ) {
+ rebaseDyld(dyldsMachHeader, slide);
+ }
+
+ // enable C++ exceptions to work inside dyld
+ dyld_exceptions_init(dyldsMachHeader, slide);
+
+ // allow dyld to use mach messaging
+ mach_init();
+
+ // set protection on segments (has to be done after mach_init)
+ segmentProtectDyld(dyldsMachHeader, slide);
+
+ // kernel sets up env pointer to be just past end of agv array
+ const char** envp = &argv[argc+1];
+
+ // kernel sets up apple pointer to be just past end of envp array
+ const char** apple = envp;
+ while(*apple != NULL) { ++apple; }
+ ++apple;
+
+ // run all C++ initializers inside dyld
+ runDyldInitializers(dyldsMachHeader, slide, argc, argv, envp, apple);
+
+ // now that we are done bootstrapping dyld, call dyld's main
+ return dyld::_main(appsMachHeader, argc, argv, envp, apple);
+}
+
+
+
+
+} // end of namespace
+
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __DYLDLIBSYSTEMHELPERS__
+#define __DYLDLIBSYSTEMHELPERS__
+
+#include <stdint.h>
+
+
+namespace dyld {
+ //
+ // This file contains the synchronization utilities used by dyld to be thread safe.
+ // This struct is implemented in in libSystem (where pthreads is available)
+ // and passed to dyld to use.
+ //
+ struct ThreadingHelpers
+ {
+ uintptr_t version;
+ void (*lockForReading)();
+ void (*unlockForReading)();
+ char* (*getThreadBufferFor_dlerror)(uint32_t sizeRequired);
+ };
+};
+
+
+
+
+
+#endif // __DYLDLIBSYSTEMHELPERS__
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <pthread.h>
+
+#include "dyldLock.h"
+
+// until the reader/writer locks are fully tested, we just use a simple recursive mutex
+#define REAL_READER_WRITER_LOCK 0
+
+
+
+//
+// This class implements a recursive reader/writer lock.
+// Recursive means a thread that has already aquired the lock can re-acquire it.
+// The lock allows either:
+// a) one "writer" thread to hold lock
+// b) multiple "reader" threads to hold
+//
+// A thread with the writer can acquire a reader lock.
+// A thread with a reader lock can acquire a writer lock iff it is the only thread with a reader lock
+//
+class RecursiveReaderWriterLock
+{
+public:
+ RecursiveReaderWriterLock() __attribute__((visibility("hidden")));
+ void initIfNeeded();
+
+
+ void lockForSingleWritingThread() __attribute__((visibility("hidden")));
+ void unlockForSingleWritingThread() __attribute__((visibility("hidden")));
+
+ void lockForMultipleReadingThreads() __attribute__((visibility("hidden")));
+ void unlockForMultipleReadingThreads() __attribute__((visibility("hidden")));
+
+private:
+#if REAL_READER_WRITER_LOCK
+ struct ThreadRecursionCount {
+ pthread_t fThread;
+ uint32_t fCount;
+ };
+ bool writerThreadIsAnyThreadBut(pthread_t thread);
+ void writerThreadRetain(pthread_t thread);
+ bool writerThreadRelease(pthread_t thread);
+
+ enum { kMaxReaderThreads = 4 };
+ bool readerThreadSetRetain(pthread_t thread);
+ bool readerThreadSetRelease(pthread_t thread);
+ bool readerThreadSetContainsAnotherThread(pthread_t thread);
+
+ ThreadRecursionCount fWriterThread;
+ ThreadRecursionCount fReaderThreads[kMaxReaderThreads];
+ pthread_cond_t fLockFree;
+ pthread_mutex_t fMutex;
+#else
+ pthread_mutex_t fMutex;
+#endif
+ bool fInitialized; // assumes this is statically initialized to false because sLock is static
+};
+
+
+//
+// initIfNeeded() is a hack so that when libSystem_debug.dylb is useable.
+// The problem is that Objective-C +load methods are called before C++ initialziers are run
+// If +load method makes a call into dyld, sLock is not initialized.
+//
+// The long term solution is for objc and dyld to work more closely together so that instead
+// of running all +load methods before all initializers, we run each image's +load then its
+// initializers all in bottom up order.
+//
+// This lazy initialization is not thread safe, but as long as someone does not create a
+// new thread in a +load method, the C++ constructor for sLock will be called before main()
+// so there will only be one thead.
+//
+void RecursiveReaderWriterLock::initIfNeeded()
+{
+ if ( ! fInitialized ) {
+ pthread_mutexattr_t recursiveMutexAttr;
+ pthread_mutexattr_init(&recursiveMutexAttr);
+ pthread_mutexattr_settype(&recursiveMutexAttr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init(&fMutex, &recursiveMutexAttr);
+ #if REAL_READER_WRITER_LOCK
+ pthread_cond_init(&fLockFree, NULL);
+ fWriterThread.fThread = NULL;
+ fWriterThread.fCount = 0;
+ for (int i=0; i < kMaxReaderThreads; ++i) {
+ fReaderThreads[i].fThread = NULL;
+ fReaderThreads[i].fCount = 0;
+ }
+ #endif
+ fInitialized = true;
+ }
+}
+
+RecursiveReaderWriterLock::RecursiveReaderWriterLock()
+{
+ initIfNeeded();
+}
+
+void RecursiveReaderWriterLock::lockForSingleWritingThread()
+{
+ this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+ pthread_mutex_lock(&fMutex);
+ pthread_t thisThread = pthread_self();
+ // wait as long as there is another writer or any readers on a different thread
+ while ( writerThreadIsAnyThreadBut(thisThread) || readerThreadSetContainsAnotherThread(thisThread) ) {
+ pthread_cond_wait(&fLockFree, &fMutex);
+ }
+ writerThreadRetain(thisThread);
+ pthread_mutex_unlock(&fMutex);
+#else
+ pthread_mutex_lock(&fMutex);
+#endif
+}
+
+void RecursiveReaderWriterLock::unlockForSingleWritingThread()
+{
+ this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+ pthread_mutex_lock(&fMutex);
+ if ( writerThreadRelease(pthread_self()) ) {
+ pthread_cond_broadcast(&fLockFree);
+ }
+ pthread_mutex_unlock(&fMutex);
+#else
+ pthread_mutex_unlock(&fMutex);
+#endif
+}
+
+
+void RecursiveReaderWriterLock::lockForMultipleReadingThreads()
+{
+ this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+ pthread_mutex_lock(&fMutex);
+ pthread_t thisThread = pthread_self();
+ // wait as long as there is a writer on another thread or too many readers already
+ while ( writerThreadIsAnyThreadBut(thisThread) || !readerThreadSetRetain(thisThread) ) {
+ pthread_cond_wait(&fLockFree, &fMutex);
+ }
+ pthread_mutex_unlock(&fMutex);
+#else
+ pthread_mutex_lock(&fMutex);
+#endif
+}
+
+
+void RecursiveReaderWriterLock::unlockForMultipleReadingThreads()
+{
+ this->initIfNeeded();
+#if REAL_READER_WRITER_LOCK
+ pthread_mutex_lock(&fMutex);
+ if ( readerThreadSetRelease(pthread_self()) ) {
+ pthread_cond_broadcast(&fLockFree);
+ }
+ pthread_mutex_unlock(&fMutex);
+#else
+ pthread_mutex_unlock(&fMutex);
+#endif
+}
+
+#if REAL_READER_WRITER_LOCK
+bool RecursiveReaderWriterLock::writerThreadIsAnyThreadBut(pthread_t thread)
+{
+ return ( (fWriterThread.fThread != NULL) && (fWriterThread.fThread != thread) );
+}
+
+void RecursiveReaderWriterLock::writerThreadRetain(pthread_t thread)
+{
+ ++fWriterThread.fCount;
+}
+
+bool RecursiveReaderWriterLock::writerThreadRelease(pthread_t thread)
+{
+ return ( --fWriterThread.fCount == 0 );
+}
+
+
+bool RecursiveReaderWriterLock::readerThreadSetRetain(pthread_t thread)
+{
+ // if thread is already in set, bump its count
+ for (int i=0; i < kMaxReaderThreads; ++i) {
+ if ( fReaderThreads[i].fThread == thread ) {
+ ++fReaderThreads[i].fCount;
+ return true;
+ }
+ }
+ // find empty slot in set
+ for (int i=0; i < kMaxReaderThreads; ++i) {
+ if ( fReaderThreads[i].fThread == NULL ) {
+ fReaderThreads[i].fThread = thread;
+ fReaderThreads[i].fCount = 1;
+ return true;
+ }
+ }
+
+ // all reader slots full
+ return false;
+}
+
+bool RecursiveReaderWriterLock::readerThreadSetRelease(pthread_t thread)
+{
+ for (int i=0; i < kMaxReaderThreads; ++i) {
+ if ( fReaderThreads[i].fThread == thread ) {
+ if ( --fReaderThreads[i].fCount == 0 ) {
+ fReaderThreads[i].fThread = NULL;
+ return true;
+ }
+ return false;
+ }
+ }
+ // should never get here
+ return false;
+}
+
+bool RecursiveReaderWriterLock::readerThreadSetContainsAnotherThread(pthread_t thread)
+{
+ for (int i=0; i < kMaxReaderThreads; ++i) {
+ if ( (fReaderThreads[i].fThread != NULL) && (fReaderThreads[i].fThread != thread) )
+ return true;
+ }
+ return false;
+}
+#endif
+
+
+// dyld's global reader/writer lock
+static RecursiveReaderWriterLock sLock;
+
+
+LockReaderHelper::LockReaderHelper()
+{
+ sLock.lockForMultipleReadingThreads();
+}
+
+LockReaderHelper::~LockReaderHelper()
+{
+ sLock.unlockForMultipleReadingThreads();
+}
+
+
+LockWriterHelper::LockWriterHelper()
+{
+ sLock.lockForSingleWritingThread();
+}
+
+LockWriterHelper::~LockWriterHelper()
+{
+ sLock.unlockForSingleWritingThread();
+}
+
+
+// needed by lazy binding
+void lockForLazyBinding()
+{
+ sLock.lockForMultipleReadingThreads();
+}
+
+void unlockForLazyBinding()
+{
+ sLock.unlockForMultipleReadingThreads();
+}
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 __DYLDLOCK__
+#define __DYLDLOCK__
+
+//
+// This file contains the syncronization utilities used by dyld to be thread safe.
+// Access to all dyld data structures is protected by a reader-writer lock.
+// This lock allows multiple "reader" threads to access dyld data structures at
+// the same time. If there is a "writer" thread, it is the only thread allowed
+// access to dyld data structures.
+//
+// The implementation of all dyld API's must acquire the global lock around accesses
+// to dyld's data structures. This is done using the macros DYLD_*_LOCK_THIS_BLOCK.
+// Example:
+//
+// void dyld_api_modifying_dyld() {
+// DYLD_WRITER_LOCK_THIS_BLOCK;
+// // free to do stuff here
+// // that modifies dyld data structures
+// }
+//
+// void dyld_api_examinging_dyld() {
+// DYLD_READER_LOCK_THIS_BLOCK
+// // can only do stuff here
+// // that examines but does not modify dyld data structures
+// }
+//
+// void dyld_api_state_free() {
+// DYLD_NO_LOCK_THIS_BLOCK
+// // can only do stuff here
+// // that does not require locking
+// }
+//
+
+
+#define DYLD_READER_LOCK_THIS_BLOCK LockReaderHelper _dyld_lock;
+#define DYLD_WRITER_LOCK_THIS_BLOCK LockWriterHelper _dyld_lock;
+#define DYLD_NO_LOCK_THIS_BLOCK
+
+// used by dyld wrapper functions in libSystem
+class LockReaderHelper
+{
+public:
+ LockReaderHelper() __attribute__((visibility("hidden")));
+ ~LockReaderHelper() __attribute__((visibility("hidden")));
+};
+
+// used by dyld wrapper functions in libSystem
+class LockWriterHelper
+{
+public:
+ LockWriterHelper() __attribute__((visibility("hidden")));
+ ~LockWriterHelper() __attribute__((visibility("hidden")));
+};
+
+// used by lazy binding
+extern void lockForLazyBinding() __attribute__((visibility("hidden")));
+extern void unlockForLazyBinding() __attribute__((visibility("hidden")));
+
+
+
+#endif // __DYLDLOCK__
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <new>
+#include <malloc/malloc.h>
+//#include <stdio.h>
+
+
+//
+// dyld does not use malloc anywhere, instead C++ new is used.
+// All dyld allocations go in dyld-only zone so as to be not co-mingled with target proccess's allocations
+//
+//
+//
+
+static malloc_zone_t* sZone = NULL; // could be initialized to malloc_create_zone, but that would require careful ordering of initializers
+
+
+void* operator new(std::size_t len) throw (std::bad_alloc)
+{
+ if ( sZone == NULL ) {
+ sZone = malloc_create_zone(40960, 0);
+ malloc_set_zone_name(sZone, "dyld heap");
+ }
+ //fprintf(stderr, "new(%d)\n", len);
+ return malloc_zone_malloc(sZone, len);
+}
+
+void* operator new[](std::size_t len) throw (std::bad_alloc)
+{
+ if ( sZone == NULL ) {
+ sZone = malloc_create_zone(40960, 0);
+ malloc_set_zone_name(sZone, "dyld heap");
+ }
+ //fprintf(stderr, "new[](%d)\n", len);
+ return malloc_zone_malloc(sZone, len);
+}
+
+
+void operator delete(void* obj) throw()
+{
+ //fprintf(stderr, "delete(%p)\n", obj);
+ malloc_zone_free(sZone, obj);
+}
+
+
+void operator delete[](void* obj) throw()
+{
+ //fprintf(stderr, "delete[](%p)\n", obj);
+ malloc_zone_free(sZone, obj);
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 1999-2005 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@
+ */
+/*
+ * C runtime startup for i386 and ppc interface to the dynamic linker.
+ * This is the same as the entry point in crt0.o with the addition of the
+ * address of the mach header passed as the an extra first argument.
+ *
+ * Kernel sets up stack frame to look like:
+ *
+ * | STRING AREA |
+ * +-------------+
+ * | 0 |
+* +-------------+
+ * | apple[n] |
+ * +-------------+
+ * :
+ * +-------------+
+ * | apple[0] |
+ * +-------------+
+ * | 0 |
+ * +-------------+
+ * | env[n] |
+ * +-------------+
+ * :
+ * :
+ * +-------------+
+ * | env[0] |
+ * +-------------+
+ * | 0 |
+ * +-------------+
+ * | arg[argc-1] |
+ * +-------------+
+ * :
+ * :
+ * +-------------+
+ * | arg[0] |
+ * +-------------+
+ * | argc |
+ * +-------------+
+ * sp-> | mh | address of where the a.out's file offset 0 is in memory
+ * +-------------+
+ *
+ * Where arg[i] and env[i] point into the STRING AREA
+ */
+
+ .globl __dyld_start
+
+
+#ifdef __i386__
+ .data
+__dyld_start_static_picbase:
+ .long L__dyld_start_picbase
+
+
+ .text
+ .align 2
+# stable entry points into dyld
+ .globl _stub_binding_helper
+_stub_binding_helper:
+ jmp _stub_binding_helper_interface
+ nop
+ nop
+ nop
+ .globl _dyld_func_lookup
+_dyld_func_lookup:
+ jmp __Z18lookupDyldFunctionPKcPm
+
+ .text
+ .align 4, 0x90
+ .globl __dyld_start
+__dyld_start:
+ pushl $0 # push a zero for debugger end of frames marker
+ movl %esp,%ebp # pointer to base of kernel frame
+ andl $-16,%esp # force SSE alignment
+
+ # call dyldbootstrap::start(app_mh, argc, argv, slide)
+ call L__dyld_start_picbase
+L__dyld_start_picbase:
+ popl %ebx # set %ebx to runtime value of picbase
+ movl __dyld_start_static_picbase-L__dyld_start_picbase(%ebx), %eax
+ subl %eax, %ebx # slide = L__dyld_start_picbase - [__dyld_start_static_picbase]
+ pushl %ebx # param4 = slide
+ lea 12(%ebp),%ebx
+ pushl %ebx # param3 = argv
+ movl 8(%ebp),%ebx
+ pushl %ebx # param2 = argc
+ movl 4(%ebp),%ebx
+ pushl %ebx # param1 = mh
+ call __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl
+
+ # clean up stack and jump to result
+ movl %ebp,%esp # restore the unaligned stack pointer
+ addl $8,%esp # remove the mh argument, and debugger end
+ # frame marker
+ movl $0,%ebp # restore ebp back to zero
+ jmp %eax # jump to the entry point
+
+
+ .globl dyld_stub_binding_helper
+dyld_stub_binding_helper:
+ hlt
+L_end:
+#endif /* __i386__ */
+
+#if __ppc__ || __ppc64__
+#include <architecture/ppc/mode_independent_asm.h>
+
+ .data
+ .align 2
+__dyld_start_static_picbase:
+ .g_long L__dyld_start_picbase
+
+#if __ppc__
+ .set L_mh_offset,0
+ .set L_argc_offset,4
+ .set L_argv_offset,8
+#else
+ .set L_mh_offset,0
+ .set L_argc_offset,8 ; stack is 8-byte aligned and there is a 4-byte hole between argc and argv
+ .set L_argv_offset,16
+#endif
+
+ .text
+ .align 2
+; stable entry points into dyld
+ .globl _stub_binding_helper
+_stub_binding_helper:
+ b _stub_binding_helper_interface
+ nop
+ .globl _dyld_func_lookup
+_dyld_func_lookup:
+ b __Z18lookupDyldFunctionPKcPm
+
+
+
+ .text
+ .align 2
+__dyld_start:
+ mr r26,r1 ; save original stack pointer into r26
+ subi r1,r1,GPR_BYTES ; make space for linkage
+ clrrgi r1,r1,5 ; align to 32 bytes
+ addi r0,0,0 ; load 0 into r0
+ stg r0,0(r1) ; terminate initial stack frame
+ stgu r1,-SF_MINSIZE(r1); allocate minimal stack frame
+
+ ; call dyldbootstrap::start(app_mh, argc, argv, slide)
+ lg r3,L_mh_offset(r26) ; r3 = mach_header
+ lwz r4,L_argc_offset(r26) ; r4 = argc (int == 4 bytes)
+ addi r5,r26,L_argv_offset ; r5 = argv
+ bcl 20,31,L__dyld_start_picbase
+L__dyld_start_picbase:
+ mflr r31 ; put address of L__dyld_start_picbase in r31
+ addis r6,r31,ha16(__dyld_start_static_picbase-L__dyld_start_picbase)
+ lg r6,lo16(__dyld_start_static_picbase-L__dyld_start_picbase)(r6)
+ subf r6,r6,r31 ; r6 = slide
+ bl __ZN13dyldbootstrap5startEPK11mach_headeriPPKcl
+
+ ; clean up stack and jump to result
+ mtctr r3 ; Put entry point in count register
+ mr r12,r3 ; also put in r12 for ABI convention.
+ addi r1,r26,GPR_BYTES; Restore the stack pointer and remove the
+ ; mach_header argument.
+ bctr ; jump to the program's entry point
+
+ .globl dyld_stub_binding_helper
+dyld_stub_binding_helper:
+ trap
+L_end:
+#endif /* __ppc__ */
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * 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@
+ */
+
+int dummy_dyld_symbol = 1;
+
+#include <stdio.h>
+#include <stdlib.h>
+
+// The following API's are deprecated.
+// In Mac OS X 10.4 we only do a minimal implementation of these API's
+// to keep from breaking existing clients (Omni and MS Crash Reporters).
+//
+// This minmal implementation only allows inspection of one process and
+// only reveals the current images in that process (no notification of
+// later image changes). It assumes both processes use the same dyld
+// and dyld has not slid in either process.
+//
+#if __ppc__
+
+#include "mach-o/dyld_debug.h"
+#include "mach-o/dyld_gdb.h"
+
+// global state set up by _dyld_debug_subscribe_to_events() and accessed by _dyld_debug_module_name()
+static const struct dyld_image_info* sImages = NULL;
+static uint32_t sImagesCount = 0;
+static task_port_t sImagesTaskPort = 0;
+
+
+// reads an address range out of another process
+// returns a malloc'ed block that caller should free
+static void* xprocess_read(task_port_t target_task, const void* address, size_t len)
+{
+ void* result = NULL;
+ mach_vm_address_t page_address = (uint32_t)address & (-4096);
+ mach_vm_address_t last_page_address = ((uint32_t)address + len + 4095) & (-4096);
+ mach_vm_size_t page_size = last_page_address - page_address;
+ uint8_t* local_start;
+ uint32_t local_len;
+ kern_return_t r = vm_read(
+ target_task,
+ page_address,
+ page_size,
+ (vm_offset_t*)&local_start,
+ &local_len);
+ if ( r == KERN_SUCCESS ) {
+ result = malloc(len);
+ if ( result != NULL )
+ memcpy(result, &local_start[(uint32_t)address - page_address], len);
+ vm_deallocate(mach_task_self(), (uintptr_t)local_start, local_len);
+ }
+ return result;
+}
+
+// reads a c-string out of another process. The returned string should be vm_deallocated.
+// All strings must be less than 1 to 2 pages long
+static const char* xprocess_read_string(task_port_t target_task, const void* address)
+{
+ char* result = NULL;
+ mach_vm_address_t page_address = (uint32_t)address & (-4096);
+ mach_vm_size_t page_size = 0x2000; // always read two pages
+ uint8_t* local_start;
+ uint32_t local_len;
+ kern_return_t r = vm_read(
+ target_task,
+ page_address,
+ page_size,
+ (vm_offset_t*)&local_start,
+ &local_len);
+ if ( r == KERN_SUCCESS ) {
+ const char* str = (char*)&local_start[(uint32_t)address - page_address];
+ return str;
+ }
+ return result;
+}
+
+
+// SPI into dyld to get address of _dyld_get_all_image_infos data structure
+static const struct dyld_all_image_infos* dyld_get_all_image_infos()
+{
+ static const struct dyld_all_image_infos* (*p)() = NULL;
+
+ if ( p == NULL )
+ _dyld_func_lookup("__dyld_get_all_image_infos", (void**)&p);
+
+ if ( p != NULL )
+ return p();
+ else
+ return NULL;
+}
+
+
+
+/*
+ * _dyld_debug_module_name() is passed a dyld_debug_module struct and
+ * sets image_name and module_name as well as the nameCnts. If the module
+ * does not refer to a valid module DYLD_INVALID_ARGUMENTS is returned.
+ */
+enum dyld_debug_return
+_dyld_debug_module_name(
+task_port_t target_task,
+unsigned long send_timeout,
+unsigned long rcv_timeout,
+boolean_t inconsistent_data_ok,
+struct dyld_debug_module module,
+char **image_name,
+unsigned long *image_nameCnt,
+char **module_name,
+unsigned long *module_nameCnt)
+{
+ // examine sImage* info set up by _dyld_debug_subscribe_to_events()
+ if ( sImagesTaskPort == target_task ) {
+ unsigned int i;
+ for (i=0; i < sImagesCount; ++i) {
+ if ( module.header == sImages[i].imageLoadAddress ) {
+ // copy requested string
+ const char* path = xprocess_read_string(sImagesTaskPort, sImages[i].imageFilePath);
+ if ( path != NULL ) {
+ *image_name = (char*)path;
+ *image_nameCnt = strlen(path);
+ *module_name = NULL;
+ *module_nameCnt = 0;
+ return DYLD_SUCCESS;
+ }
+ }
+ }
+ }
+
+ // not supported
+ return DYLD_INVALID_ARGUMENTS;
+}
+
+
+/*
+ * set_dyld_debug_error_func() is called to register a function to be called
+ * when error occurs in the dyld debug API's.
+ */
+void
+_dyld_debug_set_error_func(
+void (*func)(struct dyld_debug_error_data *e))
+{
+ // do nothing
+}
+
+
+
+// Examine a mach_header in another process and determine its slid
+static ptrdiff_t slideForHeader(task_port_t target_task, const struct mach_header* otherAddressHeader)
+{
+ const struct mach_header* mh = xprocess_read(target_task, otherAddressHeader, 0x2000);
+ if ( mh != NULL ) {
+ int i;
+ const struct segment_command *sgp =
+ (const struct segment_command *)((char*)mh + sizeof(mh));
+
+ for (i = 0; i < mh->ncmds; i++){
+ if (sgp->cmd == LC_SEGMENT) {
+ if (sgp->fileoff == 0 && sgp->filesize != 0) {
+ return (uintptr_t)mh - (uintptr_t)sgp->vmaddr;
+ }
+ }
+ sgp = (const struct segment_command *)((char *)sgp + sgp->cmdsize);
+ }
+ free((void*)mh);
+ }
+ return 0;
+}
+
+
+/*
+ * _dyld_debug_subscribe_to_events creates a new thread that is will call the
+ * specified dyld_event_routine when dynamic link events occur in the target
+ * task. This uses _dyld_debug_add_event_subscriber() and is just a different
+ * interface to get events.
+ */
+enum dyld_debug_return
+_dyld_debug_subscribe_to_events(
+task_port_t target_task,
+unsigned long send_timeout,
+unsigned long rcv_timeout,
+boolean_t inconsistent_data_ok,
+void (*dyld_event_routine)(struct dyld_event event))
+{
+ sImages = NULL;
+ sImagesCount = 0;
+ sImagesTaskPort = 0;
+ // get location of dyld_get_all_image_infos in this process
+ // It is possible that dyld slid in one of the processes, in which case this fails
+ const struct dyld_all_image_infos* infoOtherAddressSpace = dyld_get_all_image_infos();
+ if ( infoOtherAddressSpace != NULL ) {
+ const struct dyld_all_image_infos* infos;
+ infos = (const struct dyld_all_image_infos*)xprocess_read(target_task, infoOtherAddressSpace, sizeof(struct dyld_all_image_infos));
+ if ( infos != NULL ) {
+ // sanity check version
+ if ( infos->version == 1 ) {
+ sImages = xprocess_read(target_task, infos->infoArray, infos->infoArrayCount * sizeof(struct dyld_image_info));
+ if ( sImages != NULL ) {
+ int i;
+ // save info info into sImage* globals for use by later calls to _dyld_debug_module_name()
+ sImagesCount = infos->infoArrayCount;
+ sImagesTaskPort = target_task;
+ // tell caller about every image
+ for (i=0; i < infos->infoArrayCount; ++i) {
+ struct dyld_event addEvent;
+ bzero(&addEvent, sizeof(struct dyld_event));
+ const struct mach_header* mh = sImages[i].imageLoadAddress;
+ addEvent.type = DYLD_IMAGE_ADDED;
+ addEvent.arg[0].header = (struct mach_header*)mh;
+ addEvent.arg[0].vmaddr_slide = slideForHeader(target_task, mh);
+ addEvent.arg[0].module_index = 0;
+ (*dyld_event_routine)(addEvent);
+ }
+ }
+ }
+ // we free the dyld_all_image_infos struct, but not the array we copied
+ // The array is left in sImage* for use by later calls to _dyld_debug_module_name()
+ free((void*)infos);
+ }
+ }
+
+ // tell client event handler no more images
+ struct dyld_event event;
+ event.type = DYLD_PAST_EVENTS_END;
+ (*dyld_event_routine)(event);
+
+ return DYLD_SUCCESS;
+}
+
+#endif
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stddef.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <mach-o/loader.h>
+
+#include <vector>
+
+#include "mach-o/dyld_gdb.h"
+
+
+// old gdb interface to dyld only supported on 32-bit ppc and i386 (not ppc64_
+#if OLD_GDB_DYLD_INTERFACE
+
+unsigned int gdb_dyld_version = 2;
+
+
+/*
+ * gdb_dyld_state_changed() is a dummy routine called by dyld after images get
+ * added or removed/ Gdb is expected to set a break point at
+ * gdb_dyld_state_changed() then re-read dyld internal data as specified in
+ * the header file dyld_gdb.h
+ */
+void gdb_dyld_state_changed()
+{
+ // do nothing
+}
+
+#define NLIBRARY_IMAGES 200
+#define NOBJECT_IMAGES 1
+
+
+struct image {
+ const char* physical_name; // physical image name (file name)
+ uint32_t vmaddr_slide; // the slide from the staticly linked address
+ const mach_header* mh; // address of the mach header of the image
+ uint32_t valid; // TRUE if this is struct is valid
+ const char* name; // image name for reporting errors
+};
+
+
+struct library_images {
+ struct image images[NLIBRARY_IMAGES];
+ uint32_t nimages;
+ struct library_images* next_images;
+};
+struct object_images {
+ struct image images[NOBJECT_IMAGES];
+ uint32_t nimages;
+ struct library_images* next_images;
+};
+
+unsigned int gdb_nobject_images = NOBJECT_IMAGES;
+unsigned int gdb_object_image_size = sizeof(image);
+unsigned int gdb_nlibrary_images = NLIBRARY_IMAGES;
+unsigned int gdb_library_image_size = sizeof(image);
+
+extern "C" {
+object_images object_images = { {}, 0 , NULL };
+library_images library_images = { {}, 0 , NULL };
+void send_event(const struct dyld_event* event);
+}
+
+
+enum dyld_event_type {
+ DYLD_IMAGE_ADDED = 0,
+ DYLD_IMAGE_REMOVED = 5
+};
+
+struct dyld_event {
+ enum dyld_event_type type;
+ const struct mach_header* header;
+ uintptr_t slide;
+};
+
+
+// gdb only notices changes bundles/dylibs loaded at runtime
+// if the "send_event()" function in dyld is called...
+void send_event(const struct dyld_event* event);
+void (*send_event_ptr)(const struct dyld_event* event) = &send_event;
+
+void addImageForgdb(const mach_header* mh, uintptr_t slide, const char* physicalPath, const char* logicalPath)
+{
+ struct library_images* li = &library_images;
+ while ( li->nimages >= NLIBRARY_IMAGES ) {
+ if ( li->next_images == NULL ) {
+ struct library_images* li2 = new struct library_images();
+ li2->nimages = 0;
+ li2->next_images = NULL;
+ li->next_images = li2;
+ li = li2;
+ }
+ else {
+ li = li->next_images;
+ }
+ }
+ image* info = &li->images[li->nimages++];
+ info->physical_name = physicalPath;
+ info->vmaddr_slide = slide;
+ info->mh = mh;
+ info->valid = 1;
+ info->name = logicalPath;
+
+ // ping gdb about change
+ dyld_event event;
+ event.type = DYLD_IMAGE_ADDED;
+ event.header = mh;
+ event.slide = slide;
+
+ // we have to indirect through a function pointer to keep gcc-3.5 from inlining away the function call
+ // rdar://problem/3830560
+ (*send_event_ptr)(&event);
+}
+
+// move this to after use, otherwise gcc will see it has an empty implementation and
+// optimize away the call site
+void send_event(const struct dyld_event* event)
+{
+ // This function exists to let gdb set a break point
+ // and catch libraries being added...
+}
+
+
+void removeImageForgdb(const mach_header* mh)
+{
+ for (struct library_images* li = &library_images; li != NULL; li = li->next_images) {
+ for( uint32_t n=0; n < li->nimages; ++n) {
+ struct image* image = &li->images[n];
+ if ( image->mh == mh ) {
+ image->physical_name = NULL;
+ image->vmaddr_slide = 0;
+ image->mh = 0;
+ image->valid = 0;
+ image->name = NULL;
+ return;
+ }
+ }
+ }
+}
+
+#endif
+
+static std::vector<dyld_image_info> sImageInfos;
+
+
+
+void addImagesToAllImages(uint32_t infoCount, const dyld_image_info info[])
+{
+ // set infoArray to NULL to denote it is in-use
+ dyld_all_image_infos.infoArray = NULL;
+
+ // append all new images
+ for (uint32_t i=0; i < infoCount; ++i)
+ sImageInfos.push_back(info[i]);
+ dyld_all_image_infos.infoArrayCount = sImageInfos.size();
+
+ // set infoArray back to base address of vector
+ dyld_all_image_infos.infoArray = &sImageInfos[0];
+
+ // tell gdb that about the new images
+ dyld_all_image_infos.notification(dyld_image_adding, infoCount, info);
+}
+
+void removeImageFromAllImages(const struct mach_header* loadAddress)
+{
+ dyld_image_info goingAway;
+
+ // set infoArray to NULL to denote it is in-use
+ dyld_all_image_infos.infoArray = NULL;
+
+ // remove image from infoArray
+ for (std::vector<dyld_image_info>::iterator it=sImageInfos.begin(); it != sImageInfos.end(); it++) {
+ if ( it->imageLoadAddress == loadAddress ) {
+ goingAway = *it;
+ sImageInfos.erase(it);
+ break;
+ }
+ }
+ dyld_all_image_infos.infoArrayCount = sImageInfos.size();
+
+ // set infoArray back to base address of vector
+ dyld_all_image_infos.infoArray = &sImageInfos[0];
+
+ // tell gdb that about the new images
+ dyld_all_image_infos.notification(dyld_image_removing, 1, &goingAway);
+}
+
+
+static void gdb_image_notifier(enum dyld_image_mode mode, uint32_t infoCount, const dyld_image_info info[])
+{
+ // do nothing
+ // gdb sets a break point here to catch notifications
+ //fprintf(stderr, "dyld: gdb_image_notifier(%s, %d, ...)\n", mode ? "dyld_image_removing" : "dyld_image_adding", infoCount);
+ //for (uint32_t i=0; i < dyld_all_image_infos.infoArrayCount; ++i)
+ // fprintf(stderr, "dyld: %d loading at %p %s\n", i, dyld_all_image_infos.infoArray[i].imageLoadAddress, dyld_all_image_infos.infoArray[i].imageFilePath);
+}
+
+
+
+struct dyld_all_image_infos dyld_all_image_infos = { 1, 0, NULL, &gdb_image_notifier, false };
+
+
+
--- /dev/null
+/* -*- mode: C++; c-basic-offset: 4; tab-width: 4 -*-
+ *
+ * Copyright (c) 2004-2005 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 <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <notify.h>
+#include <time.h>
+
+//
+// Stub functions needed for dyld to link with libc.a instead of libSystem.dylib
+//
+//
+static char* dyld_progname = "dyld";
+
+//
+// libc has calls to _dyld_lookup_and_bind to find args and environment. Since
+// dyld links with a staic copy of libc, those calls need to find dyld's args and env
+// not the host process. We implement a special _dyld_lookup_and_bind() that
+// just knows how to bind the few symbols needed by dyld.
+//
+void _dyld_lookup_and_bind(const char* symbolName, void** address, void* module)
+{
+ if ( strcmp(symbolName, "_environ") == 0 ) {
+ // dummy up empty environment list
+ static char *p = NULL;
+ static char **pp = &p;
+ *address = &pp;
+ return;
+ }
+ else if ( strcmp(symbolName, "___progname") == 0 ) {
+ *address = &dyld_progname;
+ return;
+ }
+
+ fprintf(stderr, "dyld: internal error: unknown symbol '%s'\n", symbolName);
+}
+
+
+int NSIsSymbolNameDefined(const char* symbolName)
+{
+ if ( strcmp(symbolName, "___progname") == 0 ) {
+ return 1;
+ }
+ fprintf(stderr, "dyld: internal error: unknown symbol '%s'\n", symbolName);
+ return 0;
+}
+
+
+/*
+ * To avoid linking in libm. These variables are defined as they are used in
+ * pthread_init() to put in place a fast sqrt().
+ */
+size_t hw_sqrt_len = 0;
+
+double
+sqrt(double x)
+{
+ return(0.0);
+}
+double
+hw_sqrt(double x)
+{
+ return(0.0);
+}
+
+/*
+ * More stubs to avoid linking in libm. This works as along as we don't use
+ * long doubles.
+ */
+long
+__fpclassifyd(double x)
+{
+ return(0);
+}
+
+long
+__fpclassify(long double x)
+{
+ return(0);
+}
+
+
+char* __hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve)
+{
+ return NULL;
+}
+
+char* __hldtoa(/*long*/ double e, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve)
+{
+ return NULL;
+}
+
+int __fegetfltrounds(void)
+{
+ return 1; /* FE_NEAREST */
+}
+
+/*
+ * We have our own localtime() to avoid needing the notify API which is used
+ * by the code in libc.a for localtime() but is in libnotify.
+ */
+struct tm* localtime(const time_t* t)
+{
+ return (struct tm*)NULL;
+}
+
--- /dev/null
+/*
+ * 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@
+ */
+
+
+
+#ifdef __i386__
+/*
+ * This is the interface for the stub_binding_helper for i386:
+ * The caller has pushed the address of the a lazy pointer to be filled in with
+ * the value for the defined symbol and pushed the address of the the mach
+ * header this pointer comes from.
+ *
+ * sp+4 address of lazy pointer
+ * sp+0 address of mach header
+ *
+ * After the symbol has been resolved and the pointer filled in this is to pop
+ * these arguments off the stack and jump to the address of the defined symbol.
+ */
+ .text
+ .align 4,0x90
+ .globl _stub_binding_helper_interface
+_stub_binding_helper_interface:
+ call __ZN4dyld14bindLazySymbolEPK11mach_headerPm
+ addl $8,%esp
+ jmpl %eax
+#endif /* __i386__ */
+
+
+#if __ppc__ || __ppc64__
+#include <architecture/ppc/mode_independent_asm.h>
+/*
+ * This is the interface for the stub_binding_helper for the ppc:
+ * The caller has placed in r11 the address of the a lazy pointer to be filled
+ * in with the value for the defined symbol and placed in r12 the address of
+ * the the mach header this pointer comes from.
+ *
+ * r11 address of lazy pointer
+ * r12 address of mach header
+ */
+#define LRSAVE MODE_CHOICE(8,16)
+#define STACK_SIZE MODE_CHOICE(144,288)
+#define R3SAVE MODE_CHOICE(56,112)
+#define R4SAVE MODE_CHOICE(60,120)
+#define R5SAVE MODE_CHOICE(64,128)
+#define R6SAVE MODE_CHOICE(68,136)
+#define R7SAVE MODE_CHOICE(72,144)
+#define R8SAVE MODE_CHOICE(76,152)
+#define R9SAVE MODE_CHOICE(80,160)
+#define R10SAVE MODE_CHOICE(84,168)
+
+
+ .text
+ .align 2
+ .globl _stub_binding_helper_interface
+_stub_binding_helper_interface:
+ mflr r0 ; get link register value
+ stg r0,LRSAVE(r1) ; save link register value in the linkage area
+ stgu r1,-STACK_SIZE(r1) ; save stack pointer and update it
+
+ stg r3,R3SAVE(r1) ; save all registers that could contain
+ stg r4,R4SAVE(r1) ; parameters to the routine that is being
+ stg r5,R5SAVE(r1) ; bound.
+ stg r6,R6SAVE(r1)
+ stg r7,R7SAVE(r1)
+ stg r8,R8SAVE(r1)
+ stg r9,R9SAVE(r1)
+ stg r10,R10SAVE(r1)
+
+ mr r3,r12 ; move address of mach header to 1st parameter
+ mr r4,r11 ; move address of lazy pointer to 2nd parameter
+ ; call dyld::bindLazySymbol(mh, lazy_symbol_pointer_address)
+ bl __ZN4dyld14bindLazySymbolEPK11mach_headerPm
+ mr r12,r3 ; move the symbol`s address into r12
+ mtctr r12 ; move the symbol`s address into count register
+
+ lg r0,STACK_SIZE+LRSAVE(r1) ; get old link register value
+
+ lg r3,R3SAVE(r1) ; restore all registers that could contain
+ lg r4,R4SAVE(r1) ; parameters to the routine that was bound.
+ lg r5,R5SAVE(r1)
+ lg r6,R6SAVE(r1)
+ lg r7,R7SAVE(r1)
+ lg r8,R8SAVE(r1)
+ lg r9,R9SAVE(r1)
+ lg r10,R10SAVE(r1)
+
+ addi r1,r1,STACK_SIZE; restore old stack pointer
+ mtlr r0 ; restore link register
+
+ bctr ; jump to the symbol`s address that was bound
+
+#endif /* __ppc__ */
+
+
+
+
+
+
+
+
+
+
+
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+
+sub PASS
+{
+ my ($format, $args) = @_;
+ if(!defined $args)
+ { $args = []; }
+ printf("PASS \"$format\"\n", @$args);
+}
+
+sub FAIL
+{
+ my ($format, $args) = @_;
+ if(!defined $args)
+ { $args = []; }
+ printf("FAIL \"$format\"\n", @$args);
+}
+
+my $pass_string = shift @ARGV;
+my $fail_string = shift @ARGV;
+
+if(0 != system(@ARGV))
+{
+ PASS($pass_string);
+}
+else
+{
+ FAIL($fail_string);
+}
+exit 0;
+
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+
+sub PASS
+{
+ my ($format, $args) = @_;
+ if(!defined $args)
+ { $args = []; }
+ printf("PASS \"$format\"\n", @$args);
+}
+
+sub FAIL
+{
+ my ($format, $args) = @_;
+ if(!defined $args)
+ { $args = []; }
+ printf("FAIL \"$format\"\n", @$args);
+}
+
+my $pass_string = shift @ARGV;
+my $fail_string = shift @ARGV;
+
+if(0 == system(@ARGV))
+{
+ PASS($pass_string);
+}
+else
+{
+ FAIL($fail_string);
+}
+exit 0;
+
--- /dev/null
+#!/usr/bin/perl
+
+use strict;
+use Data::Dumper;
+use File::Find;
+use Cwd qw(realpath);
+
+my @args = @ARGV;
+
+my $makefiles =
+{
+ 'makefile' => undef,
+ 'Makefile' => undef,
+};
+
+my $find_opts =
+{
+ 'wanted' => \&find_callback,
+};
+
+my $keywords =
+{
+ 'root' => '',
+ 'cwd' => '',
+ 'cmd' => '',
+ 'exit' => '',
+ 'stdout' => [],
+ 'stderr' => [],
+};
+
+my $keyword;
+my $max_keyword_len = 0;
+foreach $keyword (keys %$keywords)
+{ if($max_keyword_len < length($keyword)) { $max_keyword_len = length($keyword); } }
+my $delim = ':';
+$max_keyword_len += length($delim) + length(' ');
+
+my $last_keyword = '';
+
+sub print_line
+{
+ my ($keyword, $val) = @_;
+
+ if(!exists($$keywords{$keyword}))
+ {
+ print STDERR "error: keyword $keyword not in \$keywords set\n";
+ exit(1);
+ }
+
+ my $keyword_len = 0;
+
+ if($keyword ne $last_keyword)
+ {
+ print("$keyword"); print($delim);
+ $keyword_len = length($keyword) + length($delim);
+ }
+ if($max_keyword_len > $keyword_len)
+ {
+ my $num_spaces = $max_keyword_len - $keyword_len;
+ print(' ' x $num_spaces);
+ }
+ print("$val");
+ if(0)
+ {
+ $last_keyword = $keyword;
+ }
+}
+
+my $root = '.';
+$root = &realpath($root);
+print_line("root", "$root\n");
+
+find($find_opts, $root);
+
+sub find_callback
+{
+ if(exists($$makefiles{$_}))
+ {
+ my $makefile = $_;
+ my $reldir = $File::Find::dir;
+ $reldir =~ s|^$root/||;
+
+ &print_line("cwd", "\$root/$reldir\n");
+ my $cmd = [ "make" ];
+
+ my $arg; foreach $arg (@ARGV) { push @$cmd, $arg; } # better way to do this?
+ &print_line("cmd", "@$cmd\n");
+
+ open(SAVEOUT, ">&STDOUT") || die("$!");
+ open(SAVEERR, ">&STDERR") || die("$!");
+ open(STDOUT, ">/tmp/unit-tests-stdout") || die("$!");
+ open(STDERR, ">/tmp/unit-tests-stderr") || die("$!");
+
+ my $exit = system(@$cmd);
+
+ close(STDOUT) || die("$!");
+ close(STDERR) || die("$!");
+ open(STDOUT, ">&SAVEOUT") || die("$!");
+ open(STDERR, ">&SAVEERR") || die("$!");
+
+ &print_line("exit", "$exit\n");
+
+ open(OUT, "</tmp/unit-tests-stdout") || die("$!");
+ while(<OUT>)
+ {
+ &print_line("stdout", "$_");
+ }
+ close(OUT) || die("$!");
+ unlink("/tmp/unit-tests-stdout");
+
+ open(ERR, "</tmp/unit-tests-stderr") || die("$!");
+ while(<ERR>)
+ {
+ &print_line("stderr", "$_");
+ }
+ close(ERR) || die("$!");
+ }
+ unlink("/tmp/unit-tests-stderr");
+}
--- /dev/null
+#!/usr/bin/perl -w
+
+use strict;
+use Data::Dumper;
+use File::Find;
+use Cwd;
+
+$Data::Dumper::Terse = 1;
+
+my $root = undef;
+my $entry = '';
+my $pass_count = 0;
+my $total_count = 0;
+
+# first match "root: "
+
+# a line starting with "cwd:" marks the beginning of a new test case
+# call process_entry() on each test case
+while(<>)
+{
+ if(m/^root:\s+(.*?)$/)
+ {
+ $root = $1;
+ }
+ elsif(m/^cwd:\s+(.*?)$/)
+ {
+ if(length($entry))
+ {
+ &process_entry($root, $entry);
+ $entry = '';
+ }
+ $entry .= $_;
+ }
+ else
+ {
+ $entry .= $_;
+ }
+}
+# don't forget last test case (no cwd: to mark end)
+if(length($entry))
+{
+ &process_entry($root, $entry);
+}
+
+# show totals
+my $percentage = $pass_count * 100 / $total_count;
+print "\n";
+printf " * * * %d of %d unit-tests passed (%.1f percent) * * *\n", $pass_count, $total_count, $percentage;
+
+
+sub process_entry
+{
+ my ($root, $lines) = @_;
+
+ # build an associative array of keys to value(s)
+ my $lines_seq = [split /\n/, $lines];
+ #print Dumper($lines_seq);
+ my $tbl = { 'root' => $root, 'stdout' => [], 'stderr' => [] };
+ my $line;
+ foreach $line (@$lines_seq)
+ {
+ if($line =~ m/^(\w+):\s+(.*)$/)
+ {
+ my $key = $1;
+ my $val = $2;
+ if(!exists($$tbl{$key}))
+ { $$tbl{$key} = ''; }
+
+ if($key eq 'stdout' || $key eq 'stderr') # if type is @array
+ {
+ push @{$$tbl{$key}}, $val;
+ }
+ else
+ {
+ $$tbl{$key} .= $val;
+ }
+ }
+ else
+ {
+ print "ERROR: $line";
+ }
+ }
+ #print Dumper($tbl);
+ #return;
+
+ my $test_name = $$tbl{cwd};
+ if ($test_name =~ m|.*/([a-zA-Z0-9-+_]+)$|)
+ {
+ $test_name = $1;
+ }
+
+ #if make failed (exit was non-zero), mark this as a failure
+ if(0 ne $$tbl{exit})
+ {
+ printf "%-40s FAIL Makefile failure\n", $test_name;
+ $total_count++;
+ return;
+ }
+ my $seen_result = 0;
+
+ # scan all stdout looking for lines that start with PASS or FAIL
+ foreach $line (@{$$tbl{stdout}})
+ {
+ if($line =~ m/^(PASS|XPASS|FAIL|XFAIL).+/)
+ {
+ printf "%-40s %s\n", $test_name, $line;
+ $total_count++;
+ if($line =~ m/^PASS.+/)
+ {
+ $pass_count++;
+ }
+ $seen_result = 1;
+ }
+ }
+ if(!$seen_result)
+ {
+ printf "%-40s AMBIGIOUS missing [X]PASS/[X]FAIL\n", $test_name;
+ $total_count++;
+ }
+}
--- /dev/null
+# stuff to include in every test Makefile
+
+SHELL = /bin/sh
+
+CC = gcc-4.0 ${ARCH}
+CCFLAGS = -Wall -g -std=c99
+
+CXX = g++-4.0 ${ARCH}
+CXXFLAGS = -Wall -g
+
+RM = rm
+RMFLAGS = -rf
--- /dev/null
+#include <stdarg.h>
+#include <stdio.h>
+
+#define DEFINE_TEST_FUNC(name) \
+ static \
+ inline \
+ void \
+ name(const char *format, ...) \
+ { \
+ va_list args; \
+ va_start(args, format); \
+ common(stdout, #name, format, args); \
+ va_end(args); \
+ return; \
+ }
+
+static
+inline
+void
+common(FILE *file, const char *prefix, const char *format, va_list args)
+{
+ fprintf(file, "%s \"", prefix);
+ vfprintf(file, format, args);
+ fprintf(file, "\"\n"); // should check for trailing newline
+ return;
+}
+
+DEFINE_TEST_FUNC(PASS);
+DEFINE_TEST_FUNC(XPASS);
+DEFINE_TEST_FUNC(FAIL);
+DEFINE_TEST_FUNC(XFAIL);
+
+DEFINE_TEST_FUNC(UNTESTED);
+DEFINE_TEST_FUNC(UNSUPPORTED);
+DEFINE_TEST_FUNC(UNRESOLVED);
--- /dev/null
+#!/bin/sh
+
+# cd into test-cases directory
+cd `echo "$0" | sed 's/run-all-unit-tests/test-cases/'`
+
+echo ""
+echo " * * * Running all unit tests for 32-bits * * *"
+
+# make clean
+../bin/make-recursive.pl clean > /dev/null
+
+# build default architecture
+../bin/make-recursive.pl | ../bin/result-filter.pl
+
+# if G5, then also run all test cases built for ppc64
+if [ `machine` = "ppc970" ]
+then
+ echo ""
+ echo " * * * Running all unit tests for 64-bits * * *"
+
+ # make clean
+ ../bin/make-recursive.pl clean > /dev/null
+
+ # build 64-bit architecture
+ ../bin/make-recursive.pl ARCH="-arch ppc64" | ../bin/result-filter.pl
+fi
+
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c libbar.dylib libfoo.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main
+
+libfoo.dylib : foo.c libbar.dylib
+ ${CC} -I${TESTROOT}/include -dynamiclib foo.c -o libfoo.dylib libbar.dylib
+
+libbar.dylib : bar.c
+ ${CC} -I${TESTROOT}/include -dynamiclib bar.c -o libbar.dylib -install_name /usr/local/hide/libbar.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libbar.dylib libfoo.dylib
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/4058724
+
+int main()
+{
+ // test that image can be found via install path
+ const struct mach_header * mh1 = NSAddImage("libbar.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
+ const struct mach_header * mh2 = NSAddImage("libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_MATCH_FILENAME_BY_INSTALLNAME);
+ if ( mh2 != NULL )
+ PASS("NSAddImage-MATCH_BY_INSTALLNAME");
+ else
+ FAIL("NSAddImage-MATCH_BY_INSTALLNAME");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c
+ ${CC} -I${TESTROOT}/include main.c -o main
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/3748251
+
+int main()
+{
+ // test that NSAddImage() does not crash if image is not loaded
+ const struct mach_header * mh = NSAddImage("/System/Library/Frameworks/Cocoa.framework/Cocoa", NSADDIMAGE_OPTION_RETURN_ONLY_IF_LOADED);
+ if ( mh == NULL )
+ PASS("NSAddImage-RETURN_ONLY_IF_LOADED");
+ else
+ FAIL("NSAddImage-RETURN_ONLY_IF_LOADED");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_FALLBACK_LIBRARY_PATH="hide" && ./main
+
+all: main hide/libzzz.dylib
+
+main : main.c
+ ${CC} -I${TESTROOT}/include main.c -o main
+
+hide/libzzz.dylib: zzz.c
+ mkdir -p hide
+ ${CC} zzz.c -dynamiclib -o hide/libzzz.dylib
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main hide
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+/// rdar://problem/3751226
+
+int main()
+{
+ // test that NSAddImage() uses fallback path when given a leaf name
+ const struct mach_header * mh = NSAddImage("libzzz.dylib", NSADDIMAGE_OPTION_WITH_SEARCHING);
+ if ( mh != NULL )
+ PASS("NSAddImage-leafname");
+ else
+ FAIL("NSAddImage-leafname");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+void zzz() {}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+// test to see if bss section is properly expanded
+
+static int mydata[1000000];
+
+bool checkdata()
+{
+ return ( mydata[500000] == 0 );
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 1;
+ }
+
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 1;
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 1;
+ }
+
+ CheckFunc func = NSAddressOfSymbol(sym);
+ if ( !func() ) {
+ FAIL("NSAddressOfSymbol failed");
+ return 1;
+ }
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 1;
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ return 1;
+ }
+
+ PASS("bundle-basic");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+// test to see if bss section is properly expanded
+
+static int mydata[1000000];
+
+bool checkdata()
+{
+ return ( mydata[500000] == 0 );
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+ int fd = open("test.bundle", O_RDONLY, 0);
+ if ( fd == -1 ) {
+ FAIL("open() failed");
+ return 1;
+ }
+
+ struct stat stat_buf;
+ if ( fstat(fd, &stat_buf) == -1) {
+ FAIL("fstat() failed");
+ return 1;
+ }
+
+ void* loadAddress = mmap(NULL, stat_buf.st_size, PROT_READ, MAP_FILE | MAP_PRIVATE, fd, 0);
+ if ( loadAddress == ((void*)(-1)) ) {
+ FAIL("mmap() failed");
+ return 1;
+ }
+
+ close(fd);
+
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromMemory(loadAddress, stat_buf.st_size, &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromMemory failed");
+ return 1;
+ }
+
+ NSModule mod = NSLinkModule(ofi, "he_he", NSLINKMODULE_OPTION_NONE);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 1;
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 1;
+ }
+
+ CheckFunc func = NSAddressOfSymbol(sym);
+ if ( !func() ) {
+ FAIL("NSAddressOfSymbol failed");
+ return 1;
+ }
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 1;
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ return 1;
+ }
+
+ // Should check that loadAddress is unmmaped now (by call to NSDestroyObjectFileImage)
+
+ PASS("bundle-memory-load");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+static int value = 0;
+
+int getValue()
+{
+ return value;
+}
+
+void setValue(int v)
+{
+ value = v;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+///
+/// The point of this test case is to "load" a bundle once, but link it multiple times.
+/// Each link creats a new instantiation of the bundle (e.g. new base address and new globals).
+///
+///
+
+typedef void (*setter)(int);
+typedef int (*getter)(void);
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 0;
+ }
+
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 0;
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_setValue");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 0;
+ }
+
+ setter func = NSAddressOfSymbol(sym);
+ (*func)(1);
+ //fprintf(stderr, "address of foo() = %p in bundle first load %p\n", func, mod);
+
+
+ NSModule mod2 = NSLinkModule(ofi, "test2.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod2 == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ if ( mod == mod2 ) {
+ FAIL("2nd NSLinkModule return same function address as first");
+ return 0;
+ }
+
+ NSSymbol sym2getter = NSLookupSymbolInModule(mod2, "_getValue");
+ if ( sym2getter == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ getter func2getter = NSAddressOfSymbol(sym2getter);
+ if ( (*func2getter)() != 0 ) {
+ FAIL("_getValue() on second link returned non-zero");
+ return 0;
+ }
+
+ NSSymbol sym2 = NSLookupSymbolInModule(mod2, "_setValue");
+ if ( sym2 == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ setter func2 = NSAddressOfSymbol(sym2);
+ (*func2)(2);
+
+ //fprintf(stderr, "address of foo() = %p in bundle second load %p\n", func2, mod2);
+ if ( func == func2 ) {
+ FAIL("2nd NSAddressOfSymbol return same function address as 1st");
+ return 0;
+ }
+
+
+ NSModule mod3 = NSLinkModule(ofi, "test3.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod3 == NULL ) {
+ FAIL("3rd NSLinkModule failed");
+ return 0;
+ }
+ if ( mod3 == mod ) {
+ FAIL("3rd NSLinkModule return same function address as 1st");
+ return 0;
+ }
+ if ( mod3 == mod2 ) {
+ FAIL("3rd NSLinkModule return same function address as 2nd");
+ return 0;
+ }
+
+ NSSymbol sym3 = NSLookupSymbolInModule(mod3, "_setValue");
+ if ( sym3 == NULL ) {
+ FAIL("3rd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ setter func3 = NSAddressOfSymbol(sym3);
+ (*func3)(3);
+ //fprintf(stderr, "address of foo() = %p in bundle third load %p\n", func3, mod3);
+ if ( func3 == func ) {
+ FAIL("3rd NSAddressOfSymbol return same function address as 1st");
+ return 0;
+ }
+ if ( func3 == func2 ) {
+ FAIL("3rd NSAddressOfSymbol return same function address as 2nd");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod3, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("3rd NSUnLinkModule failed");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod2, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("2nd NSUnLinkModule failed");
+ return 0;
+ }
+
+ // now link again after unlinking everything
+ NSModule mod4 = NSLinkModule(ofi, "test4.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod4 == NULL ) {
+ FAIL("4th NSLinkModule failed");
+ return 0;
+ }
+
+ // check that this is really a new copy by verifying the getValue() returns zero
+ NSSymbol sym4getter = NSLookupSymbolInModule(mod2, "_getValue");
+ if ( sym4getter == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ getter func4getter = NSAddressOfSymbol(sym4getter);
+ if ( (*func4getter)() != 0 ) {
+ FAIL("_getValue() on fourth link returned non-zero");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod4, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("4th NSUnLinkModule failed");
+ return 0;
+ }
+
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ return 0;
+ }
+
+ PASS("bundle-multi-link");
+ return 0;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+ return 4;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+///
+/// The point of this test is to load the same bundle file multiple times and
+/// verify each time it is linked is a new instantiations (new globals, etc)
+///
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 0;
+ }
+
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 0;
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_foo");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 0;
+ }
+
+ void* func = NSAddressOfSymbol(sym);
+ fprintf(stderr, "1st address of foo() = %p in module %p in OFI %p\n", func, mod, ofi);
+
+
+ NSObjectFileImage ofi2;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi2) != NSObjectFileImageSuccess ) {
+ FAIL("2nd NSCreateObjectFileImageFromFile failed");
+ return 0;
+ }
+
+ NSModule mod2 = NSLinkModule(ofi2, "test2.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod2 == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed");
+ return 0;
+ }
+ if ( mod == mod2 ) {
+ FAIL("2nd NSLinkModule return same function address as first\n");
+ return 0;
+ }
+
+ NSSymbol sym2 = NSLookupSymbolInModule(mod2, "_foo");
+ if ( sym2 == NULL ) {
+ FAIL("2nd NSLookupSymbolInModule failed\n");
+ return 0;
+ }
+
+ void* func2 = NSAddressOfSymbol(sym2);
+ fprintf(stderr, "2nd address of foo() = %p in module %p in OFI %p\n", func2, mod2, ofi2);
+ if ( func == func2 ) {
+ FAIL("2nd NSAddressOfSymbol return same function address as 1st\n");
+ return 0;
+ }
+
+
+ NSObjectFileImage ofi3;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi3) != NSObjectFileImageSuccess ) {
+ FAIL("3rd NSCreateObjectFileImageFromFile failed");
+ return 0;
+ }
+ NSModule mod3 = NSLinkModule(ofi3, "test3.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod3 == NULL ) {
+ FAIL("3rd NSLinkModule failed\n");
+ return 0;
+ }
+ if ( mod3 == mod ) {
+ FAIL("3rd NSLinkModule return same function address as 1st\n");
+ return 0;
+ }
+ if ( mod3 == mod2 ) {
+ FAIL("3rd NSLinkModule return same function address as 2nd\n");
+ return 0;
+ }
+
+ NSSymbol sym3 = NSLookupSymbolInModule(mod3, "_foo");
+ if ( sym3 == NULL ) {
+ FAIL("3rd NSLookupSymbolInModule failed\n");
+ return 0;
+ }
+ void* func3 = NSAddressOfSymbol(sym3);
+ fprintf(stderr, "3rd address of foo() = %p in module %p in OFI %p\n", func3, mod3, ofi3);
+ if ( func3 == func ) {
+ FAIL("3rd NSAddressOfSymbol return same function address as 1st\n");
+ return 0;
+ }
+ if ( func3 == func2 ) {
+ FAIL("3rd NSAddressOfSymbol return same function address as 2nd\n");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 0;
+ }
+
+ if ( !NSUnLinkModule(mod3, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("3rd NSUnLinkModule failed");
+ return 0;
+ }
+
+ // note, we are calling NSDestroyObjectFileImage() before NSUnLinkModule()
+ if ( !NSDestroyObjectFileImage(ofi2) ) {
+ FAIL("2nd NSDestroyObjectFileImage failed");
+ return 0;
+ }
+ if ( !NSUnLinkModule(mod2, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("2nd NSUnLinkModule failed");
+ return 0;
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("1st NSDestroyObjectFileImage failed");
+ return 0;
+ }
+ if ( !NSDestroyObjectFileImage(ofi3) ) {
+ FAIL("3rd NSDestroyObjectFileImage failed");
+ return 0;
+ }
+
+ PASS("bundle-multi-load");
+ return 0;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+// test to see if NSLINKMODULE_OPTION_PRIVATE works
+
+void findme()
+{
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 1;
+ }
+
+ NSModule modPriv = NSLinkModule(ofi, "test.bundle-private", NSLINKMODULE_OPTION_PRIVATE);
+ if ( modPriv == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 1;
+ }
+
+ NSSymbol symPriv = NSLookupSymbolInModule(modPriv, "_findme");
+ if ( symPriv == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 1;
+ }
+
+ if ( NSIsSymbolNameDefined("_findme") ) {
+ FAIL("NSIsSymbolNameDefined (incorrectly) found symbol in private bundle");
+ return 1;
+ }
+
+ NSModule modPublic = NSLinkModule(ofi, "test.bundle-public", NSLINKMODULE_OPTION_NONE);
+ if ( modPublic == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 1;
+ }
+
+ NSSymbol symPublic = NSLookupSymbolInModule(modPublic, "_findme");
+ if ( symPublic == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 1;
+ }
+
+ if ( !NSIsSymbolNameDefined("_findme") ) {
+ FAIL("NSIsSymbolNameDefined did not found symbol in public bundle");
+ return 1;
+ }
+
+ if ( !NSUnLinkModule(modPriv, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 1;
+ }
+
+ if ( !NSUnLinkModule(modPublic, NSUNLINKMODULE_OPTION_NONE) ) {
+ FAIL("NSUnLinkModule failed");
+ return 1;
+ }
+
+ if ( NSIsSymbolNameDefined("_findme") ) {
+ FAIL("NSIsSymbolNameDefined found unlinked symbol in public bundle");
+ return 1;
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ return 1;
+ }
+
+ PASS("bundle-private");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c libstuff.dylib
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c libstuff.dylib
+
+libstuff.dylib : lib.c
+ ${CC} ${CCFLAGS} lib.c -dynamiclib -o libstuff.dylib -install_name libcantfind.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle libstuff.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int bar();
+
+
+int foo()
+{
+ return bar();
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+
+int bar()
+{
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <string.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 1;
+ }
+
+ // make sure not-yet-linked-ofi is not visible through _dyld_get_image_name
+ int count = _dyld_image_count();
+ for(int i=0; i < count; ++i) {
+ const char* name = _dyld_get_image_name(i);
+ if ( strcmp(name, "test.bundle") == 0 ) {
+ FAIL("unlinked test.bundle found via _dyld_get_image_name()");
+ return 1;
+ }
+ }
+
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ if ( mod != NULL ) {
+ FAIL("NSLinkModule succeeded but should have failed");
+ return 1;
+ }
+
+ // make sure link-failed-ofi is not visible through _dyld_get_image_name
+ count = _dyld_image_count();
+ for(int i=0; i < count; ++i) {
+ const char* name = _dyld_get_image_name(i);
+ if ( strcmp(name, "test.bundle") == 0 ) {
+ FAIL("failed linked test.bundle found via _dyld_get_image_name()");
+ return 1;
+ }
+ }
+
+ PASS("bundle-unlinkable");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+// test to see if bss section is properly expanded
+
+static int mydata[10];
+
+bool checkdata()
+{
+ return ( mydata[10] == 0 );
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+typedef bool (*CheckFunc)();
+
+int main()
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 1;
+ }
+
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_NONE);
+ if ( mod == NULL ) {
+ FAIL("NSLinkModule failed");
+ return 1;
+ }
+
+ NSSymbol sym = NSLookupSymbolInModule(mod, "_checkdata");
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInModule failed");
+ return 1;
+ }
+
+ CheckFunc func = NSAddressOfSymbol(sym);
+ if ( !func() ) {
+ FAIL("NSAddressOfSymbol failed");
+ return 1;
+ }
+
+ if ( !NSUnLinkModule(mod, NSUNLINKMODULE_OPTION_KEEP_MEMORY_MAPPED) ) {
+ FAIL("NSUnLinkModule failed");
+ return 1;
+ }
+
+ if ( !NSDestroyObjectFileImage(ofi) ) {
+ FAIL("NSDestroyObjectFileImage failed");
+ return 1;
+ }
+
+ // call function again, even though bundle is unloaded
+ func();
+
+
+ PASS("bundle-basic");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c bar.dylib foo.bundle foo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c bar.dylib
+
+foo.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle -o foo.bundle foo.c
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib -o foo.dylib foo.c
+
+bar.dylib : bar.c
+ ${CC} ${CCFLAGS} -dynamiclib -o bar.dylib bar.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+
+void bar()
+{
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+
+void foo()
+{
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+void loadAsBundle(const char* path)
+{
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile(path, &ofi) == NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile() incorrectly allowed %s to be loaded", path);
+ exit(1);
+ }
+}
+
+void loadAsDylib(const char* path)
+{
+ if ( NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR) != NULL ) {
+ FAIL("NSAddImage() incorrectly allowed %s to be loaded", path);
+ exit(1);
+ }
+}
+
+
+extern void bar();
+
+int main()
+{
+ // verify that NSAddImage fails to load MH_BUNDLE
+ loadAsDylib("foo.bundle");
+
+ // verify that NSCreateObjectFileImageFromFile fails to load MH_DYLIB
+ loadAsBundle("foo.dylib");
+
+ // verify that NSCreateObjectFileImageFromFile fails to load MH_DYLIB already linked against main
+ loadAsBundle("bar.dylib");
+ // verify that bar.dylib was not unloaded when above failed
+ bar();
+
+ PASS("bundle-v-dylib");
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c bar.dylib foo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c foo.dylib
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib -o foo.dylib foo.c
+
+bar.dylib : bar.c
+ ${CC} ${CCFLAGS} -dynamiclib -o bar.dylib bar.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.dylib bar.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+void bar()
+{
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+void foo()
+{
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+#include <pthread.h>
+
+#include "test.h"
+
+/// rdar://problem/3811777
+
+// barrier thread 1 thread 2
+// add image
+// 1
+// acquire sMyLock
+// 2
+// in callback acquire sMyLock call lazy pointer
+// release sMyLock release sMyLock
+
+extern void foo();
+
+
+static volatile int sBarrier = 0;
+static pthread_mutex_t sBarrierMutex;
+static pthread_cond_t sBarrierFree;
+
+static void blockUntilBarrier(int n)
+{
+ pthread_mutex_lock(&sBarrierMutex);
+ while ( sBarrier < n )
+ pthread_cond_wait(&sBarrierFree, &sBarrierMutex);
+ pthread_mutex_unlock(&sBarrierMutex);
+}
+
+static void advanceToBarrier(int n)
+{
+ pthread_mutex_lock(&sBarrierMutex);
+ sBarrier = n;
+ pthread_cond_broadcast(&sBarrierFree);
+ pthread_mutex_unlock(&sBarrierMutex);
+}
+
+
+
+
+
+static pthread_mutex_t sMyLock;
+
+static void* thread2(void* arg)
+{
+ // thread 2
+ blockUntilBarrier(1);
+ pthread_mutex_lock(&sMyLock);
+ advanceToBarrier(2);
+ foo();
+ pthread_mutex_unlock(&sMyLock);
+ return NULL;
+}
+
+
+
+static void myImageHandler(const struct mach_header *mh, intptr_t vmaddr_slide)
+{
+ // thread 1
+ if ( NSLookupSymbolInImage(mh, "_bar", 0) != NULL ) {
+ advanceToBarrier(1);
+ blockUntilBarrier(2);
+ pthread_mutex_lock(&sMyLock);
+ pthread_mutex_unlock(&sMyLock);
+ }
+}
+
+int main()
+{
+ pthread_mutex_init(&sBarrierMutex, NULL);
+ pthread_cond_init(&sBarrierFree, NULL);
+ pthread_mutex_init(&sMyLock, NULL);
+
+ // self-terminate this process if it locks up for two seconds
+ alarm(2);
+
+ advanceToBarrier(0);
+
+ pthread_t pthread2;
+ if ( pthread_create(&pthread2, NULL, thread2, NULL) != 0 ) {
+ FAIL("pthread_create failed");
+ exit(0);
+ }
+
+ // thread 1
+ _dyld_register_func_for_add_image(&myImageHandler);
+ NSAddImage("bar.dylib", 0);
+
+ PASS("deadlock");
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int bar()
+{
+ return 2;
+}
+
+static int foo()
+{
+ return 3;
+}
+
+int bar2()
+{
+ return 4;
+}
+
+// checks global symbol
+static void verifybar()
+{
+ Dl_info info;
+ if ( dladdr(&bar, &info) == 0 ) {
+ FAIL("dladdr(&bar, xx) failed");
+ exit(0);
+ }
+ if ( strcmp(info.dli_sname, "bar") != 0 ) {
+ if ( strcmp(info.dli_sname, "_bar") == 0 ) {
+ XFAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+ }
+ else {
+ FAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+ exit(0);
+ }
+ }
+ if ( info.dli_saddr != &bar) {
+ FAIL("dladdr()->dli_saddr is not &bar");
+ exit(0);
+ }
+ if ( info.dli_fbase != _dyld_get_image_header_containing_address(&bar) ) {
+ FAIL("dladdr()->dli_fbase is not image that contains &bar");
+ exit(0);
+ }
+}
+
+// checks local symbol (should resolve to previoius global symbol bar)
+static void verifyfoo()
+{
+ Dl_info info;
+ if ( dladdr(&foo, &info) == 0 ) {
+ FAIL("dladdr(&foo, xx) failed");
+ exit(0);
+ }
+ if ( strcmp(info.dli_sname, "bar") != 0 ) {
+ if ( strcmp(info.dli_sname, "_bar") == 0 ) {
+ XFAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+ }
+ else {
+ FAIL("dladdr()->dli_sname is \"%s\" instead of \"bar\"", info.dli_sname);
+ exit(0);
+ }
+ }
+ if ( info.dli_saddr != &bar) {
+ FAIL("dladdr()->dli_saddr is not &bar");
+ exit(0);
+ }
+ if ( info.dli_fbase != _dyld_get_image_header_containing_address(&bar) ) {
+ FAIL("dladdr()->dli_fbase is not image that contains &bar");
+ exit(0);
+ }
+}
+
+
+int main()
+{
+ verifybar();
+ verifyfoo();
+
+
+ PASS("dladdr");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle -o test.bundle foo.c
+
+main : main.c test.bundle
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main()
+{
+ // regular open
+ void* handle = dlopen("test.bundle", RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"test.bundle\", RTLD_LAZY) failed");
+ exit(1);
+ }
+
+ // regular close
+ int result = dlclose(handle);
+ if ( result != 0 ) {
+ FAIL("dlclose() failed");
+ exit(1);
+ }
+
+ // now try to close again (expect to fail)
+ result = dlclose(handle);
+ if ( result != -1 ) {
+ FAIL("dlclose() on released handle should have returned -1, but returned %d", result);
+ exit(1);
+ }
+
+ // now try to close a bad handle value (expect to fail)
+ result = dlclose((void*)0x12345);
+ if ( result != -1 ) {
+ FAIL("dlclose() on bogus handle should have returned -1, but returned %d", result);
+ exit(1);
+ }
+
+ PASS("dlclose-basic");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int main()
+{
+ // open same bundle three times
+ void* handle1 = dlopen("test.bundle", RTLD_LAZY);
+ if ( handle1 == NULL ) {
+ FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+ exit(0);
+ }
+
+ void* handle2 = dlopen("test.bundle", RTLD_LAZY);
+ if ( handle2 == NULL ) {
+ FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+ exit(0);
+ }
+
+ void* handle3 = dlopen("test.bundle", RTLD_LAZY);
+ if ( handle3 == NULL ) {
+ FAIL("dlclose-bundle-unload: dlopen(\"test.bundle\", RTLD_LAZY) failed with dlerror()=%s", dlerror());
+ exit(0);
+ }
+
+ // get symbol
+ void* sym = dlsym(handle1, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlclose-bundle-unload: dlsym(handle1, \"foo\") failed");
+ exit(0);
+ }
+
+ // close same bundle three times
+ if ( dlclose(handle3) != 0 ) {
+ FAIL("dlclose-bundle-unload: dlclose(handle3) != 0, dlerrr()=%s", dlerror());
+ exit(0);
+ }
+
+ if ( dlclose(handle2) != 0 ) {
+ FAIL("dlclose-bundle-unload: dlclose(handle2) != 0, dlerrr()=%s", dlerror());
+ exit(0);
+ }
+
+ if ( dlclose(handle1) != 0 ) {
+ FAIL("dlclose-bundle-unload: dlclose(handle1) != 0, dlerrr()=%s", dlerror());
+ exit(0);
+ }
+
+
+ // extra close should fail
+ if ( dlclose(handle1) == 0 ) {
+ FAIL("dlclose-bundle-unload: dlclose(handle4) == 0, but should have failed");
+ exit(0);
+ }
+
+
+
+ PASS("dlclose-bundle-unload");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+#include <pthread.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that the dlerror message is kept per thread
+///
+
+static void* work(void* arg)
+{
+ const char* str = (char*)arg;
+ for(int i=0; i < 1000; ++i) {
+ //fprintf(stderr, "dlopen(%s)\n", str);
+ void* handle = dlopen(str, RTLD_LAZY);
+ if ( handle != NULL ) {
+ FAIL("dlopen(%s) unexpectedly succeeded", str);
+ exit(0);
+ }
+ char* msg = dlerror();
+ //fprintf(stderr, "dlopen(%s) => %s\n", str, msg);
+ if ( (msg == NULL) || (strstr(msg, str) == NULL) ) {
+ FAIL("dlerror() did not contain library name that could not be loaded", str);
+ exit(0);
+ }
+
+
+ }
+ return 0;
+}
+
+
+
+int main()
+{
+ dlsym(RTLD_DEFAULT, "foobar");
+ fprintf(stderr, "%s\n", dlerror());
+
+ pthread_t worker1;
+ if ( pthread_create(&worker1, NULL, work, "/frazzle/bar") != 0 ) {
+ FAIL("pthread_create failed");
+ exit(0);
+ }
+
+ pthread_t worker2;
+ if ( pthread_create(&worker2, NULL, work, "/frazzle/foo") != 0 ) {
+ FAIL("pthread_create failed");
+ exit(0);
+ }
+
+ pthread_t worker3;
+ if ( pthread_create(&worker3, NULL, work, "/frazzle/dazzle") != 0 ) {
+ FAIL("pthread_create failed");
+ exit(0);
+ }
+
+ void* result;
+ fprintf(stderr, "waiting for worker 1\n");
+ pthread_join(worker1, &result);
+ fprintf(stderr, "waiting for worker 2\n");
+ pthread_join(worker2, &result);
+ fprintf(stderr, "waiting for worker 3\n");
+ pthread_join(worker3, &result);
+
+ PASS("dlerror-thread-test");
+ return 0;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main "`pwd`/libfoo.dylib"
+ export DYLD_LIBRARY_PATH="`pwd`/alt" && ./main "`pwd`/libfoo.dylib"
+
+all: main alt/libfoo.dylib
+
+main : main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+alt/libfoo.dylib : foo.c
+ mkdir -p alt
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt/libfoo.dylib" -DALT
+
+libfoo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/libfoo.dylib"
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib alt/libfoo.dylib alt
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+#ifdef ALT
+ return 1;
+#else
+ return 0;
+#endif
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h> // for getenv()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+typedef int (*fooproc)();
+
+int main(int argc, const char* argv[])
+{
+ void* handle = dlopen(argv[1], RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", argv[1]);
+ exit(0);
+ }
+
+ fooproc sym = (fooproc)dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"foo\") failed");
+ exit(0);
+ }
+
+ int expectedResult = 0;
+ if ( getenv("DYLD_LIBRARY_PATH") != NULL )
+ expectedResult = 1;
+
+ int actualResult = (*sym)();
+
+ if ( actualResult != expectedResult )
+ FAIL("dlopen-DYLD_LIBRARY_PATH using wrong dylib");
+ else
+ PASS("dlopen-DYLD_LIBRARY_PATH");
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+#
+# tests combinations of dlopen() and LD_LIBRARY_PATH
+#
+# if dlopen() path contains a slash, LD_LIBRARY_PATH is ignored
+#
+# 1) leaf name found in current directory (On linux this fails because . is usually not in default LD_LIBRARY_PATH path)
+# 2) cwd relative path
+# 3) full path
+# 4) leaf name and LD_LIBRARY_PATH overrides cwd (On 10.3, this fails because cwd was always searched before LD_LIBRARY_PATH??)
+# 5) leaf name and LD_LIBRARY_PATH set to alternate directory
+# 6) fullpath and LD_LIBRARY_PATH set to alt
+#
+
+run: all
+ cd alt1 && ../main "libfoo.dylib" 1 "leafname found in cwd"
+ ./main "./alt1/libfoo.dylib" 1 "relative path"
+ ./main "`pwd`/alt2/libfoo.dylib" 2 "fullpath"
+ export LD_LIBRARY_PATH="`pwd`/alt1" && ./main "libfoo.dylib" 1 "leafname and LD_LIBRARY_PATH overrides cwd"
+ export LD_LIBRARY_PATH="`pwd`/alt1" && cd alt3 && ../main "libfoo.dylib" 1 "leafname and alt LD_LIBRARY_PATH"
+ export LD_LIBRARY_PATH="`pwd`/alt1" && ./main "`pwd`/alt2/libfoo.dylib" 2 "fullpath and LD_LIBRARY_PATH"
+
+all: main alt1/libfoo.dylib alt2/libfoo.dylib alt3
+
+main : main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+alt1/libfoo.dylib : foo.c
+ mkdir -p alt1
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt1/libfoo.dylib" -DVALUE=1
+
+alt2/libfoo.dylib : foo.c
+ mkdir -p alt2
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/alt2/libfoo.dylib" -DVALUE=2
+
+libfoo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o "`pwd`/libfoo.dylib" -DVALUE=0
+
+alt3 :
+ mkdir -p alt3
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib alt1 alt2 alt3
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return VALUE;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+#include <stdlib.h> // for getenv()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+typedef int (*fooproc)();
+
+//
+// argv[1] is path to dlopen()
+// argv[2] is exepect result from foo()
+// argv[3] is message
+//
+int main(int argc, const char* argv[])
+{
+ void* handle = dlopen(argv[1], RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen-LD_LIBRARY_PATH %s, dlopen(\"%s\") failed", argv[3], argv[1]);
+ exit(0);
+ }
+
+ fooproc sym = (fooproc)dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlopen-LD_LIBRARY_PATH %s, dlsym(handle, \"foo\") failed", argv[3]);
+ exit(0);
+ }
+
+ int expectedResult = atoi(argv[2]);
+
+ int actualResult = (*sym)();
+
+ if ( actualResult != expectedResult )
+ FAIL("dlopen-LD_LIBRARY_PATH %s", argv[3]);
+ else
+ PASS("dlopen-LD_LIBRARY_PATH %s", argv[3]);
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main foo.bundle bar.bundle
+ ./main foo.dylib bar.bundle
+
+all: main foo.bundle foo.dylib bar.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.bundle : bar.c
+ ${CC} ${CCFLAGS} -flat_namespace -bundle bar.c -o bar.bundle -undefined suppress
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+ return foo;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+
+
+int main(int argc, const char* argv[])
+{
+ // open first object which defines foo
+ void* handle = dlopen(argv[1], RTLD_GLOBAL);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", argv[1]);
+ exit(1);
+ }
+
+ // open second object which uses foo
+ void* handle2 = dlopen(argv[2], RTLD_NOW);
+ if ( handle2 == NULL ) {
+ FAIL("dlopen(\"%s\") failed", argv[2]);
+ exit(1);
+ }
+
+ PASS("dlopen-RTLD_GLOBAL");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c foo.dylib bar.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c foo.dylib
+
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.dylib : bar.c
+ ${CC} ${CCFLAGS} -dynamiclib bar.c -o bar.dylib
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.dylib bar.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar()
+{
+ return 2;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main(int argc, const char* argv[])
+{
+ // main alreadly links with foo.dylib
+ // now dynamically link with bar.dylib
+ void* handle = dlopen("./bar.dylib", RTLD_GLOBAL);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlopen(\"%s\", RTLD_GLOBAL) failed: %s", argv[1], msg);
+ return EXIT_SUCCESS;
+ }
+
+ // verify we can find _foo
+ void* fooSym = dlsym(RTLD_DEFAULT, "foo");
+ if ( fooSym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(RTLD_DEFAULT, \"foo\") failed: %s", msg);
+ return EXIT_SUCCESS;
+ }
+
+ // verify we can find _bar
+ void* barSym = dlsym(RTLD_DEFAULT, "bar");
+ if ( barSym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(RTLD_DEFAULT, \"bar\") failed: %s", msg);
+ return EXIT_SUCCESS;
+ }
+
+ // open foo privately (since it was already opened global, RTLD_LOCAL should have no effect
+ void* handleFoo = dlopen("./foo.dylib", RTLD_LOCAL);
+ if ( handleFoo == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", "./foo.dylib", msg);
+ return EXIT_SUCCESS;
+ }
+
+ // open foo privately (since it was already opened global, RTLD_LOCAL should have no effect
+ void* handleBar = dlopen("./bar.dylib", RTLD_LOCAL);
+ if ( handleBar == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", "./bar.dylib", msg);
+ return EXIT_SUCCESS;
+ }
+
+ // verify we can still find _foo
+ fooSym = dlsym(RTLD_DEFAULT, "foo");
+ if ( fooSym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(RTLD_DEFAULT, \"foo\") failed: %s", msg);
+ return EXIT_SUCCESS;
+ }
+
+ // verify we can still find _bar
+ barSym = dlsym(RTLD_DEFAULT, "bar");
+ if ( barSym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(RTLD_DEFAULT, \"bar\") failed: %s", msg);
+ return EXIT_SUCCESS;
+ }
+
+ PASS("dlopen-RTLD_LOCAL-ignore");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main foo.bundle bar.bundle
+ ./main foo.dylib bar.bundle
+
+all: main foo.bundle foo.dylib bar.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+bar.bundle : bar.c
+ ${CC} ${CCFLAGS} -flat_namespace -bundle bar.c -o bar.bundle -undefined suppress
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib bar.bundle
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+ return foo;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+int main(int argc, const char* argv[])
+{
+ // open first object which defines foo
+ void* handle = dlopen(argv[1], RTLD_LOCAL);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ // Panther dlopen() fails on RTLD_LOCAL of a dylib
+ if ( strstr(msg, "RTLD_LOCAL") != NULL )
+ XFAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", argv[1], msg);
+ else
+ FAIL("dlopen(\"%s\", RTLD_LOCAL) failed: %s", argv[1], msg);
+ return EXIT_SUCCESS;
+ }
+
+ // open second object which uses foo
+ void* handle2 = dlopen(argv[2], RTLD_NOW);
+ if ( handle2 != NULL ) {
+ FAIL("dlopen(\"%s\") succeeded but foo should have been not found", argv[2]);
+ return EXIT_SUCCESS;
+ }
+ const char* msg = dlerror();
+ if ( strstr(msg, "foo") == NULL ) {
+ FAIL("dlopen(\"%s\") correctly failed, but foo was not in error mesage: %s", argv[2], msg);
+ return EXIT_SUCCESS;
+ }
+
+
+ PASS("dlopen-RTLD_LOCAL");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 10;
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that RTLD_NODELETE prevents an image from being unloaded
+///
+
+static int trySO(const char* path)
+{ // main links against libfoo.dylib so it should already be loaded
+ void* handle = dlopen(path, RTLD_NODELETE);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlopen(\"%s\" RTLD_NODELETE) failed but it should have worked: %s", path, msg);
+ exit(0);
+ }
+ void* sym = dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(handle, \"foo\") failed but it should have worked: %s", msg);
+ exit(0);
+ }
+
+ int result = dlclose(handle);
+ if ( result != 0 ) {
+ if ( result == 1 ) {
+ // panther dyld returns 1 if you try to dlclose() a dylib
+ XFAIL("dlclose(handle[%s]) returned %d", path, result);
+ }
+ else {
+ FAIL("dlclose(handle) returned %d", result);
+ exit(0);
+ }
+ }
+
+ // now try to access foo. If .so was unmapped, this will bus error
+ return *((int*)sym);
+}
+
+
+int main()
+{
+ trySO("test.bundle");
+ trySO("test.dylib");
+
+ PASS("dlopen-RTLD_NODELETE");
+ return 0;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main libfoo.dylib
+
+main : main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c libfoo.dylib -o main
+
+libfoo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib
+
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that RTLD_NOLOAD binds finds existing images
+///
+
+
+int main()
+{
+ // main links against libfoo.dylib so it should already be loaded
+ void* handle = dlopen("libfoo.dylib", RTLD_NOLOAD);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ // Panther dlcompat does not check existing loaded images (only those opened with dlopen)
+ if ( strstr(msg, "RTLD_NOLOAD") != NULL )
+ XFAIL("dlopen(libfoo.dylib, RTLD_NOLOAD) failed but it should have worked: %s", msg);
+ else
+ FAIL("dlopen(libfoo.dylib, RTLD_NOLOAD) failed but it should have worked: %s", msg);
+ return 0;
+ }
+ void* sym = dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ const char* msg = dlerror();
+ FAIL("dlsym(handle, \"foo\") failed but it should have worked: %s", msg);
+ return 0;
+ }
+
+ // libfobbulate.dylib does not exist, so load should return NULL
+ void* handle2 = dlopen("libfobbulate.dylib", RTLD_NOLOAD);
+ if ( handle2 != NULL ) {
+ FAIL("dlopen(libfobbulate.dylib, RTLD_NOLOAD) succeeded but it should have failed");
+ return 0;
+ }
+
+
+
+ PASS("dlopen-RTLD_NOLOAD");
+ return 0;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle foo.dylib foo_foo2.dylib
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c foo_foo2.dylib
+ ${CC} ${CCFLAGS} -bundle bundle.c foo_foo2.dylib -o test.bundle
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+foo_foo2.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -DFOO2 -o foo_foo2.dylib -install_name foo.dylib
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle foo.dylib foo_foo2.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern int foo();
+extern int foo2();
+
+void doit()
+{
+ foo();
+ foo2();
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
+
+#if FOO2
+int foo2()
+{
+ return 10;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that TLD_NOW binds all lazy symbols.
+/// We do this by making sure a lazy symbol does not exist
+/// and dlopen() errors out with a message string
+/// that contains the missing symbol name.
+///
+
+
+int main()
+{
+ void* handle = dlopen("test.bundle", RTLD_NOW);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ if ( strstr(msg, "foo2") != NULL ) {
+ PASS("dlopen-RTLD_NOW");
+ exit(0);
+ }
+ FAIL("dlopen(test.bundle, RTLD_NOW) failed but error message did not contain foo2: %s", msg);
+ exit(0);
+ }
+ FAIL("dlopen(test.bundle, RTLD_NOW) succeed but should have failed because foo2 does not exist");
+ exit(0);
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+static void trySO(const char* path)
+{
+ void* handle = dlopen(path, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", path);
+ exit(0);
+ }
+
+ void* sym = dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"foo\") failed");
+ exit(0);
+ }
+
+ int result = dlclose(handle);
+ if ( result != 0 ) {
+ if ( result == 1 ) {
+ // panther dyld returns 1 if you try to dlclose() a dylib
+ XFAIL("dlclose(handle) returned %d", result);
+ }
+ else {
+ FAIL("dlclose(handle) returned %d", result);
+ exit(0);
+ }
+ }
+
+}
+
+
+
+int main()
+{
+ trySO("test.bundle");
+ trySO("test.dylib");
+
+ PASS("dlopen-basic bundle and dylib");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test1.dylib test2.dylib
+
+main : main.c test1.dylib test2.dylib test3.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test1.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -DINIT_NAME=myinit -o test1.dylib
+
+test2.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -DINIT_NAME=_init -o test2.dylib
+
+test3.dylib : bar.c
+ ${CC} ${CCFLAGS} -dynamiclib bar.c -o test3.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test1.dylib test2.dylib test3.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+static int initCount = 0;
+
+
+void _init()
+{
+ initCount++;
+}
+
+int getInitCount()
+{
+ return initCount;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+static int initCount = 0;
+
+void INIT_NAME() __attribute__((constructor));
+
+void INIT_NAME()
+{
+ initCount++;
+}
+
+int getInitCount()
+{
+ return initCount;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+typedef int (*getInitCountProc)(void);
+
+
+static void trySO(const char* path)
+{
+ void* handle = dlopen(path, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", path);
+ exit(0);
+ }
+
+ getInitCountProc sym = (getInitCountProc)dlsym(handle, "getInitCount");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"getInitCount\") failed");
+ exit(0);
+ }
+
+ int count = (*sym)();
+ if ( count != 1 ) {
+ FAIL("initializer in %s called %d times", path, count);
+ exit(0);
+ }
+
+}
+
+
+
+int main()
+{
+ trySO("test1.dylib");
+ trySO("test2.dylib");
+ //trySO("test3.dylib"); // Mac OS X 10.4 does not automatically run _init functions
+ PASS("dlopen-initializer");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main-local-first
+ ./main-global-first
+
+all: main-local-first main-global-first foo.bundle foo.dylib
+
+main-local-first : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -DLOCAL_FIRST -o main-local-first
+
+main-global-first : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include main.c -o main-global-first
+
+foo.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o foo.bundle
+
+foo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib main-global-first main-local-first
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int foo;
+
+int bar()
+{
+ return foo;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo = 0;
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+#include <string.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+
+
+static void* openWithModeGetSymbol(const char* path, int mode, const char* symbol)
+{
+ void* handle = dlopen(path, mode);
+ if ( handle == NULL ) {
+ const char* msg = dlerror();
+ if ( ((mode & RTLD_LOCAL) != 0) && (strstr(msg, "RTLD_LOCAL") != NULL) )
+ XFAIL("dlopen(\"%s\") failed: %s", path, msg);
+ else
+ FAIL("dlopen(\"%s\") failed: %s", path, msg);
+ exit(0);
+ }
+
+ void* sym = dlsym(handle, symbol);
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"%s\") failed", symbol);
+ exit(0);
+ }
+ return sym;
+}
+
+static void trySO(const char* path)
+{
+#if LOCAL_FIRST
+ void* symLocal = openWithModeGetSymbol(path, RTLD_LOCAL, "foo");
+ void* symGlobal = openWithModeGetSymbol(path, RTLD_GLOBAL, "foo");
+#else
+ void* symGlobal = openWithModeGetSymbol(path, RTLD_GLOBAL, "foo");
+ void* symLocal = openWithModeGetSymbol(path, RTLD_LOCAL, "foo");
+#endif
+ if ( symLocal != symGlobal ) {
+ FAIL("global load after local load failed");
+ exit(0);
+ }
+}
+
+
+int main(int argc, const char* argv[])
+{
+ trySO("foo.bundle");
+ trySO("foo.dylib");
+
+ PASS("dlopen-local-and-global");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int main()
+{
+ void* handle1 = dlopen("test.bundle", RTLD_LAZY);
+ void* handle2 = dlopen("test.bundle", RTLD_LAZY);
+ void* handle3 = dlopen("test.dylib", RTLD_LAZY);
+ void* handle4 = dlopen("test.dylib", RTLD_LAZY);
+ if ((NULL == handle1)||(NULL == handle2)) {
+ FAIL("dlopen(\"test.bundle\") failed");
+ }
+ if ((NULL == handle3)||(NULL == handle4)) {
+ FAIL("dlopen(\"test.dylib\") failed");
+ }
+ if (handle1 != handle2) {
+ FAIL("dlopen handle1 and handle2 are not equal %p != %p",handle1,handle2);
+ }
+ if (handle3 != handle4) {
+ FAIL("dlopen handle3 and handle4 are not equal %p != %p",handle3,handle4);
+ }
+ if (dlclose(handle4)) {
+ XFAIL("Could not close handle4");
+ }
+ if (dlclose(handle2)) {
+ FAIL("Could not close handle2");
+ }
+ void* sym = dlsym(handle1, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle1, \"foo\") failed");
+ exit(0);
+ }
+ sym = dlsym(handle3, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle3, \"foo\") failed");
+ exit(0);
+ }
+ if (dlclose(handle1)) {
+ XFAIL("Could not close handle1");
+ }
+ if (dlclose(handle3)) {
+ XFAIL("Could not close handle3");
+ }
+
+ PASS("dlopen-multi");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+ return 42;
+}
+
+
+int main()
+{
+ // passing NULL as path to dlopen() has the special meaning of
+ // "get handle to main executable"
+ void* handle = dlopen(NULL, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(NULL, RTLD_LAZY) failed");
+ exit(1);
+ }
+
+ // make sure we find "foo" in this main executable
+ void* sym = dlsym(handle, "foo");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"foo\") failed");
+ exit(1);
+ }
+ if ( sym != &foo ) {
+ FAIL("dlsym(handle, \"foo\") returned wrong address");
+ exit(1);
+ }
+
+ PASS("dlopen-zero");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main test.bundle test.dylib
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : foo.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle foo.c -o test.bundle
+
+test.dylib : foo.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib foo.c -o test.dylib
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <string.h>
+#include <dlfcn.h>
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+char* strdup(const char* str)
+{
+ return "from foo";
+}
+
+typedef char* (*strdupProc)(const char* str);
+
+
+void myinit() __attribute__((constructor));
+void myinit()
+{
+ strdupProc sym = (strdupProc)dlsym(RTLD_DEFAULT, "strdup");
+ if ( sym == NULL ) {
+ FAIL("dlsym(RTLD_DEFAULT, \"strdup\") failed");
+ exit(0);
+ }
+
+ const char* result = (*sym)("hello");
+ if ( strcmp(result, "from main") != 0 ) {
+ FAIL("dlsym(RTLD_DEFAULT, \"strdup\") returned wrong strdup: %s", result);
+ exit(0);
+ }
+
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+typedef char* (*strdupProc)(const char* str);
+
+
+char* strdup(const char* str)
+{
+ return "from main";
+}
+
+
+static void trySO(const char* path)
+{
+ void* handle = dlopen(path, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", path);
+ exit(0);
+ }
+
+ strdupProc sym = (strdupProc)dlsym(RTLD_DEFAULT, "strdup");
+ if ( sym == NULL ) {
+ FAIL("dlsym(RTLD_DEFAULT, \"strdup\") failed");
+ exit(0);
+ }
+
+ const char* result = (*sym)("hello");
+ if ( strcmp(result, "from main") != 0 ) {
+ FAIL("dlsym(RTLD_DEFAULT, \"strdup\") returned wrong strdup: %s", result);
+ exit(0);
+ }
+
+}
+
+
+
+int main()
+{
+ trySO("test.bundle");
+ trySO("test.dylib");
+
+ PASS("dlsym-RTLD_DEFAULT bundle and dylib");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c test.bundle test.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : test.c foo1.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle test.c foo1.dylib -o test.bundle
+
+test.dylib : test.c foo2.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c foo2.dylib -o test.dylib
+
+foo1.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo1.dylib
+
+foo2.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo2.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib foo1.dylib foo2.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This process has five foo functions. They are in:
+/// main, test.bundle, test.dylib, foo1.dylib, foo2.dylib
+///
+/// Both test.bundle and test.dylib call dlsym(RTLD_NEXT, "foo");
+/// They should find the ones in foo1.dylib and foo2.dylib respectively.
+/// We test this be looking up those symbols explictly.
+///
+
+
+int foo()
+{
+ return 0;
+}
+
+typedef void* (*TestProc)(void);
+
+static void trySO(const char* pathToLoad, const char* indirectLibrary)
+{
+ void* indirectHandle = dlopen(indirectLibrary, RTLD_LAZY);
+ if ( indirectHandle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", indirectLibrary);
+ exit(0);
+ }
+
+ void* indirectFoo = (TestProc)dlsym(indirectHandle, "foo");
+ if ( indirectFoo == NULL ) {
+ FAIL("dlsym(handle, \"test\") failed");
+ exit(0);
+ }
+
+ void* handle = dlopen(pathToLoad, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", pathToLoad);
+ exit(0);
+ }
+
+ TestProc sym = (TestProc)dlsym(handle, "test");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"test\") failed");
+ exit(0);
+ }
+
+ void* targetFoo = (*sym)();
+
+ //printf("targetFoo = %p, indirectFoo = %p\n", targetFoo, indirectFoo);
+
+ if ( targetFoo != indirectFoo ) {
+ FAIL("dlsym-RTLD_NEXT wrong foo found");
+ exit(0);
+ }
+
+}
+
+
+
+int main()
+{
+ trySO("test.bundle", "foo1.dylib");
+ trySO("test.dylib", "foo2.dylib");
+
+ PASS("dlsym-RTLD_NEXT bundle and dylib");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+void* test()
+{
+ return dlsym(RTLD_NEXT, "foo");
+}
+
+int foo()
+{
+ return 2;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c test.bundle test.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+test.bundle : test.c foo1.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle test.c foo1.dylib -o test.bundle
+
+test.dylib : test.c foo2.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c foo2.dylib -o test.dylib
+
+foo1.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo1.dylib
+
+foo2.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o foo2.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle test.dylib foo1.dylib foo2.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This process has five foo functions. They are in:
+/// main, test.bundle, test.dylib, foo1.dylib, foo2.dylib
+///
+/// Both test.bundle and test.dylib call dlsym(RTLD_SELF, "foo");
+/// They should find the ones in their own linkage unit and
+/// call FAIL() otherwise.
+/// We also check that this works in the main executable.
+///
+
+#ifdef RTLD_SELF
+
+int foo()
+{
+ return 0;
+}
+
+typedef void (*TestProc)(void);
+
+static void trySO(const char* pathToLoad)
+{
+ void* handle = dlopen(pathToLoad, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlopen(\"%s\") failed", pathToLoad);
+ exit(0);
+ }
+
+ TestProc sym = (TestProc)dlsym(handle, "test");
+ if ( sym == NULL ) {
+ FAIL("dlsym(handle, \"test\") failed");
+ exit(0);
+ }
+
+ (*sym)();
+}
+
+#endif
+
+
+int main()
+{
+#ifdef RTLD_SELF
+ trySO("test.bundle");
+ trySO("test.dylib");
+
+ if ( dlsym(RTLD_SELF, "foo") != &foo ) {
+ FAIL("dlsym(RTLD_SELF, \"foo\") returned wrong value");
+ }
+
+ PASS("dlsym-RTLD_SELF bundle and dylib");
+#else
+ XFAIL("dlsym-RTLD_SELF not implemented");
+#endif
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+ return 2;
+}
+
+void test()
+{
+#ifdef RTLD_SELF
+ if ( dlsym(RTLD_SELF, "foo") != &foo )
+ FAIL("dlsym(RTLD_SELF, \"foo\") returned wrong value");
+#endif
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h>
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+int foo()
+{
+ return 42;
+}
+
+
+int main()
+{
+ void* handle = (void*)0x12345; // bogus value
+
+ // expect dlsym() to return NULL
+ void* sym = dlsym(handle, "foo");
+ if ( sym != NULL ) {
+ FAIL("dlsym(handle, \"foo\") should not have succeeded");
+ exit(1);
+ }
+ // expect dlerro() to mention "handle"
+ if ( strstr(dlerror(), "handle") == NULL ) {
+ FAIL("dlerror() after dlsym(handle, \"foo\") does not mention \"handle\"");
+ exit(1);
+ }
+
+ PASS("dlsym-error");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main foo.dylib
+ ./main foo.bundle
+
+all: main
+
+main : main.c foo.bundle foo.dylib foo3.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+
+foo.bundle : foo.c foo1.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -bundle foo.c foo1.dylib -o foo.bundle
+
+foo.dylib : foo.c foo1.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib foo.c foo1.dylib -o foo.dylib
+
+foo1.dylib : foo1.c foo2.dylib
+ ${CC} ${CCFLAGS} -dynamiclib foo1.c -o foo1.dylib foo2.dylib
+
+foo2.dylib : foo2.c
+ ${CC} ${CCFLAGS} -dynamiclib foo2.c -o foo2.dylib
+
+foo3.dylib : foo3.c
+ ${CC} ${CCFLAGS} -dynamiclib foo3.c -o foo3.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo.bundle foo.dylib foo1.dylib foo2.dylib foo3.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo1()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo2()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int foo3()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+///
+/// This tests that dlsym() will search indirect libraries
+/// rdar://problem/4047391
+///
+
+
+
+int main(int argc, const char* argv[])
+{
+ const char* path = argv[1];
+ const char* otherPath = "foo3.dylib";
+
+ void* handle = dlopen(path, RTLD_LAZY);
+ if ( handle == NULL ) {
+ FAIL("dlsym-indirect dlopen(\"%s\") failed", path);
+ exit(0);
+ }
+
+ void* handle3 = dlopen(otherPath, RTLD_LAZY);
+ if ( handle3 == NULL ) {
+ FAIL("dlsym-indirect dlopen(\"%s\") failed", otherPath);
+ exit(0);
+ }
+
+ void* foo = dlsym(handle, "foo");
+ if ( foo == NULL ) {
+ FAIL("dlsym-indirect dlsym(handle, \"foo\") failed");
+ exit(0);
+ }
+
+ void* foo1 = dlsym(handle, "foo1");
+ if ( foo1 == NULL ) {
+ FAIL("dlsym-indirect dlsym(handle, \"foo1\") failed");
+ //exit(0);
+ }
+
+ void* foo2 = dlsym(handle, "foo2");
+ if ( foo2 == NULL ) {
+ FAIL("dlsym-indirect dlsym(handle, \"foo2\") failed");
+ //exit(0);
+ }
+
+ void* foo3 = dlsym(handle, "foo3");
+ if ( foo3 != NULL ) {
+ FAIL("dlsym-indirect dlsym(handle, \"foo3\") should have failed");
+ //exit(0);
+ }
+
+ PASS("dlsym-indirect %s", path);
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ${TESTROOT}/bin/exit-zero-pass.pl "_dyld_launched_prebound() was implemented" "_dyld_launched_prebound() was not implemented" ./main
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+ _dyld_launched_prebound();
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ${TESTROOT}/bin/exit-zero-pass.pl "dyld did slide" "dyld did not slide" ./main
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} main
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdlib.h> // EXIT_SUCCESS
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+//
+// This builds an executable that is just big enough to force dyld to slide a bit
+//
+
+#define ARRAY_SIZE 301800000
+
+int bigarray1[ARRAY_SIZE];
+int bigarray2[ARRAY_SIZE];
+
+int
+main()
+{
+ // call a dyld function that will internally throw an exception to test dyld slide properly
+ NSAddImage("/foo/bar", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+
+ return EXIT_SUCCESS;
+}
+
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export HOME="`pwd`/hide" && ./main user
+ export HOME="`pwd`/hide" && ./main-suid root
+
+all: main main-suid
+
+main: main.c hide/lib/libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+main-suid: main
+ cp main main-suid
+ sudo chown root main-suid
+ sudo chmod 4755 main-suid
+
+hide/lib/libfoo.dylib : foo.c
+ mkdir -p hide/lib
+ ${CC} ${CCFLAGS} foo.c -dynamiclib -o hide/lib/libfoo.dylib
+
+clean:
+ ${RM} ${RMFLAGS} *~ main main-suid hide
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> // strcmp(), strncmp()
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+//
+// binaries set to run as some other user id never use $HOME part of fallback-path
+//
+
+int main(int argc, const char *argv[])
+{
+ const struct mach_header* mh = NSAddImage("/foo/bar/libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+
+ if ( strcmp(argv[1], "root") == 0 ) {
+ if ( mh == NULL )
+ PASS("fallback-with-suid root");
+ else
+ FAIL("fallback-with-suid root");
+ }
+ else {
+ if ( mh != NULL )
+ PASS("fallback-with-suid user");
+ else
+ FAIL("fallback-with-suid user");
+ }
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c libbar.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib
+
+
+libbar.dylib : bar.c getbar.c
+ ${CC} ${CCFLAGS} -dynamiclib getbar.c bar.c -o libbar.dylib -flat_namespace
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libbar.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int bar = 2;
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar;
+
+int* getbar()
+{
+ return &bar;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// getbar() is implemented in libbar.dylib which has its own bar
+// libbar.dylib is built flat-namespace so it should use the bar from main
+// libbar.dylib is built multi_module so that the static linker won't complain
+// about two bar's.
+
+extern int* getbar();
+int bar = 1;
+
+int main()
+{
+ if ( getbar() != &bar )
+ FAIL("flat-data found wrong bar");
+ else
+ PASS("flat-data");
+
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ DYLD_INSERT_LIBRARIES="/usr/lib/libMallocDebug.A.dylib" DYLD_FORCE_FLAT_NAMESPACE="" ./main
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -framework CoreFoundation -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <CoreFoundation/CoreFoundation.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main()
+{
+ CFStringRef string = CFStringCreateWithFormat(NULL, NULL, CFSTR(""));
+ PASS("flat-lookup-everywhere");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+libfoo.dylib : foo.c libbar.dylib
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib libbar.dylib -flat_namespace -prebind -seg1addr 20000
+
+
+libbar.dylib : bar.c
+ ${CC} ${CCFLAGS} -dynamiclib bar.c -o libbar.dylib -prebind -seg1addr 30000
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libbar.dylib libfoo.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar()
+{
+ return 1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar();
+
+int foo()
+{
+ return bar();
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// foo() internally calls bar()
+// libfoo.dylib is build flat and prebound to libbar.dylib
+// but the bar in this main executable should override the prebound bar
+
+extern int foo();
+
+int main()
+{
+ if ( foo() != 0 )
+ FAIL("flat-prebound found wrong bar");
+ else
+ PASS("flat-prebound");
+
+ return EXIT_SUCCESS;
+}
+
+int bar()
+{
+ return 0;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all : main
+
+main: main.c
+ ${CC} main.c -o main -I${TESTROOT}/include
+
+clean:
+ ${RM} ${RMFLAGS} main
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+///
+/// rdar://problem/3736945
+///
+/// Test that a std framework can be dynamically loaded via the fallback paths
+///
+///
+
+
+
+int
+main(int argc, const char* argv[])
+{
+ const struct mach_header *image;
+
+ image = NSAddImage("Carbon.framework/Carbon",
+ NSADDIMAGE_OPTION_RETURN_ON_ERROR | NSADDIMAGE_OPTION_WITH_SEARCHING);
+ if ( image != NULL )
+ PASS("Carbon loaded");
+ else
+ FAIL("Could not load Carbon");
+
+ return 0;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+#
+# This test the ability of dyld to continue searching if a file was found but not usable.
+# Uses DYLD_LIBRARY_PATH to search through many bogus files
+#
+#
+
+
+run: all
+ export DYLD_LIBRARY_PATH=locations/datafile:locations/exec:locations/dir && ${TESTROOT}/bin/exit-non-zero-pass.pl "ignore-bad-files intended failure" "ignore-bad-files intended failure" ./main
+ export DYLD_LIBRARY_PATH=locations/datafile:locations/exec:locations/dir:locations/real && ${TESTROOT}/bin/exit-zero-pass.pl "ignore-bad-files intended success" "ignore-bad-files intended success" ./main
+
+all: main locations/real/libfoo.dylib locations/exec/libfoo.dylib locations/datafile/libfoo.dylib locations/dir/libfoo.dylib
+
+main: main.c locations/real/libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c locations/real/libfoo.dylib
+
+
+# real dylib to use
+locations/real/libfoo.dylib : foo.c
+ mkdir -p locations/real
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o locations/real/libfoo.dylib foo.c -install_name libfoo.dylib
+
+# not a dylib - but a mach-o main executable
+locations/exec/libfoo.dylib : main.c
+ mkdir -p locations/exec
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o locations/exec/libfoo.dylib main.c foo.c
+
+# some random data file
+locations/datafile/libfoo.dylib : main.c
+ mkdir -p locations/datafile
+ cat main.c > locations/datafile/libfoo.dylib
+
+# not a file - but a directory
+locations/dir/libfoo.dylib :
+ mkdir -p locations/dir/libfoo.dylib
+
+# file with wrong architecture
+#locations/wrongarch/libfoo.dylib :
+# mkdir -p locations/wrongarch
+# ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o locations/wrongarch/libfoo.dylib foo.c -install_name libfoo.dylib -arch ppc64
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main locations
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+void foo() {}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern void foo();
+
+int
+main(int argc, const char* argv[])
+{
+ foo();
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run : check1 check2 check3 check4 check5 check6 check7 check8
+
+all : main1 main2 main3 main4 main5 main6 main7 main8
+
+main : main.c libfoo.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main libfoo.dylib
+
+libfoo.dylib : foo.c
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/libfoo.dylib
+
+libfoo_debug.dylib : foo.c
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -DDEBUG -o $$PWD/libfoo_debug.dylib -install_name $$PWD/libfoo.dylib
+
+hide/libfoo.dylib : foo.c
+ mkdir -p $$PWD/hide
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/hide/libfoo.dylib -install_name $$PWD/libfoo.dylib
+
+hide/libfoo_debug.dylib : foo.c
+ mkdir -p $$PWD/hide
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/hide/libfoo_debug.dylib -install_name $$PWD/libfoo.dylib
+
+# bar_debug has bar_debug as install name
+libbar.dylib : foo.c
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/libbar.dylib
+
+libbar_debug.dylib : foo.c
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -DDEBUG -o $$PWD/libbar_debug.dylib
+
+hide/libbar.dylib : foo.c
+ mkdir -p $$PWD/hide
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/hide/libbar.dylib -install_name $$PWD/libbar.dylib
+
+hide/libbar_debug.dylib : foo.c
+ mkdir -p $$PWD/hide
+ ${CC} -I${TESTROOT}/include foo.c -dynamiclib -o $$PWD/hide/libbar_debug.dylib -install_name $$PWD/libbar_debug.dylib
+
+clean:
+ rm -rf libfoo.dylib libfoo_debug.dylib hide libbar.dylib libbar_debug.dylib main1 main2 main3 main4 main5 main6 main7 main8
+
+
+#
+# check1: main links with libfoo.dylib sets DYLD_IMAGE_SUFFIX=_debug and dynamically loads libfoo.dylib
+# (fails on 10.3)
+#
+main1 : main.c libfoo.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main1 libfoo.dylib
+
+check1: main1
+ DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main1 libfoo.dylib
+ DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main1 $$PWD/libfoo.dylib
+
+
+#
+# check2: main links with libfoo_debug.dylib and dynamically loads libfoo.dylib
+#
+main2 : main.c libfoo_debug.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main2 libfoo_debug.dylib
+
+check2: main2
+ echo "pwd-1 is ${PWD}"
+ echo "pwd-2 is $$PWD"
+ pwd
+ ./main2 $$PWD/libfoo.dylib
+
+
+#
+# check3: main links with libfoo.dylib sets DYLD_LIBRARY_PATH=hide and dynamically loads libfoo.dylib
+#
+main3 : main.c libfoo.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main3 libfoo.dylib
+
+check3: main3
+ DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && ./main3 $$PWD/libfoo.dylib
+
+
+#
+# check4: main links with libfoo.dylib sets DYLD_LIBRARY_PATH=hide, DYLD_IMAGE_SUFFIX=_debug and dynamically loads libfoo.dylib
+# (fails on 10.3)
+#
+main4 : main.c libfoo.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main4 libfoo.dylib
+
+check4: main4
+ DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main4 $$PWD/libfoo.dylib
+
+
+#
+# check5: main links with libbar.dylib sets DYLD_IMAGE_SUFFIX=_debug and dynamically loads libbar.dylib
+# (fails on 10.3)
+#
+main5 : main.c libbar.dylib libbar_debug.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main5 libbar.dylib
+
+check5: main5
+ DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main5 $$PWD/libbar.dylib
+
+
+#
+# check6: main links with libbar_debug.dylib and dynamically loads libbar.dylib
+# (fails on 10.3)
+#
+main6 : main.c libbar_debug.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main6 libbar_debug.dylib
+
+check6: main6
+ DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main6 $$PWD/libbar.dylib
+
+
+#
+# check7: main links with libbar.dylib sets DYLD_LIBRARY_PATH=hide and dynamically loads libbar.dylib
+#
+main7 : main.c libbar.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main7 libbar.dylib
+
+check7: main7
+ DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && ./main7 $$PWD/libbar.dylib
+
+
+#
+# check8: main links with libbar.dylib sets DYLD_LIBRARY_PATH=hide, DYLD_IMAGE_SUFFIX=_debug and dynamically loads libbar.dylib
+# (fails on 10.3)
+#
+main8 : main.c libbar.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main8 libbar.dylib
+
+check8: main8
+ DYLD_LIBRARY_PATH=$$PWD/hide && export DYLD_LIBRARY_PATH && DYLD_IMAGE_SUFFIX=_debug && export DYLD_IMAGE_SUFFIX && ./main8 $$PWD/libbar.dylib
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+
+void foo()
+{
+ printf("foo");
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+int main(int argc, const char* argv[])
+{
+ if ( argc < 2 ) {
+ FAIL("too few arguments to main()");
+ return EXIT_SUCCESS;
+ }
+
+ uint32_t imageCount = _dyld_image_count();
+ const struct mach_header* mh = NSAddImage(argv[1], 0);
+ if ( imageCount != _dyld_image_count() ) {
+ FAIL("image count changed");
+ return EXIT_SUCCESS;
+ }
+
+ PASS("images loaded properly");
+ return EXIT_SUCCESS;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+
+main: main.c libtest.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libtest.dylib
+
+libtest.dylib: foo1.c foo2.c base.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o libtest.dylib foo1.c foo2.c base.c -init _myDashInit
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libtest.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int state = 1;
+bool badOrder = false;
+
+void setState(int nextState)
+{
+ if ( nextState == state )
+ ++state;
+ else
+ badOrder = true;
+
+}
+
+
+void baseCheck()
+{
+ if ( badOrder ) {
+ switch ( state ) {
+ case 1:
+ FAIL("init-order -init not run first");
+ break;
+ case 2:
+ FAIL("init-order myInit1 not run second");
+ break;
+ case 3:
+ FAIL("init-order myInit2 not run third");
+ break;
+ case 4:
+ FAIL("init-order myInit3 not run fourth");
+ break;
+ }
+ }
+ else
+ PASS("init-order");
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void setState(int);
+extern void baseCheck();
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+
+
+
+// should run second because first initiallzer in first .o file
+static __attribute__((constructor)) void myInit1()
+{
+ //fprintf(stderr, "myInit1()\n");
+ setState(2);
+}
+
+
+// should run thrid because second initiallzer in first .o file
+static __attribute__((constructor)) void myInit2()
+{
+ //fprintf(stderr, "myInit2()\n");
+ setState(3);
+}
+
+
+// should run first becuase -init runs first
+void myDashInit()
+{
+ //fprintf(stderr, "myDashInit()\n");
+ setState(1);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+
+// should run fourth because first initiallzer in second .o file
+static __attribute__((constructor)) void myInit3()
+{
+ //fprintf(stderr, "myInit3()\n");
+ setState(4);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+int __attribute__((weak)) coal1 = 3;
+int __attribute__((weak)) coal2 = 2;
+
+static __attribute__((constructor)) void myinit()
+{
+ //fprintf(stderr, "myinit() in foo1.c\n");
+ baseVerifyCoal1("in foo3", &coal1);
+ baseVerifyCoal2("in foo3", &coal2);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+ baseCheck();
+ return EXIT_SUCCESS;
+}
+
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main arg1 arg2
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int my_argc = 0;
+static char **my_argv = NULL;
+static char **my_envp = NULL;
+static char **my_appl = NULL;
+
+void
+__attribute__((constructor))
+my_init(int argc, char **argv, char **envp, char **appl)
+{
+ my_argc = argc;
+ my_argv = argv;
+ my_envp = envp;
+ my_appl = appl;
+}
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+ if(argc == my_argc
+ && argv == my_argv
+ && envp == my_envp
+ && appl == my_appl)
+ {
+ PASS("initializer/constructor was called with arguments");
+ }
+ else
+ {
+ FAIL("initializer/constructor was not called with arguments");
+ }
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_INSERT_LIBRARIES="libfoo.dylib" && ./main
+
+all:
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o libfoo.dylib foo.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 Apple Computer, Inc. All rights reserved.
+ *
+ * @APPLE_LICENSE_HEADER_START@
+ *
+ * This file contains Original Code and/or Modifications of Original Code
+ * as defined in and that are subject to the Apple Public Source License
+ * Version 2.0 (the 'License'). You may not use this file except in
+ * compliance with the License. Please obtain a copy of the License at
+ * http://www.opensource.apple.com/apsl/ and read it before using this
+ * file.
+ *
+ * The Original Code and all software distributed under the License are
+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
+ * Please see the License for the specific language governing rights and
+ * limitations under the License.
+ *
+ * @APPLE_LICENSE_HEADER_END@
+ */
+#include <stdlib.h>
+
+#include "test.h"
+
+static
+void
+__attribute__((constructor))
+my_init()
+{
+ PASS("initializer/constructor was called");
+ exit(EXIT_SUCCESS);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+ FAIL("initializer/constructor was not called");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_INSERT_LIBRARIES="/usr/lib/libldap.dylib:/usr/lib/libpcap.dylib" && ./main
+
+all: main
+
+main: main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+ sudo chown root main
+ sudo chmod 4755 main
+
+clean:
+ ${RM} ${RMFLAGS} *~ main
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <string.h> // strcmp(), strncmp()
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+//
+// binaries set to run as some other user id never use DYLD_INSERT_LIBRARIES
+// That environment variable is cleared by dyld (its right-hand-side is set to empty)
+//
+
+int main(int argc, const char *argv[])
+{
+ const char* rhs = getenv("DYLD_INSERT_LIBRARIES");
+ if ( rhs == NULL )
+ FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not set");
+ else if ( rhs[0] != '\0' )
+ FAIL("insert-libraries-with-suid DYLD_INSERT_LIBRARIES not cleared");
+ else
+ PASS("insert-libraries-with-suid");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+main : main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+
+libfoo.dylib : foo.c
+ ${CC} ${CCFLAGS} -dynamiclib foo.c -o libfoo.dylib
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h> // fprintf(), NULL
+
+bool floattest(double p1, float p2, double p3, float p4, double p5, float p6,
+ double p7, float p8, double p9, float p10, double p11, float p12,
+ double p13, float p14)
+{
+ if ( p1 != 1.0 )
+ return false;
+ if ( p2 != 2.0 )
+ return false;
+ if ( p3 != 3.0 )
+ return false;
+ if ( p4 != 4.0 )
+ return false;
+ if ( p5 != 5.0 )
+ return false;
+ if ( p6 != 6.0 )
+ return false;
+ if ( p7 != 7.0 )
+ return false;
+ if ( p8 != 8.0 )
+ return false;
+ if ( p9 != 9.0 )
+ return false;
+ if ( p10 != 10.0 )
+ return false;
+ if ( p11 != 11.0 )
+ return false;
+ if ( p12 != 12.0 )
+ return false;
+ if ( p13 != 13.0 )
+ return false;
+ if ( p14 != 14.0 )
+ return false;
+ return true;
+}
+
+bool inttest(long long p1, long long p2, long long p3, long long p4, long long p5)
+{
+ if ( p1 != 0x100000002)
+ return false;
+ if ( p2 != 0x300000004)
+ return false;
+ if ( p3 != 0x500000006)
+ return false;
+ if ( p4 != 0x700000008)
+ return false;
+ if ( p5 != 0x90000000A)
+ return false;
+ return true;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+#include <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <dlfcn.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern bool floattest(double p1, float p2, double p3, float p4, double p5, float p6,
+ double p7, float p8, double p9, float p10, double p11, float p12,
+ double p13, float p14);
+
+extern bool inttest(long long p1, long long p2, long long p3, long long p4, long long p5);
+
+
+
+int main()
+{
+ if ( ! floattest(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0) ) {
+ FAIL("lazy-pointer-binding float parameters");
+ return EXIT_SUCCESS;
+ }
+
+ if ( ! inttest(0x100000002, 0x300000004, 0x500000006, 0x700000008, 0x90000000A) ) {
+ FAIL("lazy-pointer-binding int parameters");
+ return EXIT_SUCCESS;
+ }
+
+ PASS("lazy-pointer-binding");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+###
+### rdar://problem/3684168
+###
+### The process has two different libfoo.dylib.
+### When DYLD_LIBRARY_PATH is used, both resolve to the same library.
+### It gets worse. One of the libraries re-exports from the other.
+### So, without loop detection in dyld, it will infinitely recurse.
+###
+
+PWD = `pwd`
+
+
+run : all
+ # verify it runs as-is
+ ./main
+ # verify dyld doesn't hang on the circularity
+ DYLD_LIBRARY_PATH=$(PWD) && export DYLD_LIBRARY_PATH && ${TESTROOT}/bin/exit-zero-pass.pl "lib-name-overload" "lib-name-overload" ./main
+
+all : main
+
+other/libfoo.dylib : foo2.c
+ mkdir -p other
+ gcc foo2.c -dynamiclib -o $(PWD)/other/libfoo.dylib
+
+libfoo.dylib : foo.c other/libfoo.dylib
+ gcc foo.c -dynamiclib $(PWD)/other/libfoo.dylib -sub_library libfoo -o $(PWD)/libfoo.dylib
+
+main : main.c libfoo.dylib
+ gcc main.c -I${TESTROOT}/include -o main libfoo.dylib
+
+
+clean:
+ rm -rf main other libfoo.dylib
\ No newline at end of file
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int foo = 0;
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+int foo2 = 0;
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+///
+/// rdar://problem/3684168
+///
+
+
+
+extern int foo2;
+
+int main()
+{
+ return foo2;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+###
+### This test case is to verify that two different dylibs with the same name
+### and each loaded via the same @loader_path does not confuse dyld
+### into just loading one of them.
+###
+
+## Note, until ld understands @loader_path we have to do a funky make
+
+
+run: all
+ ./main
+
+all: main
+
+foo/libfoo.dylib : foo.c foo/libbase.dylib
+ mkdir -p foo
+ ${CC} foo.c foo/libbase.dylib -dynamiclib -o "`pwd`/foo/libfoo.dylib"
+
+foo/libbase.dylib : base.c
+ mkdir -p foo
+ ${CC} base.c -DFOO -dynamiclib -o foo/libbase.dylib
+
+
+bar/libbar.dylib : bar.c bar/libbase.dylib
+ mkdir -p bar
+ ${CC} bar.c bar/libbase.dylib -dynamiclib -o "`pwd`/bar/libbar.dylib"
+
+bar/libbase.dylib : base.c
+ mkdir -p bar
+ ${CC} base.c -Dbar -dynamiclib -o bar/libbase.dylib
+
+
+main : main.c foo/libfoo.dylib bar/libbar.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main foo/libfoo.dylib bar/libbar.dylib
+ # this breaks partial makes, but ld can't see @loader_path or it freaks
+ install_name_tool -change foo/libbase.dylib '@loader_path/libbase.dylib' foo/libfoo.dylib
+ install_name_tool -change bar/libbase.dylib '@loader_path/libbase.dylib' bar/libbar.dylib
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main foo bar
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+extern int base;
+
+bool bar()
+{
+ return (base == 2);
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 FOO
+int base = 1;
+#else
+int base = 2;
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdbool.h>
+
+
+extern int base;
+
+bool foo()
+{
+ return (base == 1);
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+extern bool foo();
+extern bool bar();
+
+int main()
+{
+ if ( foo() && bar() )
+ PASS("loader_path");
+ else
+ FAIL("loader_path-dup both libraries not loaded");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ ./main
+
+all: main
+
+hide/hole/libfoo.dylib : foo.c
+ mkdir -p hide/hole
+ ${CC} foo.c -dynamiclib -o hide/hole/libfoo.dylib -install_name libfoo.dylib
+
+hide/libbar.dylib : bar.c hide/hole/libfoo.dylib
+ ${CC} bar.c -dynamiclib -o hide/libbar.dylib -install_name libbar.dylib hide/hole/libfoo.dylib
+ install_name_tool -change libfoo.dylib '@loader_path/hole/libfoo.dylib' hide/libbar.dylib
+
+hide/libfoo3.dylib : foo.c
+ ${CC} foo.c -dynamiclib -o hide/libfoo3.dylib -install_name libfoo3.dylib
+
+libfoo2.dylib : foo.c
+ ${CC} foo.c -dynamiclib -o libfoo2.dylib
+
+
+main : main.c libfoo2.dylib hide/libbar.dylib hide/libfoo3.dylib
+ ${CC} -I${TESTROOT}/include main.c -o main hide/libbar.dylib libfoo2.dylib
+ install_name_tool -change libfoo2.dylib '@loader_path/libfoo2.dylib' main
+ install_name_tool -change libbar.dylib '@loader_path/hide/libbar.dylib' main
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib hide libfoo2.dylib
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+void bar() {}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+void foo()
+{
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+#include <mach-o/dyld.h>
+
+#include "test.h"
+
+
+int main()
+{
+ NSAddImage("@loader_path/hide/libfoo3.dylib", 0);
+
+ PASS("loader_path");
+ return EXIT_SUCCESS;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_FALLBACK_FRAMEWORK_PATH="dir" && ${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+
+all: main dir/Foo.framework/Versions/Current/Foo
+
+Foo.framework/Versions/Current/Foo:
+ mkdir -p Foo.framework/Versions/A
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -o Foo.framework/Versions/A/Foo Foo.c
+ cd Foo.framework/Versions/ && ln -s A Current
+ cd Foo.framework/ && ln -s Versions/Current/Foo Foo
+
+dir/Foo.framework/Versions/Current/Foo:
+ $(MAKE) Foo.framework/Versions/Current/Foo
+ rm -f Foo.framework/Foo
+ mkdir dir
+ mv Foo.framework dir
+
+main:
+ $(MAKE) Foo.framework/Versions/Current/Foo
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -F. -framework Foo -o main main.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main dir/ Foo.framework/
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+int
+main(int argc, char **argv, char **envp, char**appl)
+{
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ cd absent/ && ../${TESTROOT}/bin/exit-non-zero-pass.pl "pass message" "fail message" ./main
+ cd present/ && ./main
+
+all: foo.c main.c
+ ${CC} -dynamiclib -prebind -seg1addr 400000 -o libfoo.dylib foo.c
+ mkdir -p absent/
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -lfoo -DLIB_ABSENT -o absent/main main.c
+ mkdir -p present/
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -lfoo -DLIB_PRESENT -o present/main main.c
+ mv libfoo.dylib present/
+
+clean:
+ ${RM} ${RMFLAGS} *~ libfoo.dylib absent/main present/{main,libfoo.dylib}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+int
+main(int argc, char **argv)
+{
+#if defined(LIB_PRESENT)
+ PASS("pass message");
+#endif
+#if defined(LIB_ABSENT)
+ FAIL("fail message");
+#endif
+
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+###
+### rdar://problem/3884004 Libraries can be half-baked if an error occurs during their first use
+###
+### We indirectly load libfoo which depends on libbar. The libbar that is loaded does not contain
+### what libfoo needs, so libfoo fails to bind. The bug was that libfoo was left marked as bound,
+### so the next use of libfoo seemed to succeed, when it should have failed.
+###
+
+
+run: all
+ export DYLD_IMAGE_SUFFIX="_missing" && ${TESTROOT}/bin/exit-zero-pass.pl "partial-library-load" "partial-library-load" ./main
+
+all: main test.bundle
+
+main : main.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c
+
+test.bundle : bundle.c libfoo.dylib
+ ${CC} ${CCFLAGS} -bundle -o test.bundle bundle.c libfoo.dylib
+
+libfoo.dylib : foo.c libbar_missing.dylib libbar.dylib
+ ${CC} ${CCFLAGS} foo.c -dynamiclib -o libfoo.dylib libbar.dylib
+
+libbar_missing.dylib : bar.c
+ ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar_missing.dylib -install_name libbar.dylib
+
+libbar.dylib : bar.c
+ ${CC} ${CCFLAGS} bar.c -dynamiclib -o libbar.dylib -DHAS_BAR2=1
+
+clean:
+ ${RM} ${RMFLAGS} *~ main test.bundle libfoo.dylib libbar.dylib libbar_missing.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+int bar1 = 1;
+#if HAS_BAR2
+int bar2 = 2;
+#endif
+int bar3 = 3;
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int foo();
+
+void bun()
+{
+ foo();
+
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+extern int bar1;
+extern int bar2;
+extern int bar3;
+
+
+
+int foo()
+{
+ return bar1 + bar2 + bar3;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <string.h>
+#include <mach-o/dyld.h>
+
+#include "test.h" // PASS(), FAIL()
+
+
+int main()
+{
+ // load bundle which indirectly loads libfoo and libbar
+ NSObjectFileImage ofi;
+ if ( NSCreateObjectFileImageFromFile("test.bundle", &ofi) != NSObjectFileImageSuccess ) {
+ FAIL("NSCreateObjectFileImageFromFile failed");
+ return 1;
+ }
+
+ // link bundle, this will fail because bar2 is missing from libbar
+ NSModule mod = NSLinkModule(ofi, "test.bundle", NSLINKMODULE_OPTION_RETURN_ON_ERROR);
+ if ( mod != NULL ) {
+ FAIL("NSLinkModule succeeded but should have failed");
+ return 1;
+ }
+
+ // load libfoo, this should fail because it can't be loaded
+ const struct mach_header* mh = NSAddImage("libfoo.dylib", NSADDIMAGE_OPTION_RETURN_ON_ERROR);
+ if ( mh != NULL ) {
+ return 1;
+ }
+
+#if 0
+ // find foo
+ NSSymbol sym = NSLookupSymbolInImage(mh, "_foo", NSLOOKUPSYMBOLINIMAGE_OPTION_BIND);
+ if ( sym == NULL ) {
+ FAIL("NSLookupSymbolInImage failed");
+ return 1;
+ }
+
+ // if foo() was only partially bound, this will crash
+ int (*fooPtr)() = NSAddressOfSymbol(sym);
+ (*fooPtr)();
+#endif
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+###
+### This test case is to verify that dyld cannot be tricked into loading
+### the "same" library twice.
+###
+### The tricky scenario is:
+### 1) a library dyld is to load is specified with a symlink path
+### 2) the library the that is the target of the symlink is already loaded
+### via a different path. In this case becuase of DYLD_LIBRARY_PATH.
+###
+###
+###
+###
+
+
+
+run: all
+ ./main
+ export DYLD_LIBRARY_PATH="`pwd`/fake" && ./main
+
+
+all: main real/liblink.dylib real/libtest.dylib fake/libtest.dylib
+
+
+main: main.c stub/libtest.dylib stub/liblink.dylib real/libbase.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c stub/libtest.dylib stub/liblink.dylib real/libbase.dylib
+
+stub/libtest.dylib: test.c
+ mkdir -p stub
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c -DDO_NOTHING -o stub/libtest.dylib -install_name "`pwd`/real/libtest.dylib"
+
+stub/liblink.dylib: link.c
+ mkdir -p stub
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib link.c -o stub/liblink.dylib -install_name "`pwd`/real/liblink.dylib"
+
+
+real/libbase.dylib: base.c
+ mkdir -p real
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib base.c -o "`pwd`/real/libbase.dylib"
+
+real/libtest.dylib: test.c real/libbase.dylib
+ mkdir -p real
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c real/libbase.dylib -o "`pwd`/real/libtest.dylib"
+
+real/liblink.dylib: link.c
+ mkdir -p real
+ cd real && ln -s libtest.dylib liblink.dylib
+
+
+fake/libtest.dylib: test.c real/libbase.dylib
+ mkdir -p fake
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib test.c real/libbase.dylib -o "`pwd`/fake/libtest.dylib" -install_name "`pwd`/real/libtest.dylib"
+
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main real stub fake
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static int initCount = 0;
+
+void setState(int x)
+{
+ ++initCount;
+}
+
+
+void baseCheck()
+{
+ switch ( initCount ) {
+ case 0:
+ FAIL("sym-link-load no initializers run");
+ break;
+ case 1:
+ PASS("sym-link-load");
+ break;
+ case 2:
+ default:
+ FAIL("sym-link-load initializers double run (library double loaded)");
+ break;
+ }
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void setState(int);
+extern void baseCheck();
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+ baseCheck();
+ return EXIT_SUCCESS;
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+
+#ifndef DO_NOTHING
+
+// should run second because first initiallzer in first .o file
+static __attribute__((constructor)) void test_init()
+{
+ //fprintf(stderr, "test_init()\n");
+ setState(1);
+}
+
+#endif
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+###
+### This test case is to verify __TEXT reliocations work
+###
+###
+
+
+
+run: all
+ ./main
+
+all: main
+
+main: main.c libbar.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libbar.dylib
+
+libbar.dylib: foo.s bar.c
+ ${CC} ${CCFLAGS} -dynamiclib -o libbar.dylib bar.c foo.s -read_only_relocs suppress -Os
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libbar.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+
+extern int* foo;
+
+bool testBar()
+{
+ return (*foo == 10);
+}
+
+int bar = 10;
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+ .text
+ .globl _foo
+_foo:
+ .long _bar
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+#include <stdbool.h>
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern bool testBar();
+
+int main(int argc, const char* argv[])
+{
+ if ( testBar() )
+ PASS("text-reloc");
+ else
+ FAIL("text-reloc");
+ return EXIT_SUCCESS;
+}
+
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+ ./dynamic-test
+
+all: dynamic-test static-test
+
+
+static-test: a1.o a2.o main.o
+ $(CXX) -I${TESTROOT}/include a1.o a2.o main.o -o static-test
+
+dynamic-test: main.o a1.o liba2.dylib
+ $(CXX) -I${TESTROOT}/include main.o a1.o -L. -la2 -o dynamic-test
+
+liba2.dylib: a2.o
+ $(CXX) -I${TESTROOT}/include a2.o -dynamiclib -o liba2.dylib
+
+a1.o: a1.cc a.h
+ $(CXX) -I${TESTROOT}/include -c a1.cc
+
+a2.o: a2.cc a.h
+ $(CXX) -I${TESTROOT}/include -c a2.cc
+
+main.o: main.cc
+ $(CXX) -I${TESTROOT}/include -c main.cc
+
+
+clean:
+ ${RM} ${RMFLAGS} *.o *.dylib static-test dynamic-test
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+template <typename X>
+struct wrapper {
+ static X x;
+};
+
+template <typename X> X wrapper<X>::x;
--- /dev/null
+#include "a.h"
+
+int get_x_1 (void) { return wrapper<int>::x; }
+void set_x_1 (int x_) { wrapper<int>::x = x_; }
--- /dev/null
+#include "a.h"
+
+int get_x_2 (void) { return wrapper<int>::x; }
+void set_x_2 (int x_) { wrapper<int>::x = x_; }
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+extern void set_x_1(int);
+extern void set_x_2(int);
+extern int get_x_1(void);
+extern int get_x_2(void);
+
+int main()
+{
+ set_x_1 (17);
+ set_x_2 (76);
+
+ if (get_x_1() == 76 && get_x_2() == 76)
+ PASS("weak-coalesce=c++");
+ else
+ FAIL("weak-coalesce=c++");
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+ ./main
+
+all: main
+
+
+main: main.c libfoo1.dylib libbase.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo1.dylib libbase.dylib
+
+libfoo1.dylib: foo1.c libfoo2.dylib libbase.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo1.dylib foo1.c libfoo2.dylib libbase.dylib
+
+libfoo2.dylib: foo2.c libfoo3.dylib libbase.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo2.dylib foo2.c libfoo3.dylib libbase.dylib
+
+libfoo3.dylib: foo3.c libbase.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo3.dylib foo3.c libbase.dylib -prebind -seg1addr 20000
+
+libbase.dylib: base.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libbase.dylib base.c -prebind -seg1addr 10000
+
+
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo1.dylib libfoo2.dylib libfoo3.dylib libbase.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdbool.h>
+
+#include "base.h"
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+static bool wasProblem = false;
+
+static const char* coal1Where = NULL;
+static int* coal1Addr = NULL;
+static int checkInCountCoal1 = 0;
+
+void baseVerifyCoal1(const char* where, int* addr)
+{
+ //fprintf(stderr, "baseVerifyCoal1(%s, %p)\n", where, addr);
+ ++checkInCountCoal1;
+ if ( coal1Where == NULL ) {
+ coal1Where = where;
+ coal1Addr = addr;
+ }
+ else {
+ if ( addr != coal1Addr ) {
+ fprintf(stderr, "coal1 resolved to different locations. %p in %s and %p in %s\n",
+ coal1Addr, coal1Where, addr, where);
+ wasProblem = true;
+ }
+ }
+}
+
+
+static const char* coal2Where = NULL;
+static int* coal2Addr = NULL;
+static int checkInCountCoal2 = 0;
+
+void baseVerifyCoal2(const char* where, int* addr)
+{
+ //fprintf(stderr, "baseVerifyCoal2(%s, %p)\n", where, addr);
+ ++checkInCountCoal2;
+ if ( coal2Where == NULL ) {
+ coal2Where = where;
+ coal2Addr = addr;
+ }
+ else {
+ if ( addr != coal2Addr ) {
+ fprintf(stderr, "coal2 resolved to different locations. %p in %s and %p in %s\n",
+ coal2Addr, coal2Where, addr, where);
+ wasProblem = true;
+ }
+ }
+}
+
+
+
+void baseCheck()
+{
+ if ( wasProblem || (checkInCountCoal1 != 4) || (checkInCountCoal2 != 4) )
+ FAIL("weak-coal");
+ else
+ PASS("weak-coal");
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+extern void baseCheck();
+
+extern int coal1;
+extern int coal2;
+
+extern void baseVerifyCoal1(const char* where, int* addr);
+extern void baseVerifyCoal2(const char* where, int* addr);
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+
+
+int __attribute__((weak)) coal1 = 1;
+int __attribute__((weak)) coal2 = 1;
+
+
+static __attribute__((constructor)) void myinit()
+{
+ //fprintf(stderr, "myinit() in foo1.c\n");
+ baseVerifyCoal1("in foo1", &coal1);
+ baseVerifyCoal2("in foo1", &coal2);
+}
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+
+int coal1 = 2;
+int __attribute__((weak)) coal2 = 2;
+
+static __attribute__((constructor)) void myinit()
+{
+ //fprintf(stderr, "myinit() in foo1.c\n");
+ baseVerifyCoal1("in foo2", &coal1);
+ baseVerifyCoal2("in foo2", &coal2);
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include "base.h"
+
+int __attribute__((weak)) coal1 = 3;
+int __attribute__((weak)) coal2 = 2;
+
+static __attribute__((constructor)) void myinit()
+{
+ //fprintf(stderr, "myinit() in foo1.c\n");
+ baseVerifyCoal1("in foo3", &coal1);
+ baseVerifyCoal2("in foo3", &coal2);
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+
+#include "base.h"
+
+int main()
+{
+
+ //fprintf(stderr, "myinit() in foo1.c\n");
+ baseVerifyCoal1("in main", &coal1);
+ baseVerifyCoal2("in main", &coal2);
+
+ baseCheck();
+ return EXIT_SUCCESS;
+}
+
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ cd absent/ && ../${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+ cd present/ && ../${TESTROOT}/bin/exit-zero-pass.pl "pass message" "fail message" ./main
+
+all: foo.c main.c
+ ${CC} -dynamiclib -prebind -seg1addr 400000 -o libfoo.dylib foo.c
+ mkdir -p absent/
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -Wl,-weak-lfoo -o absent/main main.c
+ mkdir -p present/
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -prebind -I${TESTROOT}/include -L. -Wl,-weak-lfoo -o present/main main.c
+ mv libfoo.dylib present/
+
+clean:
+ ${RM} ${RMFLAGS} *~ libfoo.dylib absent present
--- /dev/null
+/*
+ * Copyright (c) 2005 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 "foo.h"
+
+int foo()
+{
+ return 10;
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+extern int foo();
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h>
+
+#include "test.h"
+
+int
+main(int argc, char **argv)
+{
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+
+run: all
+ ./main
+
+all: main
+
+
+main: main.c libfoo.dylib
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -o main main.c libfoo.dylib
+
+libfoo.dylib: foo.c
+ ${CC} ${CCFLAGS} -I${TESTROOT}/include -dynamiclib -single_module -o libfoo.dylib foo.c
+
+clean:
+ ${RM} ${RMFLAGS} *~ main libfoo.dylib
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+
+
+
+int __attribute__((weak)) myfunc()
+{
+ return 0;
+}
+
+int __attribute__((weak)) foo()
+{
+ return myfunc();
+}
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h> // fprintf(), NULL
+#include <stdlib.h> // exit(), EXIT_SUCCESS
+
+#include "test.h" // PASS(), FAIL(), XPASS(), XFAIL()
+
+// foo is defined in libfoo.dylib
+// it calls myfunc()
+extern int foo();
+
+int main()
+{
+ if ( foo() == 10 )
+ PASS("weak-override");
+ else
+ FAIL("weak-override");
+ return EXIT_SUCCESS;
+}
+
+
+// myfunc() also defined in libfoo.dylib but weak there, so this should override
+int myfunc()
+{
+ return 10;
+}
+
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ (export DYLD_IMAGE_SUFFIX=_missing && ./main) || echo "FAIL \"weak-symbol-flat\""
+ ./main 1
+
+all : main libfoo.dylib libfoo_missing.dylib
+
+libfoo.dylib : foo.c
+ ${CC} -dynamiclib -DSYMBOL_PRESENT -o libfoo.dylib foo.c
+
+libfoo_missing.dylib : foo.c
+ ${CC} -dynamiclib -o libfoo_missing.dylib foo.c -install_name libfoo.dylib
+
+main: main.c libfoo.dylib
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -I${TESTROOT}/include -L. -lfoo -o main main.c -flat_namespace
+
+clean:
+ ${RM} ${RMFLAGS} *~ libfoo.dylib libfoo_missing.dylib main
+
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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@
+ */
+
+
+#ifdef SYMBOL_PRESENT
+int foo()
+{
+ return 10;
+}
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <AvailabilityMacros.h>
+
+int foo() WEAK_IMPORT_ATTRIBUTE;
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h> // EXIT_SUCCESS
+
+#include "test.h"
+#include "foo.h"
+
+int main(int argc, const char *argv[])
+{
+ if (argc > 1) {
+ // when arg is passed, libfoo is used and foo should be defined
+ if ( &foo == NULL )
+ FAIL("weak-symbol-flat foo not found");
+ else if ( foo() != 10 )
+ FAIL("weak-symbol-flat foo not found");
+ else
+ PASS("weak-symbol-flat when symbol found");
+ }
+ else {
+ // when no args are passed, libfoo_missing is used and foo should be undefined
+ if ( &foo != NULL )
+ FAIL("weak-symbol-flat foo found");
+ else
+ PASS("weak-symbol-flat when symbol missing");
+ }
+ return EXIT_SUCCESS;
+}
--- /dev/null
+##
+# Copyright (c) 2005 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@
+##
+TESTROOT = ../..
+include ${TESTROOT}/include/common.makefile
+
+run: all
+ export DYLD_IMAGE_SUFFIX=_missing && ${TESTROOT}/bin/exit-zero-pass.pl "weak-symbol" "weak-symbol" ./main
+
+all: foo.c main.c
+ ${CC} foo.c -dynamiclib -o libfoo.dylib -DSYMBOL_PRESENT
+ ${CC} foo.c -dynamiclib -o libfoo_missing.dylib -install_name libfoo.dylib
+ export MACOSX_DEPLOYMENT_TARGET=10.2 && ${CC} -I${TESTROOT}/include -L. -lfoo main.c -o main
+
+clean:
+ ${RM} ${RMFLAGS} *~ libfoo.dylib libfoo_missing.dylib main
--- /dev/null
+/*
+ * Copyright (c) 2005 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 SYMBOL_PRESENT
+int foo()
+{
+ return 10;
+}
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <AvailabilityMacros.h>
+
+int foo() WEAK_IMPORT_ATTRIBUTE;
--- /dev/null
+/*
+ * Copyright (c) 2005 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 <stdio.h>
+#include <stdlib.h> // EXIT_SUCCESS
+
+#include "test.h"
+#include "foo.h"
+
+int main(int argc, const char* argv[])
+{
+ if ( &foo == NULL )
+ {
+ PASS("weak-symbol not available");
+ }
+ return 0;
+}