diff --git a/compat/compat.gyp b/compat/compat.gyp index 54dc8571..86197d49 100644 --- a/compat/compat.gyp +++ b/compat/compat.gyp @@ -16,20 +16,12 @@ 'targets': [ { 'target_name': 'compat', - 'type': 'none', - 'include_dirs': [ - 'mac', - 'non_win', - ], - 'direct_dependent_settings': { - 'include_dirs': [ - 'mac', - 'non_win', - ], - }, + 'type': 'static_library', 'sources': [ 'mac/AvailabilityMacros.h', 'mac/mach/mach.h', + 'mac/mach-o/getsect.cc', + 'mac/mach-o/getsect.h', 'mac/mach-o/loader.h', 'mac/servers/bootstrap.h', 'non_mac/mach/mach.h', @@ -39,6 +31,31 @@ 'non_win/verrsrc.h', 'non_win/winnt.h', ], + 'conditions': [ + ['OS=="mac"', { + 'dependencies': [ + '../third_party/apple_cctools/apple_cctools.gyp:apple_cctools', + ], + 'include_dirs': [ + 'mac', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'mac', + ], + }, + }], + ['OS!="win"', { + 'include_dirs': [ + 'non_win', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + 'non_win', + ], + }, + }], + ], }, ], } diff --git a/compat/mac/mach-o/getsect.cc b/compat/mac/mach-o/getsect.cc new file mode 100644 index 00000000..5401b39b --- /dev/null +++ b/compat/mac/mach-o/getsect.cc @@ -0,0 +1,107 @@ +// Copyright 2014 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +// This is only necessary when building code that might run on systems earlier +// than 10.7. When building for 10.7 or later, getsectiondata() and +// getsegmentdata() are always present in libmacho and made available through +// libSystem. When building for earlier systems, custom definitions of +// these functions are needed. +// +// This file checks the deployment target instead of the SDK. The deployment +// target is correct because it identifies the earliest possible system that +// the code being compiled is expected to run on. + +#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + +#include +#include + +#include "third_party/apple_cctools/cctools/include/mach-o/getsect.h" + +namespace { + +// Returns a dlopen() handle to the same library that provides the +// getsectbyname() function. getsectbyname() is always present in libmacho. +// getsectiondata() and getsegmentdata() are not always present, but when they +// are, they’re in the same library as getsectbyname(). If the library cannot +// be found or a handle to it cannot be returned, returns NULL. +void* SystemLibMachOHandle() { + Dl_info info; + if (!dladdr(reinterpret_cast(getsectbyname), &info)) { + return NULL; + } + return dlopen(info.dli_fname, RTLD_LAZY | RTLD_LOCAL); +} + +// Returns a function pointer to a function in libmacho based on a lookup of +// that function by symbol name. Returns NULL if libmacho cannot be found or +// opened, or if the named symbol cannot be found in libmacho. +void* LookUpSystemLibMachOSymbol(const char* symbol) { + static void* dl_handle = SystemLibMachOHandle(); + if (!dl_handle) { + return NULL; + } + return dlsym(dl_handle, symbol); +} + +#ifndef __LP64__ +typedef mach_header MachHeader; +#else +typedef mach_header_64 MachHeader; +#endif + +typedef uint8_t*(*GetSectionDataType)( + const MachHeader*, const char*, const char*, unsigned long*); +typedef uint8_t*(*GetSegmentDataType)( + const MachHeader*, const char*, unsigned long*); + +} // namespace + +extern "C" { + +// These implementations look up their functions in libmacho at run time. If +// the system libmacho provides these functions as it normally does on Mac OS X +// 10.7 and later, the system’s versions are used directly. Otherwise, the +// versions in third_party/apple_cctools are used, which are actually just +// copies of the system’s functions. + +uint8_t* getsectiondata(const MachHeader* mhp, + const char* segname, + const char* sectname, + unsigned long* size) { + static GetSectionDataType system_getsectiondata = + reinterpret_cast( + LookUpSystemLibMachOSymbol("getsectiondata")); + if (system_getsectiondata) { + return system_getsectiondata(mhp, segname, sectname, size); + } + return crashpad_getsectiondata(mhp, segname, sectname, size); +} + +uint8_t* getsegmentdata( + const MachHeader* mhp, const char* segname, unsigned long* size) { + static GetSegmentDataType system_getsegmentdata = + reinterpret_cast( + LookUpSystemLibMachOSymbol("getsegmentdata")); + if (system_getsegmentdata) { + return system_getsegmentdata(mhp, segname, size); + } + return crashpad_getsegmentdata(mhp, segname, size); +} + +} // extern "C" + +#endif // MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 diff --git a/compat/mac/mach-o/getsect.h b/compat/mac/mach-o/getsect.h new file mode 100644 index 00000000..f982c4b4 --- /dev/null +++ b/compat/mac/mach-o/getsect.h @@ -0,0 +1,69 @@ +// Copyright 2014 The Crashpad Authors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CRASHPAD_COMPAT_MAC_MACH_O_GETSECT_H_ +#define CRASHPAD_COMPAT_MAC_MACH_O_GETSECT_H_ + +#include_next + +#include + +// This file checks the SDK instead of the deployment target. The SDK is correct +// because this file is concerned with providing compile-time declarations, +// which are either present in a specific SDK version or not. + +#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// Don’t use a typedef to account for the mach_header/mach_header_64 difference +// between the 32-bit and 64-bit versions of getsectiondata() and +// getsegmentdata(). This file should be faithfully equivalent to the native +// SDK, and adding typedefs here would pollute the namespace in a way that the +// native SDK does not. + +#if !defined(__LP64__) + +uint8_t* getsectiondata(const struct mach_header* mhp, + const char* segname, + const char* sectname, + unsigned long* size); + +uint8_t* getsegmentdata( + const struct mach_header* mhp, const char* segname, unsigned long* size); + +#else + +uint8_t* getsectiondata(const struct mach_header_64* mhp, + const char* segname, + const char* sectname, + unsigned long* size); + +uint8_t* getsegmentdata( + const struct mach_header_64* mhp, const char* segname, unsigned long* size); + +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 + +#endif // CRASHPAD_COMPAT_MAC_MACH_O_GETSECT_H_ diff --git a/third_party/apple_cctools/README.crashpad b/third_party/apple_cctools/README.crashpad index 22bb638e..a2aadf72 100644 --- a/third_party/apple_cctools/README.crashpad +++ b/third_party/apple_cctools/README.crashpad @@ -19,6 +19,26 @@ to Mac OS X 10.7 did not include the getsectiondata() and getsegmentdata() functions. This library is present here to provide implementations of these functions for systems that do not have them. +Crashpad code is not expected to use this library directly. It should use the +getsectiondata() and getsegmentdata() wrappers in compat, which will use +system-provided implementations if present at runtime, and will otherwise fall +back to the implementations in this library. + Local Modifications: - Only cctools/APPLE_LICENSE, cctools/libmacho/getsecbyname.c, and cctools/include/mach-o/getsect.h are included. + - getsecbyname.c and getsect.h have been trimmed to remove everything other + than the getsectiondata() and getsegmentdata() functions. The #include guards + in getsect.h have been made unique. + - getsectiondata() is renamed to crashpad_getsectiondata(), and + getsegmentdata() is renamed to crashpad_getsegmentdata(). + - These functions are only declared and defined if the deployment target is + older than 10.7. This library is not needed otherwise, because in that case, + the system always provides implementations in runtime libraries. + - Originally, each of these two functions were implemented twice: once for + 32-bit code and once for 64-bit code. Aside from the types and constants + used, the two implementations were completely identical. This has been + simplified to have a shared implementation that relies on local typedefs and + constants being defined properly. This change was only made in + getsecbyname.c. getsect.h was not changed to avoid leaking new definitions + beyond this header. diff --git a/third_party/apple_cctools/apple_cctools.gyp b/third_party/apple_cctools/apple_cctools.gyp new file mode 100644 index 00000000..7e0dfd43 --- /dev/null +++ b/third_party/apple_cctools/apple_cctools.gyp @@ -0,0 +1,34 @@ +# Copyright 2014 The Crashpad Authors. All rights reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +{ + 'targets': [ + { + 'target_name': 'apple_cctools', + 'type': 'static_library', + 'include_dirs': [ + '../..', + ], + 'direct_dependent_settings': { + 'include_dirs': [ + '../..', + ], + }, + 'sources': [ + 'cctools/include/mach-o/getsect.h', + 'cctools/libmacho/getsecbyname.c', + ], + }, + ], +} diff --git a/third_party/apple_cctools/cctools/include/mach-o/getsect.h b/third_party/apple_cctools/cctools/include/mach-o/getsect.h index caa980de..639b8061 100644 --- a/third_party/apple_cctools/cctools/include/mach-o/getsect.h +++ b/third_party/apple_cctools/cctools/include/mach-o/getsect.h @@ -20,8 +20,13 @@ * * @APPLE_LICENSE_HEADER_END@ */ -#ifndef _MACH_O_GETSECT_H_ -#define _MACH_O_GETSECT_H_ +#ifndef CRASHPAD_THIRD_PARTY_APPLE_CCTOOLS_CCTOOLS_INCLUDE_MACH_O_GETSECT_H_ +#define CRASHPAD_THIRD_PARTY_APPLE_CCTOOLS_CCTOOLS_INCLUDE_MACH_O_GETSECT_H_ + +#include + +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 #include #include @@ -30,44 +35,17 @@ extern "C" { #endif /* __cplusplus */ -/* - * Runtime interfaces for Mach-O programs. For both 32-bit and 64-bit programs, - * where the sizes returned will be 32-bit or 64-bit based on the size of - * 'unsigned long'. - */ -extern char *getsectdata( - const char *segname, - const char *sectname, - unsigned long *size); - -extern char *getsectdatafromFramework( - const char *FrameworkName, - const char *segname, - const char *sectname, - unsigned long *size); - -extern unsigned long get_end(void); -extern unsigned long get_etext(void); -extern unsigned long get_edata(void); - #ifndef __LP64__ /* * Runtime interfaces for 32-bit Mach-O programs. */ -extern const struct section *getsectbyname( - const char *segname, - const char *sectname); - -extern uint8_t *getsectiondata( +extern uint8_t *crashpad_getsectiondata( const struct mach_header *mhp, const char *segname, const char *sectname, unsigned long *size); -extern const struct segment_command *getsegbyname( - const char *segname); - -extern uint8_t *getsegmentdata( +extern uint8_t *crashpad_getsegmentdata( const struct mach_header *mhp, const char *segname, unsigned long *size); @@ -76,68 +54,23 @@ extern uint8_t *getsegmentdata( /* * Runtime interfaces for 64-bit Mach-O programs. */ -extern const struct section_64 *getsectbyname( - const char *segname, - const char *sectname); - -extern uint8_t *getsectiondata( +extern uint8_t *crashpad_getsectiondata( const struct mach_header_64 *mhp, const char *segname, const char *sectname, unsigned long *size); -extern const struct segment_command_64 *getsegbyname( - const char *segname); - -extern uint8_t *getsegmentdata( +extern uint8_t *crashpad_getsegmentdata( const struct mach_header_64 *mhp, const char *segname, unsigned long *size); #endif /* defined(__LP64__) */ -/* - * Interfaces for tools working with 32-bit Mach-O files. - */ -extern char *getsectdatafromheader( - const struct mach_header *mhp, - const char *segname, - const char *sectname, - uint32_t *size); - -extern const struct section *getsectbynamefromheader( - const struct mach_header *mhp, - const char *segname, - const char *sectname); - -extern const struct section *getsectbynamefromheaderwithswap( - struct mach_header *mhp, - const char *segname, - const char *sectname, - int fSwap); - -/* - * Interfaces for tools working with 64-bit Mach-O files. - */ -extern char *getsectdatafromheader_64( - const struct mach_header_64 *mhp, - const char *segname, - const char *sectname, - uint64_t *size); - -extern const struct section_64 *getsectbynamefromheader_64( - const struct mach_header_64 *mhp, - const char *segname, - const char *sectname); - -extern const struct section *getsectbynamefromheaderwithswap_64( - struct mach_header_64 *mhp, - const char *segname, - const char *sectname, - int fSwap); - #ifdef __cplusplus } #endif /* __cplusplus */ -#endif /* _MACH_O_GETSECT_H_ */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */ + +#endif /* CRASHPAD_THIRD_PARTY_APPLE_CCTOOLS_CCTOOLS_INCLUDE_MACH_O_GETSECT_H_ */ diff --git a/third_party/apple_cctools/cctools/libmacho/getsecbyname.c b/third_party/apple_cctools/cctools/libmacho/getsecbyname.c index 52620f52..1db1cbec 100644 --- a/third_party/apple_cctools/cctools/libmacho/getsecbyname.c +++ b/third_party/apple_cctools/cctools/libmacho/getsecbyname.c @@ -20,326 +20,50 @@ * * @APPLE_LICENSE_HEADER_END@ */ -#ifndef RLD -#include -#include + +#include "third_party/apple_cctools/cctools/include/mach-o/getsect.h" + +#if !defined(MAC_OS_X_VERSION_10_7) || \ + MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 + #include -#ifdef __DYNAMIC__ -#include /* defines _dyld_lookup_and_bind() */ -#endif /* defined(__DYNAMIC__) */ -#ifndef __OPENSTEP__ -#include -#else /* defined(__OPENSTEP__) */ -#if !defined(__DYNAMIC__) -#define DECLARE_VAR(var, type) \ -extern type var -#define SETUP_VAR(var) -#define USE_VAR(var) var -#else -#define STRINGIFY(a) # a -#define DECLARE_VAR(var, type) \ -static type * var ## _pointer = NULL -#define SETUP_VAR(var) \ -if ( var ## _pointer == NULL) { \ - _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ - (uint32_t *) & var ## _pointer, NULL); \ -} -#define USE_VAR(var) (* var ## _pointer) -#endif -#endif /* __OPENSTEP__ */ - -/* - * This routine returns the section structure for the named section in the - * named segment for the mach_header pointer passed to it if it exist. - * Otherwise it returns zero. - */ -const struct section * -getsectbynamefromheader( -struct mach_header *mhp, -const char *segname, -const char *sectname) -{ - struct segment_command *sgp; - struct section *sp; - uint32_t i, j; - - sgp = (struct segment_command *) - ((char *)mhp + sizeof(struct mach_header)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT) - if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || - mhp->filetype == MH_OBJECT){ - sp = (struct section *)((char *)sgp + - sizeof(struct segment_command)); - for(j = 0; j < sgp->nsects; j++){ - if(strncmp(sp->sectname, sectname, - sizeof(sp->sectname)) == 0 && - strncmp(sp->segname, segname, - sizeof(sp->segname)) == 0) - return(sp); - sp = (struct section *)((char *)sp + - sizeof(struct section)); - } - } - sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); - } - return((struct section *)0); -} - -/* - * This routine returns the section structure for the named section in the - * named segment for the mach_header_64 pointer passed to it if it exist. - * Otherwise it returns zero. - */ -const struct section_64 * -getsectbynamefromheader_64( -struct mach_header_64 *mhp, -const char *segname, -const char *sectname) -{ - struct segment_command_64 *sgp; - struct section_64 *sp; - uint32_t i, j; - - sgp = (struct segment_command_64 *) - ((char *)mhp + sizeof(struct mach_header_64)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT_64) - if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || - mhp->filetype == MH_OBJECT){ - sp = (struct section_64 *)((char *)sgp + - sizeof(struct segment_command_64)); - for(j = 0; j < sgp->nsects; j++){ - if(strncmp(sp->sectname, sectname, - sizeof(sp->sectname)) == 0 && - strncmp(sp->segname, segname, - sizeof(sp->segname)) == 0) - return(sp); - sp = (struct section_64 *)((char *)sp + - sizeof(struct section_64)); - } - } - sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); - } - return((struct section_64 *)0); -} - -/* - * This routine returns the section structure for the named section in the - * named segment for the mach_header pointer passed to it if it exist. - * Otherwise it returns zero. If fSwap == YES (the mach header has been - * swapped to the endiannes of the current machine, but the segments and - * sections are different) then the segment and sections are swapped. - */ -const struct section * -getsectbynamefromheaderwithswap( - struct mach_header *mhp, - const char *segname, - const char *sectname, - int fSwap) -{ - struct segment_command *sgp; - struct section *sp; - uint32_t i, j; - - sgp = (struct segment_command *) - ((char *)mhp + sizeof(struct mach_header)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { - - if (fSwap) { -#ifdef __LITTLE_ENDIAN__ - swap_segment_command(sgp, NX_BigEndian); -#else - swap_segment_command(sgp, NX_LittleEndian); -#endif /* __LITTLE_ENDIAN__ */ - } - - if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || - mhp->filetype == MH_OBJECT){ - sp = (struct section *)((char *)sgp + - sizeof(struct segment_command)); - - if (fSwap) { -#ifdef __LITTLE_ENDIAN__ - swap_section(sp, sgp->nsects, NX_BigEndian); -#else - swap_section(sp, sgp->nsects, NX_LittleEndian); -#endif /* __LITTLE_ENDIAN__ */ - } - - for(j = 0; j < sgp->nsects; j++){ - if(strncmp(sp->sectname, sectname, - sizeof(sp->sectname)) == 0 && - strncmp(sp->segname, segname, - sizeof(sp->segname)) == 0) - return(sp); - sp = (struct section *)((char *)sp + - sizeof(struct section)); - } - } - sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); - } else { - sgp = (struct segment_command *)((char *)sgp + - (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); - } - } - return((struct section *)0); -} - -/* - * This routine returns the section_64 structure for the named section in the - * named segment for the mach_header_64 pointer passed to it if it exist. - * Otherwise it returns zero. If fSwap == YES (the mach header has been - * swapped to the endiannes of the current machine, but the segments and - * sections are different) then the segment and sections are swapped. - */ -const struct section_64 * -getsectbynamefromheaderwithswap_64( - struct mach_header_64 *mhp, - const char *segname, - const char *sectname, - int fSwap) -{ - struct segment_command_64 *sgp; - struct section_64 *sp; - uint32_t i, j; - - sgp = (struct segment_command_64 *) - ((char *)mhp + sizeof(struct mach_header_64)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { - - if (fSwap) { -#ifdef __LITTLE_ENDIAN__ - swap_segment_command_64(sgp, NX_BigEndian); -#else - swap_segment_command_64(sgp, NX_LittleEndian); -#endif /* __LITTLE_ENDIAN__ */ - } - - if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || - mhp->filetype == MH_OBJECT){ - sp = (struct section_64 *)((char *)sgp + - sizeof(struct segment_command_64)); - - if (fSwap) { -#ifdef __LITTLE_ENDIAN__ - swap_section_64(sp, sgp->nsects, NX_BigEndian); -#else - swap_section_64(sp, sgp->nsects, NX_LittleEndian); -#endif /* __LITTLE_ENDIAN__ */ - } - - for(j = 0; j < sgp->nsects; j++){ - if(strncmp(sp->sectname, sectname, - sizeof(sp->sectname)) == 0 && - strncmp(sp->segname, segname, - sizeof(sp->segname)) == 0) - return(sp); - sp = (struct section_64 *)((char *)sp + - sizeof(struct section_64)); - } - } - sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); - } else { - sgp = (struct segment_command_64 *)((char *)sgp + - (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); - } - } - return((struct section_64 *)0); -} - -/* - * This routine returns the a pointer the section structure of the named - * section in the named segment if it exist in the mach executable it is - * linked into. Otherwise it returns zero. - */ #ifndef __LP64__ - -const struct section * -getsectbyname( -const char *segname, -const char *sectname) -{ -#ifndef __OPENSTEP__ - struct mach_header *mhp = _NSGetMachExecuteHeader(); -#else /* defined(__OPENSTEP__) */ - static struct mach_header *mhp = NULL; - DECLARE_VAR(_mh_execute_header, struct mach_header); - SETUP_VAR(_mh_execute_header); - mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); -#endif /* __OPENSTEP__ */ - return(getsectbynamefromheader(mhp, segname, sectname)); -} - +typedef struct mach_header mach_header_32_64; +typedef struct segment_command segment_command_32_64; +typedef struct section section_32_64; +#define LC_SEGMENT_32_64 LC_SEGMENT #else /* defined(__LP64__) */ - -const struct section_64 * -getsectbyname( -const char *segname, -const char *sectname) -{ - struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); - - return(getsectbynamefromheader_64(mhp, segname, sectname)); -} - +typedef struct mach_header_64 mach_header_32_64; +typedef struct segment_command_64 segment_command_32_64; +typedef struct section_64 section_32_64; +#define LC_SEGMENT_32_64 LC_SEGMENT_64 #endif /* defined(__LP64__) */ -/* - * This routine returns the a pointer to the data for the named section in the - * named segment if it exist in the mach executable it is linked into. Also - * it returns the size of the section data indirectly through the pointer size. - * Otherwise it returns zero for the pointer and the size. - */ -char * -getsectdata( -const char *segname, -const char *sectname, -unsigned long *size) -{ -#ifndef __LP64__ - const struct section *sp; -#else /* defined(__LP64__) */ - const struct section_64 *sp; -#endif /* defined(__LP64__) */ - - sp = getsectbyname(segname, sectname); - if(sp == NULL){ - *size = 0; - return(NULL); - } - *size = sp->size; - return((char *)(sp->addr)); -} - /* * This routine returns the a pointer to the section contents of the named * section in the named segment if it exists in the image pointed to by the * mach header. Otherwise it returns zero. */ -#ifndef __LP64__ -uint8_t * -getsectiondata( -const struct mach_header *mhp, +uint8_t * +crashpad_getsectiondata( +const mach_header_32_64 *mhp, const char *segname, const char *sectname, unsigned long *size) { - struct segment_command *sgp, *zero; - struct section *sp, *find; + segment_command_32_64 *sgp, *zero; + section_32_64 *sp, *find; uint32_t i, j; zero = 0; find = 0; sp = 0; - sgp = (struct segment_command *) - ((char *)mhp + sizeof(struct mach_header)); + sgp = (segment_command_32_64 *) + ((char *)mhp + sizeof(mach_header_32_64)); for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT){ + if(sgp->cmd == LC_SEGMENT_32_64){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) @@ -347,8 +71,8 @@ unsigned long *size) } if(find == 0 && strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ - sp = (struct section *)((char *)sgp + - sizeof(struct segment_command)); + sp = (section_32_64 *)((char *)sgp + + sizeof(segment_command_32_64)); for(j = 0; j < sgp->nsects; j++){ if(strncmp(sp->sectname, sectname, sizeof(sp->sectname)) == 0 && @@ -358,12 +82,12 @@ unsigned long *size) if(zero != 0) goto done; } - sp = (struct section *)((char *)sp + - sizeof(struct section)); + sp = (section_32_64 *)((char *)sp + + sizeof(section_32_64)); } } } - sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + sgp = (segment_command_32_64 *)((char *)sgp + sgp->cmdsize); } return(0); done: @@ -371,21 +95,21 @@ done: return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); } -uint8_t * -getsegmentdata( -const struct mach_header *mhp, +uint8_t * +crashpad_getsegmentdata( +const mach_header_32_64 *mhp, const char *segname, unsigned long *size) { - struct segment_command *sgp, *zero, *find; + segment_command_32_64 *sgp, *zero, *find; uint32_t i; zero = 0; find = 0; - sgp = (struct segment_command *) - ((char *)mhp + sizeof(struct mach_header)); + sgp = (segment_command_32_64 *) + ((char *)mhp + sizeof(mach_header_32_64)); for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT){ + if(sgp->cmd == LC_SEGMENT_32_64){ if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ zero = sgp; if(find != 0) @@ -398,7 +122,7 @@ unsigned long *size) goto done; } } - sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); + sgp = (segment_command_32_64 *)((char *)sgp + sgp->cmdsize); } return(0); done: @@ -406,192 +130,4 @@ done: return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); } -#else /* defined(__LP64__) */ - -uint8_t * -getsectiondata( -const struct mach_header_64 *mhp, -const char *segname, -const char *sectname, -unsigned long *size) -{ - struct segment_command_64 *sgp, *zero; - struct section_64 *sp, *find; - uint32_t i, j; - - zero = 0; - find = 0; - sp = 0; - sgp = (struct segment_command_64 *) - ((char *)mhp + sizeof(struct mach_header_64)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT_64){ - if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ - zero = sgp; - if(find != 0) - goto done; - } - if(find == 0 && - strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ - sp = (struct section_64 *)((char *)sgp + - sizeof(struct segment_command_64)); - for(j = 0; j < sgp->nsects; j++){ - if(strncmp(sp->sectname, sectname, - sizeof(sp->sectname)) == 0 && - strncmp(sp->segname, segname, - sizeof(sp->segname)) == 0){ - find = sp; - if(zero != 0) - goto done; - } - sp = (struct section_64 *)((char *)sp + - sizeof(struct section_64)); - } - } - } - sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); - } - return(0); -done: - *size = sp->size; - return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); -} - -uint8_t * -getsegmentdata( -const struct mach_header_64 *mhp, -const char *segname, -unsigned long *size) -{ - struct segment_command_64 *sgp, *zero, *find; - uint32_t i; - - zero = 0; - find = 0; - sgp = (struct segment_command_64 *) - ((char *)mhp + sizeof(struct mach_header_64)); - for(i = 0; i < mhp->ncmds; i++){ - if(sgp->cmd == LC_SEGMENT_64){ - if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ - zero = sgp; - if(find != 0) - goto done; - } - if(find == 0 && - strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ - find = sgp; - if(zero != 0) - goto done; - } - } - sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); - } - return(0); -done: - *size = sgp->vmsize; - return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); -} - -#endif /* defined(__LP64__) */ - -/* - * This routine returns the a pointer to the data for the named section in the - * named segment if it exist in the mach header passed to it. Also it returns - * the size of the section data indirectly through the pointer size. Otherwise - * it returns zero for the pointer and the size. - */ -char * -getsectdatafromheader( -struct mach_header *mhp, -const char *segname, -const char *sectname, -unsigned long *size) -{ - const struct section *sp; - - sp = getsectbynamefromheader(mhp, segname, sectname); - if(sp == NULL){ - *size = 0; - return(NULL); - } - *size = sp->size; - return((char *)((uintptr_t)(sp->addr))); -} - -/* - * This routine returns the a pointer to the data for the named section in the - * named segment if it exist in the 64-bit mach header passed to it. Also it - * returns the size of the section data indirectly through the pointer size. - * Otherwise it returns zero for the pointer and the size. - */ -char * -getsectdatafromheader_64( -struct mach_header_64 *mhp, -const char *segname, -const char *sectname, -unsigned long *size) -{ - const struct section_64 *sp; - - sp = getsectbynamefromheader_64(mhp, segname, sectname); - if(sp == NULL){ - *size = 0; - return(NULL); - } - *size = sp->size; - return((char *)((uintptr_t)(sp->addr))); -} - -#ifdef __DYNAMIC__ -/* - * This routine returns the a pointer to the data for the named section in the - * named segment if it exist in the named Framework. Also it returns the size - * of the section data indirectly through the pointer size. Otherwise it - * returns zero for the pointer and the size. The last component of the path - * of the Framework is passed as FrameworkName. - */ -void * -getsectdatafromFramework( -const char *FrameworkName, -const char *segname, -const char *sectname, -unsigned long *size) -{ - uint32_t i, n; - uintptr_t vmaddr_slide; -#ifndef __LP64__ - struct mach_header *mh; - const struct section *s; -#else /* defined(__LP64__) */ - struct mach_header_64 *mh; - const struct section_64 *s; -#endif /* defined(__LP64__) */ - char *name, *p; - - n = _dyld_image_count(); - for(i = 0; i < n ; i++){ - name = _dyld_get_image_name(i); - p = strrchr(name, '/'); - if(p != NULL && p[1] != '\0') - name = p + 1; - if(strcmp(name, FrameworkName) != 0) - continue; - mh = _dyld_get_image_header(i); - vmaddr_slide = _dyld_get_image_vmaddr_slide(i); -#ifndef __LP64__ - s = getsectbynamefromheader(mh, segname, sectname); -#else /* defined(__LP64__) */ - s = getsectbynamefromheader_64(mh, segname, sectname); -#endif /* defined(__LP64__) */ - if(s == NULL){ - *size = 0; - return(NULL); - } - *size = s->size; - return((void *)(s->addr + vmaddr_slide)); - } - *size = 0; - return(NULL); -} -#endif /* __DYNAMIC__ */ -#endif /* !defined(RLD) */ +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7 */ diff --git a/util/mac/mach_o_image_reader_test.cc b/util/mac/mach_o_image_reader_test.cc index 2a1e15aa..b0ea5143 100644 --- a/util/mac/mach_o_image_reader_test.cc +++ b/util/mac/mach_o_image_reader_test.cc @@ -14,6 +14,7 @@ #include "util/mac/mach_o_image_reader.h" +#include #include #include #include @@ -592,6 +593,7 @@ TEST(MachOImageReader, Self_DyldImages) { } } +#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7 // If dyld is new enough to record UUIDs, check the UUID of any module that // it says has one. Note that dyld doesn’t record UUIDs of anything that // loaded out of the shared cache, but it should at least have a UUID for the @@ -626,6 +628,7 @@ TEST(MachOImageReader, Self_DyldImages) { EXPECT_EQ(expected_uuid, actual_uuid); } } +#endif } } // namespace diff --git a/util/test/mac/dyld.h b/util/test/mac/dyld.h index 854d7776..068e8deb 100644 --- a/util/test/mac/dyld.h +++ b/util/test/mac/dyld.h @@ -22,7 +22,7 @@ extern "C" { // Returns a pointer to this process’ dyld_all_image_infos structure. This is // implemented as a non-public dyld API, declared in 10.9.2 // dyld-239.4/include/mach-o/dyld_priv.h. -const dyld_all_image_infos* _dyld_get_all_image_infos(); +const struct dyld_all_image_infos* _dyld_get_all_image_infos(); } // extern "C"