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 2008 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#pragma ident	"@(#)decl.h	1.23	08/03/18 SMI" 	/* SVr4.0 1.9	*/
34
35#define SEG_CTF "__CTF"
36#define SECT_CTF "__ctf"
37
38#include <pthread.h> /* In lieu of Solaris <thread.h> */
39#define USYNC_THREAD IGNORED /* Take PTHREAD_PROCESS_PRIVATE default in pthread_*_init() */
40#define DEFAULTMUTEX PTHREAD_MUTEX_INITIALIZER
41
42typedef pthread_mutex_t mutex_t;
43typedef pthread_rwlock_t rwlock_t;
44typedef pthread_key_t thread_key_t;
45
46#define RW_LOCK_HELD(x) 1 /* Only used in "assert" */
47#define MUTEX_HELD(x) 1 /* Only used in "assert" */
48
49#define rwlock_init(x,y,z) pthread_rwlock_init(x,((const pthread_rwlockattr_t *)NULL))
50#define rw_rdlock(x) pthread_rwlock_rdlock(x)
51#define rw_wrlock(x) pthread_rwlock_wrlock(x)
52#define rw_unlock(x) pthread_rwlock_unlock(x)
53
54#define mutex_init(x,y,z) pthread_mutex_init(x,((const pthread_mutexattr_t *)NULL))
55#define mutex_lock(x) pthread_mutex_lock(x)
56#define mutex_unlock(x) pthread_mutex_unlock(x)
57
58#define NOTE(x) /* NOTHING */ /* In lieu of Solaris #include <note.h> */
59
60#include <libelf.h>
61#include "machelf.h" /* In lieu of Solaris <sys/machelf.h> */
62#include <gelf.h>
63#include <msg.h>
64
65#include <unistd.h>
66#define PAGESIZE getpagesize()
67
68#define SHT_SPARC_GOTDATA -1
69#define SHT_AMD64_UNWIND -1
70
71#define SWAP16(v)		v = OSSwapInt16(v)
72#define SWAP32(v)		v = OSSwapInt32(v)
73#define SWAP64(v)		v = OSSwapInt64(v)
74
75#include <mach-o/loader.h>
76extern void __swap_mach_header(struct mach_header *);
77extern void __swap_mach_header_64(struct mach_header_64 *);
78extern void __swap_segment_command(struct segment_command *);
79extern void __swap_segment_command_64(struct segment_command_64 *);
80extern void __swap_section(struct section *);
81extern void __swap_section_64(struct section_64 *);
82extern void __swap_symtab_command(struct symtab_command *);
83
84#ifdef	__cplusplus
85extern "C" {
86#endif
87
88typedef struct Member	Member;
89typedef struct Memlist	Memlist;
90typedef struct Memident	Memident;
91typedef struct Dnode	Dnode;
92typedef struct Snode32	Snode32;
93typedef struct Snode64	Snode64;
94
95
96/*
97 * Data alignment
98 *	An elf file is defined to have its structures aligned on
99 *	appropriate boundaries.  The following type lets the
100 *	library test whether the file's alignment meets its own
101 *	constraints in memory.  This assumes every machine uses
102 *	an alignment that is no greater than an object's size.
103 *	The pointer isn't relevant for the file, but the code uses
104 *	it to get memory alignment.  ANSI C void * holds any pointer,
105 *	making it appropriate here.
106 */
107
108typedef union
109{
110	Elf32_Word	w;
111	Elf32_Addr	a;
112	Elf32_Off	o;
113} Elf32;
114
115typedef union {
116	Elf64_Xword	x;
117	Elf64_Word	w;
118	Elf64_Addr	a;
119	Elf64_Off	o;
120	Elf_Void	*p;
121} Elf64;
122
123
124/*
125 * Memory allocation
126 *	Structures are obtained several ways: file mapping,
127 *	malloc(), from the user.  A status bit in the structures
128 *	tells whether an object was obtained with malloc() and
129 *	therefore should be released with free().  The bits
130 *	named ...ALLOC indicate this.
131 */
132
133
134/*
135 * Data descriptor
136 *	db_data must be first in the Dnode structure, because
137 *	&db_data must == &Dnode.
138 *
139 *	db_buf is a pointer to an allocated buffer.  The same value
140 *	goes into db_data.d_buf originally, but the user can touch
141 *	it.  If the data buffer is not to be freed, db_buf is null.
142 *
143 *	When "reading" an input file's buffer, the data are left
144 *	alone until needed.  When they've been converted to internal
145 *	form, the READY flag is set.
146 *
147 *	db_raw points to a parallel raw buffer.  Raw buffers
148 *	have null db_raw.
149 */
150
151struct	Dnode
152{
153	Elf_Data	db_data;
154	Elf_Scn		*db_scn;	/* section parent */
155	Dnode		*db_next;
156	Dnode		*db_raw;	/* raw data */
157	off_t		db_off;		/* orig file offset, 0 o/w */
158	size_t		db_fsz;		/* orig file size, 0 o/w */
159	size_t		db_shsz;	/* orig shdr size, 0 o/w */
160	size_t		db_osz;		/* output size for update */
161	Elf_Void	*db_buf;	/* allocated data buffer */
162	unsigned	db_uflags;	/* user flags: ELF_F_... */
163	unsigned	db_myflags;	/* internal flags: DBF_... */
164	Elf64_Off	db_xoff;	/* extended offset for 32-bit Elf64 */
165};
166
167#define	DBF_ALLOC	0x1	/* applies to Dnode itself */
168#define	DBF_READY	0x2	/* buffer ready */
169
170
171/*
172 * Section descriptor
173 *	These are sometimes allocated in a block.  If the SF_ALLOC
174 *	bit is set in the flags, the Scn address may be passed to free.
175 *	The caller must first follow the s_next list to the next freeable
176 *	node, because free can clobber the s_next value in the block.
177 */
178
179struct	Elf_Scn
180{
181	mutex_t		s_mutex;
182	Elf_Scn		*s_next;	/* next section */
183	Elf		*s_elf; 	/* parent file */
184	Dnode		*s_hdnode;	/* head Dnode */
185	Dnode		*s_tlnode;	/* tail Dnode */
186	Elf_Void	*s_shdr;	/* Elf32 or Elf64 scn header */
187	size_t		s_index;	/* section index */
188	int		s_err;		/* for delaying data error */
189	unsigned	s_shflags;	/* user shdr flags */
190	unsigned	s_uflags;	/* user flags */
191	unsigned	s_myflags;	/* SF_... */
192	Dnode		s_dnode;	/* every scn needs one */
193};
194
195NOTE(MUTEX_PROTECTS_DATA(Elf_Scn::s_mutex, Elf_Scn Dnode Elf_Data))
196NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf_Data))
197NOTE(SCHEME_PROTECTS_DATA("Scn lock held", Elf32_Shdr Elf32_Sym))
198NOTE(READ_ONLY_DATA(Elf_Scn::s_elf))
199NOTE(READ_ONLY_DATA(Dnode::db_scn))
200
201
202/*
203 * Designates whether or not we are in a threaded_app.
204 */
205extern int *_elf_libc_threaded;
206#define	elf_threaded	(_elf_libc_threaded && *_elf_libc_threaded)
207
208#ifdef	__lock_lint
209#define	SCNLOCK(x)	(void) mutex_lock(&((Elf_Scn *)x)->s_mutex);
210#else
211#define	SCNLOCK(x) \
212	if (elf_threaded) \
213		(void) mutex_lock(&((Elf_Scn *)x)->s_mutex);
214#endif
215
216#ifdef	__lock_lint
217#define	SCNUNLOCK(x)	(void) mutex_unlock(&((Elf_Scn *)x)->s_mutex);
218#else
219#define	SCNUNLOCK(x) \
220	if (elf_threaded) \
221		(void) mutex_unlock(&((Elf_Scn *)x)->s_mutex);
222#endif
223
224#ifdef	__lock_lint
225#define	UPGRADELOCKS(e, s)\
226		(void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \
227		(void) rw_unlock(&((Elf *)e)->ed_rwlock); \
228		(void) rw_wrlock(&((Elf *)e)->ed_rwlock);
229#else
230#define	UPGRADELOCKS(e, s)\
231	if (elf_threaded) { \
232		(void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \
233		(void) rw_unlock(&((Elf *)e)->ed_rwlock); \
234		(void) rw_wrlock(&((Elf *)e)->ed_rwlock); \
235	}
236#endif
237
238#ifdef	__lock_lint
239#define	DOWNGRADELOCKS(e, s)\
240		(void) rw_unlock(&((Elf *)e)->ed_rwlock); \
241		(void) rw_rdlock(&((Elf *)e)->ed_rwlock); \
242		(void) mutex_lock(&((Elf_Scn *)s)->s_mutex);
243#else
244#define	DOWNGRADELOCKS(e, s)\
245	if (elf_threaded) { \
246		(void) rw_unlock(&((Elf *)e)->ed_rwlock); \
247		(void) rw_rdlock(&((Elf *)e)->ed_rwlock); \
248		(void) mutex_lock(&((Elf_Scn *)s)->s_mutex); \
249	}
250#endif
251
252#ifdef	__lock_lint
253#define	READLOCKS(e, s) \
254		(void) rw_rdlock(&((Elf *)e)->ed_rwlock); \
255		(void) mutex_lock(&((Elf_Scn *)s)->s_mutex);
256#else
257#define	READLOCKS(e, s) \
258	if (elf_threaded) { \
259		(void) rw_rdlock(&((Elf *)e)->ed_rwlock); \
260		(void) mutex_lock(&((Elf_Scn *)s)->s_mutex); \
261	}
262#endif
263
264#ifdef	__lock_lint
265#define	READUNLOCKS(e, s) \
266		(void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \
267		(void) rw_unlock(&((Elf *)e)->ed_rwlock);
268#else
269#define	READUNLOCKS(e, s) \
270	if (elf_threaded) { \
271		(void) mutex_unlock(&((Elf_Scn *)s)->s_mutex); \
272		(void) rw_unlock(&((Elf *)e)->ed_rwlock); \
273	}
274#endif
275
276
277
278
279#define	SF_ALLOC	0x1	/* applies to Scn */
280#define	SF_READY	0x2	/* has section been cooked */
281
282
283struct	Snode32
284{
285	Elf_Scn		sb_scn;		/* must be first */
286	Elf32_Shdr	sb_shdr;
287};
288
289struct	Snode64
290{
291	Elf_Scn		sb_scn;		/* must be first */
292	Elf64_Shdr	sb_shdr;
293};
294
295
296/*
297 *	A file's status controls how the library can use file data.
298 *	This is important to keep "raw" operations and "cooked"
299 *	operations from interfering with each other.
300 *
301 *	A file's status is "fresh" until something touches it.
302 *	If the first thing is a raw operation, we freeze the data
303 *	and force all cooking operations to make a copy.  If the
304 *	first operation cooks, raw operations use the file system.
305 */
306
307typedef enum
308{
309	ES_FRESH = 0,	/* unchanged */
310	ES_COOKED,	/* translated */
311	ES_FROZEN	/* raw, can't be translated */
312} Status;
313
314
315/*
316 * Elf descriptor
317 *	The major handle between user code and the library.
318 *
319 *	Descriptors can have parents: archive members reference
320 *	the archive itself.  Relevant "offsets:"
321 *
322 *	ed_baseoff	The file offset, relative to zero, to the first
323 *			byte in the file.  For all files, this gives
324 *			the lseek(fd, ed_baseoff, 0) value.
325 *
326 *	ed_memoff	The offset from the beginning of the nesting file
327 *			to the bytes of a member.  For an archive member,
328 *			this is the offset from the beginning of the
329 *			archive to the member bytes (not the hdr).  If an
330 *			archive member slides, memoff changes.
331 *
332 *	ed_siboff	Similar to ed_memoff, this gives the offset from
333 *			the beginning of the nesting file to the following
334 *			sibling's header (not the sibling's bytes).  This
335 *			value is necessary, because of archive sliding.
336 *
337 *	ed_nextoff	For an archive, this gives the offset of the next
338 *			member to process on elf_begin.  That is,
339 *			(ed_ident + ed_nextoff) gives pointer to member hdr.
340 *
341 *	Keeping these absolute and relative offsets allows nesting of
342 *	files, including archives within archives, etc.  The only current
343 *	nesting file is archive, but others might be supported.
344 *
345 *	ed_image	This is a pointer to the base memory image holding
346 *			the file.  Library code assumes the image is aligned
347 *			to a boundary appropriate for any object.  This must
348 *			be true, because we get an image only from malloc
349 *			or mmap, both of which guarantee alignment.
350 */
351
352struct Elf
353{
354	rwlock_t	ed_rwlock;
355	Elf		*ed_parent;	/* archive parent */
356	int		ed_activ;	/* activation count */
357	int		ed_fd;		/* file descriptor */
358	Status		ed_status;	/* file's memory status */
359	off_t		ed_baseoff;	/* base file offset, zero based */
360	size_t		ed_memoff;	/* offset within archive */
361	size_t		ed_siboff;	/* sibling offset with archive */
362	size_t		ed_nextoff;	/* next archive member hdr offset */
363	char		*ed_image;	/* pointer to file image */
364	size_t		ed_imagesz;	/* # bytes in ed_image */
365	char		*ed_wrimage;	/* pointer to output image */
366	size_t		ed_wrimagesz;	/* # bytes in ed_wrimagesz */
367	char		*ed_ident;	/* file start, getident() bytes */
368	size_t		ed_identsz;	/* # bytes for getident() */
369	char		*ed_raw;	/* raw file ptr */
370	size_t		ed_fsz;		/* file size */
371	unsigned	*ed_vm;		/* virtual memory map */
372	size_t		ed_vmsz;	/* # regions in vm */
373	unsigned	ed_encode;	/* data encoding */
374	unsigned	ed_version;	/* file version */
375	int		ed_class;	/* file class */
376	Elf_Kind	ed_kind;	/* file type */
377	Elf_Void	*ed_ehdr;	/* Elf{32,64}_Ehdr elf header */
378	Elf_Void	*ed_phdr;	/* Elf{32,64}_Phdr phdr table */
379	size_t		ed_phdrsz;	/* sizeof phdr table */
380	Elf_Void	*ed_shdr;	/* Elf{32,64}_Shdr shdr table */
381	Elf_Scn		*ed_hdscn;	/* head scn */
382	Elf_Scn		*ed_tlscn;	/* tail scn */
383	size_t		ed_scntabsz;	/* number sects. alloc. in table */
384	Memlist		*ed_memlist;	/* list of archive member nodes */
385	Member		*ed_armem;	/* archive member header */
386	Elf_Void	*ed_arsym;	/* archive symbol table */
387	size_t		ed_arsymsz;	/* archive symbol table size */
388	size_t		ed_arsymoff;	/* archive symbol table hdr offset */
389	char		*ed_arstr;	/* archive string table */
390	size_t		ed_arstrsz;	/* archive string table size */
391	size_t		ed_arstroff;	/* archive string table hdr offset */
392	unsigned	ed_myflags;	/* EDF_... */
393	unsigned	ed_ehflags;	/* ehdr flags */
394	unsigned	ed_phflags;	/* phdr flags */
395	unsigned	ed_uflags;	/* elf descriptor flags */
396};
397
398NOTE(RWLOCK_PROTECTS_DATA(Elf::ed_rwlock, Elf))
399NOTE(RWLOCK_COVERS_LOCKS(Elf::ed_rwlock, Elf_Scn::s_mutex))
400
401#ifdef	__lock_lint
402#define	ELFRLOCK(e)	(void) rw_rdlock(&((Elf *)e)->ed_rwlock);
403#else
404#define	ELFRLOCK(e) \
405	if (elf_threaded) \
406		(void) rw_rdlock(&((Elf *)e)->ed_rwlock);
407#endif
408
409#ifdef	__lock_lint
410#define	ELFWLOCK(e)	(void) rw_wrlock(&((Elf *)e)->ed_rwlock);
411#else
412#define	ELFWLOCK(e) \
413	if (elf_threaded) \
414		(void) rw_wrlock(&((Elf *)e)->ed_rwlock);
415#endif
416
417#ifdef	__lock_lint
418#define	ELFUNLOCK(e)	(void) rw_unlock(&((Elf *)e)->ed_rwlock);
419#else
420#define	ELFUNLOCK(e) \
421	if (elf_threaded) \
422		(void) rw_unlock(&((Elf *)e)->ed_rwlock);
423#endif
424
425#define	EDF_ASALLOC	0x1	/* applies to ed_arsym */
426#define	EDF_EHALLOC	0x2	/* applies to ed_ehdr */
427#define	EDF_PHALLOC	0x4	/* applies to ed_phdr */
428#define	EDF_SHALLOC	0x8	/* applies to ed_shdr */
429#define	EDF_COFFAOUT	0x10	/* original file was coff a.out */
430#define	EDF_RAWALLOC	0x20	/* applies to ed_raw */
431#define	EDF_READ	0x40	/* file can be read */
432#define	EDF_WRITE	0x80	/* file can be written */
433#define	EDF_MEMORY	0x100	/* file opened via elf_memory() */
434#define	EDF_ASTRALLOC	0x200	/* applies to ed_arstr */
435#define	EDF_MPROTECT	0x400	/* applies to slideable archives */
436#define	EDF_IMALLOC	0x800	/* wrimage dynamically allocated */
437#define	EDF_WRALLOC	0x1000	/* wrimage is to by dyn allocated */
438#define	EDF_RDKERNTYPE	0x2000	/* When Mach-o is fat, choose member matching the running kernel. */
439
440
441typedef enum
442{
443	OK_YES = 0,
444	OK_NO = ~0
445} Okay;
446
447#define	_(a)		a
448
449/*
450 * Max size for an Elf error message string
451 */
452#define	MAXELFERR	1024
453
454/*
455 * General thread management macros
456 */
457#ifdef __lock_lint
458#define	ELFACCESSDATA(a, b) \
459	(void) mutex_lock(&_elf_globals_mutex); \
460	a = b; \
461	(void) mutex_unlock(&_elf_globals_mutex);
462#else
463#define	ELFACCESSDATA(a, b) \
464	if (elf_threaded) { \
465		(void) mutex_lock(&_elf_globals_mutex); \
466		a = b; \
467		(void) mutex_unlock(&_elf_globals_mutex); \
468	} else \
469		a = b;
470#endif
471
472#ifdef __lock_lint
473#define	ELFRWLOCKINIT(lock) \
474	(void) rwlock_init((lock), USYNC_THREAD, 0);
475#else
476#define	ELFRWLOCKINIT(lock) \
477	if (elf_threaded) { \
478		(void) rwlock_init((lock), USYNC_THREAD, 0); \
479	}
480#endif
481
482#ifdef	__lock_lint
483#define	ELFMUTEXINIT(lock) \
484	(void) mutex_init(lock, USYNC_THREAD, 0);
485#else
486#define	ELFMUTEXINIT(lock) \
487	if (elf_threaded) { \
488		(void) mutex_init(lock, USYNC_THREAD, 0); \
489	}
490#endif
491
492
493extern Member		*_elf_armem(Elf *, char *, size_t);
494extern void		_elf_arinit(Elf *);
495extern Okay		_elf_cook(Elf *);
496extern Okay		_elf_cookscn(Elf_Scn * s);
497extern Okay		_elf32_cookscn(Elf_Scn * s);
498extern Okay		_elf64_cookscn(Elf_Scn * s);
499extern Dnode		*_elf_dnode(void);
500extern Elf_Data		*_elf_locked_getdata(Elf_Scn *, Elf_Data *);
501extern size_t		_elf32_entsz(Elf *elf, Elf32_Word, unsigned);
502extern size_t		_elf64_entsz(Elf *elf, Elf64_Word, unsigned);
503extern Okay		_elf_inmap(Elf *);
504extern char		*_elf_outmap(int, size_t, unsigned *);
505extern size_t		_elf_outsync(int, char *, size_t, unsigned);
506extern size_t		_elf32_msize(Elf_Type, unsigned);
507extern size_t		_elf64_msize(Elf_Type, unsigned);
508extern Elf_Type		_elf32_mtype(Elf *, Elf32_Word, unsigned);
509extern Elf_Type		_elf64_mtype(Elf *, Elf64_Word, unsigned);
510extern char		*_elf_read(int, off_t, size_t);
511extern Snode32		*_elf32_snode(void);
512extern Snode64		*_elf64_snode(void);
513extern void		_elf_unmap(char *, size_t);
514extern Okay		_elf_vm(Elf *, size_t, size_t);
515extern int		_elf32_ehdr(Elf *, int);
516extern int		_elf32_phdr(Elf *, int);
517extern int		_elf32_shdr(Elf *, int);
518extern int		_elf64_ehdr(Elf *, int);
519extern int		_elf64_phdr(Elf *, int);
520extern int		_elf64_shdr(Elf *, int);
521extern int		_elf_byte;
522extern const Elf32_Ehdr	_elf32_ehdr_init;
523extern const Elf64_Ehdr	_elf64_ehdr_init;
524extern unsigned		_elf_encode;
525extern void		_elf_seterr(Msg, int);
526extern const Snode32	_elf32_snode_init;
527extern const Snode64	_elf64_snode_init;
528extern const Dnode	_elf_dnode_init;
529extern unsigned		_elf_work;
530extern mutex_t		_elf_globals_mutex;
531extern off_t		_elf64_update(Elf * elf, Elf_Cmd cmd);
532extern int		_elf64_swap_wrimage(Elf *elf);
533
534/* CSTYLED */
535NOTE(MUTEX_PROTECTS_DATA(_elf_globals_mutex, \
536	_elf_byte _elf32_ehdr_init _elf64_ehdr_init _elf_encode \
537	_elf_snode_init _elf_work))
538
539#ifdef	__cplusplus
540}
541#endif
542
543#endif	/* _DECL_H */
544