public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* MEMORY commands in link scripts
@ 2004-11-05 11:59 Jon Beniston
  2004-11-05 12:55 ` Dave Korn
  0 siblings, 1 reply; 6+ messages in thread
From: Jon Beniston @ 2004-11-05 11:59 UTC (permalink / raw)
  To: binutils

Hi,

Is there any way to either use non-constants for the ORIGIN or LENGTH values
in a MEMORY command, or some how access these values else where in a link
script. What I would like to be able to do is, something like:

base = 0x100;
size = 0x100;

MEMORY {
  ram (rw) : ORIGIN = base, LENGTH = size;
}

...

SECTIONS {
   PROVIDE(_fstack = base + size - 4)
}

Or, alternatively:

SECTIONS {
   PROVIDE(_fstack = ORIGIN(ram) + LENGTH(ram) - 4)
}

To put it another way, I would like to be able to override the size /
position of a memory from the command line.

Cheers,
Jon


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

* RE: MEMORY commands in link scripts
  2004-11-05 11:59 MEMORY commands in link scripts Jon Beniston
@ 2004-11-05 12:55 ` Dave Korn
  2004-11-05 13:26   ` Jon Beniston
  0 siblings, 1 reply; 6+ messages in thread
From: Dave Korn @ 2004-11-05 12:55 UTC (permalink / raw)
  To: jbeniston, binutils

> -----Original Message-----
> From: binutils-owner On Behalf Of Jon Beniston
> Sent: 05 November 2004 11:59

> Hi,
> 
> Is there any way to either use non-constants for the ORIGIN 
> or LENGTH values
> in a MEMORY command, or some how access these values else 
> where in a link script. 

  Alas no.  Although the documentation suggests this should be possible, it
isn't.  See

http://sources.redhat.com/ml/binutils/2004-03/msg00540.html
http://sources.redhat.com/ml/binutils/2004-03/msg00571.html

for detailed explanation.  The docs should be updated.  I've filed a
bugzilla report.  Should have done so months ago.  Sorry all.

http://sources.redhat.com/bugzilla/show_bug.cgi?id=518

  Your best bet would be to work around it in your build system, perhaps by
building a linker script as a make target, or perhaps you could use multiple
-T options, and do something like

echo "base = ${BASE}" > ldscript.tmp
echo "size = ${SIZE}" >> ldscript.tmp
echo "MEMORY {" >> ldscript.tmp
echo "  ram (rw) : ORIGIN = ${BASE}, LENGTH = ${SIZE};" >> ldscript.tmp
echo "}" >>ldscript.tmp

then have a main linker script that has all the unchanging parts in it:

--------------------ldscript.main--------------------

  .... 

SECTIONS {
   PROVIDE(_fstack = base + size - 4)
}

  .... 

--------------------ldscript.main--------------------

and on your link command line, use "-T ldscript.tmp -T ldscript.main" to
assemble the two parts into one script.

    cheers, 
      DaveK
-- 
Can't think of a witty .sigline today....

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

* RE: MEMORY commands in link scripts
  2004-11-05 12:55 ` Dave Korn
@ 2004-11-05 13:26   ` Jon Beniston
  2004-11-08  8:46     ` Nick Clifton
  0 siblings, 1 reply; 6+ messages in thread
From: Jon Beniston @ 2004-11-05 13:26 UTC (permalink / raw)
  To: 'Dave Korn', binutils

> 
>   Alas no.  Although the documentation suggests this should 
> be possible, it isn't.  See

Cheers for that explaination.

I still think it might be useful have ORIGIN() and LENGTH() functions. If I
were to create a patch to implement this, is it likely to be accepted? Would
overloading the  ADDR() and SIZEOF() functions be more approriate?

Cheers,
Jon


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

* Re: MEMORY commands in link scripts
  2004-11-05 13:26   ` Jon Beniston
@ 2004-11-08  8:46     ` Nick Clifton
  2004-11-08 11:51       ` Jon Beniston
  0 siblings, 1 reply; 6+ messages in thread
From: Nick Clifton @ 2004-11-08  8:46 UTC (permalink / raw)
  To: jbeniston; +Cc: 'Dave Korn', binutils

Hi Jon,

> I still think it might be useful have ORIGIN() and LENGTH() functions. If I
> were to create a patch to implement this, is it likely to be accepted? 

Yes, provided that a) it worked, b) it was tested and c) you had a 
copyright assignment on file with the FSF.

 >Would overloading the ADDR() and SIZEOF() functions be more approriate?

No, definitely not.  Keep things simple. :-)

Cheers
   Nick


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

* RE: MEMORY commands in link scripts
  2004-11-08  8:46     ` Nick Clifton
@ 2004-11-08 11:51       ` Jon Beniston
  2004-11-19  9:31         ` Nick Clifton
  0 siblings, 1 reply; 6+ messages in thread
From: Jon Beniston @ 2004-11-08 11:51 UTC (permalink / raw)
  To: binutils

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

Hi,

> > I still think it might be useful have ORIGIN() and LENGTH() 
> functions. 

Attached is a patch that implements these two functions.

Cheers,
Jon

2004-11-08  Jon Beniston <jon@beniston.com>

	* ld/ldlex.l: Allow ORIGIN and LENGTH in EXPRESSION.
	* ld/ldgram.y: Add ORIGIN and LENGTH expressions.
	* ld/ldexp.c (fold_name): Implement LENGTH() and ORIGIN() functions 
	which return the length and origin of a memory.
	* ld/ld.texinfo: Document LENGTH() and ORIGIN() functions.

[-- Attachment #2: mem_origin_and_length.patch --]
[-- Type: application/octet-stream, Size: 5759 bytes --]

? mem_origin_and_length.patch
Index: ld.texinfo
===================================================================
RCS file: /cvs/src/src/ld/ld.texinfo,v
retrieving revision 1.129
diff -c -p -r1.129 ld.texinfo
*** ld.texinfo	26 Oct 2004 18:41:51 -0000	1.129
--- ld.texinfo	8 Nov 2004 11:38:45 -0000
*************** the next available address within the me
*** 3881,3886 ****
--- 3881,3896 ----
  output sections directed to a memory region are too large for the
  region, the linker will issue an error message.
  
+ It is possible to access the origin and length of a memory in an 
+ expression via the @code{ORIGIN(@var{memory})} and @code{LENGTH(@var{memory})} 
+ functions:
+ 
+ @smallexample
+ @group
+   _fstack = ORIGIN(ram) + LENGTH(ram) - 4;  
+ @end group
+ @end smallexample
+ 
  @node PHDRS
  @section PHDRS Command
  @kindex PHDRS
*************** SECTIONS @{ @dots{}
*** 4656,4661 ****
--- 4666,4675 ----
  @end group
  @end smallexample
  
+ @item LENGTH(@var{memory})
+ @kindex LENGTH(@var{memory})
+ Return the length of the named @var{memory}.
+ 
  @item LOADADDR(@var{section})
  @kindex LOADADDR(@var{section})
  @cindex section load address in expression
*************** This function is closely related to @cod
*** 4680,4685 ****
--- 4694,4703 ----
  use the @code{MEMORY} command to define discontinuous memory for the
  output file, the two functions are equivalent.
  
+ @item ORIGIN(@var{memory})
+ @kindex ORIGIN(@var{memory})
+ Return the origin of the named @var{memory}.
+ 
  @item SEGMENT_START(@var{segment}, @var{default})
  @kindex SEGMENT_START(@var{segment}, @var{default})
  Return the base address of the named @var{segment}.  If an explicit
Index: ldexp.c
===================================================================
RCS file: /cvs/src/src/ld/ldexp.c,v
retrieving revision 1.38
diff -c -p -r1.38 ldexp.c
*** ldexp.c	26 Oct 2004 18:41:51 -0000	1.38
--- ldexp.c	8 Nov 2004 11:38:45 -0000
*************** exp_print_token (token_code_type code, i
*** 105,111 ****
      { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
      { DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
      { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
!     { SEGMENT_START, "SEGMENT_START" }
    };
    unsigned int idx;
  
--- 105,113 ----
      { DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
      { DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
      { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
!     { SEGMENT_START, "SEGMENT_START" },
!     { ORIGIN, "ORIGIN" },
!     { LENGTH, "LENGTH" }
    };
    unsigned int idx;
  
*************** fold_name (etree_type *tree,
*** 645,650 ****
--- 647,678 ----
  	}
        break;
  
+     case LENGTH:
+       {
+         lang_memory_region_type *mem;
+         
+         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
+         if (mem != NULL) 
+           result = new_abs (mem->length);
+         else          
+           einfo (_("%F%S: undefined memory `%s' referenced in expression\n"),
+ 		   tree->name.name);
+       }
+       break;
+ 
+     case ORIGIN:
+       {
+         lang_memory_region_type *mem;
+         
+         mem = lang_memory_region_lookup (tree->name.name, FALSE);  
+         if (mem != NULL) 
+           result = new_abs (mem->origin);
+         else          
+           einfo (_("%F%S: undefined memory `%s' referenced in expression\n"),
+ 		   tree->name.name);
+       }
+       break;
+ 
      default:
        FAIL ();
        break;
Index: ldgram.y
===================================================================
RCS file: /cvs/src/src/ld/ldgram.y,v
retrieving revision 1.37
diff -c -p -r1.37 ldgram.y
*** ldgram.y	26 Oct 2004 18:41:51 -0000	1.37
--- ldgram.y	8 Nov 2004 11:38:45 -0000
*************** exp	:
*** 863,868 ****
--- 863,872 ----
  			{ $$ = exp_binop (MIN_K, $3, $5 ); }
  	|	ASSERT_K '(' exp ',' NAME ')'
  			{ $$ = exp_assert ($3, $5); }
+ 	|	ORIGIN '(' NAME ')'
+ 			{ $$ = exp_nameop(ORIGIN, $3); }
+ 	|	LENGTH '(' NAME ')'
+ 			{ $$ = exp_nameop(LENGTH, $3); }
  	;
  
  
Index: ldlex.l
===================================================================
RCS file: /cvs/src/src/ld/ldlex.l,v
retrieving revision 1.27
diff -c -p -r1.27 ldlex.l
*** ldlex.l	26 Oct 2004 18:41:51 -0000	1.27
--- ldlex.l	8 Nov 2004 11:38:48 -0000
*************** V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
*** 242,252 ****
  <BOTH,SCRIPT,EXPRESSION,MRI>":"		{ RTOKEN(':'); }
  <BOTH,SCRIPT,EXPRESSION,MRI>";"		{ RTOKEN(';');}
  <BOTH,SCRIPT>"MEMORY"		{ RTOKEN(MEMORY);}
! <BOTH,SCRIPT>"ORIGIN"		{ RTOKEN(ORIGIN);}
  <BOTH,SCRIPT>"VERSION"		{ RTOKEN(VERSIONK);}
  <EXPRESSION,BOTH,SCRIPT>"BLOCK"		{ RTOKEN(BLOCK);}
  <EXPRESSION,BOTH,SCRIPT>"BIND"		{ RTOKEN(BIND);}
! <BOTH,SCRIPT>"LENGTH"		{ RTOKEN(LENGTH);}
  <EXPRESSION,BOTH,SCRIPT>"ALIGN"			{ RTOKEN(ALIGN_K);}
  <EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_ALIGN"	{ RTOKEN(DATA_SEGMENT_ALIGN);}
  <EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_RELRO_END"	{ RTOKEN(DATA_SEGMENT_RELRO_END);}
--- 242,252 ----
  <BOTH,SCRIPT,EXPRESSION,MRI>":"		{ RTOKEN(':'); }
  <BOTH,SCRIPT,EXPRESSION,MRI>";"		{ RTOKEN(';');}
  <BOTH,SCRIPT>"MEMORY"		{ RTOKEN(MEMORY);}
! <BOTH,SCRIPT,EXPRESSION>"ORIGIN"		{ RTOKEN(ORIGIN);}
  <BOTH,SCRIPT>"VERSION"		{ RTOKEN(VERSIONK);}
  <EXPRESSION,BOTH,SCRIPT>"BLOCK"		{ RTOKEN(BLOCK);}
  <EXPRESSION,BOTH,SCRIPT>"BIND"		{ RTOKEN(BIND);}
! <BOTH,SCRIPT,EXPRESSION>"LENGTH"		{ RTOKEN(LENGTH);}
  <EXPRESSION,BOTH,SCRIPT>"ALIGN"			{ RTOKEN(ALIGN_K);}
  <EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_ALIGN"	{ RTOKEN(DATA_SEGMENT_ALIGN);}
  <EXPRESSION,BOTH,SCRIPT>"DATA_SEGMENT_RELRO_END"	{ RTOKEN(DATA_SEGMENT_RELRO_END);}

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

* Re: MEMORY commands in link scripts
  2004-11-08 11:51       ` Jon Beniston
@ 2004-11-19  9:31         ` Nick Clifton
  0 siblings, 0 replies; 6+ messages in thread
From: Nick Clifton @ 2004-11-19  9:31 UTC (permalink / raw)
  To: jbeniston; +Cc: binutils

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

Hi Jon,

> 2004-11-08  Jon Beniston <jon@beniston.com>
> 
> 	* ld/ldlex.l: Allow ORIGIN and LENGTH in EXPRESSION.
> 	* ld/ldgram.y: Add ORIGIN and LENGTH expressions.
> 	* ld/ldexp.c (fold_name): Implement LENGTH() and ORIGIN() functions 
> 	which return the length and origin of a memory.
> 	* ld/ld.texinfo: Document LENGTH() and ORIGIN() functions.

Approved and applied.

Note - I felt that this patch deserved a mention in the ld/NEWS file 
since it implements a new feature and also a testsuite case to check to 
make sure that it works.  So I have added the attached patch to do these 
things.

Cheers
   Nick

ld/ChangeLog

	* NEWS: Mention support for ORIGIN and LENGTH operators.

ld/testsuite/ChangeLog
2004-11-19  Nick Clifton  <nickc@redhat.com>

	* ld-scripts/script.exp: Add test of memory linker script.
	Reorganize code to remove unnecessary indentation.
	Fix target tests to avoid using --image-base with *-nto targets.
	* ld-scripts/memory.t: New linker script to test the MEMORY
	section and the ORIGIN and LENGTH operators.


[-- Attachment #2: ld.patch --]
[-- Type: text/plain, Size: 6091 bytes --]

Index: ld/NEWS
===================================================================
RCS file: /cvs/src/src/ld/NEWS,v
retrieving revision 1.54
diff -c -3 -p -r1.54 NEWS
*** ld/NEWS	8 Nov 2004 13:17:24 -0000	1.54
--- ld/NEWS	19 Nov 2004 09:24:01 -0000
***************
*** 1,5 ****
--- 1,8 ----
  -*- text -*-
  
+ * New linker script functions: ORIGIN() and LENGTH() which return information
+   about a specified memory region.
+ 
  * Port to MAXQ processor contributed by HCL Tech.
  
  * Added SEGMENT_START to the linker script language to permit the user to

Index: ld/testsuite/ld-scripts/script.exp
===================================================================
RCS file: /cvs/src/src/ld/testsuite/ld-scripts/script.exp,v
retrieving revision 1.6
diff -c -3 -p -r1.6 script.exp
*** ld/testsuite/ld-scripts/script.exp	18 Nov 2002 08:28:41 -0000	1.6
--- ld/testsuite/ld-scripts/script.exp	19 Nov 2004 09:24:04 -0000
*************** proc check_script { } {
*** 31,77 ****
  
      if ![ld_nm $nm "" tmpdir/script] {
  	unresolved $testname
      } else {
! 	if {![info exists nm_output(text_start)] \
! 	     || ![info exists nm_output(text_end)] \
! 	     || ![info exists nm_output(data_start)] \
! 	     || ![info exists nm_output(data_end)]} {
! 	    send_log "bad output from nm\n"
! 	    verbose "bad output from nm"
! 	    fail $testname
! 	} else {
! 	    set text_end 0x104
! 	    set data_end 0x1004
!             if [istarget *c4x*-*-*] then {
!                 set text_end 0x101
!                 set data_end 0x1001
!             }
! 	    if [istarget *c54x*-*-*] then {
! 		set text_end 0x102
! 		set data_end 0x1002
! 	    }
! 	    if {$nm_output(text_start) != 0x100} {
! 		send_log "text_start == $nm_output(text_start)\n"
! 		verbose "text_start == $nm_output(text_start)"
! 		fail $testname
! 	    } else { if {$nm_output(text_end) < $text_end \
! 			  || $nm_output(text_end) > 0x110} {
! 		send_log "text_end == $nm_output(text_end)\n"
! 		verbose "text_end == $nm_output(text_end)"
! 		fail $testname
! 	    } else { if {$nm_output(data_start) != 0x1000} {
! 		send_log "data_start == $nm_output(data_start)\n"
! 		verbose "data_start == $nm_output(data_start)"
! 		fail $testname
! 	    } else { if {$nm_output(data_end) < $data_end \
! 			 || $nm_output(data_end) > 0x1010} {
! 		send_log "data_end == $nm_output(data_end)\n"
! 		verbose "data_end == $nm_output(data_end)"
! 		fail $testname
! 	    } else {
! 		pass $testname
! 	    } } } }
! 	}
      }
  }
  
--- 31,93 ----
  
      if ![ld_nm $nm "" tmpdir/script] {
  	unresolved $testname
+ 	return
+     } 
+ 
+     if {![info exists nm_output(text_start)] \
+ 	    || ![info exists nm_output(text_end)] \
+ 	    || ![info exists nm_output(data_start)] \
+ 	    || ![info exists nm_output(data_end)]} {
+ 	send_log "bad output from nm\n"
+ 	verbose "bad output from nm"
+ 	fail $testname
+ 	return
+     } 
+ 
+     set passes 1
+     set text_end 0x104
+     set data_end 0x1004
+ 
+     if [istarget *c4x*-*-*] then {
+ 	set text_end 0x101
+ 	set data_end 0x1001
+     }
+ 
+     if [istarget *c54x*-*-*] then {
+ 	set text_end 0x102
+ 	set data_end 0x1002
+     }
+ 
+     if {$nm_output(text_start) != 0x100} {
+ 	send_log "text_start == $nm_output(text_start)\n"
+ 	verbose "text_start == $nm_output(text_start)"
+ 	set passes 0
+     } 
+ 
+     if {$nm_output(text_end) < $text_end \
+ 	    || $nm_output(text_end) > 0x110} {
+ 	send_log "text_end == $nm_output(text_end)\n"
+ 	verbose "text_end == $nm_output(text_end)"
+ 	set passes 0
+     } 
+ 
+     if {$nm_output(data_start) != 0x1000} {
+ 	send_log "data_start == $nm_output(data_start)\n"
+ 	verbose "data_start == $nm_output(data_start)"
+ 	set passes 0
+     } 
+ 
+     if {$nm_output(data_end) < $data_end \
+ 	    || $nm_output(data_end) > 0x1010} {
+ 	send_log "data_end == $nm_output(data_end)\n"
+ 	verbose "data_end == $nm_output(data_end)"
+ 	set passes 0
+     } 
+ 
+     if { $passes } {
+ 	pass $testname
      } else {
! 	fail $testname
      }
  }
  
*************** if {[istarget "*-*-pe*"] \
*** 81,87 ****
      || [istarget "*-*-cygwin*"] \
      || [istarget "*-*-mingw32*"] \
      || [istarget "*-*-winnt*"] \
!     || [istarget "*-*-nt*"] \
      || [istarget "*-*-interix*"] } then {
    set flags "--image-base 0"
  }
--- 97,103 ----
      || [istarget "*-*-cygwin*"] \
      || [istarget "*-*-mingw32*"] \
      || [istarget "*-*-winnt*"] \
!     || [istarget "*-*-nt"] \
      || [istarget "*-*-interix*"] } then {
    set flags "--image-base 0"
  }
*************** if ![ld_simple_link $ld tmpdir/script "$
*** 99,101 ****
--- 115,127 ----
  } else {
      check_script
  }
+ 
+ set testname "MEMORY"
+ 
+ if ![ld_simple_link $ld tmpdir/script "$flags -T $srcdir/$subdir/memory.t tmpdir/script.o"] {
+     fail $testname
+ } else {
+     check_script
+ }
+ 
+ 

Index: ld/testsuite/ld-scripts/memory.t
===================================================================
0a1,39
> MEMORY
> {
>   TEXTMEM (ARX) : ORIGIN = 0x100, LENGTH = 32K
>   DATAMEM (AW)  : org = 0x1000, l = (64 * 1024)
> }
> 
> SECTIONS
> {
>   . = 0;
>   .text :
>   {
>     /* The value returned by the ORIGIN operator is a constant.
>        However it is being assigned to a symbol declared within
>        a section.  Therefore the symbol is section-relative and
>        its value will include the offset of that section from
>        the start of memory.  ie the declaration:
>           text_start = ORIGIN (TEXTMEM);
>        here will result in text_start having a value of 0x200.
>        Hence we need to subtract the absolute value of the
>        location counter at this point in order to give text_start
>        a value that is truely absolute, and which coincidentally
>        will allow the tests in script.exp to work.  */
>  	
>     text_start = ORIGIN(TEXTMEM) - ABSOLUTE (.);
>     *(.text)
>     *(.pr)
>     text_end = .;
>   } > TEXTMEM
>   
>   data_start = ORIGIN (DATAMEM);
>   .data :
>   {
>     *(.data)
>     *(.rw)
>     data_end = .;
>   } >DATAMEM
> 
>   fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM);  
> }

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

end of thread, other threads:[~2004-11-19  9:31 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2004-11-05 11:59 MEMORY commands in link scripts Jon Beniston
2004-11-05 12:55 ` Dave Korn
2004-11-05 13:26   ` Jon Beniston
2004-11-08  8:46     ` Nick Clifton
2004-11-08 11:51       ` Jon Beniston
2004-11-19  9:31         ` Nick Clifton

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).