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