xref: /illumos-gate/usr/src/cmd/sgs/libelf/common/decl.h (revision 7c478bd9)
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