summaryrefslogtreecommitdiff
path: root/usr/src/cmd/sgs/libld/common/_map.h
blob: f05ddf01cea4f938b2b21ba3702d4f17fef647b4 (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
362
363
364
365
366
367
368
369
370
371
372
373
/*
 * 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) 2010, Oracle and/or its affiliates. All rights reserved.
 */

/*
 * Local include file for libld mapfile subsystem.
 */

#ifndef	_MAP_DOT_H
#define	_MAP_DOT_H

#ifdef	__cplusplus
extern "C" {
#endif

/*
 * Macro used to size name buffer corresponding to a NULL terminated array
 * of structures each of which contains a name string. Macro is used per-name.
 * 2 extra characters are allowed per item to allow for a ', ' delimiter
 * or NULL termination.
 */
#define	KW_NAME_SIZE(_size) (_size##_SIZE + 2)

/*
 * Variant of isspace() that excludes newline characters. Requires <ctype.h>.
 */
#define	isspace_nonl(_s) (isspace(_s) && ((_s) != '\n'))

/*
 * Type used to insert NULL characters in the mapfile text and later
 * back them out and restore the original character. The mapfile text
 * is held in a single string, so when we want to access sub-strings,
 * it is necessary to temporarily insert NULLs to prevent the entire
 * mapfile from that point forward being output.
 */
typedef struct {
	char	*np_ptr;	/* Address patched with NULL character */
	char	np_ch;		/* Character originally found at *np_ptr */
} ld_map_npatch_t;

/*
 * ld_map_gettoken() uses a table of 128 bytes to determine how to
 * process a token starting with any 7-bit ASCII value. The table is
 * indexed by the character code, and returns one of the TK_* token values.
 */
typedef const char mf_tokdisp_t[128];

/*
 * The definition of an unquoted identifier differs based on the mapfile
 * version. Rather than write a separate function to locate identifiers
 * for each version, we use a single function that relies on a per-character
 * table that encodes which characters can start an identifier, and which
 * can continue one, for each supported mapfile version.
 *
 * Two bits are used for each version, one for the start attribute, and the
 * other for continuation. The first two bits are not used (version 0), the
 * next 2 are used for version 1, the following 2 for version 2, and so on.
 */
#define	TKID_ATTR_B_START	1
#define	TKID_ATTR_B_CONT	2

#define	TKID_ATTR_START(_ver)	(TKID_ATTR_B_START << (_ver * 2))
#define	TKID_ATTR_CONT(_ver)	(TKID_ATTR_B_CONT << (_ver * 2))

/* Convenience macros for chars that both start and continue an identifier */
#define	TKID_ATTR(_ver) ((TKID_ATTR_B_START | TKID_ATTR_B_CONT) << (_ver * 2))

/*
 * State for a mapfile held in memory.
 */
typedef struct {
	Ofl_desc	*mf_ofl;	/* Output descriptor being processed */
	char		*mf_name;	/* Mapfile name */
	Ifl_desc	*mf_ifl;	/* NULL, or pseudo input file */
					/*	descriptor from ld_map_ifl() */
	char		*mf_text;	/* Text of mapfile */
	char		*mf_next;	/* Next char in mapfile to examine */
	const char	*mf_tokdisp;	/* mf_tokdisp_t dispatch table to use */
	Lineno		mf_lineno;	/* Line # within mf_text */
	int		mf_version;	/* Mapfile syntax version */
	int		mf_tkid_start;	/* TKID bitvalue for characters that */
					/*	start an unquoted identifier */
	int		mf_tkid_cont;	/* TKID bitvalue for characters that */
					/*	continue an unquoted ident. */
	int		mf_next_ch;	/* 0, or character read from *mf_next */
					/*	prior to inserting NULL */
	Aliste		mf_ec_insndx;	/* Insert index for entrance criteria */
					/*	Each mapfile starts at the */
					/*	top, inserting each ec in the */
					/*	file in the order seen. */
} Mapfile;

/*
 * A very large percentage of mapfile errors start with the
 * calling sequence:
 *	ld_eprintf(ofl, ERR_XXX, format, mf->mf_name, mf->mf_lineno...)
 * The mf_fatal() and mf_warn() varadic macros are used to supply all
 * of boilerplate, resulting in visually simpler code.
 *
 * mf_fatal0()/mf_warn0() are used when the format does not require any
 * additional arguments and the varargs list is empty. The GNU cpp has a
 * syntax for eliminating the extra comma (, ##__VA_ARGS__), but this isn't
 * supported by the Sun compilers yet.
 */
#define	mf_fatal0(_mf, _fmt) \
	ld_eprintf((_mf)->mf_ofl, ERR_FATAL, _fmt, (_mf)->mf_name, \
	    EC_LINENO((_mf)->mf_lineno))
#define	mf_fatal(_mf, _fmt, ...) \
	ld_eprintf((_mf)->mf_ofl, ERR_FATAL, _fmt, (_mf)->mf_name, \
	    EC_LINENO((_mf)->mf_lineno), __VA_ARGS__)

#define	mf_warn0(_mf, _fmt) \
	ld_eprintf((_mf)->mf_ofl, ERR_WARNING, _fmt, (_mf)->mf_name, \
	    EC_LINENO((_mf)->mf_lineno))
#define	mf_warn(_mf, _fmt, ...) \
	ld_eprintf((_mf)->mf_ofl, ERR_WARNING, _fmt, (_mf)->mf_name, \
	    EC_LINENO((_mf)->mf_lineno), __VA_ARGS__)

/* Possible return values from ld_map_gettoken */
typedef enum {
	TK_ERROR =	-1,	/* Error in lexical analysis */
	TK_EOF =	0,	/* End of file: Requires TK_F_EOFOK to be set */
				/*	or EOF results in TK_ERROR */
	TK_STRING =	1,	/* String literal */
	TK_COLON =	2,	/* : */
	TK_SEMICOLON =	3,	/* ; */
	TK_EQUAL =	4,	/* = */
	TK_PLUSEQ =	5,	/* += */
	TK_MINUSEQ =	6,	/* -= */
	TK_ATSIGN =	7,	/* @ */
	TK_DASH =	8,	/* - */
	TK_LEFTBKT =	9,	/* { */
	TK_RIGHTBKT =	10,	/* } */
	TK_PIPE =	11,	/* | */
	TK_INT =	12,	/* Integer value: Unsigned machine word */
	TK_STAR =	13,	/* * */
	TK_BANG =	14,	/* ! */
	TK_LEFTSQR =	15,	/* [ */
	TK_RIGHTSQR =	16,	/* ] */

	/*
	 * Items below this point are for the use of ld_map_gettoken().
	 * They indicate a character that requires the lexical analyzer
	 * to carry out some additional computation (OPeration), resulting
	 * in one of the simple token types above, which is returned to
	 * the caller. The TK_OP_ tokens are implementation details that are
	 * never returned to a caller of ld_map_gettoken().
	 */
	TK_OP_EOF,		/* end of file */
	TK_OP_ILLCHR,		/* unprintable illegal character */
	TK_OP_BADCHR,		/* printable but unexpected character */
	TK_OP_WS,		/* whitespace */
	TK_OP_NL,		/* newline */
	TK_OP_SIMQUOTE,		/* simple quoting */
	TK_OP_CQUOTE,		/* quoting with C string literal escapes */
	TK_OP_CMT,		/* Comment */
	TK_OP_CDIR,		/* Control directive */
	TK_OP_NUM,		/* Decimial, hex, or octal value */
	TK_OP_ID,		/* unquoted identifier using syntax rules */
				/*	appropriate for mapfile version */
	TK_OP_CEQUAL,		/* One of += or -= */
} Token;

/*
 * Type used by ld_map_gettoken() to return values for token types that
 * have them.
 */
typedef union {
	char	*tkv_str;		/* TK_STRING */
	struct {			/* TK_INT */
		char	*tkvi_str;	/* String making up integer */
		size_t	tkvi_cnt;	/* # characters in tkvi_str */
		Xword	tkvi_value;	/* Resulting value */
	} tkv_int;
} ld_map_tkval_t;

/*
 * Values for gettoken() flags argument. These flags are used to
 * alter gettoken() default behavior under certain conditions.
 */
#define	TK_F_EOFOK	0x1	/* Quietly return TK_EOF instead of normal */
				/*	TK_ERROR "premature EOF" error */
#define	TK_F_STRLC	0x2	/* TK_STRING: Convert string to lowercase */
#define	TK_F_KEYWORD	0x4	/* For directives and attributes: Disallow */
				/*	quoted TK_STRING tokens */
#define	TK_F_MULOK	0x8	/* TK_INT: Allow multiplicand[multiplier] */
				/*	syntax */

/*
 * Possible return values from ld_map_strtoxword()
 */
typedef enum {
	STRTOXWORD_OK,		/* Operation successful */
	STRTOXWORD_TOOBIG,	/* Otherwise valid value is too large */
	STRTOXWORD_BAD		/* String not recognized as an integer */
} ld_map_strtoxword_t;

/*
 * Possible return values from ld_map_seg_insert()
 */
typedef enum {
	SEG_INS_OK = 0,		/* Segment was inserted */
	SEG_INS_FAIL = 1,	/* Segment not inserted --- fatal */
	SEG_INS_SKIP = 2	/* Segment not inserted --- ignore */
} ld_map_seg_ins_t;

/*
 * Enumeration of different symbol scope possible in a mapfile
 */
typedef enum {
	FLG_SCOPE_HIDD,		/* symbol defined hidden/local */
	FLG_SCOPE_DFLT,		/* symbol defined default/global */
	FLG_SCOPE_PROT,		/* symbol defined protected/symbolic */
	FLG_SCOPE_EXPT,		/* symbol defined exported */
	FLG_SCOPE_SNGL,		/* symbol defined singleton */
	FLG_SCOPE_ELIM		/* symbol defined eliminate */
} ld_map_scope_t;

/* State of a mapfile symbol version */
typedef struct {
	const char	*mv_name;	/* NULL, or version name */
	Ver_desc	*mv_vdp;	/* Descriptor for version */
	ld_map_scope_t	mv_scope;	/* Current scope type */
	size_t		mv_errcnt;	/* Count of errors against version */
} ld_map_ver_t;

/* State of a mapfile symbol definition */
typedef struct {
	const char	*ms_name;	/* symbol name */
	sd_flag_t	ms_sdflags;	/* 0 / mapfile set flags */
	Word		ms_shndx;	/* SHN_UNDEF / mapfile set sec index */
	uchar_t		ms_type;	/* STT_NOTYPE / mapfile set type */
	Addr		ms_value;	/* user set value, if ms_value_set */
	Addr		ms_size;	/* 0 / mapfile set size */
	Boolean		ms_size_set;	/* True if ms_size set, even if to 0 */
	const char	*ms_filtee;	/* NULL or filtee name */
	Boolean		ms_value_set;	/* TRUE if ms_value set, even if to 0 */
	Word		ms_dft_flag;	/* 0, or type of filter in ms_filtee */
} ld_map_sym_t;

#if	defined(_ELF64)

#define	ld_map_cap_sanitize	ld64_map_cap_sanitize
#define	ld_map_cap_set_ovflag	ld64_map_cap_set_ovflag
#define	ld_map_dv		ld64_map_dv
#define	ld_map_dv_entry		ld64_map_dv_entry
#define	ld_map_gettoken		ld64_map_gettoken
#define	ld_map_ifl		ld64_map_ifl
#define	ld_map_parse_v1		ld64_map_parse_v1
#define	ld_map_parse_v2		ld64_map_parse_v2
#define	ld_map_peektoken	ld64_map_peektoken
#define	ld_map_seg_alloc	ld64_map_seg_alloc
#define	ld_map_seg_ent_add	ld64_map_seg_ent_add
#define	ld_map_seg_ent_files	ld64_map_seg_ent_files
#define	ld_map_seg_index	ld64_map_seg_index
#define	ld_map_seg_insert	ld64_map_seg_insert
#define	ld_map_seg_lookup	ld64_map_seg_lookup
#define	ld_map_seg_os_order_add	ld64_map_seg_os_order_add
#define	ld_map_seg_size_symbol	ld64_map_seg_size_symbol
#define	ld_map_seg_stack	ld64_map_seg_stack
#define	ld_map_strtoxword	ld64_map_strtoxword
#define	ld_map_sym_enter	ld64_map_sym_enter
#define	ld_map_sym_filtee	ld64_map_sym_filtee
#define	ld_map_sym_scope	ld64_map_sym_scope
#define	ld_map_sym_autoreduce	ld64_map_sym_autoreduce
#define	ld_map_sym_ver_fini	ld64_map_sym_ver_fini
#define	ld_map_sym_ver_init	ld64_map_sym_ver_init
#define	ld_map_tokenstr		ld64_map_tokenstr

#else

#define	ld_map_cap_sanitize	ld32_map_cap_sanitize
#define	ld_map_cap_set_ovflag	ld32_map_cap_set_ovflag
#define	ld_map_dv		ld32_map_dv
#define	ld_map_dv_entry		ld32_map_dv_entry
#define	ld_map_gettoken		ld32_map_gettoken
#define	ld_map_ifl		ld32_map_ifl
#define	ld_map_parse_v1		ld32_map_parse_v1
#define	ld_map_parse_v2		ld32_map_parse_v2
#define	ld_map_peektoken	ld32_map_peektoken
#define	ld_map_seg_alloc	ld32_map_seg_alloc
#define	ld_map_seg_ent_add	ld32_map_seg_ent_add
#define	ld_map_seg_ent_files	ld32_map_seg_ent_files
#define	ld_map_seg_index	ld32_map_seg_index
#define	ld_map_seg_insert	ld32_map_seg_insert
#define	ld_map_seg_lookup	ld32_map_seg_lookup
#define	ld_map_seg_os_order_add	ld32_map_seg_os_order_add
#define	ld_map_seg_size_symbol	ld32_map_seg_size_symbol
#define	ld_map_seg_stack	ld32_map_seg_stack
#define	ld_map_strtoxword	ld32_map_strtoxword
#define	ld_map_sym_enter	ld32_map_sym_enter
#define	ld_map_sym_filtee	ld32_map_sym_filtee
#define	ld_map_sym_scope	ld32_map_sym_scope
#define	ld_map_sym_autoreduce	ld32_map_sym_autoreduce
#define	ld_map_sym_ver_fini	ld32_map_sym_ver_fini
#define	ld_map_sym_ver_init	ld32_map_sym_ver_init
#define	ld_map_tokenstr		ld32_map_tokenstr

#endif

/*
 * Core functions used to parse mapfiles
 */
extern void		ld_map_lowercase(char *);
extern Token		ld_map_gettoken(Mapfile *, int, ld_map_tkval_t *);
extern Token		ld_map_peektoken(Mapfile *);
extern Boolean		ld_map_parse_v1(Mapfile *);
extern Boolean		ld_map_parse_v2(Mapfile *);
extern ld_map_strtoxword_t ld_map_strtoxword(const char *restrict,
			    char **restrict, Xword *);
extern const char	*ld_map_tokenstr(Token, ld_map_tkval_t *,
			    Conv_inv_buf_t *);

/*
 * Support code shared between the different mapfile parsing code, used to
 * provide a common implementation manipulating link-editor state.
 */
extern Boolean		ld_map_cap_sanitize(Mapfile *, Word, Capmask *);
extern void		ld_map_cap_set_ovflag(Mapfile *, Word);
extern void		*ld_map_kwfind(const char *, void *, size_t, size_t);
extern char		*ld_map_kwnames(void *, size_t, size_t, char *, size_t);
extern Sdf_desc		*ld_map_dv(Mapfile *, const char *);
extern Boolean		ld_map_dv_entry(Mapfile *, Sdf_desc *, Boolean,
			    const char *);
extern Ifl_desc		*ld_map_ifl(Mapfile *);
extern Sg_desc		*ld_map_seg_alloc(const char *, Word, sg_flags_t);
extern Ent_desc		*ld_map_seg_ent_add(Mapfile *, Sg_desc *, const char *);
extern Boolean		ld_map_seg_ent_files(Mapfile *mf, Ent_desc *,
			    Word, const char *);
extern Xword		ld_map_seg_index(Mapfile *, Sg_desc *);
extern ld_map_seg_ins_t	ld_map_seg_insert(Mapfile *, dbg_state_t, Sg_desc *,
			    avl_index_t where);
extern Boolean		ld_map_seg_os_order_add(Mapfile *, Sg_desc *,
			    const char *);
extern Boolean		ld_map_seg_size_symbol(Mapfile *, Sg_desc *, Token,
			    const char *symname);
extern Sg_desc		*ld_map_seg_stack(Mapfile *);
extern Boolean		ld_map_sym_enter(Mapfile *, ld_map_ver_t *,
			    ld_map_sym_t *, Ass_desc *);
extern void		ld_map_sym_filtee(Mapfile *, ld_map_ver_t *,
			    ld_map_sym_t *, Word, const char *);
extern void		ld_map_sym_scope(Mapfile *, const char *,
			    ld_map_ver_t *);
extern void		ld_map_sym_autoreduce(Mapfile *, ld_map_ver_t *);
extern Boolean		ld_map_sym_ver_fini(Mapfile *, ld_map_ver_t *);
extern Boolean		ld_map_sym_ver_init(Mapfile *, char *, ld_map_ver_t *);

#ifdef	__cplusplus
}
#endif

#endif /* _MAP_DOT_H */