2004-07-07 Guilherme Destefani Adding linker script command TEMPORARY Useful to use a temporary symbol just for calculation, that's not stored in the bfd backend --- ld/ld.texinfo 2004-04-12 19:56:35.000000000 +0000 +++ ld/ld.texinfo 2004-07-07 21:59:50.000000000 +0000 @@ -2632,6 +2632,7 @@ @menu * Simple Assignments:: Simple Assignments * PROVIDE:: PROVIDE +* TEMPORARY:: TEMPORARY @end menu @node Simple Assignments @@ -2724,6 +2725,16 @@ If the program references @samp{etext} but does not define it, the linker will use the definition in the linker script. +@node TEMPORARY +@subsection TEMPORARY +@cindex TEMPORARY +In some cases, it is desirable for a linker script to use a name + just to hold a value without sending a symbol to the bfd backend. +The @code{TEMPORARY} keyword may be used to define that type of variable. +The syntax is: +@code{TEMPORARY(@var{symbol} = @var{expression})}. + + @node SECTIONS @section SECTIONS Command @kindex SECTIONS --- ld/ldexp.c 2004-03-03 20:24:34.000000000 +0000 +++ ld/ldexp.c 2004-07-07 21:59:50.000000000 +0000 @@ -456,7 +456,8 @@ bfd_vma dot) { etree_value_type result; - + temporary_variable_list_type *temporary; + result.valid_p = FALSE; switch (tree->type.node_code) @@ -494,6 +495,10 @@ if (allocation_done != lang_first_phase_enum) result = new_rel_from_section (dot, current_section); } + else if ( (temporary = lang_temporary_lookup(tree->name.name) ) ) + { + result = new_abs(temporary->value); + } else if (allocation_done != lang_first_phase_enum) { struct bfd_link_hash_entry *h; @@ -657,6 +662,7 @@ case etree_assign: case etree_provide: case etree_provided: + case etree_temporary: if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) { /* Assignment to dot can only be done during allocation. */ @@ -698,6 +704,12 @@ current_section, allocation_done, dot, dotp); if (result.valid_p) + { + if(tree->type.node_class == etree_temporary) + { + lang_temporary_set(tree->assign.dst,result.value); + } + else { bfd_boolean create; struct bfd_link_hash_entry *h; @@ -734,6 +746,7 @@ tree->type.node_class = etree_provided; } } + } } break; @@ -871,6 +884,21 @@ return n; } +/* Handle TEMPORARY. */ + +etree_type * +exp_temporary (const char *dst, etree_type *src) +{ + etree_type *n; + + n = stat_alloc (sizeof (n->assign)); + n->assign.type.node_code = '='; + n->assign.type.node_class = etree_temporary; + n->assign.src = src; + n->assign.dst = dst; + return n; +} + /* Handle ASSERT. */ etree_type * --- ld/ldexp.h 2004-01-14 21:07:52.000000000 +0000 +++ ld/ldexp.h 2004-07-07 21:59:50.000000000 +0000 @@ -40,6 +40,7 @@ etree_assign, etree_provide, etree_provided, + etree_temporary, etree_undef, etree_unspec, etree_value, @@ -126,6 +127,8 @@ (int, const char *, etree_type *); etree_type *exp_provide (const char *, etree_type *); +etree_type *exp_temporary + (const char *, etree_type *); etree_type *exp_assert (etree_type *, const char *); void exp_print_tree --- ld/ldgram.y 2004-03-03 20:24:34.000000000 +0000 +++ ld/ldgram.y 2004-07-07 22:05:11.183145976 +0000 @@ -147,7 +147,7 @@ %type filename %token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL -%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START +%token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START TEMPORARY %token VERS_TAG VERS_IDENTIFIER %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT %token KEEP @@ -611,6 +611,10 @@ { lang_add_assignment (exp_provide ($3, $5)); } + | TEMPORARY '(' NAME '=' mustbe_exp ')' + { + lang_add_assignment (exp_temporary ($3, $5)); + } ; --- ld/ldlang.c 2004-04-12 19:56:36.000000000 +0000 +++ ld/ldlang.c 2004-07-07 21:59:50.000000000 +0000 @@ -643,6 +643,55 @@ return lookup; } +/* A temporary variable can be used to store a value without + saving it on the bfd backends + The syntax to declare a a temporary variable is: + TEMPORARAY ( VARNAME = EXPRESSION ); + Then the value can be used later on like any other symbol. + The linker use a liked list to store those values in memory. +*/ + +static temporary_variable_list_type *lang_temporary_list = NULL; +static temporary_variable_list_type **lang_temporary_list_tail = &lang_temporary_list; + +temporary_variable_list_type *lang_temporary_lookup(char const *const name) +{ + temporary_variable_list_type *temp; + + if (name == NULL) + return NULL; + + for (temp = lang_temporary_list; temp != NULL; temp = temp->next) + if (strcmp (temp->name, name) == 0) + break; + return temp; +} + +temporary_variable_list_type *lang_temporary_set(char const *const name, bfd_vma value) +{ + temporary_variable_list_type *temp; + + if (! name[0] ) + return NULL; + + if ( (temp = lang_temporary_lookup (name)) ) + /*Reuse element already defined*/ + free (temp->name); + else + { + /*Allocate a new element and link it to list*/ + temp = xmalloc(sizeof(temporary_variable_list_type)); + temp->next = NULL; + + *lang_temporary_list_tail = temp; + lang_temporary_list_tail = &temp->next; + } + + temp->name = xstrdup(name); + temp->value = value; + return temp; +} + static void lang_map_flags (flagword flag) { --- ld/ldlang.h 2004-04-12 19:56:36.000000000 +0000 +++ ld/ldlang.h 2004-07-07 21:59:50.000000000 +0000 @@ -103,6 +103,14 @@ const char *name; } lang_output_statement_type; +/* Used to store temporary link script variables in memory*/ +typedef struct temporary_variable_list_struct +{ + struct temporary_variable_list_struct *next; + bfd_vma value; + char *name; +} temporary_variable_list_type; + /* Section types specified in a linker script. */ enum section_type @@ -426,6 +434,10 @@ (const char *const, bfd_boolean); extern lang_memory_region_type *lang_memory_region_default (asection *); +extern temporary_variable_list_type *lang_temporary_lookup + (char const *const); +extern temporary_variable_list_type *lang_temporary_set + (char const *const, bfd_vma); extern void lang_map (void); extern void lang_set_flags --- ld/ldlex.l 2004-04-12 19:56:36.000000000 +0000 +++ ld/ldlex.l 2004-07-07 22:08:07.602326184 +0000 @@ -268,6 +268,7 @@ "INPUT" { RTOKEN(INPUT);} "GROUP" { RTOKEN(GROUP);} "DEFINED" { RTOKEN(DEFINED);} +"TEMPORARY" { RTOKEN(TEMPORARY); } "CREATE_OBJECT_SYMBOLS" { RTOKEN(CREATE_OBJECT_SYMBOLS);} "CONSTRUCTORS" { RTOKEN( CONSTRUCTORS);} "FORCE_COMMON_ALLOCATION" { RTOKEN(FORCE_COMMON_ALLOCATION);} --- ld/ldexp.c 2004-07-07 22:26:51.276778088 -0300 +++ ld/ldexp.c 2004-07-07 22:25:06.401721520 -0300 @@ -989,6 +989,11 @@ exp_print_tree (tree->assign.src); fprintf (config.map_file, ")"); break; + case etree_temporary: + fprintf (config.map_file, "TEMPORARY (%s, ", tree->assign.dst); + exp_print_tree (tree->assign.src); + fprintf (config.map_file, ")"); + break; case etree_binary: fprintf (config.map_file, "("); exp_print_tree (tree->binary.lhs);