1/* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21/* Copyright (c) 1988 AT&T */ 22/* All Rights Reserved */ 23 24 25/* 26 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30#ifndef _DECL_H 31#define _DECL_H 32 33#pragma ident "@(#)decl.h 1.23 08/03/18 SMI" /* SVr4.0 1.9 */ 34 35#define SEG_CTF "__CTF" 36#define SECT_CTF "__ctf" 37 38#include <pthread.h> /* In lieu of Solaris <thread.h> */ 39#define USYNC_THREAD IGNORED /* Take PTHREAD_PROCESS_PRIVATE default in pthread_*_init() */ 40#define DEFAULTMUTEX PTHREAD_MUTEX_INITIALIZER 41 42typedef pthread_mutex_t mutex_t; 43typedef pthread_rwlock_t rwlock_t; 44typedef pthread_key_t thread_key_t; 45 46#define RW_LOCK_HELD(x) 1 /* Only used in "assert" */ 47#define MUTEX_HELD(x) 1 /* Only used in "assert" */ 48 49#define rwlock_init(x,y,z) pthread_rwlock_init(x,((const pthread_rwlockattr_t *)NULL)) 50#define rw_rdlock(x) pthread_rwlock_rdlock(x) 51#define rw_wrlock(x) pthread_rwlock_wrlock(x) 52#define rw_unlock(x) pthread_rwlock_unlock(x) 53 54#define mutex_init(x,y,z) pthread_mutex_init(x,((const pthread_mutexattr_t *)NULL)) 55#define mutex_lock(x) pthread_mutex_lock(x) 56#define mutex_unlock(x) pthread_mutex_unlock(x) 57 58#define NOTE(x) /* NOTHING */ /* In lieu of Solaris #include <note.h> */ 59 60#include <libelf.h> 61#include "machelf.h" /* In lieu of Solaris <sys/machelf.h> */ 62#include <gelf.h> 63#include <msg.h> 64 65#include <unistd.h> 66#define PAGESIZE getpagesize() 67 68#define SHT_SPARC_GOTDATA -1 69#define SHT_AMD64_UNWIND -1 70 71#define SWAP16(v) v = OSSwapInt16(v) 72#define SWAP32(v) v = OSSwapInt32(v) 73#define SWAP64(v) v = OSSwapInt64(v) 74 75#include <mach-o/loader.h> 76extern void __swap_mach_header(struct mach_header *); 77extern void __swap_mach_header_64(struct mach_header_64 *); 78extern void __swap_segment_command(struct segment_command *); 79extern void __swap_segment_command_64(struct segment_command_64 *); 80extern void __swap_section(struct section *); 81extern void __swap_section_64(struct section_64 *); 82extern void __swap_symtab_command(struct symtab_command *); 83 84#ifdef __cplusplus 85extern "C" { 86#endif 87 88typedef struct Member Member; 89typedef struct Memlist Memlist; 90typedef struct Memident Memident; 91typedef struct Dnode Dnode; 92typedef struct Snode32 Snode32; 93typedef struct Snode64 Snode64; 94 95 96/* 97 * Data alignment 98 * An elf file is defined to have its structures aligned on 99 * appropriate boundaries. The following type lets the 100 * library test whether the file's alignment meets its own 101 * constraints in memory. This assumes every machine uses 102 * an alignment that is no greater than an object's size. 103 * The pointer isn't relevant for the file, but the code uses 104 * it to get memory alignment. ANSI C void * holds any pointer, 105 * making it appropriate here. 106 */ 107 108typedef union 109{ 110 Elf32_Word w; 111 Elf32_Addr a; 112 Elf32_Off o; 113} Elf32; 114 115typedef union { 116 Elf64_Xword x; 117 Elf64_Word w; 118 Elf64_Addr a; 119 Elf64_Off o; 120 Elf_Void *p; 121} Elf64; 122 123 124/* 125 * Memory allocation 126 * Structures are obtained several ways: file mapping, 127 * malloc(), from the user. A status bit in the structures 128 * tells whether an object was obtained with malloc() and 129 * therefore should be released with free(). The bits 130 * named ...ALLOC indicate this. 131 */ 132 133 134/* 135 * Data descriptor 136 * db_data must be first in the Dnode structure, because 137 * &db_data must == &Dnode. 138 * 139 * db_buf is a pointer to an allocated buffer. The same value 140 * goes into db_data.d_buf originally, but the user can touch 141 * it. If the data buffer is not to be freed, db_buf is null. 142 * 143 * When "reading" an input file's buffer, the data are left 144 * alone until needed. When they've been converted to internal 145 * form, the READY flag is set. 146 * 147 * db_raw points to a parallel raw buffer. Raw buffers 148 * have null db_raw. 149 */ 150 151struct Dnode 152{ 153 Elf_Data db_data; 154 Elf_Scn *db_scn; /* section parent */ 155 Dnode *db_next; 156 Dnode *db_raw; /* raw data */ 157 off_t db_off; /* orig file offset, 0 o/w */ 158 size_t db_fsz; /* orig file size, 0 o/w */ 159 size_t db_shsz; /* orig shdr size, 0 o/w */ 160 size_t db_osz; /* output size for update */ 161 Elf_Void *db_buf; /* allocated data buffer */ 162 unsigned db_uflags; /* user flags: ELF_F_... */ 163 unsigned db_myflags; /* internal flags: DBF_... */ 164 Elf64_Off db_xoff; /* extended offset for 32-bit Elf64 */ 165}; 166 167#define DBF_ALLOC 0x1 /* applies to Dnode itself */ 168#define DBF_READY 0x2 /* buffer ready */ 169 170 171/* 172 * Section descriptor 173 * These are sometimes allocated in a block. If the SF_ALLOC 174 * bit is set in the flags, the Scn address may be passed to free. 175 * The caller must first follow the s_next list to the next freeable 176 * node, because free can clobber the s_next value in the block. 177 */ 178 179struct Elf_Scn 180{ 181 mutex_t s_mutex; 182 Elf_Scn *s_next; /* next section */ 183 Elf *s_elf; /* parent file */ 184 Dnode *s_hdnode; /* head Dnode */ 185 Dnode *s_tlnode; /* tail Dnode */ 186 Elf_Void *s_shdr; /* Elf32 or Elf64 scn header */ 187 size_t s_index; /* section index */ 188 int s_err; /* for delaying data error */ 189 unsigned s_shflags; /* user shdr flags */ 190 unsigned s_uflags; /* user flags */ 191 unsigned s_myflags; /* SF_... */ 192 Dnode s_dnode; /* every scn needs one */ 193}; 194 195NOTE(MUTEX_PROTECTS_DATA(Elf_Scn::s_mutex, Elf_Scn Dnode Elf_Data)) 196NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf_Data)) 197NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf32_Shdr Elf32_Sym)) 198NOTE(READ_ONLY_DATA(Elf_Scn::s_elf)) 199NOTE(READ_ONLY_DATA(Dnode::db_scn)) 200 201 202/* 203 * Designates whether or not we are in a threaded_app. 204 */ 205extern int *_elf_libc_threaded; 206#define elf_threaded (_elf_libc_threaded && *_elf_libc_threaded) 207 208#ifdef __lock_lint 209#define SCNLOCK(x) (void) mutex_lock(&((Elf_Scn *)x)->s_mutex); 210#else 211#define SCNLOCK(x) \ 212 if (elf_threaded) \ 213 (void) mutex_lock(&((Elf_Scn *)x)->s_mutex); 214#endif 215 216#ifdef __lock_lint 217#define SCNUNLOCK(x) (void) mutex_unlock(&((Elf_Scn *)x)->s_mutex); 218#else 219#define SCNUNLOCK(x) \ 220 if (elf_threaded) \ 221 (void) mutex_unlock(&((Elf_Scn *)x)->s_mutex); 222#endif 223 224#ifdef __lock_lint 225#define UPGRADELOCKS(e, s)\ 226 (void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \ 227 (void) rw_unlock(&((Elf *)e)->ed_rwlock); \ 228 (void) rw_wrlock(&((Elf *)e)->ed_rwlock); 229#else 230#define UPGRADELOCKS(e, s)\ 231 if (elf_threaded) { \ 232 (void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \ 233 (void) rw_unlock(&((Elf *)e)->ed_rwlock); \ 234 (void) rw_wrlock(&((Elf *)e)->ed_rwlock); \ 235 } 236#endif 237 238#ifdef __lock_lint 239#define DOWNGRADELOCKS(e, s)\ 240 (void) rw_unlock(&((Elf *)e)->ed_rwlock); \ 241 (void) rw_rdlock(&((Elf *)e)->ed_rwlock); \ 242 (void) mutex_lock(&((Elf_Scn *)s)->s_mutex); 243#else 244#define DOWNGRADELOCKS(e, s)\ 245 if (elf_threaded) { \ 246 (void) rw_unlock(&((Elf *)e)->ed_rwlock); \ 247 (void) rw_rdlock(&((Elf *)e)->ed_rwlock); \ 248 (void) mutex_lock(&((Elf_Scn *)s)->s_mutex); \ 249 } 250#endif 251 252#ifdef __lock_lint 253#define READLOCKS(e, s) \ 254 (void) rw_rdlock(&((Elf *)e)->ed_rwlock); \ 255 (void) mutex_lock(&((Elf_Scn *)s)->s_mutex); 256#else 257#define READLOCKS(e, s) \ 258 if (elf_threaded) { \ 259 (void) rw_rdlock(&((Elf *)e)->ed_rwlock); \ 260 (void) mutex_lock(&((Elf_Scn *)s)->s_mutex); \ 261 } 262#endif 263 264#ifdef __lock_lint 265#define READUNLOCKS(e, s) \ 266 (void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \ 267 (void) rw_unlock(&((Elf *)e)->ed_rwlock); 268#else 269#define READUNLOCKS(e, s) \ 270 if (elf_threaded) { \ 271 (void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \ 272 (void) rw_unlock(&((Elf *)e)->ed_rwlock); \ 273 } 274#endif 275 276 277 278 279#define SF_ALLOC 0x1 /* applies to Scn */ 280#define SF_READY 0x2 /* has section been cooked */ 281 282 283struct Snode32 284{ 285 Elf_Scn sb_scn; /* must be first */ 286 Elf32_Shdr sb_shdr; 287}; 288 289struct Snode64 290{ 291 Elf_Scn sb_scn; /* must be first */ 292 Elf64_Shdr sb_shdr; 293}; 294 295 296/* 297 * A file's status controls how the library can use file data. 298 * This is important to keep "raw" operations and "cooked" 299 * operations from interfering with each other. 300 * 301 * A file's status is "fresh" until something touches it. 302 * If the first thing is a raw operation, we freeze the data 303 * and force all cooking operations to make a copy. If the 304 * first operation cooks, raw operations use the file system. 305 */ 306 307typedef enum 308{ 309 ES_FRESH = 0, /* unchanged */ 310 ES_COOKED, /* translated */ 311 ES_FROZEN /* raw, can't be translated */ 312} Status; 313 314 315/* 316 * Elf descriptor 317 * The major handle between user code and the library. 318 * 319 * Descriptors can have parents: archive members reference 320 * the archive itself. Relevant "offsets:" 321 * 322 * ed_baseoff The file offset, relative to zero, to the first 323 * byte in the file. For all files, this gives 324 * the lseek(fd, ed_baseoff, 0) value. 325 * 326 * ed_memoff The offset from the beginning of the nesting file 327 * to the bytes of a member. For an archive member, 328 * this is the offset from the beginning of the 329 * archive to the member bytes (not the hdr). If an 330 * archive member slides, memoff changes. 331 * 332 * ed_siboff Similar to ed_memoff, this gives the offset from 333 * the beginning of the nesting file to the following 334 * sibling's header (not the sibling's bytes). This 335 * value is necessary, because of archive sliding. 336 * 337 * ed_nextoff For an archive, this gives the offset of the next 338 * member to process on elf_begin. That is, 339 * (ed_ident + ed_nextoff) gives pointer to member hdr. 340 * 341 * Keeping these absolute and relative offsets allows nesting of 342 * files, including archives within archives, etc. The only current 343 * nesting file is archive, but others might be supported. 344 * 345 * ed_image This is a pointer to the base memory image holding 346 * the file. Library code assumes the image is aligned 347 * to a boundary appropriate for any object. This must 348 * be true, because we get an image only from malloc 349 * or mmap, both of which guarantee alignment. 350 */ 351 352struct Elf 353{ 354 rwlock_t ed_rwlock; 355 Elf *ed_parent; /* archive parent */ 356 int ed_activ; /* activation count */ 357 int ed_fd; /* file descriptor */ 358 Status ed_status; /* file's memory status */ 359 off_t ed_baseoff; /* base file offset, zero based */ 360 size_t ed_memoff; /* offset within archive */ 361 size_t ed_siboff; /* sibling offset with archive */ 362 size_t ed_nextoff; /* next archive member hdr offset */ 363 char *ed_image; /* pointer to file image */ 364 size_t ed_imagesz; /* # bytes in ed_image */ 365 char *ed_wrimage; /* pointer to output image */ 366 size_t ed_wrimagesz; /* # bytes in ed_wrimagesz */ 367 char *ed_ident; /* file start, getident() bytes */ 368 size_t ed_identsz; /* # bytes for getident() */ 369 char *ed_raw; /* raw file ptr */ 370 size_t ed_fsz; /* file size */ 371 unsigned *ed_vm; /* virtual memory map */ 372 size_t ed_vmsz; /* # regions in vm */ 373 unsigned ed_encode; /* data encoding */ 374 unsigned ed_version; /* file version */ 375 int ed_class; /* file class */ 376 Elf_Kind ed_kind; /* file type */ 377 Elf_Void *ed_ehdr; /* Elf{32,64}_Ehdr elf header */ 378 Elf_Void *ed_phdr; /* Elf{32,64}_Phdr phdr table */ 379 size_t ed_phdrsz; /* sizeof phdr table */ 380 Elf_Void *ed_shdr; /* Elf{32,64}_Shdr shdr table */ 381 Elf_Scn *ed_hdscn; /* head scn */ 382 Elf_Scn *ed_tlscn; /* tail scn */ 383 size_t ed_scntabsz; /* number sects. alloc. in table */ 384 Memlist *ed_memlist; /* list of archive member nodes */ 385 Member *ed_armem; /* archive member header */ 386 Elf_Void *ed_arsym; /* archive symbol table */ 387 size_t ed_arsymsz; /* archive symbol table size */ 388 size_t ed_arsymoff; /* archive symbol table hdr offset */ 389 char *ed_arstr; /* archive string table */ 390 size_t ed_arstrsz; /* archive string table size */ 391 size_t ed_arstroff; /* archive string table hdr offset */ 392 unsigned ed_myflags; /* EDF_... */ 393 unsigned ed_ehflags; /* ehdr flags */ 394 unsigned ed_phflags; /* phdr flags */ 395 unsigned ed_uflags; /* elf descriptor flags */ 396}; 397 398NOTE(RWLOCK_PROTECTS_DATA(Elf::ed_rwlock, Elf)) 399NOTE(RWLOCK_COVERS_LOCKS(Elf::ed_rwlock, Elf_Scn::s_mutex)) 400 401#ifdef __lock_lint 402#define ELFRLOCK(e) (void) rw_rdlock(&((Elf *)e)->ed_rwlock); 403#else 404#define ELFRLOCK(e) \ 405 if (elf_threaded) \ 406 (void) rw_rdlock(&((Elf *)e)->ed_rwlock); 407#endif 408 409#ifdef __lock_lint 410#define ELFWLOCK(e) (void) rw_wrlock(&((Elf *)e)->ed_rwlock); 411#else 412#define ELFWLOCK(e) \ 413 if (elf_threaded) \ 414 (void) rw_wrlock(&((Elf *)e)->ed_rwlock); 415#endif 416 417#ifdef __lock_lint 418#define ELFUNLOCK(e) (void) rw_unlock(&((Elf *)e)->ed_rwlock); 419#else 420#define ELFUNLOCK(e) \ 421 if (elf_threaded) \ 422 (void) rw_unlock(&((Elf *)e)->ed_rwlock); 423#endif 424 425#define EDF_ASALLOC 0x1 /* applies to ed_arsym */ 426#define EDF_EHALLOC 0x2 /* applies to ed_ehdr */ 427#define EDF_PHALLOC 0x4 /* applies to ed_phdr */ 428#define EDF_SHALLOC 0x8 /* applies to ed_shdr */ 429#define EDF_COFFAOUT 0x10 /* original file was coff a.out */ 430#define EDF_RAWALLOC 0x20 /* applies to ed_raw */ 431#define EDF_READ 0x40 /* file can be read */ 432#define EDF_WRITE 0x80 /* file can be written */ 433#define EDF_MEMORY 0x100 /* file opened via elf_memory() */ 434#define EDF_ASTRALLOC 0x200 /* applies to ed_arstr */ 435#define EDF_MPROTECT 0x400 /* applies to slideable archives */ 436#define EDF_IMALLOC 0x800 /* wrimage dynamically allocated */ 437#define EDF_WRALLOC 0x1000 /* wrimage is to by dyn allocated */ 438#define EDF_RDKERNTYPE 0x2000 /* When Mach-o is fat, choose member matching the running kernel. */ 439 440 441typedef enum 442{ 443 OK_YES = 0, 444 OK_NO = ~0 445} Okay; 446 447#define _(a) a 448 449/* 450 * Max size for an Elf error message string 451 */ 452#define MAXELFERR 1024 453 454/* 455 * General thread management macros 456 */ 457#ifdef __lock_lint 458#define ELFACCESSDATA(a, b) \ 459 (void) mutex_lock(&_elf_globals_mutex); \ 460 a = b; \ 461 (void) mutex_unlock(&_elf_globals_mutex); 462#else 463#define ELFACCESSDATA(a, b) \ 464 if (elf_threaded) { \ 465 (void) mutex_lock(&_elf_globals_mutex); \ 466 a = b; \ 467 (void) mutex_unlock(&_elf_globals_mutex); \ 468 } else \ 469 a = b; 470#endif 471 472#ifdef __lock_lint 473#define ELFRWLOCKINIT(lock) \ 474 (void) rwlock_init((lock), USYNC_THREAD, 0); 475#else 476#define ELFRWLOCKINIT(lock) \ 477 if (elf_threaded) { \ 478 (void) rwlock_init((lock), USYNC_THREAD, 0); \ 479 } 480#endif 481 482#ifdef __lock_lint 483#define ELFMUTEXINIT(lock) \ 484 (void) mutex_init(lock, USYNC_THREAD, 0); 485#else 486#define ELFMUTEXINIT(lock) \ 487 if (elf_threaded) { \ 488 (void) mutex_init(lock, USYNC_THREAD, 0); \ 489 } 490#endif 491 492 493extern Member *_elf_armem(Elf *, char *, size_t); 494extern void _elf_arinit(Elf *); 495extern Okay _elf_cook(Elf *); 496extern Okay _elf_cookscn(Elf_Scn * s); 497extern Okay _elf32_cookscn(Elf_Scn * s); 498extern Okay _elf64_cookscn(Elf_Scn * s); 499extern Dnode *_elf_dnode(void); 500extern Elf_Data *_elf_locked_getdata(Elf_Scn *, Elf_Data *); 501extern size_t _elf32_entsz(Elf *elf, Elf32_Word, unsigned); 502extern size_t _elf64_entsz(Elf *elf, Elf64_Word, unsigned); 503extern Okay _elf_inmap(Elf *); 504extern char *_elf_outmap(int, size_t, unsigned *); 505extern size_t _elf_outsync(int, char *, size_t, unsigned); 506extern size_t _elf32_msize(Elf_Type, unsigned); 507extern size_t _elf64_msize(Elf_Type, unsigned); 508extern Elf_Type _elf32_mtype(Elf *, Elf32_Word, unsigned); 509extern Elf_Type _elf64_mtype(Elf *, Elf64_Word, unsigned); 510extern char *_elf_read(int, off_t, size_t); 511extern Snode32 *_elf32_snode(void); 512extern Snode64 *_elf64_snode(void); 513extern void _elf_unmap(char *, size_t); 514extern Okay _elf_vm(Elf *, size_t, size_t); 515extern int _elf32_ehdr(Elf *, int); 516extern int _elf32_phdr(Elf *, int); 517extern int _elf32_shdr(Elf *, int); 518extern int _elf64_ehdr(Elf *, int); 519extern int _elf64_phdr(Elf *, int); 520extern int _elf64_shdr(Elf *, int); 521extern int _elf_byte; 522extern const Elf32_Ehdr _elf32_ehdr_init; 523extern const Elf64_Ehdr _elf64_ehdr_init; 524extern unsigned _elf_encode; 525extern void _elf_seterr(Msg, int); 526extern const Snode32 _elf32_snode_init; 527extern const Snode64 _elf64_snode_init; 528extern const Dnode _elf_dnode_init; 529extern unsigned _elf_work; 530extern mutex_t _elf_globals_mutex; 531extern off_t _elf64_update(Elf * elf, Elf_Cmd cmd); 532extern int _elf64_swap_wrimage(Elf *elf); 533 534/* CSTYLED */ 535NOTE(MUTEX_PROTECTS_DATA(_elf_globals_mutex, \ 536 _elf_byte _elf32_ehdr_init _elf64_ehdr_init _elf_encode \ 537 _elf_snode_init _elf_work)) 538 539#ifdef __cplusplus 540} 541#endif 542 543#endif /* _DECL_H */ 544