Implement MEMORY attributes for unknown sections
authorMichael Meissner <gnu@the-meissners.org>
Fri, 2 Jan 1998 17:27:05 +0000 (17:27 +0000)
committerMichael Meissner <gnu@the-meissners.org>
Fri, 2 Jan 1998 17:27:05 +0000 (17:27 +0000)
ld/ChangeLog
ld/emulparams/d30v_e.sh [new file with mode: 0644]
ld/emulparams/d30v_o.sh [new file with mode: 0644]
ld/emulparams/d30velf.sh [new file with mode: 0644]
ld/ldlang.c

index 5993a1aafa48c6319cf86997bf408194ecbe4f6f..250435eed7ce06d966f3f468de5c6776c001601c 100644 (file)
@@ -1,4 +1,31 @@
+Fri Jan  2 20:15:37 1998  Michael Meissner  <meissner@cygnus.com>
+
+       * ldgram.y (attributes_opt): Pass region pointer to
+       lang_set_flags, not &region->flags.
+
+       * ldlang.c (lang_memory_default): New function to figure out a
+       default memory region for a section if it was not specified.
+       (lang_memory_region_lookup): Zero flags, not_flags field.
+       (lang_map{,_flags}): Print attribute flags in memory map.
+       (lang_size_sections): Call lang_memory_default to get default
+       memory region.
+       (lang_set_flags): Implement attribute flags for real.  Take new
+       argument to give the flags we are to skip for this region.
+
+       * ldlang.h (memory_region_struct): Add not_flags field, make both
+       flags fields flagword type.
+       (lang_output_section_state): Make flags field flagword type.
+       (lang_set_flags): Update prototype to match new calling sequence.
+       (lang_memory_region_default): Add prototype.
+
 start-sanitize-d30v
+       * emulparams/d30v{_e,_o,elf}.sh ({TEXT,DATA,EMEM}_DEF_SECTION):
+       Define whether or not the region gets default sections, and if so,
+       what sections.
+
+       * scripttempl/elfd30v.sc (MEMORY): Set up which of the regions get
+       default sections.
+
 Thu Jan  1 22:58:04 1998  Michael Meissner  <meissner@cygnus.com>
 
        * scripttempl/elfd30v.sc (.eh_frame): Link into the data section.
diff --git a/ld/emulparams/d30v_e.sh b/ld/emulparams/d30v_e.sh
new file mode 100644 (file)
index 0000000..193d36a
--- /dev/null
@@ -0,0 +1,18 @@
+MACHINE=
+SCRIPT_NAME=elfd30v
+OUTPUT_FORMAT="elf32-d30v"
+TEXT_START_ADDR=0x00000000
+DATA_START_ADDR=0x20000000
+EMEM_START_ADDR=0x80000000
+STACK_START_ADDR=0x20008000
+TEXT_SIZE=64K
+DATA_SIZE=32K
+EMEM_SIZE=8M
+TEXT_MEMORY=emem
+DATA_MEMORY=emem
+BSS_MEMORY=emem
+TEXT_DEF_SECTION=""
+DATA_DEF_SECTION=""
+EMEM_DEF_SECTION="(rwx)"
+ARCH=d30v
+EMBEDDED=t
diff --git a/ld/emulparams/d30v_o.sh b/ld/emulparams/d30v_o.sh
new file mode 100644 (file)
index 0000000..038621c
--- /dev/null
@@ -0,0 +1,18 @@
+MACHINE=
+SCRIPT_NAME=elfd30v
+OUTPUT_FORMAT="elf32-d30v"
+TEXT_START_ADDR=0x00000000
+DATA_START_ADDR=0x20000000
+EMEM_START_ADDR=0x80000000
+STACK_START_ADDR=0x20008000
+TEXT_SIZE=64K
+DATA_SIZE=32K
+EMEM_SIZE=8M
+TEXT_MEMORY=text
+DATA_MEMORY=data
+BSS_MEMORY=data
+TEXT_DEF_SECTION="(x)"
+DATA_DEF_SECTION="(rw)"
+EMEM_DEF_SECTION=""
+ARCH=d30v
+EMBEDDED=t
diff --git a/ld/emulparams/d30velf.sh b/ld/emulparams/d30velf.sh
new file mode 100644 (file)
index 0000000..038621c
--- /dev/null
@@ -0,0 +1,18 @@
+MACHINE=
+SCRIPT_NAME=elfd30v
+OUTPUT_FORMAT="elf32-d30v"
+TEXT_START_ADDR=0x00000000
+DATA_START_ADDR=0x20000000
+EMEM_START_ADDR=0x80000000
+STACK_START_ADDR=0x20008000
+TEXT_SIZE=64K
+DATA_SIZE=32K
+EMEM_SIZE=8M
+TEXT_MEMORY=text
+DATA_MEMORY=data
+BSS_MEMORY=data
+TEXT_DEF_SECTION="(x)"
+DATA_DEF_SECTION="(rw)"
+EMEM_DEF_SECTION=""
+ARCH=d30v
+EMBEDDED=t
index b66efbb7234e06d4ddef1430cce6bc6e6f04db2d..b364f9dea071d908c985028300bd66d5e363be52 100644 (file)
@@ -128,6 +128,7 @@ static bfd_vma size_input_section
           lang_output_section_statement_type *output_section_statement,
           fill_type fill, bfd_vma dot, boolean relax));
 static void lang_finish PARAMS ((void));
+static void ignore_bfd_errors PARAMS ((const char *, ...));
 static void lang_check PARAMS ((void));
 static void lang_common PARAMS ((void));
 static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR));
@@ -412,7 +413,6 @@ lang_memory_region_type *
 lang_memory_region_lookup (name)
      CONST char *CONST name;
 {
-
   lang_memory_region_type *p;
 
   for (p = lang_memory_region_list;
@@ -451,6 +451,8 @@ lang_memory_region_lookup (name)
     *lang_memory_region_list_tail = new;
     lang_memory_region_list_tail = &new->next;
     new->origin = 0;
+    new->flags = 0;
+    new->not_flags = 0;
     new->length = ~(bfd_size_type)0;
     new->current = 0;
     new->had_full_message = false;
@@ -460,6 +462,31 @@ lang_memory_region_lookup (name)
 }
 
 
+lang_memory_region_type *
+lang_memory_default (section)
+     asection *section;
+{
+  lang_memory_region_type *p;
+
+  flagword sec_flags = section->flags;
+
+  /* Override SEC_DATA to mean a writable section.  */
+  if (sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE) == SEC_ALLOC)
+    sec_flags |= SEC_DATA;
+
+  for (p = lang_memory_region_list;
+       p != (lang_memory_region_type *) NULL;
+       p = p->next)
+    {
+      if ((p->flags & sec_flags) != 0
+         && (p->not_flags & sec_flags) == 0)
+       {
+         return p;
+       }
+    }
+  return lang_memory_region_lookup ("*default*");
+}
+
 lang_output_section_statement_type *
 lang_output_section_find (name)
      CONST char *CONST name;
@@ -518,14 +545,34 @@ lang_output_section_statement_lookup (name)
   return lookup;
 }
 
+static void
+lang_map_flags (flag)
+     flagword flag;
+{
+  if (flag & SEC_ALLOC)
+    minfo ("a");
+
+  if (flag & SEC_CODE)
+    minfo ("x");
+
+  if (flag & SEC_READONLY)
+    minfo ("r");
+
+  if (flag & SEC_DATA)
+    minfo ("w");
+
+  if (flag & SEC_LOAD)
+    minfo ("l");
+}
+
 void
 lang_map ()
 {
   lang_memory_region_type *m;
 
   minfo ("\nMemory Configuration\n\n");
-  fprintf (config.map_file, "%-16s %-18s %-18s\n",
-          "Name", "Origin", "Length");
+  fprintf (config.map_file, "%-16s %-18s %-18s %s\n",
+          "Name", "Origin", "Length", "Attributes");
 
   for (m = lang_memory_region_list;
        m != (lang_memory_region_type *) NULL;
@@ -545,7 +592,26 @@ lang_map ()
          ++len;
        }
 
-      minfo ("0x%V\n", m->length);
+      minfo ("0x%V", m->length);
+      if (m->flags || m->not_flags)
+       {
+#ifndef BFD64
+         minfo ("        ");
+#endif
+         if (m->flags)
+           {
+             print_space ();
+             lang_map_flags (m->flags);
+           }
+
+         if (m->not_flags)
+           {
+             minfo (" !");
+             lang_map_flags (m->not_flags);
+           }
+       }
+
+      print_nl ();
     }
 
   fprintf (config.map_file, "\nLinker script and memory map\n\n");
@@ -2101,7 +2167,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
              */
           if (os->region == (lang_memory_region_type *) NULL)
           {
-            os->region = lang_memory_region_lookup ("*default*");
+            os->region = lang_memory_default (os->bfd_section);
           }
           dot = os->region->current;
           if (os->section_alignment == -1)
@@ -2630,6 +2696,20 @@ lang_finish ()
     }
 }
 
+/* This is a small function used when we want to ignore errors from
+   BFD.  */
+
+static void
+#ifdef ANSI_PROTOTYPES
+ignore_bfd_errors (const char *s, ...)
+#else
+ignore_bfd_errors (s)
+     const char *s;
+#endif
+{
+  /* Don't do anything.  */
+}
+
 /* Check that the architecture of all the input files is compatible
    with the output file.  Also call the backend to let it do any
    other checking that is needed.  */
@@ -2649,13 +2729,31 @@ lang_check ()
       compatible = bfd_arch_get_compatible (input_bfd,
                                            output_bfd);
       if (compatible == NULL)
-       einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
-              bfd_printable_name (input_bfd), input_bfd,
-              bfd_printable_name (output_bfd));
-
-      else if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
        {
-         einfo ("%E%X: failed to merge target specific data of file %B\n", input_bfd);
+         if (command_line.warn_mismatch)
+           einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n",
+                  bfd_printable_name (input_bfd), input_bfd,
+                  bfd_printable_name (output_bfd));
+       }
+      else
+       {
+         bfd_error_handler_type pfn;
+
+         /* If we aren't supposed to warn about mismatched input
+             files, temporarily set the BFD error handler to a
+             function which will do nothing.  We still want to call
+             bfd_merge_private_bfd_data, since it may set up
+             information which is needed in the output file.  */
+         if (! command_line.warn_mismatch)
+           pfn = bfd_set_error_handler (ignore_bfd_errors);
+         if (! bfd_merge_private_bfd_data (input_bfd, output_bfd))
+           {
+             if (command_line.warn_mismatch)
+               einfo ("%E%X: failed to merge target specific data of file %B\n",
+                      input_bfd);
+           }
+         if (! command_line.warn_mismatch)
+           bfd_set_error_handler (pfn);
        }
     }
 }
@@ -2853,36 +2951,41 @@ lang_place_orphans ()
 
 void
 lang_set_flags (ptr, flags)
-     int *ptr;
+     lang_memory_region_type *ptr;
      CONST char *flags;
 {
-  boolean state = false;
+  flagword *ptr_flags = &ptr->flags;
 
-  *ptr = 0;
+  ptr->flags = ptr->not_flags = 0;
   while (*flags)
     {
-      if (*flags == '!')
-       {
-         state = false;
-         flags++;
-       }
-      else
-       state = true;
       switch (*flags)
        {
-       case 'R':
-         /*      ptr->flag_read = state; */
+       case '!':
+         ptr_flags = (ptr_flags == &ptr->flags) ? &ptr->not_flags : &ptr->flags;
          break;
-       case 'W':
-         /*      ptr->flag_write = state; */
+
+       case 'A': case 'a':
+         *ptr_flags |= SEC_ALLOC;
          break;
-       case 'X':
-         /*      ptr->flag_executable= state;*/
+
+       case 'R': case 'r':
+         *ptr_flags |= SEC_READONLY;
+         break;
+
+       case 'W': case 'w':
+         *ptr_flags |= SEC_DATA;
          break;
-       case 'L':
-       case 'I':
-         /*      ptr->flag_loadable= state;*/
+
+       case 'X': case 'x':
+         *ptr_flags |= SEC_CODE;
          break;
+
+       case 'L': case 'l':
+       case 'I': case 'i':
+         *ptr_flags |= SEC_LOAD;
+         break;
+
        default:
          einfo ("%P%F: invalid syntax in flags\n");
          break;