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