10.6 SDK compatibility.

TEST=util_test MachOImageReader.* (and all others with a 10.6 SDK build)
R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/561933004
This commit is contained in:
Mark Mentovai 2014-09-12 12:13:27 -04:00
parent 24fc801715
commit ab4978b51e
9 changed files with 312 additions and 593 deletions

View File

@ -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',
],
},
}],
],
},
],
}

View File

@ -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 <mach-o/getsect.h>
// 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 <dlfcn.h>
#include <stddef.h>
#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, theyre 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<void*>(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 systems versions are used directly. Otherwise, the
// versions in third_party/apple_cctools are used, which are actually just
// copies of the systems functions.
uint8_t* getsectiondata(const MachHeader* mhp,
const char* segname,
const char* sectname,
unsigned long* size) {
static GetSectionDataType system_getsectiondata =
reinterpret_cast<GetSectionDataType>(
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<GetSegmentDataType>(
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

View File

@ -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 <mach-o/getsect.h>
#include <AvailabilityMacros.h>
// 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 <mach-o/loader.h>
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
// Dont 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_

View File

@ -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.

View File

@ -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',
],
},
],
}

View File

@ -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 <AvailabilityMacros.h>
#if !defined(MAC_OS_X_VERSION_10_7) || \
MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7
#include <stdint.h>
#include <mach-o/loader.h>
@ -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_ */

View File

@ -20,326 +20,50 @@
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef RLD
#include <mach-o/ldsyms.h>
#include <mach-o/swap.h>
#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 <string.h>
#ifdef __DYNAMIC__
#include <mach-o/dyld.h> /* defines _dyld_lookup_and_bind() */
#endif /* defined(__DYNAMIC__) */
#ifndef __OPENSTEP__
#include <crt_externs.h>
#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 */

View File

@ -14,6 +14,7 @@
#include "util/mac/mach_o_image_reader.h"
#include <AvailabilityMacros.h>
#include <dlfcn.h>
#include <mach-o/dyld.h>
#include <mach-o/dyld_images.h>
@ -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 doesnt 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

View File

@ -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"