decl.h revision 12792:1f56a791e275
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
40extern "C" {
41#endif
42
43typedef struct Member	Member;
44typedef struct Memlist	Memlist;
45typedef struct Memident	Memident;
46typedef struct Dnode	Dnode;
47typedef struct Snode32	Snode32;
48typedef 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
63typedef union
64{
65	Elf32_Word	w;
66	Elf32_Addr	a;
67	Elf32_Off	o;
68} Elf32;
69
70typedef 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
106struct	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
134struct	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
150NOTE(MUTEX_PROTECTS_DATA(Elf_Scn::s_mutex, Elf_Scn Dnode Elf_Data))
151NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf_Data))
152NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf32_Shdr Elf32_Sym))
153NOTE(READ_ONLY_DATA(Elf_Scn::s_elf))
154NOTE(READ_ONLY_DATA(Dnode::db_scn))
155
156
157/*
158 * Designates whether or not we are in a threaded_app.
159 */
160extern 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
238struct	Snode32
239{
240	Elf_Scn		sb_scn;		/* must be first */
241	Elf32_Shdr	sb_shdr;
242};
243
244struct	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
262typedef 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
307struct 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
353NOTE(RWLOCK_PROTECTS_DATA(Elf::ed_rwlock, Elf))
354NOTE(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
396typedef 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
448extern Member		*_elf_armem(Elf *, char *, size_t);
449extern void		_elf_arinit(Elf *);
450extern Okay		_elf_cook(Elf *);
451extern Okay		_elf_cookscn(Elf_Scn * s);
452extern Okay		_elf32_cookscn(Elf_Scn * s);
453extern Okay		_elf64_cookscn(Elf_Scn * s);
454extern Dnode		*_elf_dnode(void);
455extern Elf_Data		*_elf_locked_getdata(Elf_Scn *, Elf_Data *);
456extern size_t		_elf32_entsz(Elf *elf, Elf32_Word, unsigned);
457extern size_t		_elf64_entsz(Elf *elf, Elf64_Word, unsigned);
458extern Okay		_elf_inmap(Elf *);
459extern char		*_elf_outmap(int, size_t, unsigned *);
460extern size_t		_elf_outsync(int, char *, size_t, unsigned);
461extern size_t		_elf32_msize(Elf_Type, unsigned);
462extern size_t		_elf64_msize(Elf_Type, unsigned);
463extern Elf_Type		_elf32_mtype(Elf *, Elf32_Word, unsigned);
464extern Elf_Type		_elf64_mtype(Elf *, Elf64_Word, unsigned);
465extern char		*_elf_read(int, off_t, size_t);
466extern Snode32		*_elf32_snode(void);
467extern Snode64		*_elf64_snode(void);
468extern void		_elf_unmap(char *, size_t);
469extern Okay		_elf_vm(Elf *, size_t, size_t);
470extern int		_elf32_ehdr(Elf *, int);
471extern int		_elf32_phdr(Elf *, int);
472extern int		_elf32_shdr(Elf *, int);
473extern int		_elf64_ehdr(Elf *, int);
474extern int		_elf64_phdr(Elf *, int);
475extern int		_elf64_shdr(Elf *, int);
476extern int		_elf_byte;
477extern const Elf32_Ehdr	_elf32_ehdr_init;
478extern const Elf64_Ehdr	_elf64_ehdr_init;
479extern unsigned		_elf_encode;
480extern _elf_execfill_func_t *_elf_execfill_func;
481extern void		_elf_seterr(Msg, int);
482extern const Snode32	_elf32_snode_init;
483extern const Snode64	_elf64_snode_init;
484extern const Dnode	_elf_dnode_init;
485extern unsigned		_elf_work;
486extern mutex_t		_elf_globals_mutex;
487extern off_t		_elf64_update(Elf * elf, Elf_Cmd cmd);
488extern int		_elf64_swap_wrimage(Elf *elf);
489
490/* CSTYLED */
491NOTE(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