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