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 <mach-o/ldsyms.h> 25#include <mach-o/swap.h> 26#include <string.h> 27#ifdef __DYNAMIC__ 28#include <mach-o/dyld.h> /* defines _dyld_lookup_and_bind() */ 29#endif /* defined(__DYNAMIC__) */ 30#ifndef __OPENSTEP__ 31#include <crt_externs.h> 32#else /* defined(__OPENSTEP__) */ 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 = NULL 43#define SETUP_VAR(var) \ 44if ( var ## _pointer == NULL) { \ 45 _dyld_lookup_and_bind( STRINGIFY(_ ## var), \ 46 (uint32_t *) & var ## _pointer, NULL); \ 47} 48#define USE_VAR(var) (* var ## _pointer) 49#endif 50#endif /* __OPENSTEP__ */ 51 52/* 53 * This routine returns the section structure for the named section in the 54 * named segment for the mach_header pointer passed to it if it exist. 55 * Otherwise it returns zero. 56 */ 57const struct section * 58getsectbynamefromheader( 59struct mach_header *mhp, 60const char *segname, 61const char *sectname) 62{ 63 struct segment_command *sgp; 64 struct section *sp; 65 uint32_t i, j; 66 67 sgp = (struct segment_command *) 68 ((char *)mhp + sizeof(struct mach_header)); 69 for(i = 0; i < mhp->ncmds; i++){ 70 if(sgp->cmd == LC_SEGMENT) 71 if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || 72 mhp->filetype == MH_OBJECT){ 73 sp = (struct section *)((char *)sgp + 74 sizeof(struct segment_command)); 75 for(j = 0; j < sgp->nsects; j++){ 76 if(strncmp(sp->sectname, sectname, 77 sizeof(sp->sectname)) == 0 && 78 strncmp(sp->segname, segname, 79 sizeof(sp->segname)) == 0) 80 return(sp); 81 sp = (struct section *)((char *)sp + 82 sizeof(struct section)); 83 } 84 } 85 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); 86 } 87 return((struct section *)0); 88} 89 90/* 91 * This routine returns the section structure for the named section in the 92 * named segment for the mach_header_64 pointer passed to it if it exist. 93 * Otherwise it returns zero. 94 */ 95const struct section_64 * 96getsectbynamefromheader_64( 97struct mach_header_64 *mhp, 98const char *segname, 99const char *sectname) 100{ 101 struct segment_command_64 *sgp; 102 struct section_64 *sp; 103 uint32_t i, j; 104 105 sgp = (struct segment_command_64 *) 106 ((char *)mhp + sizeof(struct mach_header_64)); 107 for(i = 0; i < mhp->ncmds; i++){ 108 if(sgp->cmd == LC_SEGMENT_64) 109 if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || 110 mhp->filetype == MH_OBJECT){ 111 sp = (struct section_64 *)((char *)sgp + 112 sizeof(struct segment_command_64)); 113 for(j = 0; j < sgp->nsects; j++){ 114 if(strncmp(sp->sectname, sectname, 115 sizeof(sp->sectname)) == 0 && 116 strncmp(sp->segname, segname, 117 sizeof(sp->segname)) == 0) 118 return(sp); 119 sp = (struct section_64 *)((char *)sp + 120 sizeof(struct section_64)); 121 } 122 } 123 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); 124 } 125 return((struct section_64 *)0); 126} 127 128/* 129 * This routine returns the section structure for the named section in the 130 * named segment for the mach_header pointer passed to it if it exist. 131 * Otherwise it returns zero. If fSwap == YES (the mach header has been 132 * swapped to the endiannes of the current machine, but the segments and 133 * sections are different) then the segment and sections are swapped. 134 */ 135const struct section * 136getsectbynamefromheaderwithswap( 137 struct mach_header *mhp, 138 const char *segname, 139 const char *sectname, 140 int fSwap) 141{ 142 struct segment_command *sgp; 143 struct section *sp; 144 uint32_t i, j; 145 146 sgp = (struct segment_command *) 147 ((char *)mhp + sizeof(struct mach_header)); 148 for(i = 0; i < mhp->ncmds; i++){ 149 if(sgp->cmd == (fSwap ? OSSwapInt32(LC_SEGMENT) : LC_SEGMENT)) { 150 151 if (fSwap) { 152#ifdef __LITTLE_ENDIAN__ 153 swap_segment_command(sgp, NX_BigEndian); 154#else 155 swap_segment_command(sgp, NX_LittleEndian); 156#endif /* __LITTLE_ENDIAN__ */ 157 } 158 159 if(strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0 || 160 mhp->filetype == MH_OBJECT){ 161 sp = (struct section *)((char *)sgp + 162 sizeof(struct segment_command)); 163 164 if (fSwap) { 165#ifdef __LITTLE_ENDIAN__ 166 swap_section(sp, sgp->nsects, NX_BigEndian); 167#else 168 swap_section(sp, sgp->nsects, NX_LittleEndian); 169#endif /* __LITTLE_ENDIAN__ */ 170 } 171 172 for(j = 0; j < sgp->nsects; j++){ 173 if(strncmp(sp->sectname, sectname, 174 sizeof(sp->sectname)) == 0 && 175 strncmp(sp->segname, segname, 176 sizeof(sp->segname)) == 0) 177 return(sp); 178 sp = (struct section *)((char *)sp + 179 sizeof(struct section)); 180 } 181 } 182 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); 183 } else { 184 sgp = (struct segment_command *)((char *)sgp + 185 (fSwap ? OSSwapInt32(sgp->cmdsize) : sgp->cmdsize)); 186 } 187 } 188 return((struct section *)0); 189} 190 191/* 192 * This routine returns the a pointer the section structure of the named 193 * section in the named segment if it exist in the mach executable it is 194 * linked into. Otherwise it returns zero. 195 */ 196#ifndef __LP64__ 197 198const struct section * 199getsectbyname( 200const char *segname, 201const char *sectname) 202{ 203#ifndef __OPENSTEP__ 204 struct mach_header *mhp = _NSGetMachExecuteHeader(); 205#else /* defined(__OPENSTEP__) */ 206 static struct mach_header *mhp = NULL; 207 DECLARE_VAR(_mh_execute_header, struct mach_header); 208 SETUP_VAR(_mh_execute_header); 209 mhp = (struct mach_header *)(& USE_VAR(_mh_execute_header)); 210#endif /* __OPENSTEP__ */ 211 return(getsectbynamefromheader(mhp, segname, sectname)); 212} 213 214#else /* defined(__LP64__) */ 215 216const struct section_64 * 217getsectbyname( 218const char *segname, 219const char *sectname) 220{ 221 struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); 222 223 return(getsectbynamefromheader_64(mhp, segname, sectname)); 224} 225 226#endif /* defined(__LP64__) */ 227 228/* 229 * This routine returns the a pointer to the data for the named section in the 230 * named segment if it exist in the mach executable it is linked into. Also 231 * it returns the size of the section data indirectly through the pointer size. 232 * Otherwise it returns zero for the pointer and the size. 233 */ 234char * 235getsectdata( 236const char *segname, 237const char *sectname, 238unsigned long *size) 239{ 240#ifndef __LP64__ 241 const struct section *sp; 242#else /* defined(__LP64__) */ 243 const struct section_64 *sp; 244#endif /* defined(__LP64__) */ 245 246 sp = getsectbyname(segname, sectname); 247 if(sp == NULL){ 248 *size = 0; 249 return(NULL); 250 } 251 *size = sp->size; 252 return((char *)(sp->addr)); 253} 254 255/* 256 * This routine returns the a pointer to the section contents of the named 257 * section in the named segment if it exists in the image pointed to by the 258 * mach header. Otherwise it returns zero. 259 */ 260#ifndef __LP64__ 261 262uint8_t * 263getsectiondata( 264const struct mach_header *mhp, 265const char *segname, 266const char *sectname, 267unsigned long *size) 268{ 269 struct segment_command *sgp, *zero; 270 struct section *sp, *find; 271 uint32_t i, j; 272 273 zero = 0; 274 find = 0; 275 sp = 0; 276 sgp = (struct segment_command *) 277 ((char *)mhp + sizeof(struct mach_header)); 278 for(i = 0; i < mhp->ncmds; i++){ 279 if(sgp->cmd == LC_SEGMENT){ 280 if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ 281 zero = sgp; 282 if(find != 0) 283 goto done; 284 } 285 if(find == 0 && 286 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ 287 sp = (struct section *)((char *)sgp + 288 sizeof(struct segment_command)); 289 for(j = 0; j < sgp->nsects; j++){ 290 if(strncmp(sp->sectname, sectname, 291 sizeof(sp->sectname)) == 0 && 292 strncmp(sp->segname, segname, 293 sizeof(sp->segname)) == 0){ 294 find = sp; 295 if(zero != 0) 296 goto done; 297 } 298 sp = (struct section *)((char *)sp + 299 sizeof(struct section)); 300 } 301 } 302 } 303 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); 304 } 305 return(0); 306done: 307 *size = sp->size; 308 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); 309} 310 311uint8_t * 312getsegmentdata( 313const struct mach_header *mhp, 314const char *segname, 315unsigned long *size) 316{ 317 struct segment_command *sgp, *zero, *find; 318 uint32_t i; 319 320 zero = 0; 321 find = 0; 322 sgp = (struct segment_command *) 323 ((char *)mhp + sizeof(struct mach_header)); 324 for(i = 0; i < mhp->ncmds; i++){ 325 if(sgp->cmd == LC_SEGMENT){ 326 if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ 327 zero = sgp; 328 if(find != 0) 329 goto done; 330 } 331 if(find == 0 && 332 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ 333 find = sgp; 334 if(zero != 0) 335 goto done; 336 } 337 } 338 sgp = (struct segment_command *)((char *)sgp + sgp->cmdsize); 339 } 340 return(0); 341done: 342 *size = sgp->vmsize; 343 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); 344} 345 346#else /* defined(__LP64__) */ 347 348uint8_t * 349getsectiondata( 350const struct mach_header_64 *mhp, 351const char *segname, 352const char *sectname, 353unsigned long *size) 354{ 355 struct segment_command_64 *sgp, *zero; 356 struct section_64 *sp, *find; 357 uint32_t i, j; 358 359 zero = 0; 360 find = 0; 361 sp = 0; 362 sgp = (struct segment_command_64 *) 363 ((char *)mhp + sizeof(struct mach_header_64)); 364 for(i = 0; i < mhp->ncmds; i++){ 365 if(sgp->cmd == LC_SEGMENT_64){ 366 if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ 367 zero = sgp; 368 if(find != 0) 369 goto done; 370 } 371 if(find == 0 && 372 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ 373 sp = (struct section_64 *)((char *)sgp + 374 sizeof(struct segment_command_64)); 375 for(j = 0; j < sgp->nsects; j++){ 376 if(strncmp(sp->sectname, sectname, 377 sizeof(sp->sectname)) == 0 && 378 strncmp(sp->segname, segname, 379 sizeof(sp->segname)) == 0){ 380 find = sp; 381 if(zero != 0) 382 goto done; 383 } 384 sp = (struct section_64 *)((char *)sp + 385 sizeof(struct section_64)); 386 } 387 } 388 } 389 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); 390 } 391 return(0); 392done: 393 *size = sp->size; 394 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sp->addr)); 395} 396 397uint8_t * 398getsegmentdata( 399const struct mach_header_64 *mhp, 400const char *segname, 401unsigned long *size) 402{ 403 struct segment_command_64 *sgp, *zero, *find; 404 uint32_t i; 405 406 zero = 0; 407 find = 0; 408 sgp = (struct segment_command_64 *) 409 ((char *)mhp + sizeof(struct mach_header_64)); 410 for(i = 0; i < mhp->ncmds; i++){ 411 if(sgp->cmd == LC_SEGMENT_64){ 412 if(zero == 0 && sgp->fileoff == 0 && sgp->nsects != 0){ 413 zero = sgp; 414 if(find != 0) 415 goto done; 416 } 417 if(find == 0 && 418 strncmp(sgp->segname, segname, sizeof(sgp->segname)) == 0){ 419 find = sgp; 420 if(zero != 0) 421 goto done; 422 } 423 } 424 sgp = (struct segment_command_64 *)((char *)sgp + sgp->cmdsize); 425 } 426 return(0); 427done: 428 *size = sgp->vmsize; 429 return((uint8_t *)((uintptr_t)mhp - zero->vmaddr + sgp->vmaddr)); 430} 431 432#endif /* defined(__LP64__) */ 433 434/* 435 * This routine returns the a pointer to the data for the named section in the 436 * named segment if it exist in the mach header passed to it. Also it returns 437 * the size of the section data indirectly through the pointer size. Otherwise 438 * it returns zero for the pointer and the size. 439 */ 440char * 441getsectdatafromheader( 442struct mach_header *mhp, 443const char *segname, 444const char *sectname, 445unsigned long *size) 446{ 447 const struct section *sp; 448 449 sp = getsectbynamefromheader(mhp, segname, sectname); 450 if(sp == NULL){ 451 *size = 0; 452 return(NULL); 453 } 454 *size = sp->size; 455 return((char *)((uintptr_t)(sp->addr))); 456} 457 458/* 459 * This routine returns the a pointer to the data for the named section in the 460 * named segment if it exist in the 64-bit mach header passed to it. Also it 461 * returns the size of the section data indirectly through the pointer size. 462 * Otherwise it returns zero for the pointer and the size. 463 */ 464char * 465getsectdatafromheader_64( 466struct mach_header_64 *mhp, 467const char *segname, 468const char *sectname, 469unsigned long *size) 470{ 471 const struct section_64 *sp; 472 473 sp = getsectbynamefromheader_64(mhp, segname, sectname); 474 if(sp == NULL){ 475 *size = 0; 476 return(NULL); 477 } 478 *size = sp->size; 479 return((char *)((uintptr_t)(sp->addr))); 480} 481 482#ifdef __DYNAMIC__ 483/* 484 * This routine returns the a pointer to the data for the named section in the 485 * named segment if it exist in the named Framework. Also it returns the size 486 * of the section data indirectly through the pointer size. Otherwise it 487 * returns zero for the pointer and the size. The last component of the path 488 * of the Framework is passed as FrameworkName. 489 */ 490void * 491getsectdatafromFramework( 492const char *FrameworkName, 493const char *segname, 494const char *sectname, 495unsigned long *size) 496{ 497 uint32_t i, n; 498 uintptr_t vmaddr_slide; 499#ifndef __LP64__ 500 struct mach_header *mh; 501 const struct section *s; 502#else /* defined(__LP64__) */ 503 struct mach_header_64 *mh; 504 const struct section_64 *s; 505#endif /* defined(__LP64__) */ 506 char *name, *p; 507 508 n = _dyld_image_count(); 509 for(i = 0; i < n ; i++){ 510 name = _dyld_get_image_name(i); 511 p = strrchr(name, '/'); 512 if(p != NULL && p[1] != '\0') 513 name = p + 1; 514 if(strcmp(name, FrameworkName) != 0) 515 continue; 516 mh = _dyld_get_image_header(i); 517 vmaddr_slide = _dyld_get_image_vmaddr_slide(i); 518#ifndef __LP64__ 519 s = getsectbynamefromheader(mh, segname, sectname); 520#else /* defined(__LP64__) */ 521 s = getsectbynamefromheader_64(mh, segname, sectname); 522#endif /* defined(__LP64__) */ 523 if(s == NULL){ 524 *size = 0; 525 return(NULL); 526 } 527 *size = s->size; 528 return((void *)(s->addr + vmaddr_slide)); 529 } 530 *size = 0; 531 return(NULL); 532} 533#endif /* __DYNAMIC__ */ 534#endif /* !defined(RLD) */ 535