[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