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 */
|