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