Home | History | Annotate | Line # | Download | only in config
      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 (&notes, 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