summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/rtld/common/_a.out.h
blob: 0924f01af02e0c339aa6a5a9821e0b1bbf19d886 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
/*
 * CDDL HEADER START
 *
 * The contents of this file are subject to the terms of the
 * Common Development and Distribution License (the "License").
 * You may not use this file except in compliance with the License.
 *
 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
 * or http://www.opensolaris.org/os/licensing.
 * See the License for the specific language governing permissions
 * and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL HEADER in each
 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
 * If applicable, add the following below this CDDL HEADER, with the
 * fields enclosed by brackets "[]" replaced with your own identifying
 * information: Portions Copyright [yyyy] [name of copyright owner]
 *
 * CDDL HEADER END
 */

/*
 * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
 */
#ifndef	_A_DOT_OUT_DOT_H
#define	_A_DOT_OUT_DOT_H

#include <sys/types.h>
#include <sys/null.h>
#include <sys/mman.h>
#include <a.out.h>
#include <_rtld.h>

#ifdef	__cplusplus
extern "C" {
#endif

#define	max(a, b)	((a) < (b) ? (b) : (a))

typedef struct link_dynamic	Link_dynamic;

/*
 * Extern functions for a.out format file class.
 */
extern	ulong_t	aout_bndr(caddr_t);
extern	int	aout_get_mmap(Lm_list *, mmapobj_result_t *);
extern	int	aout_lookup_sym(Slookup *, Sresult *, uint_t *, int *);
extern	Rt_map	*aout_new_lmp(Lm_list *, Aliste, Fdesc *, Addr, size_t, void *,
		    Rt_map *, int *);
extern	void	aout_plt_write(caddr_t, ulong_t);
extern	int	aout_reloc(Rt_map *, uint_t, int *, APlist **);
extern	void	aout_rtbndr(caddr_t);
extern	Fct	*aout_verify(caddr_t, size_t, Fdesc *, const char *,
		    Rej_desc *);

/*
 * Private data for an a.out format file class.
 */
typedef struct _rt_aout_private {
	struct link_dynamic	*lm_ld;		/* 4.x aout dynamic pointer */
	struct ld_private	*lm_lpd;	/* private aout object area */
} Rt_aoutp;

/*
 * Special defines for a.out format file class.
 */
#define	N_UNDF	0x0		/* undefined */
#define	N_ABS	0x2		/* absolute */
#define	N_COMM	0x12		/* common (internal to ld) */
#define	N_EXT	01		/* external bit, or'ed in */

/*
 * Format of a symbol table entry.
 */
struct	nlist {
	union {
		char	*n_name;		/* for use when in-core */
		long	n_strx;		/* index into file string table */
	} n_un;
	uchar_t 	n_type;		/* type flag (N_TEXT,..)  */
	char		n_other;	/* unused */
	short		n_desc;		/* see <stab.h> */
	ulong_t		n_value;	/* value of symbol (or sdb offset) */
};

/*
 * Link editor public definitions.
 */

#ifndef _link_h
#define	_link_h

/*
 * Structure describing logical name and requirements on an object
 * which is to be loaded dynamically.
 */
struct old_link_object {
	char	*lo_name;		/* name of object */
	int	lo_library : 1,		/* searched for by library rules */
		lo_unused : 31;
	short	lo_major;		/* major version number */
	short	lo_minor;		/* minor version number */
};

struct link_object {
	long	lo_name;		/* name (often relative) */
	int	lo_library : 1,		/* searched for by library rules */
		lo_unused : 31;
	short	lo_major;		/* major version number */
	short	lo_minor;		/* minor version number */
	long	lo_next;		/* next one (often relative) */
};
typedef	struct	link_object Lnk_obj;

/*
 * Structure describing name and placement of dynamically loaded
 * objects in a process' address space.
 */
typedef struct a_link_map	A_link_map;

struct a_link_map {
	caddr_t	lm_addr;		/* address at which object mapped */
	char	*lm_name;		/* full name of loaded object */
	struct	a_link_map *lm_next;	/* next object in map */
	struct	link_object *lm_lop;	/* link object that got us here */
	caddr_t lm_lob;			/* base address for said link object */
	int	lm_rwt : 1;		/* text is read/write */
	struct	link_dynamic *lm_ld;	/* dynamic structure */
	caddr_t	lm_lpd;			/* loader private data */
};

/*
 * Version 1 of dynamic linking information.  With the exception of
 * ld_loaded (determined at execution time) and ld_stab_hash (a special
 * case of relocation handled at execution time), the values in this
 * structure reflect offsets from the containing link_dynamic structure.
 */
struct link_dynamic_1 {
	struct	a_link_map *ld_loaded;	/* list of loaded objects */
	long	ld_need;		/* list of needed objects */
	long	ld_rules;		/* search rules for library objects */
	long	ld_got;			/* global offset table */
	long	ld_plt;			/* procedure linkage table */
	long	ld_rel;			/* relocation table */
	long	ld_hash;		/* symbol hash table */
	long	ld_stab;		/* symbol table itself */
	long	(*ld_stab_hash)();	/* "pointer" to symbol hash function */
	long	ld_buckets;		/* number of hash buckets */
	long	ld_symbols;		/* symbol strings */
	long	ld_symb_size;		/* size of symbol strings */
	long	ld_text;		/* size of text area */
};

struct link_dynamic_2 {
	struct	a_link_map *ld_loaded;	/* list of loaded objects */
	long	ld_need;		/* list of needed objects */
	long	ld_rules;		/* search rules for library objects */
	long	ld_got;			/* global offset table */
	long	ld_plt;			/* procedure linkage table */
	long	ld_rel;			/* relocation table */
	long	ld_hash;		/* symbol hash table */
	long	ld_stab;		/* symbol table itself */
	long	(*ld_stab_hash)();	/* "pointer" to symbol hash function */
	long	ld_buckets;		/* number of hash buckets */
	long	ld_symbols;		/* symbol strings */
	long	ld_symb_size;		/* size of symbol strings */
	long	ld_text;		/* size of text area */
	long	ld_plt_sz;		/* size of procedure linkage table */
};

/*
 * Structure pointing to run time allocated common symbols and
 * its string.
 */
struct rtc_symb {
	struct	nlist *rtc_sp;		/* symbol for common */
	struct	rtc_symb *rtc_next;	/* next common */
};

/*
 * Debugger interface structure.
 */
struct 	ld_debug {
	int	ldd_version;		/* version # of interface */
	int	ldd_in_debugger;	/* a debugger is running us */
	int	ldd_sym_loaded;		/* we loaded some symbols */
	char    *ldd_bp_addr;		/* place for ld-generated bpt */
	int	ldd_bp_inst;		/* instruction which was there */
	struct rtc_symb *ldd_cp;	/* commons we built */
};

/*
 * Structure associated with each object which may be or which requires
 * execution-time link editing.  Used by the run-time linkage editor to
 * identify needed objects and symbol definitions and references.
 */
struct 	old_link_dynamic {
	int	ld_version;		/* version # of this structure */
	union {
		struct link_dynamic_1 ld_1;
	} ld_un;

	int	in_debugging;
	int	sym_loaded;
	char    *bp_addr;
	int	bp_inst;
	struct rtc_symb *cp; 		/* pointer to an array of runtime */
					/* allocated common symbols. */
};

struct	link_dynamic {
	int	ld_version;		/* version # of this structure */
	struct 	ld_debug *ldd;
	union {
		struct link_dynamic_1 *ld_1;
		struct link_dynamic_2 *ld_2;
	} ld_un;
};


/*
 * Get size of relocations.
 */
#define	GETGOTSZ(x)	(x->ld_version < 2 ?				\
			((struct old_link_dynamic *)x)->v1.ld_plt -	\
			((struct old_link_dynamic *)x)->v1.ld_got :	\
			(x)->v2->ld_plt - (x)->v2->ld_got)

#define	GETPLTSZ(x)	(x->ld_version < 2 ?				\
			((struct old_link_dynamic *)x)->v1.ld_rel -	\
			((struct old_link_dynamic *)x)->v1.ld_plt :	\
			(x)->v2->ld_rel - (x)->v2->ld_plt)

#define	GETRELSZ(x)	(x->ld_version < 2 ?				\
			((struct old_link_dynamic *)x)->v1.ld_hash -	\
			((struct old_link_dynamic *)x)->v1.ld_rel :	\
			(x)->v2->ld_hash - (x)->v2->ld_rel)

#define	GETHASHSZ(x)	(x->ld_version < 2 ?				\
			((struct old_link_dynamic *)x)->v1.ld_stab -	\
			((struct old_link_dynamic *)x)->v1.ld_hash :	\
			(x)->v2->ld_stab - (x)->v2->ld_hash)

#define	GETSTABSZ(x)	(x->ld_version < 2 ?				\
			((struct old_link_dynamic *)x)->v1.ld_symbols -\
			((struct old_link_dynamic *)x)->v1.ld_stab :	\
			(x)->v2->ld_symbols - (x)->v2->ld_stab)

#undef v2
#undef v1

#endif /* !_link_h */

#define	MAIN_BASE 0x2000	/* base address of a.out in 4.x system */

/*
 * Macros for getting to linker a.out format private data.
 */
#define	AOUTPRV(X)	((X)->rt_priv)
#define	AOUTDYN(X)	(((Rt_aoutp *)(X)->rt_priv)->lm_ld)
#define	LM2LP(X)	((struct ld_private *)((Rt_aoutp *) \
				(X)->rt_priv)->lm_lpd)
#define	TEXTBASE(X)	(LM2LP(X)->lp_textbase)

/*
 * Most of the above macros are used from AOUT specific routines, however there
 * are a couple of instances where we need to ensure the file being processed
 * is AOUT before dereferencing the macro.
 */
#define	THIS_IS_AOUT(X)		(FCT(X) == &aout_fct)

/*
 * Code collapsing macros.
 */
#define	v2 ld_un.ld_2
#define	v1 ld_un.ld_1
#define	JMPOFF(x)	(x)->v2->ld_plt
#define	RELOCOFF(x)	(x)->v2->ld_rel
#define	HASHOFF(x)	(x)->v2->ld_hash
#define	SYMOFF(x)	(x)->v2->ld_stab
#define	STROFF(x)	(x)->v2->ld_symbols

struct jbind {
	int	jb_inst[3];	/* need 4 instructions for jump slot */
};

struct fshash {
	int	fssymbno;	/* ordinal symbol number */
	int	next;		/* index to the hash array pointed by fs_hash */
};

/*
 * Sparc relocation types.
 */
enum reloc_type
{
	RELOC_8,	RELOC_16,	RELOC_32,	/* simplest relocs */
	RELOC_DISP8,	RELOC_DISP16,	RELOC_DISP32,	/* Disp's (pc-rel) */
	RELOC_WDISP30,	RELOC_WDISP22,			/* SR word disp's */
	RELOC_HI22,	RELOC_22,			/* SR 22-bit relocs */
	RELOC_13,	RELOC_LO10,			/* SR 13&10-bit reloc */
	RELOC_SFA_BASE,	RELOC_SFA_OFF13,		/* SR S.F.A. relocs */
	RELOC_BASE10,	RELOC_BASE13,	RELOC_BASE22,	/* base_relative pic */
	RELOC_PC10,	RELOC_PC22,			/* special pc-rel pic */
	RELOC_JMP_TBL,					/* jmp_tbl_rel in pic */
	RELOC_SEGOFF16,					/* Shlib off-in-seg */
	RELOC_GLOB_DAT, RELOC_JMP_SLOT, RELOC_RELATIVE	/* rtld relocs */
};

/*
 * Format of a relocation datum.
 */
#define	r_symbolnum 	r_index

struct	relocation_info		/* used when header.a_machtype == M_SPARC */
{
	ulong_t		r_address;	/* relocation addr (offset in seg) */
	uint_t 		r_index   :24;	/* segment index or symbol index */
	uint_t 		r_extern  : 1;	/* if F, r_index==SEG#; if T, SYM idx */
	int			  : 2;	/* <unused> */
	enum reloc_type r_type    : 5;	/* type of relocation to perform */
	long		r_addend;	/* addend for relocation value */
};

struct ld_private {
	struct	jbind *lp_plt;		/* procedure linkage table */
	struct	relocation_info *lp_rp;	/* relocation table */
	struct	fshash *lp_hash;	/* hash table */
	struct	nlist *lp_symtab;	/* symbol table */
	char	*lp_symstr;		/* symbol strings */
	caddr_t	lp_textbase;		/* base address for text addressing */
	struct	nlist *(*lp_interp)();	/* link map interpreter */
	long	lp_refcnt;		/* reference count of link map */
	struct 	dl_object *lp_dlp;	/* pointer to a dlopen object */
	caddr_t	lp_symbol_base;		/* base address for symbols */
};


/*
 * Offsets of various sections of an object file.
 */
#define	PAGSIZ		0x02000
#define	SEGSIZ		PAGSIZ

#define	N_TXTOFF(x) \
	/* text segment */ \
	((x).a_magic == ZMAGIC ? 0 : sizeof (struct exec))

#define	N_SYMOFF(x) \
	/* symbol table */ \
	(N_TXTOFF(x) + (x).a_text + (x).a_data + (x).a_trsize + (x).a_drsize)

#define	SIZE(x) \
	/* round to segment size */ \
	(M_SROUND((x).a_text) + (x).a_data + (x).a_bss)

#ifdef	__cplusplus
}
#endif

#endif	/* _A_DOT_OUT_DOT_H */