diff options
Diffstat (limited to 'gas/config')
-rw-r--r-- | gas/config/obj-elf.c | 136 | ||||
-rw-r--r-- | gas/config/obj-elf.h | 1 | ||||
-rw-r--r-- | gas/config/tc-arm.c | 2 | ||||
-rw-r--r-- | gas/config/tc-tic6x.c | 2 |
4 files changed, 139 insertions, 2 deletions
diff --git a/gas/config/obj-elf.c b/gas/config/obj-elf.c index d0fbcfb..6450328 100644 --- a/gas/config/obj-elf.c +++ b/gas/config/obj-elf.c @@ -72,6 +72,7 @@ static void obj_elf_visibility (int); static void obj_elf_symver (int); static void obj_elf_subsection (int); static void obj_elf_popsection (int); +static void obj_elf_gnu_attribute (int); static void obj_elf_tls_common (int); static void obj_elf_lcomm (int); static void obj_elf_struct (int); @@ -113,6 +114,9 @@ static const pseudo_typeS elf_pseudo_table[] = {"vtable_inherit", (void (*) (int)) &obj_elf_vtable_inherit, 0}, {"vtable_entry", (void (*) (int)) &obj_elf_vtable_entry, 0}, + /* A GNU extension for object attributes. */ + {"gnu_attribute", obj_elf_gnu_attribute, 0}, + /* These are used for dwarf. */ {"2byte", cons, 2}, {"4byte", cons, 4}, @@ -1437,6 +1441,138 @@ obj_elf_vtable_entry (int ignore ATTRIBUTE_UNUSED) BFD_RELOC_VTABLE_ENTRY); } +#define skip_whitespace(str) do { if (*(str) == ' ') ++(str); } while (0) + +static inline int +skip_past_char (char ** str, char c) +{ + if (**str == c) + { + (*str)++; + return 0; + } + else + return -1; +} +#define skip_past_comma(str) skip_past_char (str, ',') + +/* Parse an attribute directive for VENDOR. + Returns the attribute number read, or zero on error. */ + +int +obj_elf_vendor_attribute (int vendor) +{ + expressionS exp; + int type; + int tag; + unsigned int i = 0; + char *s = NULL; + + /* Read the first number or name. */ + skip_whitespace (input_line_pointer); + s = input_line_pointer; + if (ISDIGIT (*input_line_pointer)) + { + expression (& exp); + if (exp.X_op != O_constant) + goto bad; + tag = exp.X_add_number; + } + else + { + char *name; + + /* A name may contain '_', but no other punctuation. */ + for (; ISALNUM (*input_line_pointer) || *input_line_pointer == '_'; + ++input_line_pointer) + i++; + if (i == 0) + goto bad; + + name = (char *) alloca (i + 1); + memcpy (name, s, i); + name[i] = '\0'; + +#ifndef CONVERT_SYMBOLIC_ATTRIBUTE +#define CONVERT_SYMBOLIC_ATTRIBUTE(a) -1 +#endif + + tag = CONVERT_SYMBOLIC_ATTRIBUTE (name); + if (tag == -1) + { + as_bad (_("Attribute name not recognised: %s"), name); + ignore_rest_of_line (); + return 0; + } + } + + type = _bfd_elf_obj_attrs_arg_type (stdoutput, vendor, tag); + + if (skip_past_comma (&input_line_pointer) == -1) + goto bad; + if (type & 1) + { + expression (& exp); + if (exp.X_op != O_constant) + { + as_bad (_("expected numeric constant")); + ignore_rest_of_line (); + return 0; + } + i = exp.X_add_number; + } + if ((type & 3) == 3 + && skip_past_comma (&input_line_pointer) == -1) + { + as_bad (_("expected comma")); + ignore_rest_of_line (); + return 0; + } + if (type & 2) + { + int len; + + skip_whitespace (input_line_pointer); + if (*input_line_pointer != '"') + goto bad_string; + s = demand_copy_C_string (&len); + } + + switch (type & 3) + { + case 3: + bfd_elf_add_obj_attr_int_string (stdoutput, vendor, tag, i, s); + break; + case 2: + bfd_elf_add_obj_attr_string (stdoutput, vendor, tag, s); + break; + case 1: + bfd_elf_add_obj_attr_int (stdoutput, vendor, tag, i); + break; + default: + abort (); + } + + demand_empty_rest_of_line (); + return tag; +bad_string: + as_bad (_("bad string constant")); + ignore_rest_of_line (); + return 0; +bad: + as_bad (_("expected <tag> , <value>")); + ignore_rest_of_line (); + return 0; +} + +/* Parse a .gnu_attribute directive. */ + +static void +obj_elf_gnu_attribute (int ignored ATTRIBUTE_UNUSED) +{ + obj_elf_vendor_attribute (OBJ_ATTR_GNU); +} + void elf_obj_read_begin_hook (void) { diff --git a/gas/config/obj-elf.h b/gas/config/obj-elf.h index 0721654..d4fd4d5 100644 --- a/gas/config/obj-elf.h +++ b/gas/config/obj-elf.h @@ -167,6 +167,7 @@ extern void obj_elf_change_section (const char *, int, bfd_vma, int, const char *, int, int); extern struct fix *obj_elf_vtable_inherit (int); extern struct fix *obj_elf_vtable_entry (int); +extern int obj_elf_vendor_attribute (int); /* BFD wants to write the udata field, which is a no-no for the predefined section symbols in bfd/section.c. They are read-only. */ diff --git a/gas/config/tc-arm.c b/gas/config/tc-arm.c index 1ce5459..971ac6f 100644 --- a/gas/config/tc-arm.c +++ b/gas/config/tc-arm.c @@ -4336,7 +4336,7 @@ s_arm_unwind_raw (int ignored ATTRIBUTE_UNUSED) static void s_arm_eabi_attribute (int ignored ATTRIBUTE_UNUSED) { - int tag = s_vendor_attribute (OBJ_ATTR_PROC); + int tag = obj_elf_vendor_attribute (OBJ_ATTR_PROC); if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) attributes_set_explicitly[tag] = 1; diff --git a/gas/config/tc-tic6x.c b/gas/config/tc-tic6x.c index ddbfb50..65517a6 100644 --- a/gas/config/tc-tic6x.c +++ b/gas/config/tc-tic6x.c @@ -693,7 +693,7 @@ static bfd_boolean tic6x_attributes_set_explicitly[NUM_KNOWN_OBJ_ATTRIBUTES]; static void s_tic6x_c6xabi_attribute (int ignored ATTRIBUTE_UNUSED) { - int tag = s_vendor_attribute (OBJ_ATTR_PROC); + int tag = obj_elf_vendor_attribute (OBJ_ATTR_PROC); if (tag < NUM_KNOWN_OBJ_ATTRIBUTES) tic6x_attributes_set_explicitly[tag] = TRUE; |