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