1 1.1 christos /* Object attributes parsing. 2 1.1 christos Copyright (C) 2025-2026 Free Software Foundation, Inc. 3 1.1 christos 4 1.1 christos This file is part of GAS, the GNU Assembler. 5 1.1 christos 6 1.1 christos GAS is free software; you can redistribute it and/or modify 7 1.1 christos it under the terms of the GNU General Public License as published by 8 1.1 christos the Free Software Foundation; either version 3, or (at your option) 9 1.1 christos any later version. 10 1.1 christos 11 1.1 christos GAS is distributed in the hope that it will be useful, 12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of 13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 1.1 christos GNU General Public License for more details. 15 1.1 christos 16 1.1 christos You should have received a copy of the GNU General Public License 17 1.1 christos along with GAS; see the file COPYING. If not, write to the Free 18 1.1 christos Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 19 1.1 christos 02110-1301, USA. */ 20 1.1 christos 21 1.1 christos #include "obj-elf-attr.h" 22 1.1 christos 23 1.1 christos #ifdef TC_OBJ_ATTR 24 1.1 christos 25 1.1 christos #include "obstack.h" 26 1.1 christos #include "safe-ctype.h" 27 1.1 christos 28 1.1 christos /* A variant type to store information about known OAv2 identifiers. */ 29 1.1 christos typedef union { 30 1.1 christos uint8_t u8; 31 1.1 christos bool b; 32 1.1 christos } oav2_identifier_variant_value_t; 33 1.1 christos 34 1.1 christos typedef enum { 35 1.1 christos OAv2_ASM_ID_VALUE_UNDEFINED = 0, 36 1.1 christos OAv2_ASM_ID_VALUE_U8, 37 1.1 christos OAv2_ASM_ID_VALUE_BOOL, 38 1.1 christos } oav2_identifier_variant_type_info_t; 39 1.1 christos 40 1.1 christos typedef struct { 41 1.1 christos oav2_identifier_variant_value_t val; 42 1.1 christos oav2_identifier_variant_type_info_t vtype; 43 1.1 christos } oav2_identifier_variant_t; 44 1.1 christos 45 1.1 christos typedef struct { 46 1.1 christos const char *const name; 47 1.1 christos const oav2_identifier_variant_t value; 48 1.1 christos } oav2_identifier_t; 49 1.1 christos 50 1.1 christos typedef struct { 51 1.1 christos size_t len; 52 1.1 christos struct arg_variant_t *elts; 53 1.1 christos } arg_variant_list_t; 54 1.1 christos 55 1.1 christos typedef union { 56 1.1 christos const char *string; 57 1.1 christos uint64_t u64; 58 1.1 christos int64_t i64; 59 1.1 christos arg_variant_list_t list; 60 1.1 christos } arg_variant_value_t; 61 1.1 christos 62 1.1 christos typedef enum { 63 1.1 christos VALUE_UNDEFINED = 0, 64 1.1 christos VALUE_U64, 65 1.1 christos VALUE_I64, 66 1.1 christos VALUE_UNSIGNED_INTEGER = VALUE_U64, 67 1.1 christos VALUE_SIGNED_INTEGER = VALUE_I64, 68 1.1 christos VALUE_STRING, 69 1.1 christos VALUE_LIST, 70 1.1 christos VALUE_OPTIONAL_ABSENT, 71 1.1 christos } arg_variant_type_info_t; 72 1.1 christos 73 1.1 christos /* A variant type to store the argument values of an assembly directive. */ 74 1.1 christos typedef struct arg_variant_t { 75 1.1 christos arg_variant_value_t val; 76 1.1 christos arg_variant_type_info_t vtype; 77 1.1 christos } arg_variant_t; 78 1.1 christos 79 1.1 christos typedef arg_variant_t arg_t; 80 1.1 christos 81 1.1 christos #define skip_whitespace(str) do { if (is_whitespace (*(str))) ++(str); } while (0) 82 1.1 christos 83 1.1 christos static inline bool 84 1.1 christos skip_past_char (char **str, char c) 85 1.1 christos { 86 1.1 christos if (**str == c) 87 1.1 christos { 88 1.1 christos (*str)++; 89 1.1 christos return true; 90 1.1 christos } 91 1.1 christos return false; 92 1.1 christos } 93 1.1 christos #define skip_past_comma(str) skip_past_char (str, ',') 94 1.1 christos 95 1.1 christos #if (TC_OBJ_ATTR_v1) 96 1.1 christos 97 1.1 christos /* A list of attributes that have been explicitly set by the assembly code. 98 1.1 christos VENDOR is the vendor id, BASE is the tag shifted right by the number 99 1.1 christos of bits in MASK, and bit N of MASK is set if tag BASE+N has been set. */ 100 1.1 christos typedef struct recorded_attribute_info { 101 1.1 christos struct recorded_attribute_info *next; 102 1.1 christos obj_attr_vendor_t vendor; 103 1.1 christos unsigned int base; 104 1.1 christos unsigned long mask; 105 1.1 christos } recorded_attribute_info_t; 106 1.1 christos static recorded_attribute_info_t *recorded_attributes; 107 1.1 christos 108 1.1 christos static void 109 1.1 christos oav1_attr_info_free (recorded_attribute_info_t *node) 110 1.1 christos { 111 1.1 christos while (node != NULL) 112 1.1 christos { 113 1.1 christos recorded_attribute_info_t *next = node->next; 114 1.1 christos free (node); 115 1.1 christos node = next; 116 1.1 christos } 117 1.1 christos } 118 1.1 christos 119 1.1 christos void 120 1.1 christos oav1_attr_info_init (void) 121 1.1 christos { 122 1.1 christos /* Note: this "constructor" was added for symmetry with oav1_attr_info_exit. 123 1.1 christos recorded_attributes is a static variable which is automatically initialized 124 1.1 christos to NULL. There is no need to initialize it another time except for a 125 1.1 christos cosmetic reason and to possibly help fuzzing. */ 126 1.1 christos recorded_attributes = NULL; 127 1.1 christos } 128 1.1 christos 129 1.1 christos void 130 1.1 christos oav1_attr_info_exit (void) 131 1.1 christos { 132 1.1 christos oav1_attr_info_free (recorded_attributes); 133 1.1 christos } 134 1.1 christos 135 1.1 christos /* Record that we have seen an explicit specification of attribute TAG 136 1.1 christos for vendor VENDOR. */ 137 1.1 christos 138 1.1 christos static void 139 1.1 christos oav1_attr_record_seen (obj_attr_vendor_t vendor, obj_attr_tag_t tag) 140 1.1 christos { 141 1.1 christos unsigned int base; 142 1.1 christos unsigned long mask; 143 1.1 christos recorded_attribute_info_t *rai; 144 1.1 christos 145 1.1 christos base = tag / (8 * sizeof (rai->mask)); 146 1.1 christos mask = 1UL << (tag % (8 * sizeof (rai->mask))); 147 1.1 christos for (rai = recorded_attributes; rai; rai = rai->next) 148 1.1 christos if (rai->vendor == vendor && rai->base == base) 149 1.1 christos { 150 1.1 christos rai->mask |= mask; 151 1.1 christos return; 152 1.1 christos } 153 1.1 christos 154 1.1 christos rai = XNEW (recorded_attribute_info_t); 155 1.1 christos rai->next = recorded_attributes; 156 1.1 christos rai->vendor = vendor; 157 1.1 christos rai->base = base; 158 1.1 christos rai->mask = mask; 159 1.1 christos recorded_attributes = rai; 160 1.1 christos } 161 1.1 christos 162 1.1 christos /* Return true if we have seen an explicit specification of attribute TAG 163 1.1 christos for vendor VENDOR. */ 164 1.1 christos 165 1.1 christos bool 166 1.1 christos oav1_attr_seen (obj_attr_vendor_t vendor, obj_attr_tag_t tag) 167 1.1 christos { 168 1.1 christos unsigned int base; 169 1.1 christos unsigned long mask; 170 1.1 christos recorded_attribute_info_t *rai; 171 1.1 christos 172 1.1 christos base = tag / (8 * sizeof (rai->mask)); 173 1.1 christos mask = 1UL << (tag % (8 * sizeof (rai->mask))); 174 1.1 christos for (rai = recorded_attributes; rai; rai = rai->next) 175 1.1 christos if (rai->vendor == vendor && rai->base == base) 176 1.1 christos return (rai->mask & mask) != 0; 177 1.1 christos return false; 178 1.1 christos } 179 1.1 christos 180 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 181 1.1 christos 182 1.1 christos /* Expected argument tokens for object attribute directives. */ 183 1.1 christos typedef enum { 184 1.1 christos /* Base types. */ 185 1.1 christos IDENTIFIER = 0x1, 186 1.1 christos UNSIGNED_INTEGER = 0x2, 187 1.1 christos SIGNED_INTEGER = 0x4, 188 1.1 christos STRING = 0x8, 189 1.1 christos LIST = 0x10, 190 1.1 christos LT_MASK = 0xFF, 191 1.1 christos /* Higher types. */ 192 1.1 christos SUBSECTION_NAME = 0x100, 193 1.1 christos SUBSECTION_OPTION_1 = 0x200, 194 1.1 christos SUBSECTION_OPTION_2 = 0x400, 195 1.1 christos ATTRIBUTE_KEY = 0x800, 196 1.1 christos ATTRIBUTE_VALUE = 0x1000, 197 1.1 christos HT_MASK = 0xFF00, 198 1.1 christos } arg_token_t; 199 1.1 christos 200 1.1 christos /* Free an arguments list of size N. */ 201 1.1 christos static void 202 1.1 christos args_list_free (arg_t *args, size_t n) 203 1.1 christos { 204 1.1 christos for (size_t i = 0; i < n; ++i) 205 1.1 christos if (args[i].vtype == VALUE_STRING) 206 1.1 christos free ((void *) args[i].val.string); 207 1.1 christos else if (args[i].vtype == VALUE_LIST) 208 1.1 christos args_list_free (args[i].val.list.elts, args[i].val.list.len); 209 1.1 christos free (args); 210 1.1 christos } 211 1.1 christos 212 1.1 christos /* Extract a string literal from the input. */ 213 1.1 christos static bool 214 1.1 christos extract_string_literal (arg_t *arg_out) 215 1.1 christos { 216 1.1 christos int len; 217 1.1 christos char *obstack_buf = demand_copy_C_string (&len); 218 1.1 christos if (obstack_buf != NULL) 219 1.1 christos { 220 1.1 christos arg_out->val.string = xstrdup (obstack_buf); 221 1.1 christos obstack_free (¬es, obstack_buf); 222 1.1 christos arg_out->vtype = VALUE_STRING; 223 1.1 christos return true; 224 1.1 christos } 225 1.1 christos 226 1.1 christos arg_out->val.string = NULL; 227 1.1 christos return false; 228 1.1 christos } 229 1.1 christos 230 1.1 christos /* Extract an integer literal from the input. 231 1.1 christos Anything matched by O_constant is considered an integer literal (see the 232 1.1 christos usage of O_constant in expr.c to see all the matches. 233 1.1 christos Return true on success, false otherwise. If a signedness issue is detected, 234 1.1 christos 'signedness_issue' is also set to true. */ 235 1.1 christos static bool 236 1.1 christos extract_integer_literal (arg_t *arg_out, 237 1.1 christos bool want_unsigned, 238 1.1 christos bool *signedness_issue) 239 1.1 christos { 240 1.1 christos const char *cursor_begin = input_line_pointer; 241 1.1 christos expressionS exp; 242 1.1 christos expression_and_evaluate (&exp); 243 1.1 christos if (exp.X_op != O_constant) 244 1.1 christos { 245 1.1 christos char backup_c = *input_line_pointer; 246 1.1 christos *input_line_pointer = '\0'; 247 1.1 christos as_bad (_("expression '%s' does not resolve to an integer"), 248 1.1 christos cursor_begin); 249 1.1 christos /* Restore the character pointed by the current cursor position, 250 1.1 christos otherwise '\0' misleads ignore_rest_of_line(). */ 251 1.1 christos *input_line_pointer = backup_c; 252 1.1 christos return false; 253 1.1 christos } 254 1.1 christos 255 1.1 christos int64_t val = (int64_t) exp.X_add_number; 256 1.1 christos if (want_unsigned) 257 1.1 christos { 258 1.1 christos if (! exp.X_unsigned && val < 0) 259 1.1 christos { 260 1.1 christos as_bad (_("unexpected value '%" PRId64 "', expected `unsigned integer' instead"), 261 1.1 christos val); 262 1.1 christos *signedness_issue = true; 263 1.1 christos return false; 264 1.1 christos } 265 1.1 christos arg_out->val.u64 = val; 266 1.1 christos arg_out->vtype = VALUE_UNSIGNED_INTEGER; 267 1.1 christos } 268 1.1 christos else 269 1.1 christos { 270 1.1 christos arg_out->val.i64 = val; 271 1.1 christos arg_out->vtype = VALUE_SIGNED_INTEGER; 272 1.1 christos } 273 1.1 christos return true; 274 1.1 christos } 275 1.1 christos 276 1.1 christos /* Extract an identifier based on the provided character matcher. */ 277 1.1 christos static bool 278 1.1 christos extract_identifier (bool (*char_predicate) (char), arg_t *arg_out) 279 1.1 christos { 280 1.1 christos const char *s = input_line_pointer; 281 1.1 christos unsigned int i = 0; 282 1.1 christos for (; char_predicate (*input_line_pointer); ++input_line_pointer) 283 1.1 christos i++; 284 1.1 christos if (i == 0) 285 1.1 christos { 286 1.1 christos as_bad (_("invalid character '%c' in identifier"), 287 1.1 christos *input_line_pointer); 288 1.1 christos return false; 289 1.1 christos } 290 1.1 christos 291 1.1 christos arg_out->vtype = VALUE_STRING; 292 1.1 christos arg_out->val.string = xmemdup0 (s, i); 293 1.1 christos return true; 294 1.1 christos } 295 1.1 christos 296 1.1 christos #if (TC_OBJ_ATTR_v2) 297 1.1 christos /* Resolve the identifier if it matches a known tag. */ 298 1.1 christos static bool 299 1.1 christos resolve_if_matching_known_tag (const char *identifier, 300 1.1 christos const obj_attr_tag_info_t *known_identifier, 301 1.1 christos arg_t *val_out) 302 1.1 christos { 303 1.1 christos if (strcmp (known_identifier->name, identifier) != 0) 304 1.1 christos return false; 305 1.1 christos 306 1.1 christos val_out->val.u64 = known_identifier->value; 307 1.1 christos val_out->vtype = VALUE_UNSIGNED_INTEGER; 308 1.1 christos return true; 309 1.1 christos } 310 1.1 christos 311 1.1 christos /* Resolve the identifier if it matches the known one. */ 312 1.1 christos static bool 313 1.1 christos resolve_if_matching (const char *identifier, 314 1.1 christos const oav2_identifier_t *known_identifier, 315 1.1 christos arg_t *val_out) 316 1.1 christos { 317 1.1 christos /* Lowercase the identifier before comparison. */ 318 1.1 christos char normalized_identifier[100]; 319 1.1 christos unsigned int i = 0; 320 1.1 christos for (; i < sizeof (normalized_identifier) && identifier[i] != '\0'; ++i) 321 1.1 christos normalized_identifier[i] = TOLOWER (identifier[i]); 322 1.1 christos if (i >= sizeof (normalized_identifier)) 323 1.1 christos /* Identifier is too long. */ 324 1.1 christos return false; 325 1.1 christos gas_assert (identifier[i] == '\0'); 326 1.1 christos normalized_identifier[i] = '\0'; 327 1.1 christos 328 1.1 christos /* Comparison with normalized identifier. */ 329 1.1 christos if (strcmp (known_identifier->name, normalized_identifier) != 0) 330 1.1 christos return false; 331 1.1 christos 332 1.1 christos /* We only need U8 and Bool for now. */ 333 1.1 christos switch (known_identifier->value.vtype) 334 1.1 christos { 335 1.1 christos case OAv2_ASM_ID_VALUE_U8: 336 1.1 christos val_out->val.u64 = known_identifier->value.val.b; 337 1.1 christos val_out->vtype = VALUE_UNSIGNED_INTEGER; 338 1.1 christos break; 339 1.1 christos case OAv2_ASM_ID_VALUE_BOOL: 340 1.1 christos val_out->val.u64 = known_identifier->value.val.u8; 341 1.1 christos val_out->vtype = VALUE_UNSIGNED_INTEGER; 342 1.1 christos break; 343 1.1 christos default: 344 1.1 christos abort (); 345 1.1 christos } 346 1.1 christos 347 1.1 christos return true; 348 1.1 christos } 349 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 350 1.1 christos 351 1.1 christos #if (TC_OBJ_ATTR_v1) 352 1.1 christos /* Look up attribute tags defined in the backend (object attribute v1). */ 353 1.1 christos static bool 354 1.1 christos obj_attr_v1_lookup_known_attr_tag_symbol 355 1.1 christos (const char *identifier ATTRIBUTE_UNUSED, 356 1.1 christos arg_token_t token_type, 357 1.1 christos arg_t *val_out) 358 1.1 christos { 359 1.1 christos gas_assert (token_type & UNSIGNED_INTEGER); 360 1.1 christos 361 1.1 christos #ifndef CONVERT_SYMBOLIC_ATTRIBUTE 362 1.1 christos # define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1 363 1.1 christos #endif 364 1.1 christos int tag = CONVERT_SYMBOLIC_ATTRIBUTE (identifier); 365 1.1 christos if (tag < 0) 366 1.1 christos return false; 367 1.1 christos val_out->val.u64 = tag; 368 1.1 christos val_out->vtype = VALUE_UNSIGNED_INTEGER; 369 1.1 christos return true; 370 1.1 christos } 371 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 372 1.1 christos 373 1.1 christos #if (TC_OBJ_ATTR_v2) 374 1.1 christos /* Look up attribute tags defined in the backend (object attribute v2). */ 375 1.1 christos static bool 376 1.1 christos obj_attr_v2_lookup_known_attr_tag_symbol (const char *identifier, 377 1.1 christos arg_token_t token_type, 378 1.1 christos arg_t *val_out) 379 1.1 christos { 380 1.1 christos obj_attr_subsection_v2_t *subsec = elf_obj_attr_subsections (stdoutput).last; 381 1.1 christos /* This function is called when setting a value for an attribute, and it 382 1.1 christos requires an active subsection. Calling this function without setting 383 1.1 christos 'subsec' is a logical error. Invalid user code, where the subsection 384 1.1 christos has not been selected must be handled by the caller. We require 'subsec' 385 1.1 christos to be non-NULL here. */ 386 1.1 christos gas_assert (subsec != NULL); 387 1.1 christos 388 1.1 christos /* An attribute tag is an unsigned integer, so the expected token type should 389 1.1 christos always have the base type UNSIGNED_INTEGER. Otherwise, this function was 390 1.1 christos called incorrectly. */ 391 1.1 christos gas_assert (token_type & UNSIGNED_INTEGER); 392 1.1 christos 393 1.1 christos bool resolved = false; 394 1.1 christos const struct elf_backend_data *be = get_elf_backend_data (stdoutput); 395 1.1 christos const known_subsection_v2_t *known_subsec 396 1.1 christos = bfd_obj_attr_v2_identify_subsection (be, subsec->name); 397 1.1 christos if (known_subsec != NULL) 398 1.1 christos { 399 1.1 christos for (size_t i = 0; i < known_subsec->len && ! resolved; ++i) 400 1.1 christos resolved 401 1.1 christos = resolve_if_matching_known_tag (identifier, 402 1.1 christos &known_subsec->known_attrs[i].tag, 403 1.1 christos val_out); 404 1.1 christos } 405 1.1 christos 406 1.1 christos if (resolved) 407 1.1 christos /* An attribute tag is an unsigned integer, so the type of the found value 408 1.1 christos should be VALUE_UNSIGNED_INTEGER. Otherwise, check if you set correctly 409 1.1 christos the type of the value associated to the symbol. */ 410 1.1 christos gas_assert (val_out->vtype == VALUE_UNSIGNED_INTEGER); 411 1.1 christos 412 1.1 christos return resolved; 413 1.1 christos } 414 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 415 1.1 christos 416 1.1 christos /* Look up known symbols, and try to resolve the given identifier. */ 417 1.1 christos static bool 418 1.1 christos lookup_known_symbols (const char *identifier, 419 1.1 christos arg_token_t token_type, 420 1.1 christos arg_t *val_out) 421 1.1 christos { 422 1.1 christos if (identifier == NULL) 423 1.1 christos return false; 424 1.1 christos 425 1.1 christos arg_token_t high_ttype = (token_type & HT_MASK); 426 1.1 christos 427 1.1 christos #if (TC_OBJ_ATTR_v2) 428 1.1 christos static const oav2_identifier_t known_identifiers_subsection_optional[] = { 429 1.1 christos { "optional", { 430 1.1 christos .val.b = true, 431 1.1 christos .vtype = OAv2_ASM_ID_VALUE_BOOL 432 1.1 christos } 433 1.1 christos }, 434 1.1 christos { "required", { 435 1.1 christos .val.b = false, 436 1.1 christos .vtype = OAv2_ASM_ID_VALUE_BOOL 437 1.1 christos } 438 1.1 christos }, 439 1.1 christos }; 440 1.1 christos 441 1.1 christos static const oav2_identifier_t known_identifiers_subsection_encoding[] = { 442 1.1 christos { "uleb128", { 443 1.1 christos .val.u8 = obj_attr_encoding_v2_to_u8 (OA_ENC_ULEB128), 444 1.1 christos .vtype = OAv2_ASM_ID_VALUE_U8 445 1.1 christos } 446 1.1 christos }, 447 1.1 christos { "ntbs", { 448 1.1 christos .val.u8 = obj_attr_encoding_v2_to_u8 (OA_ENC_NTBS), 449 1.1 christos .vtype = OAv2_ASM_ID_VALUE_U8 450 1.1 christos } 451 1.1 christos }, 452 1.1 christos }; 453 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 454 1.1 christos 455 1.1 christos bool resolved = false; 456 1.1 christos 457 1.1 christos #if (TC_OBJ_ATTR_v2) 458 1.1 christos if (high_ttype == SUBSECTION_OPTION_1 || high_ttype == SUBSECTION_OPTION_2) 459 1.1 christos { 460 1.1 christos const oav2_identifier_t *known_identifiers 461 1.1 christos = (high_ttype == SUBSECTION_OPTION_1 462 1.1 christos ? known_identifiers_subsection_optional 463 1.1 christos : known_identifiers_subsection_encoding); 464 1.1 christos const size_t N_identifiers 465 1.1 christos = (high_ttype == SUBSECTION_OPTION_1 466 1.1 christos ? ARRAY_SIZE (known_identifiers_subsection_optional) 467 1.1 christos : ARRAY_SIZE (known_identifiers_subsection_encoding)); 468 1.1 christos 469 1.1 christos for (size_t i = 0; i < N_identifiers && ! resolved; ++i) 470 1.1 christos resolved = resolve_if_matching (identifier, 471 1.1 christos &known_identifiers[i], 472 1.1 christos val_out); 473 1.1 christos } 474 1.1 christos else 475 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 476 1.1 christos if (high_ttype == ATTRIBUTE_KEY) 477 1.1 christos { 478 1.1 christos obj_attr_version_t version = elf_obj_attr_version (stdoutput); 479 1.1 christos switch (version) 480 1.1 christos { 481 1.1 christos #if (TC_OBJ_ATTR_v1) 482 1.1 christos case OBJ_ATTR_V1: 483 1.1 christos resolved = obj_attr_v1_lookup_known_attr_tag_symbol 484 1.1 christos (identifier, token_type, val_out); 485 1.1 christos break; 486 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 487 1.1 christos #if (TC_OBJ_ATTR_v2) 488 1.1 christos case OBJ_ATTR_V2: 489 1.1 christos resolved = obj_attr_v2_lookup_known_attr_tag_symbol 490 1.1 christos (identifier, token_type, val_out); 491 1.1 christos break; 492 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 493 1.1 christos default: 494 1.1 christos abort (); 495 1.1 christos } 496 1.1 christos } 497 1.1 christos else 498 1.1 christos abort (); 499 1.1 christos 500 1.1 christos return resolved; 501 1.1 christos } 502 1.1 christos 503 1.1 christos /* Look up the symbol table of this compilation unit, and try to resolve the 504 1.1 christos given identifier. */ 505 1.1 christos static bool 506 1.1 christos lookup_symbol_table (const char *identifier, 507 1.1 christos const arg_token_t expected_ttype, 508 1.1 christos arg_t *val_out) 509 1.1 christos { 510 1.1 christos if (identifier == NULL) 511 1.1 christos return false; 512 1.1 christos 513 1.1 christos /* Note: signed integer are unsupported for now. */ 514 1.1 christos gas_assert (expected_ttype & UNSIGNED_INTEGER); 515 1.1 christos 516 1.1 christos symbolS *symbolP = symbol_find (identifier); 517 1.1 christos if (symbolP == NULL) 518 1.1 christos return false; 519 1.1 christos 520 1.1 christos if (! S_IS_DEFINED (symbolP)) 521 1.1 christos return false; 522 1.1 christos 523 1.1 christos valueT val = S_GET_VALUE (symbolP); 524 1.1 christos val_out->val.u64 = val; 525 1.1 christos val_out->vtype = VALUE_UNSIGNED_INTEGER; 526 1.1 christos 527 1.1 christos return true; 528 1.1 christos } 529 1.1 christos 530 1.1 christos /* Function similar to snprintf from the standard library, except that it 531 1.1 christos also updates the buffer pointer to point to the last written character, 532 1.1 christos and length to match the remaining space in the buffer. 533 1.1 christos Return the number of bytes printed. The function is assumed to always be 534 1.1 christos successful, and a failure with vnsprintf() will trigger an assert(). */ 535 1.1 christos static size_t 536 1.1 christos snprintf_append (char **sbuffer, size_t *length, 537 1.1 christos const char *format, ...) 538 1.1 christos { 539 1.1 christos va_list args; 540 1.1 christos va_start (args, format); 541 1.1 christos int rval = vsnprintf (*sbuffer, *length, format, args); 542 1.1 christos va_end (args); 543 1.1 christos 544 1.1 christos gas_assert (rval >= 0); 545 1.1 christos size_t written = rval; 546 1.1 christos *length -= written; 547 1.1 christos *sbuffer += written; 548 1.1 christos return written; 549 1.1 christos } 550 1.1 christos 551 1.1 christos /* Return the list of comma-separated strings matching the expected types 552 1.1 christos (i.e. the flags set in low_ttype). */ 553 1.1 christos static const char * 554 1.1 christos expectations_to_string (const arg_token_t low_ttype, 555 1.1 christos char *sbuffer, size_t length) 556 1.1 christos { 557 1.1 christos unsigned match_n = 0; 558 1.1 christos char *sbuffer_start = sbuffer; 559 1.1 christos size_t total = 0; 560 1.1 christos if (low_ttype & IDENTIFIER) 561 1.1 christos { 562 1.1 christos ++match_n; 563 1.1 christos total += snprintf_append (&sbuffer, &length, "`%s'", "identifier"); 564 1.1 christos } 565 1.1 christos 566 1.1 christos #define EXP_APPEND_TYPE_STR(type_flag, type_str) \ 567 1.1 christos if (low_ttype & type_flag) \ 568 1.1 christos { \ 569 1.1 christos if (match_n >= 1) \ 570 1.1 christos total += snprintf_append (&sbuffer, &length, "%s", ", or "); \ 571 1.1 christos ++match_n; \ 572 1.1 christos total += snprintf_append (&sbuffer, &length, "`%s'", type_str); \ 573 1.1 christos } 574 1.1 christos 575 1.1 christos EXP_APPEND_TYPE_STR (STRING, "string"); 576 1.1 christos EXP_APPEND_TYPE_STR (UNSIGNED_INTEGER, "unsigned integer"); 577 1.1 christos EXP_APPEND_TYPE_STR (SIGNED_INTEGER, "signed integer"); 578 1.1 christos #undef APPEND_TYPE_STR 579 1.1 christos 580 1.1 christos gas_assert (total <= length); 581 1.1 christos return sbuffer_start; 582 1.1 christos } 583 1.1 christos 584 1.1 christos /* In the context of object attributes, an identifier is defined with the 585 1.1 christos following lexical constraint: [a-zA-z_][a-zA-Z0-9_]*. An identifier can 586 1.1 christos be used to define the name of a subsection, its optionality, or its 587 1.1 christos encoding, as well as for an attribute's tag. */ 588 1.1 christos 589 1.1 christos static bool 590 1.1 christos is_identifier_beginner (char c) 591 1.1 christos { 592 1.1 christos return ISALPHA (c) || c == '_'; 593 1.1 christos } 594 1.1 christos 595 1.1 christos static bool 596 1.1 christos is_part_of_identifier (char c) 597 1.1 christos { 598 1.1 christos return ISALNUM (c) || c == '_'; 599 1.1 christos } 600 1.1 christos 601 1.1 christos /* Parse an argument, and set its type accordingly depending on the input 602 1.1 christos value, and the constraints on the expected argument. */ 603 1.1 christos static bool 604 1.1 christos obj_attr_parse_arg (arg_token_t expected_ttype, 605 1.1 christos bool resolve_identifier, 606 1.1 christos bool optional, 607 1.1 christos arg_t *arg_out) 608 1.1 christos { 609 1.1 christos const arg_token_t low_ttype = (expected_ttype & LT_MASK); 610 1.1 christos 611 1.1 christos if (optional && is_end_of_stmt (*input_line_pointer)) 612 1.1 christos { 613 1.1 christos arg_out->vtype = VALUE_OPTIONAL_ABSENT; 614 1.1 christos return true; 615 1.1 christos } 616 1.1 christos 617 1.1 christos /* Check whether this looks like a string literal 618 1.1 christos Note: symbol look-up for string literals is not available. */ 619 1.1 christos if (*input_line_pointer == '"') 620 1.1 christos { 621 1.1 christos bool status = extract_string_literal (arg_out); 622 1.1 christos if (status && (low_ttype & STRING)) 623 1.1 christos return true; 624 1.1 christos 625 1.1 christos if (status) 626 1.1 christos { 627 1.1 christos char sbuffer[100]; 628 1.1 christos as_bad (_("unexpected `string' \"%s\", expected %s instead"), 629 1.1 christos arg_out->val.string, 630 1.1 christos expectations_to_string (low_ttype, sbuffer, sizeof(sbuffer))); 631 1.1 christos free ((char *) arg_out->val.string); 632 1.1 christos arg_out->val.string = NULL; 633 1.1 christos arg_out->vtype = VALUE_UNDEFINED; 634 1.1 christos } 635 1.1 christos return false; 636 1.1 christos } 637 1.1 christos 638 1.1 christos /* Check whether this looks like an identifier. */ 639 1.1 christos if (is_identifier_beginner (*input_line_pointer)) 640 1.1 christos { 641 1.1 christos bool status = extract_identifier (is_part_of_identifier, arg_out); 642 1.1 christos /* is_identifier_beginner() confirmed that it was the beginning of an 643 1.1 christos identifier, so we don't expect the extraction to fail. */ 644 1.1 christos gas_assert (status); 645 1.1 christos gas_assert (arg_out->vtype == VALUE_STRING); 646 1.1 christos 647 1.1 christos if (! (low_ttype & IDENTIFIER)) 648 1.1 christos { 649 1.1 christos char sbuffer[100]; 650 1.1 christos as_bad (_("unexpected `identifier' \"%s\", expected %s instead"), 651 1.1 christos arg_out->val.string, 652 1.1 christos expectations_to_string (low_ttype, sbuffer, sizeof(sbuffer))); 653 1.1 christos free ((char *) arg_out->val.string); 654 1.1 christos arg_out->val.string = NULL; 655 1.1 christos arg_out->vtype = VALUE_UNDEFINED; 656 1.1 christos return false; 657 1.1 christos } 658 1.1 christos 659 1.1 christos /* In some cases, we don't want to resolve the identifier because it is the 660 1.1 christos actual value. */ 661 1.1 christos if (! resolve_identifier) 662 1.1 christos return true; 663 1.1 christos 664 1.1 christos /* Move the identifier out of arg_out. */ 665 1.1 christos const char *identifier = arg_out->val.string; 666 1.1 christos arg_out->val.string = NULL; 667 1.1 christos arg_out->vtype = VALUE_UNDEFINED; 668 1.1 christos bool resolved = true; 669 1.1 christos 670 1.1 christos /* The identifier is a symbol, let's try to resolve it by: 671 1.1 christos 1. using the provided list of known symbols. 672 1.1 christos a) backend-independent 673 1.1 christos b) backend-specific. */ 674 1.1 christos if (lookup_known_symbols (identifier, expected_ttype, arg_out)) 675 1.1 christos goto free_identifier; 676 1.1 christos 677 1.1 christos /* 2. using the symbol table for this compilation unit. 678 1.1 christos Note: this is the last attempt before failure. */ 679 1.1 christos if (lookup_symbol_table (identifier, low_ttype, arg_out)) 680 1.1 christos goto free_identifier; 681 1.1 christos 682 1.1 christos as_bad (_("unknown identifier '%s' in this context"), identifier); 683 1.1 christos resolved = false; 684 1.1 christos 685 1.1 christos free_identifier: 686 1.1 christos free ((char *) identifier); 687 1.1 christos return resolved; 688 1.1 christos } 689 1.1 christos 690 1.1 christos /* If it is neither a string nor an identifier, it must be an expression. */ 691 1.1 christos bool signedness_issue = false; 692 1.1 christos bool success = extract_integer_literal (arg_out, 693 1.1 christos (low_ttype & UNSIGNED_INTEGER), 694 1.1 christos &signedness_issue); 695 1.1 christos if (success && (low_ttype & (UNSIGNED_INTEGER | SIGNED_INTEGER))) 696 1.1 christos return true; 697 1.1 christos 698 1.1 christos char sbuffer[100]; 699 1.1 christos if (success) 700 1.1 christos as_bad (_("unexpected integer '%"PRIu64"', expected %s instead"), 701 1.1 christos arg_out->val.u64, 702 1.1 christos expectations_to_string (low_ttype, sbuffer, sizeof(sbuffer))); 703 1.1 christos else if ((low_ttype & UNSIGNED_INTEGER) && signedness_issue) 704 1.1 christos { 705 1.1 christos /* Already handled by extract_integer_literal(), nothing to do. */ 706 1.1 christos } 707 1.1 christos else 708 1.1 christos as_bad (_("fell back to integer literal extraction from expression, " 709 1.1 christos "but expected %s instead"), 710 1.1 christos expectations_to_string (low_ttype, sbuffer, sizeof(sbuffer))); 711 1.1 christos 712 1.1 christos arg_out->vtype = VALUE_UNDEFINED; 713 1.1 christos return false; 714 1.1 christos } 715 1.1 christos 716 1.1 christos /* Trim white space before a parameter. 717 1.1 christos Error if it meets a parameter separator before a parameter. */ 718 1.1 christos static bool 719 1.1 christos trim_whitespace_before_param (void) 720 1.1 christos { 721 1.1 christos skip_whitespace (input_line_pointer); 722 1.1 christos if (*input_line_pointer == ',') 723 1.1 christos { 724 1.1 christos as_bad (_("syntax error, comma not expected here")); 725 1.1 christos return false; 726 1.1 christos } 727 1.1 christos return true; 728 1.1 christos } 729 1.1 christos 730 1.1 christos /* Skip white space + parameter separator after a parameter. 731 1.1 christos Error if it does not meet a parameter separator after a parameter. */ 732 1.1 christos static bool 733 1.1 christos skip_whitespace_past_comma (void) 734 1.1 christos { 735 1.1 christos skip_whitespace (input_line_pointer); 736 1.1 christos if (! skip_past_comma (&input_line_pointer)) 737 1.1 christos { 738 1.1 christos as_bad (_("syntax error, comma missing here")); 739 1.1 christos return false; 740 1.1 christos } 741 1.1 christos return true; 742 1.1 christos } 743 1.1 christos 744 1.1 christos /* Can parse a list of arguments with variable length. */ 745 1.1 christos static bool 746 1.1 christos obj_attr_parse_args (arg_token_t expected_ttype, 747 1.1 christos bool resolve_identifier, 748 1.1 christos arg_t *arg_out) 749 1.1 christos { 750 1.1 christos if ((expected_ttype & LIST) == 0) 751 1.1 christos return obj_attr_parse_arg (expected_ttype, resolve_identifier, false, 752 1.1 christos arg_out); 753 1.1 christos 754 1.1 christos static const size_t LIST_MAX_SIZE = 2; 755 1.1 christos arg_t *arg_list = xcalloc (LIST_MAX_SIZE, sizeof (*arg_list)); 756 1.1 christos 757 1.1 christos /* We don't want to support recursive lists. */ 758 1.1 christos expected_ttype &= ~LIST; 759 1.1 christos 760 1.1 christos size_t n = 0; 761 1.1 christos do { 762 1.1 christos if (! trim_whitespace_before_param ()) 763 1.1 christos goto bad; 764 1.1 christos 765 1.1 christos if (! obj_attr_parse_arg (expected_ttype, resolve_identifier, false, 766 1.1 christos &arg_list[n])) 767 1.1 christos goto bad; 768 1.1 christos 769 1.1 christos ++n; 770 1.1 christos skip_whitespace (input_line_pointer); 771 1.1 christos if (is_end_of_stmt (*input_line_pointer)) 772 1.1 christos break; 773 1.1 christos 774 1.1 christos if (! skip_whitespace_past_comma ()) 775 1.1 christos goto bad; 776 1.1 christos 777 1.1 christos if (n >= LIST_MAX_SIZE) 778 1.1 christos { 779 1.1 christos as_bad ("too many arguments for a list (max: %zu)", LIST_MAX_SIZE); 780 1.1 christos goto bad; 781 1.1 christos } 782 1.1 christos } while (n < LIST_MAX_SIZE); 783 1.1 christos 784 1.1 christos arg_out->vtype = VALUE_LIST; 785 1.1 christos arg_out->val.list.len = n; 786 1.1 christos arg_out->val.list.elts = arg_list; 787 1.1 christos return true; 788 1.1 christos 789 1.1 christos bad: 790 1.1 christos args_list_free (arg_list, n); 791 1.1 christos return false; 792 1.1 christos } 793 1.1 christos 794 1.1 christos #if (TC_OBJ_ATTR_v2) 795 1.1 christos static bool 796 1.1 christos is_valid_boolean (uint64_t value) 797 1.1 christos { 798 1.1 christos return value <= 1; 799 1.1 christos } 800 1.1 christos 801 1.1 christos #define is_valid_comprehension is_valid_boolean 802 1.1 christos 803 1.1 christos static bool 804 1.1 christos is_valid_encoding (uint64_t value) 805 1.1 christos { 806 1.1 christos value = obj_attr_encoding_v2_from_u8 (value); 807 1.1 christos return OA_ENC_UNSET < value && value <= OA_ENC_MAX; 808 1.1 christos } 809 1.1 christos 810 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 811 1.1 christos 812 1.1 christos #if (TC_OBJ_ATTR_v1) 813 1.1 christos /* Determine the expected argument type based on the tag ID. */ 814 1.1 christos static arg_token_t 815 1.1 christos obj_attr_v1_get_arg_type (bfd *abfd, 816 1.1 christos obj_attr_vendor_t vendor, 817 1.1 christos obj_attr_tag_t tag) 818 1.1 christos { 819 1.1 christos int attr_type = bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); 820 1.1 christos arg_token_t arg_type; 821 1.1 christos if (attr_type == (ATTR_TYPE_FLAG_STR_VAL | ATTR_TYPE_FLAG_INT_VAL)) 822 1.1 christos arg_type = LIST | UNSIGNED_INTEGER | STRING; 823 1.1 christos else if (attr_type == ATTR_TYPE_FLAG_STR_VAL) 824 1.1 christos arg_type = STRING; 825 1.1 christos else 826 1.1 christos /* Covers the remaning cases: 827 1.1 christos - ATTR_TYPE_FLAG_INT_VAL. 828 1.1 christos - ATTR_TYPE_FLAG_INT_VAL | ATTR_TYPE_FLAG_NO_DEFAULT. */ 829 1.1 christos arg_type = UNSIGNED_INTEGER; 830 1.1 christos return arg_type; 831 1.1 christos } 832 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 833 1.1 christos 834 1.1 christos #if (TC_OBJ_ATTR_v2) 835 1.1 christos /* Determine the expected argument type based on the subsection encoding. */ 836 1.1 christos static arg_token_t 837 1.1 christos obj_attr_v2_get_arg_type (obj_attr_encoding_v2_t subsec_encoding) 838 1.1 christos { 839 1.1 christos arg_token_t arg_type; 840 1.1 christos switch (subsec_encoding) 841 1.1 christos { 842 1.1 christos case OA_ENC_ULEB128: 843 1.1 christos arg_type = UNSIGNED_INTEGER; 844 1.1 christos break; 845 1.1 christos case OA_ENC_NTBS: 846 1.1 christos arg_type = STRING; 847 1.1 christos break; 848 1.1 christos case OA_ENC_UNSET: 849 1.1 christos default: 850 1.1 christos abort (); 851 1.1 christos } 852 1.1 christos return arg_type; 853 1.1 christos } 854 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 855 1.1 christos 856 1.1 christos /* Parse the arguments of [vendor]_attribute directive. */ 857 1.1 christos static arg_t * 858 1.1 christos vendor_attribute_parse_args (obj_attr_vendor_t vendor ATTRIBUTE_UNUSED, 859 1.1 christos const obj_attr_subsection_v2_t *subsec ATTRIBUTE_UNUSED, 860 1.1 christos unsigned int nargs, ...) 861 1.1 christos { 862 1.1 christos va_list args; 863 1.1 christos va_start (args, nargs); 864 1.1 christos 865 1.1 christos arg_t *args_out = xcalloc (nargs, sizeof (arg_t)); 866 1.1 christos 867 1.1 christos for (unsigned int n = 0; n < nargs; ++n) 868 1.1 christos { 869 1.1 christos if (! trim_whitespace_before_param ()) 870 1.1 christos goto bad; 871 1.1 christos 872 1.1 christos arg_t *arg_out = &args_out[n]; 873 1.1 christos 874 1.1 christos arg_token_t expected_ttype = va_arg (args, arg_token_t); 875 1.1 christos arg_token_t high_ttype = (expected_ttype & HT_MASK); 876 1.1 christos /* Make sure that we called the right parse_args(). */ 877 1.1 christos gas_assert (high_ttype == ATTRIBUTE_KEY 878 1.1 christos || high_ttype == ATTRIBUTE_VALUE); 879 1.1 christos 880 1.1 christos if (high_ttype == ATTRIBUTE_VALUE) 881 1.1 christos { 882 1.1 christos arg_token_t type_attr_value 883 1.1 christos #if (TC_OBJ_ATTR_v1 && TC_OBJ_ATTR_v2) 884 1.1 christos = (subsec != NULL) 885 1.1 christos ? obj_attr_v2_get_arg_type (subsec->encoding) 886 1.1 christos : obj_attr_v1_get_arg_type (stdoutput, vendor, 887 1.1 christos args_out[n - 1].val.u64); 888 1.1 christos #elif (TC_OBJ_ATTR_v1) 889 1.1 christos = obj_attr_v1_get_arg_type (stdoutput, vendor, 890 1.1 christos args_out[n - 1].val.u64); 891 1.1 christos #else /* TC_OBJ_ATTR_v2 */ 892 1.1 christos = obj_attr_v2_get_arg_type (subsec->encoding); 893 1.1 christos #endif 894 1.1 christos expected_ttype |= type_attr_value; 895 1.1 christos } 896 1.1 christos 897 1.1 christos if (! obj_attr_parse_args (expected_ttype, true, arg_out)) 898 1.1 christos { 899 1.1 christos if (high_ttype == ATTRIBUTE_KEY) 900 1.1 christos { 901 1.1 christos as_bad (_("could not parse attribute tag")); 902 1.1 christos goto bad; 903 1.1 christos } 904 1.1 christos else 905 1.1 christos { 906 1.1 christos as_bad (_("could not parse attribute value")); 907 1.1 christos goto bad; 908 1.1 christos } 909 1.1 christos } 910 1.1 christos 911 1.1 christos if (n + 1 < nargs && !skip_whitespace_past_comma ()) 912 1.1 christos goto bad; 913 1.1 christos } 914 1.1 christos 915 1.1 christos demand_empty_rest_of_line (); 916 1.1 christos va_end (args); 917 1.1 christos return args_out; 918 1.1 christos 919 1.1 christos bad: 920 1.1 christos ignore_rest_of_line (); 921 1.1 christos args_list_free (args_out, nargs); 922 1.1 christos va_end (args); 923 1.1 christos return NULL; 924 1.1 christos } 925 1.1 christos 926 1.1 christos #if (TC_OBJ_ATTR_v1) 927 1.1 christos /* Record an attribute (object attribute v1 only). */ 928 1.1 christos static obj_attribute * 929 1.1 christos obj_attr_v1_record (bfd *abfd, 930 1.1 christos const obj_attr_vendor_t vendor, 931 1.1 christos const obj_attr_tag_t tag, 932 1.1 christos arg_t *parsed_arg) 933 1.1 christos { 934 1.1 christos obj_attribute *attr = bfd_elf_new_obj_attr (abfd, vendor, tag); 935 1.1 christos if (attr != NULL) 936 1.1 christos { 937 1.1 christos attr->type = bfd_elf_obj_attrs_arg_type (abfd, vendor, tag); 938 1.1 christos if (parsed_arg->vtype == VALUE_LIST) 939 1.1 christos { 940 1.1 christos arg_variant_list_t *plist = &parsed_arg->val.list; 941 1.1 christos gas_assert (plist->len == 2 942 1.1 christos && plist->elts[0].vtype == VALUE_UNSIGNED_INTEGER 943 1.1 christos && plist->elts[1].vtype == VALUE_STRING); 944 1.1 christos attr->i = plist->elts[0].val.u64; 945 1.1 christos attr->s = (char *) plist->elts[1].val.string; 946 1.1 christos plist->elts[1].val.string = NULL; 947 1.1 christos } 948 1.1 christos else if (parsed_arg->vtype == VALUE_STRING) 949 1.1 christos { 950 1.1 christos attr->s = (char *) parsed_arg->val.string; 951 1.1 christos parsed_arg->val.string = NULL; 952 1.1 christos } 953 1.1 christos else 954 1.1 christos { 955 1.1 christos attr->i = parsed_arg->val.u64; 956 1.1 christos } 957 1.1 christos } 958 1.1 christos return attr; 959 1.1 christos } 960 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 961 1.1 christos 962 1.1 christos #if (TC_OBJ_ATTR_v2) 963 1.1 christos /* Parse the arguments of [vendor]_subsection directive (v2 only). */ 964 1.1 christos static arg_t * 965 1.1 christos vendor_subsection_parse_args (unsigned int nargs, ...) 966 1.1 christos { 967 1.1 christos va_list args; 968 1.1 christos va_start (args, nargs); 969 1.1 christos 970 1.1 christos arg_t *args_out = xcalloc (nargs, sizeof (arg_t)); 971 1.1 christos 972 1.1 christos for (unsigned int n = 0; n < nargs; ++n) 973 1.1 christos { 974 1.1 christos if (! trim_whitespace_before_param ()) 975 1.1 christos goto bad; 976 1.1 christos 977 1.1 christos arg_t *arg_out = &args_out[n]; 978 1.1 christos 979 1.1 christos arg_token_t expected_ttype = va_arg (args, arg_token_t); 980 1.1 christos arg_token_t high_ttype = (expected_ttype & HT_MASK); 981 1.1 christos /* Make sure that we called the right parse_args(). */ 982 1.1 christos gas_assert (high_ttype == SUBSECTION_NAME 983 1.1 christos || high_ttype == SUBSECTION_OPTION_1 984 1.1 christos || high_ttype == SUBSECTION_OPTION_2); 985 1.1 christos 986 1.1 christos if (high_ttype == SUBSECTION_NAME) 987 1.1 christos { 988 1.1 christos if (! obj_attr_parse_arg (expected_ttype, false, false, arg_out)) 989 1.1 christos { 990 1.1 christos as_bad (_("expected <subsection_name>, <comprehension>, " 991 1.1 christos "<encoding>")); 992 1.1 christos goto bad; 993 1.1 christos } 994 1.1 christos } 995 1.1 christos else if (high_ttype == SUBSECTION_OPTION_1 996 1.1 christos || high_ttype == SUBSECTION_OPTION_2) 997 1.1 christos { 998 1.1 christos if (! obj_attr_parse_arg (expected_ttype, true, true, arg_out)) 999 1.1 christos goto bad; 1000 1.1 christos 1001 1.1 christos if (arg_out->vtype == VALUE_OPTIONAL_ABSENT) 1002 1.1 christos continue; 1003 1.1 christos 1004 1.1 christos if (high_ttype == SUBSECTION_OPTION_1 1005 1.1 christos && ! is_valid_comprehension (arg_out->val.u64)) 1006 1.1 christos { 1007 1.1 christos as_bad 1008 1.1 christos (_("invalid value '%" PRIu64 "', expected values for " 1009 1.1 christos "<comprehension> are 0 (=`required') or 1 (=`optional')"), 1010 1.1 christos arg_out->val.u64); 1011 1.1 christos goto bad; 1012 1.1 christos } 1013 1.1 christos else if (high_ttype == SUBSECTION_OPTION_2 1014 1.1 christos && ! is_valid_encoding (arg_out->val.u64)) 1015 1.1 christos { 1016 1.1 christos as_bad 1017 1.1 christos (_("invalid value '%" PRIu64 "', expected values for <encoding>" 1018 1.1 christos " are 0 (=`ULEB128') or 1 (=`NTBS')"), 1019 1.1 christos arg_out->val.u64); 1020 1.1 christos goto bad; 1021 1.1 christos } 1022 1.1 christos } 1023 1.1 christos else 1024 1.1 christos abort (); 1025 1.1 christos 1026 1.1 christos if (n + 1 < nargs 1027 1.1 christos && ! is_end_of_stmt (*input_line_pointer) 1028 1.1 christos && ! skip_whitespace_past_comma ()) 1029 1.1 christos goto bad; 1030 1.1 christos } 1031 1.1 christos 1032 1.1 christos va_end (args); 1033 1.1 christos demand_empty_rest_of_line (); 1034 1.1 christos return args_out; 1035 1.1 christos 1036 1.1 christos bad: 1037 1.1 christos ignore_rest_of_line (); 1038 1.1 christos args_list_free (args_out, nargs); 1039 1.1 christos va_end (args); 1040 1.1 christos return NULL; 1041 1.1 christos } 1042 1.1 christos 1043 1.1 christos /* Record an attribute (object attribute v2 only). */ 1044 1.1 christos static void 1045 1.1 christos obj_attr_v2_record (obj_attr_tag_t key, arg_t *arg_val) 1046 1.1 christos { 1047 1.1 christos /* An OAv2 cannot be recorded unless a subsection has been recorded. */ 1048 1.1 christos gas_assert (elf_obj_attr_subsections (stdoutput).last != NULL); 1049 1.1 christos 1050 1.1 christos union obj_attr_value_v2 obj_attr_val; 1051 1.1 christos if (arg_val->vtype == VALUE_UNSIGNED_INTEGER) 1052 1.1 christos obj_attr_val.uint = arg_val->val.u64; 1053 1.1 christos else 1054 1.1 christos { 1055 1.1 christos /* Move the string. */ 1056 1.1 christos obj_attr_val.string = arg_val->val.string; 1057 1.1 christos arg_val->val.string = NULL; 1058 1.1 christos } 1059 1.1 christos 1060 1.1 christos obj_attr_v2_t *obj_attr = bfd_elf_obj_attr_v2_init (key, obj_attr_val); 1061 1.1 christos gas_assert (obj_attr != NULL); 1062 1.1 christos 1063 1.1 christos /* Go over the list of already recorded attributes and check for 1064 1.1 christos redefinitions (which are forbidden). */ 1065 1.1 christos bool skip_recording = false; 1066 1.1 christos obj_attr_v2_t *recorded_attr = bfd_obj_attr_v2_find_by_tag 1067 1.1 christos (elf_obj_attr_subsections (stdoutput).last, obj_attr->tag, false); 1068 1.1 christos if (recorded_attr != NULL) 1069 1.1 christos { 1070 1.1 christos if ((arg_val->vtype == VALUE_UNSIGNED_INTEGER 1071 1.1 christos && recorded_attr->val.uint != obj_attr->val.uint) 1072 1.1 christos || (arg_val->vtype == VALUE_STRING 1073 1.1 christos && strcmp (recorded_attr->val.string, obj_attr->val.string) != 0)) 1074 1.1 christos as_bad (_("attribute '%" PRIu64 "' cannot be redefined"), 1075 1.1 christos recorded_attr->tag); 1076 1.1 christos skip_recording = true; 1077 1.1 christos } 1078 1.1 christos 1079 1.1 christos if (skip_recording) 1080 1.1 christos { 1081 1.1 christos if (arg_val->vtype == VALUE_STRING) 1082 1.1 christos free ((void *) obj_attr->val.string); 1083 1.1 christos free (obj_attr); 1084 1.1 christos return; 1085 1.1 christos } 1086 1.1 christos 1087 1.1 christos bfd_obj_attr_subsection_v2_append 1088 1.1 christos (elf_obj_attr_subsections (stdoutput).last, obj_attr); 1089 1.1 christos } 1090 1.1 christos 1091 1.1 christos /* Record a subsection (object attribute v2 only). 1092 1.1 christos Note: this function takes the ownership of 'name', so is responsible to free 1093 1.1 christos it if an issue occurs. */ 1094 1.1 christos static void 1095 1.1 christos obj_attr_v2_subsection_record (const char *name, 1096 1.1 christos arg_t *arg_comprehension, 1097 1.1 christos arg_t *arg_encoding) 1098 1.1 christos { 1099 1.1 christos obj_attr_subsection_v2_t *already_recorded_subsec 1100 1.1 christos = bfd_obj_attr_subsection_v2_find_by_name 1101 1.1 christos (elf_obj_attr_subsections (stdoutput).first, name, false); 1102 1.1 christos 1103 1.1 christos bool comprehension_optional = arg_comprehension->val.u64; 1104 1.1 christos obj_attr_encoding_v2_t encoding 1105 1.1 christos = obj_attr_encoding_v2_from_u8 (arg_encoding->val.u64); 1106 1.1 christos 1107 1.1 christos if (already_recorded_subsec != NULL) 1108 1.1 christos { 1109 1.1 christos bool error_redeclaration = false; 1110 1.1 christos 1111 1.1 christos if (arg_comprehension->vtype == VALUE_OPTIONAL_ABSENT) 1112 1.1 christos gas_assert (arg_encoding->vtype == VALUE_OPTIONAL_ABSENT); 1113 1.1 christos else if (comprehension_optional != already_recorded_subsec->optional) 1114 1.1 christos error_redeclaration = true; 1115 1.1 christos 1116 1.1 christos if (arg_encoding->vtype != VALUE_OPTIONAL_ABSENT 1117 1.1 christos && encoding != already_recorded_subsec->encoding) 1118 1.1 christos error_redeclaration = true; 1119 1.1 christos 1120 1.1 christos /* Check for mismatching redefinition of the subsection, i.e. the names 1121 1.1 christos match but the properties are different. */ 1122 1.1 christos if (error_redeclaration) 1123 1.1 christos { 1124 1.1 christos const char *prev_comprehension = bfd_oav2_comprehension_to_string ( 1125 1.1 christos already_recorded_subsec->optional); 1126 1.1 christos const char *prev_encoding = bfd_oav2_encoding_to_string ( 1127 1.1 christos already_recorded_subsec->encoding); 1128 1.1 christos as_bad (_("incompatible redeclaration of subsection %s"), name); 1129 1.1 christos as_info (1, _("previous declaration had properties: %s=%s, %s=%s"), 1130 1.1 christos "comprehension", prev_comprehension, 1131 1.1 christos "encoding", prev_encoding); 1132 1.1 christos goto free_name; 1133 1.1 christos } 1134 1.1 christos 1135 1.1 christos /* Move the existing subsection to the last position. */ 1136 1.1 christos bfd_obj_attr_subsection_v2_list_remove 1137 1.1 christos (&elf_obj_attr_subsections (stdoutput), already_recorded_subsec); 1138 1.1 christos bfd_obj_attr_subsection_v2_list_append 1139 1.1 christos (&elf_obj_attr_subsections (stdoutput), already_recorded_subsec); 1140 1.1 christos /* Note: 'name' was unused, and will be freed on exit. */ 1141 1.1 christos } 1142 1.1 christos else 1143 1.1 christos { 1144 1.1 christos if (arg_comprehension->vtype == VALUE_OPTIONAL_ABSENT 1145 1.1 christos || arg_encoding->vtype == VALUE_OPTIONAL_ABSENT) 1146 1.1 christos { 1147 1.1 christos as_bad (_("comprehension and encoding of a subsection cannot be " 1148 1.1 christos "omitted on the first declaration")); 1149 1.1 christos goto free_name; 1150 1.1 christos } 1151 1.1 christos 1152 1.1 christos obj_attr_subsection_scope_v2_t scope 1153 1.1 christos = bfd_elf_obj_attr_subsection_v2_scope (stdoutput, name); 1154 1.1 christos 1155 1.1 christos /* Note: ownership of 'name' is transfered to the callee when initializing 1156 1.1 christos the subsection. That is why we skip free() at the end. */ 1157 1.1 christos obj_attr_subsection_v2_t *new_subsection 1158 1.1 christos = bfd_elf_obj_attr_subsection_v2_init (name, scope, 1159 1.1 christos comprehension_optional, 1160 1.1 christos encoding); 1161 1.1 christos bfd_obj_attr_subsection_v2_list_append 1162 1.1 christos (&elf_obj_attr_subsections (stdoutput), new_subsection); 1163 1.1 christos return; 1164 1.1 christos } 1165 1.1 christos 1166 1.1 christos free_name: 1167 1.1 christos free ((void *) name); 1168 1.1 christos } 1169 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 1170 1.1 christos 1171 1.1 christos /* Parse an attribute directive (supports both v1 & v2). */ 1172 1.1 christos obj_attr_tag_t 1173 1.1 christos obj_attr_process_attribute (obj_attr_vendor_t vendor) 1174 1.1 christos { 1175 1.1 christos obj_attr_version_t version = elf_obj_attr_version (stdoutput); 1176 1.1 christos obj_attr_subsection_v2_t *subsec = NULL; 1177 1.1 christos 1178 1.1 christos #if (TC_OBJ_ATTR_v2) 1179 1.1 christos if (version == OBJ_ATTR_V2) 1180 1.1 christos { 1181 1.1 christos subsec = elf_obj_attr_subsections (stdoutput).last; 1182 1.1 christos if (subsec == NULL) 1183 1.1 christos { 1184 1.1 christos as_bad (_("declaration of an attribute outside the scope of an " 1185 1.1 christos "attribute subsection")); 1186 1.1 christos ignore_rest_of_line (); 1187 1.1 christos return 0; 1188 1.1 christos } 1189 1.1 christos } 1190 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 1191 1.1 christos 1192 1.1 christos const size_t N_ARGS = 2; 1193 1.1 christos arg_t *args = vendor_attribute_parse_args ( 1194 1.1 christos vendor, subsec, N_ARGS, 1195 1.1 christos ATTRIBUTE_KEY | IDENTIFIER | UNSIGNED_INTEGER, 1196 1.1 christos ATTRIBUTE_VALUE); 1197 1.1 christos 1198 1.1 christos if (args == NULL) 1199 1.1 christos return 0; 1200 1.1 christos 1201 1.1 christos obj_attr_tag_t tag = args[0].val.u64; 1202 1.1 christos switch (version) 1203 1.1 christos { 1204 1.1 christos #if (TC_OBJ_ATTR_v1) 1205 1.1 christos case OBJ_ATTR_V1: 1206 1.1 christos oav1_attr_record_seen (vendor, tag); 1207 1.1 christos obj_attr_v1_record (stdoutput, vendor, tag, &args[1]); 1208 1.1 christos break; 1209 1.1 christos #endif /* TC_OBJ_ATTR_v1 */ 1210 1.1 christos #if (TC_OBJ_ATTR_v2) 1211 1.1 christos case OBJ_ATTR_V2: 1212 1.1 christos obj_attr_v2_record (tag, &args[1]); 1213 1.1 christos break; 1214 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 1215 1.1 christos default: 1216 1.1 christos abort (); 1217 1.1 christos } 1218 1.1 christos 1219 1.1 christos args_list_free (args, N_ARGS); 1220 1.1 christos 1221 1.1 christos return tag; 1222 1.1 christos } 1223 1.1 christos 1224 1.1 christos #if (TC_OBJ_ATTR_v2) 1225 1.1 christos /* Parse an object attribute v2's subsection directive. */ 1226 1.1 christos void 1227 1.1 christos obj_attr_process_subsection (void) 1228 1.1 christos { 1229 1.1 christos const size_t N_ARGS = 3; 1230 1.1 christos arg_t *args = vendor_subsection_parse_args ( 1231 1.1 christos N_ARGS, 1232 1.1 christos SUBSECTION_NAME | IDENTIFIER, 1233 1.1 christos SUBSECTION_OPTION_1 | IDENTIFIER | UNSIGNED_INTEGER, 1234 1.1 christos SUBSECTION_OPTION_2 | IDENTIFIER | UNSIGNED_INTEGER); 1235 1.1 christos 1236 1.1 christos if (args == NULL) 1237 1.1 christos return; 1238 1.1 christos 1239 1.1 christos /* Note: move the value to avoid double free. */ 1240 1.1 christos const char *name = args[0].val.string; 1241 1.1 christos args[0].val.string = NULL; 1242 1.1 christos 1243 1.1 christos /* Note: ownership of 'name' is transferred to the callee. */ 1244 1.1 christos obj_attr_v2_subsection_record (name, &args[1], &args[2]); 1245 1.1 christos args_list_free (args, N_ARGS); 1246 1.1 christos } 1247 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 1248 1.1 christos 1249 1.1 christos /* Parse a .gnu_attribute directive. */ 1250 1.1 christos 1251 1.1 christos void 1252 1.1 christos obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED) 1253 1.1 christos { 1254 1.1 christos obj_attr_process_attribute (OBJ_ATTR_GNU); 1255 1.1 christos } 1256 1.1 christos 1257 1.1 christos #if (TC_OBJ_ATTR_v2) 1258 1.1 christos /* Return True if the VERSION of object attributes supports subsections, False 1259 1.1 christos otherwise. */ 1260 1.1 christos 1261 1.1 christos static inline bool 1262 1.1 christos attr_fmt_has_subsections (obj_attr_version_t version) 1263 1.1 christos { 1264 1.1 christos switch (version) 1265 1.1 christos { 1266 1.1 christos case OBJ_ATTR_V1: 1267 1.1 christos return false; 1268 1.1 christos case OBJ_ATTR_V2: 1269 1.1 christos return true; 1270 1.1 christos default: 1271 1.1 christos abort (); /* Unsupported format. */ 1272 1.1 christos } 1273 1.1 christos } 1274 1.1 christos 1275 1.1 christos /* Parse a .gnu_subsection directive. */ 1276 1.1 christos 1277 1.1 christos void 1278 1.1 christos obj_elf_gnu_subsection (int ignored ATTRIBUTE_UNUSED) 1279 1.1 christos { 1280 1.1 christos obj_attr_version_t version = elf_obj_attr_version (stdoutput); 1281 1.1 christos if (! attr_fmt_has_subsections (version)) 1282 1.1 christos { 1283 1.1 christos as_bad (_(".gnu_subsection is only available with object attributes v2")); 1284 1.1 christos ignore_rest_of_line (); 1285 1.1 christos return; 1286 1.1 christos } 1287 1.1 christos obj_attr_process_subsection (); 1288 1.1 christos } 1289 1.1 christos #endif /* TC_OBJ_ATTR_v2 */ 1290 1.1 christos 1291 1.1 christos #endif /* TC_OBJ_ATTR */ 1292