1/* 2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#ifndef RLD 24#include <string.h> 25#include <mach-o/ldsyms.h> 26#include <mach-o/getsect.h> 27#ifndef __OPENSTEP__ 28#include <crt_externs.h> 29#else /* defined(__OPENSTEP__) */ 30#ifdef __DYNAMIC__ 31#include "mach-o/dyld.h" /* defines _dyld_lookup_and_bind() */ 32#endif 33 34#if !defined(__DYNAMIC__) 35#define DECLARE_VAR(var, type) \ 36extern type var 37#define SETUP_VAR(var) 38#define USE_VAR(var) var 39#else 40#define STRINGIFY(a) # a 41#define DECLARE_VAR(var, type) \ 42static type * var ## _pointer = 0 43#define SETUP_VAR(var) \ 44if ( var ## _pointer == 0) { \ 45 _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ 46 (uint32_t *) & var ## _pointer, 0); \ 47} 48#define USE_VAR(var) (* var ## _pointer) 49#endif 50#endif /* __OPENSTEP__ */ 51 52/* 53 * This routine returns the highest address of the segments in the program (NOT 54 * the shared libraries). It is intended to be used as a stop gap for programs 55 * that make UNIX style assumptions about how memory is allocated. Typicly the 56 * asumptions under which this is used is that memory is contiguously allocated 57 * by the program's text and data from address 0 with no gaps. The value of 58 * this differs from the value of &_end in a UNIX program in that this routine 59 * returns the address of the end of the segment not the end of the last section 60 * in that segment as would be the value of the symbol &_end. 61 */ 62unsigned long 63get_end(void) 64{ 65#ifndef __LP64__ 66 67 struct segment_command *sgp; 68 unsigned long _end; 69 uint32_t i; 70#ifndef __OPENSTEP__ 71 struct mach_header *mhp = _NSGetMachExecuteHeader(); 72#else /* defined(__OPENSTEP__) */ 73 static struct mach_header *mhp = NULL; 74 DECLARE_VAR(_mh_execute_header, struct mach_header); 75 SETUP_VAR(_mh_execute_header); 76 77 mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); 78#endif /* __OPENSTEP__ */ 79 _end = 0; 80 sgp = (struct segment_command *) 81 ((char *)mhp + sizeof(struct mach_header)); 82 for(i = 0; i < mhp->ncmds; i++){ 83 if(sgp->cmd == LC_SEGMENT) 84 if(sgp->vmaddr + sgp->vmsize > _end) 85 _end = sgp->vmaddr + sgp->vmsize; 86 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); 87 } 88 return(_end); 89 90#else /* defined(__LP64__) */ 91 92 struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); 93 struct segment_command_64 *sgp; 94 unsigned long _end; 95 uint32_t i; 96 97 _end = 0; 98 sgp = (struct segment_command_64 *) 99 ((char *)mhp + sizeof(struct mach_header_64)); 100 for(i = 0; i < mhp->ncmds; i++){ 101 if(sgp->cmd == LC_SEGMENT_64) 102 if(sgp->vmaddr + sgp->vmsize > _end) 103 _end = sgp->vmaddr + sgp->vmsize; 104 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); 105 } 106 return(_end); 107 108#endif /* defined(__LP64__) */ 109} 110 111/* 112 * This returns what was the value of the UNIX link editor defined symbol 113 * _etext (the first address after the text section). Note this my or may not 114 * be the only section in the __TEXT segment. 115 */ 116unsigned long 117get_etext(void) 118{ 119#ifndef __LP64__ 120 const struct section *sp; 121#else /* defined(__LP64__) */ 122 const struct section_64 *sp; 123#endif /* defined(__LP64__) */ 124 125 sp = getsectbyname(SEG_TEXT, SECT_TEXT); 126 if(sp) 127 return(sp->addr + sp->size); 128 else 129 return(0); 130} 131 132/* 133 * This returns what was the value of the UNIX link editor defined symbol 134 * _edata (the first address after the data section). Note this my or may not 135 * be the last non-zero fill section in the __DATA segment. 136 */ 137unsigned long 138get_edata(void) 139{ 140#ifndef __LP64__ 141 const struct section *sp; 142#else /* defined(__LP64__) */ 143 const struct section_64 *sp; 144#endif /* defined(__LP64__) */ 145 146 sp = getsectbyname(SEG_DATA, SECT_DATA); 147 if(sp) 148 return(sp->addr + sp->size); 149 else 150 return(0); 151} 152#endif /* !defined(RLD) */ 153