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