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