public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
@ 2004-07-08 13:26 Guilherme Destefani
  2004-07-08 17:04 ` Zack Weinberg
  0 siblings, 1 reply; 7+ messages in thread
From: Guilherme Destefani @ 2004-07-08 13:26 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 1105 bytes --]

Hello.

This patch add to the linker a command like PROVIDE(var=value), named
TEMPORARY(var=value) that can be used to define variables just for
temporary use, so those variables won't be sent to the file as a symbol.

I made the linked list that keep those variables in memory based on the
list that keep the memory regions on memory (static
lang_memory_region_type *lang_memory_region_list; @ld/ldlang.c:517)
BUT I didn't find where that linked list is free().
I suppose that it's not free, because is a small amount of memory and
the linker will terminate and that memory will be free by the OS when
the program end anyway, but I'm not sure.
Somebody can please confirm that, or I should free that memory in the
same place (that I didn't find) that the linker free
lang_memory_region_list?

This patch was tested with binutils-2.15.90.0.3, directly on it or after
the other patchs from Fedora Core 2 binutils-2.15.90.0.3-5.src.rpm
Use patch -p0.

Thanks in advance,
-- 
Guilherme Destefani
Computer Engineer
Helix S.A.
gd _at_ helixbrasil _dot_ com _dot_ br
Brazil - Parana - Curitiba
(+5541) 362-1313

[-- Attachment #2: binutils-2.15.90.0.3-temporary.patch --]
[-- Type: text/x-patch, Size: 7445 bytes --]

2004-07-07  Guilherme Destefani <gd@helixbrasil.com>

	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 <name>  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 <name> 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 @@
 <BOTH,SCRIPT>"INPUT"			{ RTOKEN(INPUT);}
 <EXPRESSION,BOTH,SCRIPT>"GROUP"		{ RTOKEN(GROUP);}
 <EXPRESSION,BOTH,SCRIPT>"DEFINED"		{ RTOKEN(DEFINED);}
+<EXPRESSION,BOTH,SCRIPT>"TEMPORARY"		{ RTOKEN(TEMPORARY); }
 <BOTH,SCRIPT>"CREATE_OBJECT_SYMBOLS"	{ RTOKEN(CREATE_OBJECT_SYMBOLS);}
 <BOTH,SCRIPT>"CONSTRUCTORS"		{ RTOKEN( CONSTRUCTORS);}
 <BOTH,SCRIPT>"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);

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-08 13:26 RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file Guilherme Destefani
@ 2004-07-08 17:04 ` Zack Weinberg
  2004-07-08 23:45   ` Guilherme Destefani
  0 siblings, 1 reply; 7+ messages in thread
From: Zack Weinberg @ 2004-07-08 17:04 UTC (permalink / raw)
  To: Guilherme Destefani; +Cc: binutils

Guilherme Destefani <gd@helixbrasil.com.br> writes:

> This patch add to the linker a command like PROVIDE(var=value), named
> TEMPORARY(var=value) that can be used to define variables just for
> temporary use, so those variables won't be sent to the file as a symbol.

Ooh, nifty.  Would you please investigate adding the ability to set
these variables from the command line?  The desired semantic is that
TEMPORARY(var=value) gets overriden by --some-switch var=value, but
whether or not that happens, /var/ is available for calculation in
the linker script.  (--defsym symbols can't be used for arbitrary
calculation.)

zw

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-08 17:04 ` Zack Weinberg
@ 2004-07-08 23:45   ` Guilherme Destefani
  2004-07-21 13:24     ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Guilherme Destefani @ 2004-07-08 23:45 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: binutils

[-- Attachment #1: Type: text/plain, Size: 1895 bytes --]

On Thu, 2004-07-08 at 14:04, Zack Weinberg wrote:
> Guilherme Destefani <gd@helixbrasil.com.br> writes:
> 
> > This patch add to the linker a command like PROVIDE(var=value), named
> > TEMPORARY(var=value) that can be used to define variables just for
> > temporary use, so those variables won't be sent to the file as a symbol.
> 
> Ooh, nifty.  Would you please investigate adding the ability to set
> these variables from the command line? 
Yes, follows a patch to do it too.
>  The desired semantic is that
> TEMPORARY(var=value) gets overriden by --some-switch var=value, but
> whether or not that happens, /var/ is available for calculation in
> the linker script.  (--defsym symbols can't be used for arbitrary
> calculation.)
While testing if it's working, I found out that if I have a script with
those lines inside SECTIONS{
lixo = lixo_1;
TEMPORARY( lixo_1 = 0x1);
}

I have as result:
make ok;readelf -a ok|grep lixo
cc -Wl,-T -Wl,script -Wl,--deftmp -Wl,lixo1=0x19  -Wl,--deftmp
-Wl,lixo2=0x29    ok.c   -o ok
    49: 00000001     0 NOTYPE  GLOBAL DEFAULT  ABS lixo
    59: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND lixo_1

As you can see, lixo_1 ends up as undefined.
The parser accept the variable, but in the tree used to construct the
sentence lixo = lixo_1; lixo_1 is not defined yet.	Why the parser accept
a variable that wasn't defined yet?

But if the order is inverted, like this:
SECTIONS{
TEMPORARY( lixo_1 = 0x1);
lixo = lixo_1;
}

The result looks just fine:
make ok;readelf -a ok|grep lixo
cc -Wl,-T -Wl,script -Wl,--deftmp -Wl,lixo1=0x19  -Wl,--deftmp
-Wl,lixo2=0x29    ok.c   -o ok
    49: 00000001     0 NOTYPE  GLOBAL DEFAULT  ABS lixo

Why the order of declaration/use force the symbol to be undefined?
The tree isn't evaluated just when needed?

It is OK to left a small amount of memory allocated, like this patch and
the lang_memory_region_list does?
> zw
> 

[-- Attachment #2: binutils-2.15.90.0.3-temporary.patch --]
[-- Type: text/x-patch, Size: 14744 bytes --]

2004-07-07  Guilherme Destefani <gd@helixbrasil.com>

	Adding linker script command TEMPORARY
	and option --deftmp that overrides script defined variables
	Useful to use a temporary symbol just for calculation,
	that's not stored in the bfd backend

--- ld/ld.h	2004-01-14 21:07:52.000000000 +0000
+++ ld/ld.h	2004-07-08 22:47:45.000000000 +0000
@@ -231,6 +231,8 @@
 
 /* Non-zero if we are processing a --defsym from the command line.  */
 extern int parsing_defsym;
+/* Non-zero if we are processing a --deftmp from the command line.  */
+extern int parsing_deftmp;
 
 extern int yyparse (void);
 extern void add_cref (const char *, bfd *, asection *, bfd_vma);
--- ld/ld.texinfo	2004-04-12 19:56:35.000000000 +0000
+++ ld/ld.texinfo	2004-07-08 22:47:45.000000000 +0000
@@ -1089,6 +1089,21 @@
 space between @var{symbol}, the equals sign (``@key{=}''), and
 @var{expression}.
 
+@kindex --deftmp @var{symbol}=@var{exp}
+@item --deftmp @var{symbol}=@var{expression}
+Define a temporary symbol overriding the value of the @var{symbol} just in the 
+linker script, but without changing the value of the @var{symbol} on the file.
+You may use this option as many times as necessary to define multiple 
+temporary symbols in the command line.  A limited form of arithmetic
+is supported for the @var{expression} in this context: you may give a
+hexadecimal constant or the name of an existing symbol, or use @code{+}
+and @code{-} to add or subtract hexadecimal constants or symbols.
+If you need more elaborate expressions, consider
+using the linker command language from a script (@pxref{Assignments,,
+Assignment: Symbol Definitions}).  @emph{Note:} there should be no white
+space between @var{symbol}, the equals sign (``@key{=}''), and
+@var{expression}.
+
 @cindex demangling, from command line
 @kindex --demangle[=@var{style}]
 @kindex --no-demangle
@@ -2632,6 +2647,7 @@
 @menu
 * Simple Assignments::		Simple Assignments
 * PROVIDE::			PROVIDE
+* TEMPORARY::			TEMPORARY
 @end menu
 
 @node Simple Assignments
@@ -2724,6 +2740,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-07-08 22:48:38.997245672 +0000
+++ ld/ldexp.c	2004-07-08 22:47:45.000000000 +0000
@@ -491,7 +491,8 @@
 	   bfd_vma dot)
 {
   etree_value_type result;
-
+  temporary_variable_list_type *temporary;
+	
   result.valid_p = FALSE;
   
   switch (tree->type.node_code)
@@ -529,6 +530,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;
@@ -692,6 +697,8 @@
     case etree_assign:
     case etree_provide:
     case etree_provided:
+    case etree_temporary_from_argument:
+    case etree_temporary_from_script:
       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0)
 	{
 	  /* Assignment to dot can only be done during allocation.  */
@@ -733,6 +740,16 @@
 				  current_section, allocation_done,
 				  dot, dotp);
 	  if (result.valid_p)
+     {
+        if (tree->type.node_class == etree_temporary_from_argument)
+        {
+          lang_temporary_set (tree->assign.dst, result.value, temporary_from_argument_enum);
+        }
+        else if (tree->type.node_class == etree_temporary_from_script)
+        {
+          lang_temporary_set (tree->assign.dst, result.value, temporary_from_script_enum);
+        }
+        else
 	    {
 	      bfd_boolean create;
 	      struct bfd_link_hash_entry *h;
@@ -769,6 +786,7 @@
 		    tree->type.node_class = etree_provided;
 		}
 	    }
+     }
 	}
       break;
 
@@ -906,6 +924,21 @@
   return n;
 }
 
+/* Handle TEMPORARY.  */
+
+etree_type *
+exp_temporary (const char *dst, etree_type *src, short type)
+{
+  etree_type *n;
+
+  n = stat_alloc (sizeof (n->assign));
+  n->assign.type.node_code = '=';
+  n->assign.type.node_class = type;
+  n->assign.src = src;
+  n->assign.dst = dst;
+  return n;
+}
+
 /* Handle ASSERT.  */
 
 etree_type *
@@ -961,6 +994,12 @@
       exp_print_tree (tree->assign.src);
       fprintf (config.map_file, ")");
       break;
+    case etree_temporary_from_argument:
+    case etree_temporary_from_script:
+      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);
--- ld/ldexp.h	2004-07-08 22:48:38.998245520 +0000
+++ ld/ldexp.h	2004-07-08 22:47:45.000000000 +0000
@@ -40,6 +40,8 @@
     etree_assign,
     etree_provide,
     etree_provided,
+    etree_temporary_from_argument,
+    etree_temporary_from_script,
     etree_undef,
     etree_unspec,
     etree_value,
@@ -128,6 +130,8 @@
   (int, const char *, etree_type *);
 etree_type *exp_provide
   (const char *, etree_type *);
+etree_type *exp_temporary
+  (const char *, etree_type *, short);
 etree_type *exp_assert
   (etree_type *, const char *);
 void exp_print_tree
--- ld/ldgram.y	2004-07-08 22:48:38.987247192 +0000
+++ ld/ldgram.y	2004-07-08 22:47:44.000000000 +0000
@@ -147,7 +147,7 @@
 %type <name>  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 INPUT_DEFTMP CASE EXTERN START TEMPORARY
 %token <name> VERS_TAG VERS_IDENTIFIER
 %token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
 %token KEEP ONLY_IF_RO ONLY_IF_RW
@@ -163,6 +163,7 @@
 	|	INPUT_MRI_SCRIPT mri_script_file
 	|	INPUT_VERSION_SCRIPT version_script_file
 	|	INPUT_DEFSYM defsym_expr
+	|	INPUT_DEFTMP deftmp_expr
 	;
 
 
@@ -178,6 +179,15 @@
 		}
 	;
 
+deftmp_expr:
+		{ ldlex_deftmp(); }
+		NAME '=' exp
+		{
+		  ldlex_popstate();
+		  lang_add_assignment(exp_temporary ($2, $4, etree_temporary_from_argument));
+		}
+	;
+
 /* SYNTAX WITHIN AN MRI SCRIPT FILE */
 mri_script_file:
 		{
@@ -611,6 +621,10 @@
 		{
 		  lang_add_assignment (exp_provide ($3, $5));
 		}
+	|	TEMPORARY '(' NAME '=' mustbe_exp ')'
+		{
+		  lang_add_assignment (exp_temporary ($3, $5, etree_temporary_from_script));
+		}
 	;
 
 
--- ld/ldlang.c	2004-07-08 22:48:39.014243088 +0000
+++ ld/ldlang.c	2004-07-08 22:47:45.000000000 +0000
@@ -658,6 +658,61 @@
   return lang_output_section_statement_lookup_1 (name, 0);
 }
 
+/*	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, short type)
+{
+  temporary_variable_list_type *temp;
+
+  if (! name[0] )
+	  return NULL;
+
+  /*Try to reuse element already defined*/
+  if ( (temp = lang_temporary_lookup (name)) ){
+      /*A temporary variable from a script can't
+      update the variable from the command line*/
+    if (temp->type <= type)
+      free (temp->name);
+    else return temp; /*Otherwise just ignore assignment from script*/
+  }
+  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;
+  temp->type = type;
+  return temp;  
+}
+
 static void
 lang_map_flags (flagword flag)
 {
--- ld/ldlang.h	2004-07-08 22:48:36.090687536 +0000
+++ ld/ldlang.h	2004-07-08 22:47:45.000000000 +0000
@@ -103,6 +103,19 @@
   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;	
+  enum temporary_variable_enum
+  {
+    temporary_from_script_enum,
+    temporary_from_argument_enum
+  } type;
+} temporary_variable_list_type;
+
 /* Section types specified in a linker script.  */
 
 enum section_type
@@ -428,6 +441,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, short);
 extern void lang_map
   (void);
 extern void lang_set_flags
--- ld/ldlex.h	2004-01-14 21:07:52.000000000 +0000
+++ ld/ldlex.h	2004-07-08 22:47:45.000000000 +0000
@@ -30,7 +30,8 @@
   input_script,
   input_mri_script,
   input_version_script,
-  input_defsym
+  input_defsym,
+  input_deftmp
 } input_type;
 
 extern input_type parser_input;
@@ -47,6 +48,7 @@
 extern void ldlex_version_script (void);
 extern void ldlex_version_file (void);
 extern void ldlex_defsym (void);
+extern void ldlex_deftmp (void);
 extern void ldlex_expression (void);
 extern void ldlex_both (void);
 extern void ldlex_command (void);
--- ld/ldlex.l	2004-07-08 22:48:38.986247344 +0000
+++ ld/ldlex.l	2004-07-08 22:47:44.000000000 +0000
@@ -81,6 +81,7 @@
 	SCRIPT		definitely in a script
 	BOTH		either EXPRESSION or SCRIPT
 	DEFSYMEXP	in an argument to -defsym
+	DEFTMPEXP	in an argument to -deftmp
         MRI             in an MRI script
 	VERS_START	starting a Sun style mapfile
 	VERS_SCRIPT	a Sun style mapfile
@@ -114,6 +115,7 @@
 %s EXPRESSION
 %s BOTH
 %s DEFSYMEXP
+%s DEFTMPEXP
 %s MRI
 %s VERS_START
 %s VERS_SCRIPT
@@ -131,6 +133,7 @@
 	case input_mri_script: return INPUT_MRI_SCRIPT; break;
 	case input_version_script: return INPUT_VERSION_SCRIPT; break;
 	case input_defsym: return INPUT_DEFSYM; break;
+	case input_deftmp: return INPUT_DEFTMP; break;
 	default: abort ();
 	}
     }
@@ -143,6 +146,11 @@
 <DEFSYMEXP>{FILENAMECHAR1}{SYMBOLCHARN}*   { yylval.name = xstrdup (yytext); return NAME; }
 <DEFSYMEXP>"="                  { RTOKEN('='); }
 
+<DEFTMPEXP>"-"                  { RTOKEN('-');}
+<DEFTMPEXP>"+"                  { RTOKEN('+');}
+<DEFTMPEXP>{FILENAMECHAR1}{SYMBOLCHARN}*   { yylval.name = xstrdup (yytext); return NAME; }
+<DEFTMPEXP>"="                  { RTOKEN('='); }
+
 <MRI,EXPRESSION>"$"([0-9A-Fa-f])+ {
   				yylval.integer = bfd_scan_vma (yytext + 1, 0, 16);
 				yylval.bigint.str = NULL;
@@ -174,7 +182,7 @@
 				   yylval.bigint.str = NULL;
 				   return INT;
 				 }
-<SCRIPT,DEFSYMEXP,MRI,BOTH,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
+<SCRIPT,DEFSYMEXP,DEFTMPEXP,MRI,BOTH,EXPRESSION>((("$"|0[xX])([0-9A-Fa-f])+)|(([0-9])+))(M|K|m|k)? {
 				  char *s = yytext;
 				  int ibase = 0;
 
@@ -269,6 +277,7 @@
 <BOTH,SCRIPT>"INPUT"			{ RTOKEN(INPUT);}
 <EXPRESSION,BOTH,SCRIPT>"GROUP"		{ RTOKEN(GROUP);}
 <EXPRESSION,BOTH,SCRIPT>"DEFINED"		{ RTOKEN(DEFINED);}
+<EXPRESSION,BOTH,SCRIPT>"TEMPORARY"		{ RTOKEN(TEMPORARY); }
 <BOTH,SCRIPT>"CREATE_OBJECT_SYMBOLS"	{ RTOKEN(CREATE_OBJECT_SYMBOLS);}
 <BOTH,SCRIPT>"CONSTRUCTORS"		{ RTOKEN( CONSTRUCTORS);}
 <BOTH,SCRIPT>"FORCE_COMMON_ALLOCATION" { RTOKEN(FORCE_COMMON_ALLOCATION);}
@@ -442,7 +451,7 @@
 }
 
 <SCRIPT,MRI,VERS_START,VERS_SCRIPT,VERS_NODE>.	lex_warn_invalid (" in script", yytext);
-<EXPRESSION,DEFSYMEXP,BOTH>.	lex_warn_invalid (" in expression", yytext);
+<EXPRESSION,DEFSYMEXP,DEFTMPEXP,BOTH>.	lex_warn_invalid (" in expression", yytext);
 
 %%
 \f
@@ -571,6 +580,13 @@
 }
 
 void
+ldlex_deftmp (void)
+{
+  *(state_stack_p)++ = yy_start;
+  BEGIN (DEFTMPEXP);
+}
+
+void
 ldlex_expression (void)
 {
   *(state_stack_p)++ = yy_start;
--- ld/ldmisc.c	2004-01-14 21:07:52.000000000 +0000
+++ ld/ldmisc.c	2004-07-08 22:47:45.000000000 +0000
@@ -205,6 +205,8 @@
 	      /* Print script file and linenumber.  */
 	      if (parsing_defsym)
 		fprintf (fp, "--defsym %s", lex_string);
+	      else if (parsing_deftmp)
+		fprintf (fp, "--deftmp %s", lex_string);
 	      else if (ldfile_input_filename != NULL)
 		fprintf (fp, "%s:%u", ldfile_input_filename, lineno);
 	      else
--- ld/lexsup.c	2004-04-12 19:56:36.000000000 +0000
+++ ld/lexsup.c	2004-07-08 22:47:45.000000000 +0000
@@ -59,6 +59,8 @@
 
 /* Non-zero if we are processing a --defsym from the command line.  */
 int parsing_defsym = 0;
+/* Non-zero if we are processing a --deftmp from the command line.  */
+int parsing_deftmp = 0;
 
 /* Codes used for the long options with no short synonyms.  150 isn't
    special; it's just an arbitrary non-ASCII char value.  */
@@ -68,6 +70,7 @@
   OPTION_CALL_SHARED,
   OPTION_CREF,
   OPTION_DEFSYM,
+  OPTION_DEFTMP,
   OPTION_DEMANGLE,
   OPTION_DEMANGLER,
   OPTION_DYNAMIC_LINKER,
@@ -314,6 +317,8 @@
       '\0', NULL, N_("Output cross reference table"), TWO_DASHES },
   { {"defsym", required_argument, NULL, OPTION_DEFSYM},
       '\0', N_("SYMBOL=EXPRESSION"), N_("Define a symbol"), TWO_DASHES },
+  { {"deftmp", required_argument, NULL, OPTION_DEFTMP},
+      '\0', N_("SYMBOL=EXPRESSION"), N_("Define a temporary script variable"), TWO_DASHES },
   { {"demangle", optional_argument, NULL, OPTION_DEMANGLE},
       '\0', N_("[=STYLE]"), N_("Demangle symbol names [using STYLE]"), TWO_DASHES },
   { {"demangler", no_argument, NULL, OPTION_DEMANGLER},
@@ -664,6 +669,15 @@
 	  parsing_defsym = 0;
 	  lex_string = NULL;
 	  break;
+	case OPTION_DEFTMP:
+	  lex_string = optarg;
+	  lex_redirect (optarg);
+	  parser_input = input_deftmp;
+	  parsing_deftmp = 1;
+	  yyparse ();
+	  parsing_deftmp = 0;
+	  lex_string = NULL;
+	  break;
 	case OPTION_DEMANGLE:
 	  demangling = TRUE;
 	  if (optarg != NULL)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-08 23:45   ` Guilherme Destefani
@ 2004-07-21 13:24     ` Nick Clifton
  2004-07-21 15:20       ` Ian Lance Taylor
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2004-07-21 13:24 UTC (permalink / raw)
  To: Guilherme Destefani; +Cc: Zack Weinberg, binutils

Hi Guilherme,

> While testing if it's working, I found out that if I have a script with
> those lines inside SECTIONS{
> lixo = lixo_1;
> TEMPORARY( lixo_1 = 0x1);
> }
> 
> I have as result:
> make ok;readelf -a ok|grep lixo
> cc -Wl,-T -Wl,script -Wl,--deftmp -Wl,lixo1=0x19  -Wl,--deftmp
> -Wl,lixo2=0x29    ok.c   -o ok
>     49: 00000001     0 NOTYPE  GLOBAL DEFAULT  ABS lixo
>     59: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND lixo_1
> 
> As you can see, lixo_1 ends up as undefined.
> The parser accept the variable, but in the tree used to construct the
> sentence lixo = lixo_1; lixo_1 is not defined yet.	Why the parser accept
> a variable that wasn't defined yet?

Because it was never programmed not to.  There is no good reason to 
accept this, and in fact I agree that the parser ought to issue an error 
message.  It is just that I doubt if anyone has ever done this with a 
linker script before.


> It is OK to left a small amount of memory allocated, like this patch and
> the lang_memory_region_list does?

Not really.  If it is going to be very difficult to recover the memory 
then it can be permitted, but a decent effort ought to be made to avoid 
memory leaks.  Just because leaks are present in old code, it does not 
excuse leaks in new code.  In fact really the old code ought to be fixed 
as well.

Cheers
   Nick


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-21 13:24     ` Nick Clifton
@ 2004-07-21 15:20       ` Ian Lance Taylor
  2004-07-21 15:39         ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Ian Lance Taylor @ 2004-07-21 15:20 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Guilherme Destefani, Zack Weinberg, binutils

Nick Clifton <nickc@redhat.com> writes:

> > While testing if it's working, I found out that if I have a script with
> > those lines inside SECTIONS{
> > lixo = lixo_1;
> > TEMPORARY( lixo_1 = 0x1);
> > }
> > I have as result:
> > make ok;readelf -a ok|grep lixo
> > cc -Wl,-T -Wl,script -Wl,--deftmp -Wl,lixo1=0x19  -Wl,--deftmp
> > -Wl,lixo2=0x29    ok.c   -o ok
> >     49: 00000001     0 NOTYPE  GLOBAL DEFAULT  ABS lixo
> >     59: 00000000     0 NOTYPE  GLOBAL DEFAULT  UND lixo_1
> > As you can see, lixo_1 ends up as undefined.
> > The parser accept the variable, but in the tree used to construct the
> > sentence lixo = lixo_1; lixo_1 is not defined yet.	Why the parser accept
> > a variable that wasn't defined yet?
> 
> Because it was never programmed not to.  There is no good reason to
> accept this, and in fact I agree that the parser ought to issue an
> error message.  It is just that I doubt if anyone has ever done this
> with a linker script before.

Note that there is a very good reason to accept
    foo = bar
if bar is defined in some .o file.  I don't think you can report an
error in the parser.

Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-21 15:20       ` Ian Lance Taylor
@ 2004-07-21 15:39         ` Nick Clifton
  2004-07-21 15:53           ` Ian Lance Taylor
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2004-07-21 15:39 UTC (permalink / raw)
  To: Ian Lance Taylor; +Cc: Guilherme Destefani, Zack Weinberg, binutils

Hi Ian,

>>Because it was never programmed not to.  There is no good reason to
>>accept this, and in fact I agree that the parser ought to issue an
>>error message.  It is just that I doubt if anyone has ever done this
>>with a linker script before.

> Note that there is a very good reason to accept
>     foo = bar
> if bar is defined in some .o file.

Oh indeed - I meant that an error should be produced only when bar is 
not defined anywhere.

> I don't think you can report an error in the parser.

Which is presumably why the undefined symbol is created in the first 
place.  Hmm, I guess that we have to live with this behaviour, so the 
right thing to do would be to document it, yes ?

Cheers
   Nick


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file
  2004-07-21 15:39         ` Nick Clifton
@ 2004-07-21 15:53           ` Ian Lance Taylor
  0 siblings, 0 replies; 7+ messages in thread
From: Ian Lance Taylor @ 2004-07-21 15:53 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Guilherme Destefani, Zack Weinberg, binutils

Nick Clifton <nickc@redhat.com> writes:

> Which is presumably why the undefined symbol is created in the first
> place.  Hmm, I guess that we have to live with this behaviour, so the
> right thing to do would be to document it, yes ?

Arguably I suppose we could record such symbols as we create them, and
then walk the list at the end of the link and warn if the symbol was
never defined.

If anybody wants to bother.

Ian

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2004-07-21 15:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-07-08 13:26 RFC and PATCH - Defining variables in the linker script without defining them as symbols on the file Guilherme Destefani
2004-07-08 17:04 ` Zack Weinberg
2004-07-08 23:45   ` Guilherme Destefani
2004-07-21 13:24     ` Nick Clifton
2004-07-21 15:20       ` Ian Lance Taylor
2004-07-21 15:39         ` Nick Clifton
2004-07-21 15:53           ` Ian Lance Taylor

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).