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