Allow symbols in MEMORY region specification
[deliverable/binutils-gdb.git] / gas / config / obj-elf.c
index 52c6b641227537cf4bbe2443094e89c04e2e7268..4d7a8a730113848f885878698a4ed9c9eb0ba35d 100644 (file)
@@ -1,5 +1,5 @@
 /* ELF object file format
-   Copyright (C) 1992-2014 Free Software Foundation, Inc.
+   Copyright (C) 1992-2015 Free Software Foundation, Inc.
 
    This file is part of GAS, the GNU Assembler.
 
@@ -266,7 +266,7 @@ elf_file_symbol (const char *s, int appfile)
       || (symbol_rootP->bsym->flags & BSF_FILE) == 0)
     {
       symbolS *sym;
-      unsigned int name_length;
+      size_t name_length;
 
       sym = symbol_new (s, absolute_section, 0, NULL);
       symbol_set_frag (sym, &zero_address_frag);
@@ -1458,6 +1458,62 @@ skip_past_char (char ** str, char c)
 }
 #define skip_past_comma(str) skip_past_char (str, ',')
 
+/* A list of attributes that have been explicitly set by the assembly code.
+   VENDOR is the vendor id, BASE is the tag shifted right by the number
+   of bits in MASK, and bit N of MASK is set if tag BASE+N has been set.  */
+struct recorded_attribute_info {
+  struct recorded_attribute_info *next;
+  int vendor;
+  unsigned int base;
+  unsigned long mask;
+};
+static struct recorded_attribute_info *recorded_attributes;
+
+/* Record that we have seen an explicit specification of attribute TAG
+   for vendor VENDOR.  */
+
+static void
+record_attribute (int vendor, unsigned int tag)
+{
+  unsigned int base;
+  unsigned long mask;
+  struct recorded_attribute_info *rai;
+
+  base = tag / (8 * sizeof (rai->mask));
+  mask = 1UL << (tag % (8 * sizeof (rai->mask)));
+  for (rai = recorded_attributes; rai; rai = rai->next)
+    if (rai->vendor == vendor && rai->base == base)
+      {
+       rai->mask |= mask;
+       return;
+      }
+
+  rai = XNEW (struct recorded_attribute_info);
+  rai->next = recorded_attributes;
+  rai->vendor = vendor;
+  rai->base = base;
+  rai->mask = mask;
+  recorded_attributes = rai;
+}
+
+/* Return true if we have seen an explicit specification of attribute TAG
+   for vendor VENDOR.  */
+
+bfd_boolean
+obj_elf_seen_attribute (int vendor, unsigned int tag)
+{
+  unsigned int base;
+  unsigned long mask;
+  struct recorded_attribute_info *rai;
+
+  base = tag / (8 * sizeof (rai->mask));
+  mask = 1UL << (tag % (8 * sizeof (rai->mask)));
+  for (rai = recorded_attributes; rai; rai = rai->next)
+    if (rai->vendor == vendor && rai->base == base)
+      return (rai->mask & mask) != 0;
+  return FALSE;
+}
+
 /* Parse an attribute directive for VENDOR.
    Returns the attribute number read, or zero on error.  */
 
@@ -1540,6 +1596,7 @@ obj_elf_vendor_attribute (int vendor)
       s = demand_copy_C_string (&len);
     }
 
+  record_attribute (vendor, tag);
   switch (type & 3)
     {
     case 3:
@@ -2063,7 +2120,9 @@ elf_frob_symbol (symbolS *symp, int *puntp)
       char *p;
 
       p = strchr (sy_obj->versioned_name, ELF_VER_CHR);
-      know (p != NULL);
+      if (p == NULL)
+       /* We will have already reported an error about a missing version.  */
+       *puntp = TRUE;
 
       /* This symbol was given a new name with the .symver directive.
 
@@ -2076,14 +2135,15 @@ elf_frob_symbol (symbolS *symp, int *puntp)
         symbol.  However, it's not clear whether it is the best
         approach.  */
 
-      if (! S_IS_DEFINED (symp))
+      else if (! S_IS_DEFINED (symp))
        {
          /* Verify that the name isn't using the @@ syntax--this is
             reserved for definitions of the default version to link
             against.  */
          if (p[1] == ELF_VER_CHR)
            {
-             as_bad (_("invalid attempt to declare external version name as default in symbol `%s'"),
+             as_bad (_("invalid attempt to declare external version name"
+                       " as default in symbol `%s'"),
                      sy_obj->versioned_name);
              *puntp = TRUE;
            }
@@ -2346,8 +2406,7 @@ elf_frob_file_before_adjust (void)
 
                p = strchr (symbol_get_obj (symp)->versioned_name,
                            ELF_VER_CHR);
-               know (p != NULL);
-               if (p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
+               if (p != NULL && p[1] == ELF_VER_CHR && p[2] == ELF_VER_CHR)
                  {
                    size_t l = strlen (&p[3]) + 1;
                    memmove (&p[1], &p[3], l);
This page took 0.025547 seconds and 4 git commands to generate.