xref: /illumos-gate/usr/src/cmd/sgs/libld/common/_map.h (revision 8222814e)
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 
22 /*
23  * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Local include file for libld mapfile subsystem.
28  */
29 
30 #ifndef	_MAP_DOT_H
31 #define	_MAP_DOT_H
32 
33 #ifdef	__cplusplus
34 extern "C" {
35 #endif
36 
37 /*
38  * Macro used to size name buffer corresponding to a NULL terminated array
39  * of structures each of which contains a name string. Macro is used per-name.
40  * 2 extra characters are allowed per item to allow for a ', ' delimiter
41  * or NULL termination.
42  */
43 #define	KW_NAME_SIZE(_size) (_size##_SIZE + 2)
44 
45 /*
46  * Variant of isspace() that excludes newline characters. Requires <ctype.h>.
47  */
48 #define	isspace_nonl(_s) (isspace(_s) && ((_s) != '\n'))
49 
50 /*
51  * Type used to insert NULL characters in the mapfile text and later
52  * back them out and restore the original character. The mapfile text
53  * is held in a single string, so when we want to access sub-strings,
54  * it is necessary to temporarily insert NULLs to prevent the entire
55  * mapfile from that point forward being output.
56  */
57 typedef struct {
58 	char	*np_ptr;	/* Address patched with NULL character */
59 	char	np_ch;		/* Character originally found at *np_ptr */
60 } ld_map_npatch_t;
61 
62 /*
63  * ld_map_gettoken() uses a table of 128 bytes to determine how to
64  * process a token starting with any 7-bit ASCII value. The table is
65  * indexed by the character code, and returns one of the TK_* token values.
66  */
67 typedef const char mf_tokdisp_t[128];
68 
69 /*
70  * The definition of an unquoted identifier differs based on the mapfile
71  * version. Rather than write a separate function to locate identifiers
72  * for each version, we use a single function that relies on a per-character
73  * table that encodes which characters can start an identifier, and which
74  * can continue one, for each supported mapfile version.
75  *
76  * Two bits are used for each version, one for the start attribute, and the
77  * other for continuation. The first two bits are not used (version 0), the
78  * next 2 are used for version 1, the following 2 for version 2, and so on.
79  */
80 #define	TKID_ATTR_B_START	1
81 #define	TKID_ATTR_B_CONT	2
82 
83 #define	TKID_ATTR_START(_ver)	(TKID_ATTR_B_START << (_ver * 2))
84 #define	TKID_ATTR_CONT(_ver)	(TKID_ATTR_B_CONT << (_ver * 2))
85 
86 /* Convenience macros for chars that both start and continue an identifier */
87 #define	TKID_ATTR(_ver) ((TKID_ATTR_B_START | TKID_ATTR_B_CONT) << (_ver * 2))
88 
89 /*
90  * State for a mapfile held in memory.
91  */
92 typedef struct {
93 	Ofl_desc	*mf_ofl;	/* Output descriptor being processed */
94 	char		*mf_name;	/* Mapfile name */
95 	Ifl_desc	*mf_ifl;	/* NULL, or pseudo input file */
96 					/*	descriptor from ld_map_ifl() */
97 	char		*mf_text;	/* Text of mapfile */
98 	char		*mf_next;	/* Next char in mapfile to examine */
99 	const char	*mf_tokdisp;	/* mf_tokdisp_t dispatch table to use */
100 	Lineno		mf_lineno;	/* Line # within mf_text */
101 	int		mf_version;	/* Mapfile syntax version */
102 	int		mf_tkid_start;	/* TKID bitvalue for characters that */
103 					/*	start an unquoted identifier */
104 	int		mf_tkid_cont;	/* TKID bitvalue for characters that */
105 					/*	continue an unquoted ident. */
106 	int		mf_next_ch;	/* 0, or character read from *mf_next */
107 					/*	prior to inserting NULL */
108 	Aliste		mf_ec_insndx;	/* Insert index for entrance criteria */
109 					/*	Each mapfile starts at the */
110 					/*	top, inserting each ec in the */
111 					/*	file in the order seen. */
112 } Mapfile;
113 
114 /*
115  * A very large percentage of mapfile errors start with the
116  * calling sequence:
117  *	ld_eprintf(ofl, ERR_XXX, format, mf->mf_name, mf->mf_lineno...)
118  * The mf_fatal() and mf_warn() varadic macros are used to supply all
119  * of boilerplate, resulting in visually simpler code.
120  *
121  * mf_fatal0()/mf_warn0() are used when the format does not require any
122  * additional arguments and the varargs list is empty. The GNU cpp has a
123  * syntax for eliminating the extra comma (, ##__VA_ARGS__), but this isn't
124  * supported by the Sun compilers yet.
125  */
126 #define	mf_fatal0(_mf, _fmt) \
127 	ld_eprintf((_mf)->mf_ofl, ERR_FATAL, _fmt, (_mf)->mf_name, \
128 	    EC_LINENO((_mf)->mf_lineno))
129 #define	mf_fatal(_mf, _fmt, ...) \
130 	ld_eprintf((_mf)->mf_ofl, ERR_FATAL, _fmt, (_mf)->mf_name, \
131 	    EC_LINENO((_mf)->mf_lineno), __VA_ARGS__)
132 
133 #define	mf_warn0(_mf, _fmt) \
134 	ld_eprintf((_mf)->mf_ofl, ERR_WARNING, _fmt, (_mf)->mf_name, \
135 	    EC_LINENO((_mf)->mf_lineno))
136 #define	mf_warn(_mf, _fmt, ...) \
137 	ld_eprintf((_mf)->mf_ofl, ERR_WARNING, _fmt, (_mf)->mf_name, \
138 	    EC_LINENO((_mf)->mf_lineno), __VA_ARGS__)
139 
140 /* Possible return values from ld_map_gettoken */
141 typedef enum {
142 	TK_ERROR =	-1,	/* Error in lexical analysis */
143 	TK_EOF =	0,	/* End of file: Requires TK_F_EOFOK to be set */
144 				/*	or EOF results in TK_ERROR */
145 	TK_STRING =	1,	/* String literal */
146 	TK_COLON =	2,	/* : */
147 	TK_SEMICOLON =	3,	/* ; */
148 	TK_EQUAL =	4,	/* = */
149 	TK_PLUSEQ =	5,	/* += */
150 	TK_MINUSEQ =	6,	/* -= */
151 	TK_ATSIGN =	7,	/* @ */
152 	TK_DASH =	8,	/* - */
153 	TK_LEFTBKT =	9,	/* { */
154 	TK_RIGHTBKT =	10,	/* } */
155 	TK_PIPE =	11,	/* | */
156 	TK_INT =	12,	/* Integer value: Unsigned machine word */
157 	TK_STAR =	13,	/* * */
158 	TK_BANG =	14,	/* ! */
159 	TK_LEFTSQR =	15,	/* [ */
160 	TK_RIGHTSQR =	16,	/* ] */
161 
162 	/*
163 	 * Items below this point are for the use of ld_map_gettoken().
164 	 * They indicate a character that requires the lexical analyzer
165 	 * to carry out some additional computation (OPeration), resulting
166 	 * in one of the simple token types above, which is returned to
167 	 * the caller. The TK_OP_ tokens are implementation details that are
168 	 * never returned to a caller of ld_map_gettoken().
169 	 */
170 	TK_OP_EOF,		/* end of file */
171 	TK_OP_ILLCHR,		/* unprintable illegal character */
172 	TK_OP_BADCHR,		/* printable but unexpected character */
173 	TK_OP_WS,		/* whitespace */
174 	TK_OP_NL,		/* newline */
175 	TK_OP_SIMQUOTE,		/* simple quoting */
176 	TK_OP_CQUOTE,		/* quoting with C string literal escapes */
177 	TK_OP_CMT,		/* Comment */
178 	TK_OP_CDIR,		/* Control directive */
179 	TK_OP_NUM,		/* Decimial, hex, or octal value */
180 	TK_OP_ID,		/* unquoted identifier using syntax rules */
181 				/*	appropriate for mapfile version */
182 	TK_OP_CEQUAL,		/* One of += or -= */
183 } Token;
184 
185 /*
186  * Type used by ld_map_gettoken() to return values for token types that
187  * have them.
188  */
189 typedef union {
190 	char	*tkv_str;		/* TK_STRING */
191 	struct {			/* TK_INT */
192 		char	*tkvi_str;	/* String making up integer */
193 		size_t	tkvi_cnt;	/* # characters in tkvi_str */
194 		Xword	tkvi_value;	/* Resulting value */
195 	} tkv_int;
196 } ld_map_tkval_t;
197 
198 /*
199  * Values for gettoken() flags argument. These flags are used to
200  * alter gettoken() default behavior under certain conditions.
201  */
202 #define	TK_F_EOFOK	0x1	/* Quietly return TK_EOF instead of normal */
203 				/*	TK_ERROR "premature EOF" error */
204 #define	TK_F_STRLC	0x2	/* TK_STRING: Convert string to lowercase */
205 #define	TK_F_KEYWORD	0x4	/* For directives and attributes: Disallow */
206 				/*	quoted TK_STRING tokens */
207 #define	TK_F_MULOK	0x8	/* TK_INT: Allow multiplicand[multiplier] */
208 				/*	syntax */
209 
210 /*
211  * Possible return values from ld_map_strtoxword()
212  */
213 typedef enum {
214 	STRTOXWORD_OK,		/* Operation successful */
215 	STRTOXWORD_TOOBIG,	/* Otherwise valid value is too large */
216 	STRTOXWORD_BAD		/* String not recognized as an integer */
217 } ld_map_strtoxword_t;
218 
219 /*
220  * Possible return values from ld_map_seg_insert()
221  */
222 typedef enum {
223 	SEG_INS_OK = 0,		/* Segment was inserted */
224 	SEG_INS_FAIL = 1,	/* Segment not inserted --- fatal */
225 	SEG_INS_SKIP = 2	/* Segment not inserted --- ignore */
226 } ld_map_seg_ins_t;
227 
228 /*
229  * Enumeration of different symbol scope possible in a mapfile
230  */
231 typedef enum {
232 	FLG_SCOPE_HIDD,		/* symbol defined hidden/local */
233 	FLG_SCOPE_DFLT,		/* symbol defined default/global */
234 	FLG_SCOPE_PROT,		/* symbol defined protected/symbolic */
235 	FLG_SCOPE_EXPT,		/* symbol defined exported */
236 	FLG_SCOPE_SNGL,		/* symbol defined singleton */
237 	FLG_SCOPE_ELIM		/* symbol defined eliminate */
238 } ld_map_scope_t;
239 
240 /* State of a mapfile symbol version */
241 typedef struct {
242 	const char	*mv_name;	/* NULL, or version name */
243 	Ver_desc	*mv_vdp;	/* Descriptor for version */
244 	ld_map_scope_t	mv_scope;	/* Current scope type */
245 	size_t		mv_errcnt;	/* Count of errors against version */
246 } ld_map_ver_t;
247 
248 /* State of a mapfile symbol definition */
249 typedef struct {
250 	const char	*ms_name;	/* symbol name */
251 	sd_flag_t	ms_sdflags;	/* 0 / mapfile set flags */
252 	Word		ms_shndx;	/* SHN_UNDEF / mapfile set sec index */
253 	uchar_t		ms_type;	/* STT_NOTYPE / mapfile set type */
254 	Addr		ms_value;	/* user set value, if ms_value_set */
255 	Addr		ms_size;	/* 0 / mapfile set size */
256 	Boolean		ms_size_set;	/* True if ms_size set, even if to 0 */
257 	const char	*ms_filtee;	/* NULL or filtee name */
258 	Boolean		ms_value_set;	/* TRUE if ms_value set, even if to 0 */
259 	Word		ms_dft_flag;	/* 0, or type of filter in ms_filtee */
260 } ld_map_sym_t;
261 
262 #if	defined(_ELF64)
263 
264 #define	ld_map_cap_sanitize	ld64_map_cap_sanitize
265 #define	ld_map_cap_set_ovflag	ld64_map_cap_set_ovflag
266 #define	ld_map_dv		ld64_map_dv
267 #define	ld_map_dv_entry		ld64_map_dv_entry
268 #define	ld_map_gettoken		ld64_map_gettoken
269 #define	ld_map_ifl		ld64_map_ifl
270 #define	ld_map_parse_v1		ld64_map_parse_v1
271 #define	ld_map_parse_v2		ld64_map_parse_v2
272 #define	ld_map_peektoken	ld64_map_peektoken
273 #define	ld_map_seg_alloc	ld64_map_seg_alloc
274 #define	ld_map_seg_ent_add	ld64_map_seg_ent_add
275 #define	ld_map_seg_ent_files	ld64_map_seg_ent_files
276 #define	ld_map_seg_index	ld64_map_seg_index
277 #define	ld_map_seg_insert	ld64_map_seg_insert
278 #define	ld_map_seg_lookup	ld64_map_seg_lookup
279 #define	ld_map_seg_os_order_add	ld64_map_seg_os_order_add
280 #define	ld_map_seg_size_symbol	ld64_map_seg_size_symbol
281 #define	ld_map_seg_stack	ld64_map_seg_stack
282 #define	ld_map_strtoxword	ld64_map_strtoxword
283 #define	ld_map_sym_enter	ld64_map_sym_enter
284 #define	ld_map_sym_filtee	ld64_map_sym_filtee
285 #define	ld_map_sym_scope	ld64_map_sym_scope
286 #define	ld_map_sym_autoreduce	ld64_map_sym_autoreduce
287 #define	ld_map_sym_ver_fini	ld64_map_sym_ver_fini
288 #define	ld_map_sym_ver_init	ld64_map_sym_ver_init
289 #define	ld_map_tokenstr		ld64_map_tokenstr
290 
291 #else
292 
293 #define	ld_map_cap_sanitize	ld32_map_cap_sanitize
294 #define	ld_map_cap_set_ovflag	ld32_map_cap_set_ovflag
295 #define	ld_map_dv		ld32_map_dv
296 #define	ld_map_dv_entry		ld32_map_dv_entry
297 #define	ld_map_gettoken		ld32_map_gettoken
298 #define	ld_map_ifl		ld32_map_ifl
299 #define	ld_map_parse_v1		ld32_map_parse_v1
300 #define	ld_map_parse_v2		ld32_map_parse_v2
301 #define	ld_map_peektoken	ld32_map_peektoken
302 #define	ld_map_seg_alloc	ld32_map_seg_alloc
303 #define	ld_map_seg_ent_add	ld32_map_seg_ent_add
304 #define	ld_map_seg_ent_files	ld32_map_seg_ent_files
305 #define	ld_map_seg_index	ld32_map_seg_index
306 #define	ld_map_seg_insert	ld32_map_seg_insert
307 #define	ld_map_seg_lookup	ld32_map_seg_lookup
308 #define	ld_map_seg_os_order_add	ld32_map_seg_os_order_add
309 #define	ld_map_seg_size_symbol	ld32_map_seg_size_symbol
310 #define	ld_map_seg_stack	ld32_map_seg_stack
311 #define	ld_map_strtoxword	ld32_map_strtoxword
312 #define	ld_map_sym_enter	ld32_map_sym_enter
313 #define	ld_map_sym_filtee	ld32_map_sym_filtee
314 #define	ld_map_sym_scope	ld32_map_sym_scope
315 #define	ld_map_sym_autoreduce	ld32_map_sym_autoreduce
316 #define	ld_map_sym_ver_fini	ld32_map_sym_ver_fini
317 #define	ld_map_sym_ver_init	ld32_map_sym_ver_init
318 #define	ld_map_tokenstr		ld32_map_tokenstr
319 
320 #endif
321 
322 /*
323  * Core functions used to parse mapfiles
324  */
325 extern void		ld_map_lowercase(char *);
326 extern Token		ld_map_gettoken(Mapfile *, int, ld_map_tkval_t *);
327 extern Token		ld_map_peektoken(Mapfile *);
328 extern Boolean		ld_map_parse_v1(Mapfile *);
329 extern Boolean		ld_map_parse_v2(Mapfile *);
330 extern ld_map_strtoxword_t ld_map_strtoxword(const char *restrict,
331 			    char **restrict, Xword *);
332 extern const char	*ld_map_tokenstr(Token, ld_map_tkval_t *,
333 			    Conv_inv_buf_t *);
334 
335 /*
336  * Support code shared between the different mapfile parsing code, used to
337  * provide a common implementation manipulating link-editor state.
338  */
339 extern Boolean		ld_map_cap_sanitize(Mapfile *, Word, Capmask *);
340 extern void		ld_map_cap_set_ovflag(Mapfile *, Word);
341 extern void		*ld_map_kwfind(const char *, void *, size_t, size_t);
342 extern char		*ld_map_kwnames(void *, size_t, size_t, char *, size_t);
343 extern Sdf_desc		*ld_map_dv(Mapfile *, const char *);
344 extern Boolean		ld_map_dv_entry(Mapfile *, Sdf_desc *, Boolean,
345 			    const char *);
346 extern Ifl_desc		*ld_map_ifl(Mapfile *);
347 extern Sg_desc		*ld_map_seg_alloc(const char *, Word, sg_flags_t);
348 extern Ent_desc		*ld_map_seg_ent_add(Mapfile *, Sg_desc *, const char *);
349 extern Boolean		ld_map_seg_ent_files(Mapfile *mf, Ent_desc *,
350 			    Word, const char *);
351 extern Xword		ld_map_seg_index(Mapfile *, Sg_desc *);
352 extern ld_map_seg_ins_t	ld_map_seg_insert(Mapfile *, dbg_state_t, Sg_desc *,
353 			    avl_index_t where);
354 extern Boolean		ld_map_seg_os_order_add(Mapfile *, Sg_desc *,
355 			    const char *);
356 extern Boolean		ld_map_seg_size_symbol(Mapfile *, Sg_desc *, Token,
357 			    const char *symname);
358 extern Sg_desc		*ld_map_seg_stack(Mapfile *);
359 extern Boolean		ld_map_sym_enter(Mapfile *, ld_map_ver_t *,
360 			    ld_map_sym_t *, Ass_desc *);
361 extern void		ld_map_sym_filtee(Mapfile *, ld_map_ver_t *,
362 			    ld_map_sym_t *, Word, const char *);
363 extern void		ld_map_sym_scope(Mapfile *, const char *,
364 			    ld_map_ver_t *);
365 extern void		ld_map_sym_autoreduce(Mapfile *, ld_map_ver_t *);
366 extern Boolean		ld_map_sym_ver_fini(Mapfile *, ld_map_ver_t *);
367 extern Boolean		ld_map_sym_ver_init(Mapfile *, char *, ld_map_ver_t *);
368 
369 #ifdef	__cplusplus
370 }
371 #endif
372 
373 #endif /* _MAP_DOT_H */
374