[RFC] Device specific linker scripts

"Dhakshinamoorthy, Soundararajan" <[email protected]>
Newsgroups gmane.comp.hardware.avr.gcc
Message-ID <54196F45A68D5F44A17DBFF39883E26F70ED2E41@penmbx01>
Hi all,

As discussed below,
Attached is a patch, that allows customizing the linker emulation scripts with device specific parameters.  I request you all to review it and give your suggestions/proposals :).
Summary of the changes :

1. We put the device specifc configuration files under <install>/avr/lib/defs. 
2. Make gcc driver pass --part option to collect2 from mmcu.  %{mmcu=*:--part=%*}"
3. From avrelf.em cache the value of --part option from the handle_options hook.
4. Inside after_parse, find the path of defs and append the device name (which gives complete path of the defs file).
5. Add the file to the list of bfd's using lang_add_input_file(...) api.

Some observations.
* The name --part is because -mmcu when directly passed to collect2 is ambiguous with -m option.
* the /defs directly is not detected by the linker, even when put under the lib directory (I misunderstood from the previous conversations that this will be an implicit behavior)
* when adding the defs file with the -l option,  then the order in which the original linker file is included matters, as it raises unresolved symbol errors.


Thanks,
Soundararajan

________________________________________
From: [email protected] [[email protected]] on behalf of Erik Christiansen [[email protected]]
Sent: Tuesday, October 22, 2013 2:49 PM
To: [email protected]; Georg-Johann Lay
Subject: Re: [avr-gcc-list] Device specific linker scripts

On 20.10.13 21:36, Georg-Johann Lay wrote:
> Erik Christiansen schrieb:
> >On 19.10.13 19:48, Georg-Johann Lay wrote:
> >>If such linker scripts shall become the default linker scripts then you need
> >>200+ emulations to support the 200+ devices.
> >
> >One way to follow Johann's good advice might be to just use:
> >
> >  .boot :
> >  {
> >    *(.boot_vectors)
> >    *(.boot)
> >  } > text
> >
> >and have gcc set --section-start=.boot=0x12345
> >That should suffice for now.
> >
> >And yes, 4 x 205 = 820 full linker scripts is about what would happen if
> >we were, for example, to proliferate what I sometimes do for the
> >Atmega64:
> >
> >MEMORY
> >{
> >  text   (rx)   : ORIGIN = 0, LENGTH = 62K
> >  boot   (rx)   : ORIGIN = 62K, LENGTH = 2K
> >  data   (rw!x) : ORIGIN = 0x800100, LENGTH = 4K
> >  eeprom (rw!x) : ORIGIN = 0x810000, LENGTH = 2K
> >}
> >
> >SECTIONS
> >{
> >...
> >  }  > text
> >
> >  .boot :
> >  {
> >    *(.boot_vectors)
> >    *(.boot)
> >  } > boot
> >
> >  .data    : AT (ADDR (.text) + SIZEOF (.text))
> >  {
> >
> >That satisfied my strong preference for documenting the memory layout in
> >the linker script. (Having all that information in one place can save
> >time when coming back to an old project.)
>
>
> Wouldn't this cause problems if no bootloader is present and .text overlaps
> empty bootloader section?

Well, avr-ld would protest if the text region limit of 62k were exceeded,
even if the boot section were removed. I.e. The primary error would be
memory region overflow, even if a section overlap didn't follow. (Perhaps
that's what you meant, I guess.)

The custom linker script (negative) example explicitly amplified your
warning of emulation proliferation, using a method which is fine for
one-off. Your description of the generalisation issue is quite accurate.
Soundararajan is doubtless already oriented toward the preceding positive
example, or something similar.

The rest of my post looked at a possible way to avoid having to hack
avr-gcc to embed linker-related stuff, as is needed in the positive
example, since such indirection unnecessarily amplifies the amount of
work to be done for each new mcu.

...

> Still avr-gcc has to be extended to accept -mmcu=atmega12345, so that file
> has to be touched anyway.

Well, only if avr-gcc internally requires extension of compiler
functionality for the new mcu. The goal of the proposal is to avoid the
inefficiency of changing avr-gcc when only link-time changes are
necessary. I.e. it is sub-optimal to have to hack avr-gcc to emit
--section-start=... for every mcu, old and new, when it can be just
dropped into a text file, for avr-ld to use directly.

Furthermore, any future linker address customisations for an mcu are
just dropped into the same mcu def file, without resort to _any_ coding,
macro extension, or fiddling with avr-gcc to drive avr-ld.

There seems to be enough work for the available developers for any
potential effort reduction to be worth a look.

And thank you, Johann, for taking the trouble to discuss - it helps to
keep the list from being too moribund.

Erik

--
Tecoma's struggle reported on BBC: http://www.bbc.co.uk/news/business-24364204
Tecoma's Macca's-striking flash mob: " http://www.youtube.com/watch?v=H7-0T1vbnWE
Stop fat food joint opposite Tecoma preschool: www.change.org
Taking democracy (98,000 signatures) from Australia to Chicago:
http://www.abc.net.au/news/2013-09-17/tecoma-residents-take-fight-against-mcdonalds-to-chicago/4963866

_______________________________________________
AVR-GCC-list mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list

_______________________________________________
AVR-GCC-list mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/avr-gcc-list
avrelf.diff (text/x-patch, 3.7 KB)
diff --git ld/emultempl/avrelf.em ld/emultempl/avrelf.em
index 90894a1..5f064b2 100644
--- ld/emultempl/avrelf.em
+++ ld/emultempl/avrelf.em
@@ -29,6 +29,8 @@ fragment <<EOF
 
 #include "elf32-avr.h"
 #include "ldctor.h"
+#include "libiberty.h"
+#include "ldmain.h"
 
 /* The fake file and it's corresponding section meant to hold
    the linker stubs if needed.  */
@@ -44,6 +46,7 @@ static bfd_boolean avr_debug_relax = FALSE;
 static bfd_boolean avr_debug_stubs = FALSE;
 static bfd_boolean avr_replace_call_ret_sequences = TRUE;
 static bfd_vma avr_pc_wrap_around = 0x10000000;
+static char* device_name = NULL;
 
 /* Transfers information to the bfd frontend.  */
 
@@ -176,6 +179,40 @@ avr_elf_before_parse (void)
   gld${EMULATION_NAME}_before_parse ();
 }
 
+
+static void
+add_device_specific_linker_configuration_to_bfd(void)
+{
+  /* If the device name is not passed, then it could be that the linker is invoked with a emulation name, so skip adding the device specific file. But the variables in the original linker script should be handled properly in that case. */
+  if(!device_name)
+    return;
+
+  /* We are going to assume that the defs file will be in <avr-ld path>/../avr/lib/defs */
+  /* first step is to get the parent directory of avr-ld */
+  char* binpath = make_relative_prefix(program_name,".",".");
+
+  /*Allocate a string to construct a full path */
+  char *defs_path = malloc (strlen(binpath) + strlen("../lib/defs/") + strlen(device_name));
+  
+  /* Now construct the path */
+  strcpy(defs_path, binpath);
+  strcat(defs_path, "../lib/defs/");   /* Check if this path actually exists and if it doesn't then warn/error/ what ?
+  strcat(defs_path,device_name);
+   
+  /* free allocated variables. Note that we also free the global variable device_name, which is used only here. */
+  free(binpath);
+  free(device_name);
+
+  /* Now add the file as a input to the list of bfd's that will be processed */
+  lang_add_input_file(defs_path , lang_input_file_is_file_enum, NULL);
+}
+
+static void
+avr_elf_after_parse (void)
+{
+  add_device_specific_linker_configuration_to_bfd();
+}
+
 EOF
 
 
@@ -186,6 +223,8 @@ PARSE_AND_LIST_PROLOGUE='
 #define OPTION_NO_STUBS                303
 #define OPTION_DEBUG_STUBS             304
 #define OPTION_DEBUG_RELAX             305
+#define OPTION_MCU_PARAMETER           306
+
 '
 
 PARSE_AND_LIST_LONGOPTS='
@@ -199,6 +238,8 @@ PARSE_AND_LIST_LONGOPTS='
     NULL, OPTION_DEBUG_STUBS},
   { "debug-relax", no_argument,
     NULL, OPTION_DEBUG_RELAX},
+  { "part", required_argument,
+    NULL, OPTION_MCU_PARAMETER},
 '
 
 PARSE_AND_LIST_OPTIONS='
@@ -228,6 +269,8 @@ PARSE_AND_LIST_OPTIONS='
 		   "Used for debugging avr-ld.\n"));
   fprintf (file, _("  --debug-relax               "
 		   "Used for debugging avr-ld.\n"));
+  fprintf (file, _("  --part                      "
+		   "The mcu parameter as passed from the compiler. This should be explicitly mentioned when invoking the linker separately.\n"));
 '
 
 PARSE_AND_LIST_ARGS_CASES='
@@ -266,6 +309,17 @@ PARSE_AND_LIST_ARGS_CASES='
         avr_replace_call_ret_sequences = FALSE;
       }
       break;
+   case OPTION_MCU_PARAMETER:
+      {
+	 /* cache the name of the device here. Then use it in after_parse, where we try to construct the path to the device specific linker configuration file.
+          */
+         if(optarg)
+         {
+           /* cache optarg */
+           device_name=malloc(strlen(optarg));
+           strcpy(device_name,optarg);
+         }
+      }
 '
 
 #
@@ -275,3 +329,4 @@ LDEMUL_BEFORE_PARSE=avr_elf_before_parse
 LDEMUL_BEFORE_ALLOCATION=avr_elf_${EMULATION_NAME}_before_allocation
 LDEMUL_AFTER_ALLOCATION=avr_elf_after_allocation
 LDEMUL_CREATE_OUTPUT_SECTION_STATEMENTS=avr_elf_create_output_section_statements
+LDEMUL_AFTER_PARSE=avr_elf_after_parse
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.