This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] ld: add support for LOG2() in linker scripts


Hi,

I recently needed linker sections to have a size that is a power of two,
because MPUs on ARM devices conforming to PMSAv7 only support region
sizes that are powers of two[1]. It seems there was no way to do that in
a linker script so far. Previous solutions I've seen involved linking
the binary twice and automatically adjusting the linker script depending
on the binary linked in the first step.

Please find attached a patch against the GNU ld source to add a unary
LOG2() function, returning the binary logarithm of its argument, rounded
towards 0. The implementation also returns 0 for a zero argument.

A couple questions:
 - Would somebody please merge this?
 - Where can I find the source for [2], so I can add documentation?
 - Do you require some form of copyright assignment? Are there other
   formal requirements for this patch to be applied?

Please bear with me, this is my first patch submission to binutils.

[1] in reality, it's a little more complicated than that because PMSAv7
    supports sub-regions, but that's out of scope of this mail.
[2] http://sourceware.org/binutils/docs/ld/

-- 
Clemens Lang
System Software Group, University of Erlangen-Nuremberg
Adds a binary logarithm function usable in linker scripts. LOG2(x)
returns the logarithm of x, rounded down to the next integer. Returns
0 for x == 0. Can be used to determine the logarithm rounded up using
LOG2(x-1) + 1.

This is useful for ARM devices using an MPU conforming to PMSAv7, e.g.,
the Cortex-M3, where MPU regions need to be aligned depending on their
size. Without the ability to compute logarithms in linker scripts, this
cannot be achieved in a single linking pass.
---
 ld/ldexp.c  |   18 ++++++++++++++++++
 ld/ldgram.y |    4 +++-
 ld/ldlex.l  |    1 +
 3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/ld/ldexp.c b/ld/ldexp.c
index ae3919b..f038b83 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -81,6 +81,7 @@ exp_print_token (token_code_type code, int infix_p)
     { GE, ">=" },
     { LSHIFT, "<<" },
     { RSHIFT, ">>" },
+    { LOG2, "LOG2" },
     { ALIGN_K, "ALIGN" },
     { BLOCK, "BLOCK" },
     { QUAD, "QUAD" },
@@ -143,6 +144,19 @@ make_abs (void)
 }
 
 static void
+make_log2 (void)
+{
+  bfd_vma value = expld.result.value;
+  bfd_vma result = 0;
+  while (value >>= 1)
+    {
+      result++;
+    }
+  expld.result.section = NULL;
+  expld.result.value = result;
+}
+
+static void
 new_abs (bfd_vma value)
 {
   expld.result.valid_p = TRUE;
@@ -242,6 +256,10 @@ fold_unary (etree_type *tree)
 	  make_abs ();
 	  break;
 
+	case LOG2:
+	  make_log2 ();
+	  break;
+
 	case '~':
 	  expld.result.value = ~expld.result.value;
 	  break;
diff --git a/ld/ldgram.y b/ld/ldgram.y
index ee88196..5cec080 100644
--- a/ld/ldgram.y
+++ b/ld/ldgram.y
@@ -149,7 +149,7 @@ static int error_index;
 %token ALIGNMOD AT SUBALIGN HIDDEN PROVIDE PROVIDE_HIDDEN AS_NEEDED
 %type <token> assign_op atype attributes_opt sect_constraint
 %type <name>  filename
-%token CHIP LIST SECT ABSOLUTE  LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K
+%token CHIP LIST SECT ABSOLUTE LOAD NEWLINE ENDWORD ORDER NAMEWORD ASSERT_K LOG2
 %token FORMAT PUBLIC DEFSYMEND BASE ALIAS TRUNCATE REL
 %token INPUT_SCRIPT INPUT_MRI_SCRIPT INPUT_DEFSYM CASE EXTERN START
 %token <name> VERS_TAG VERS_IDENTIFIER
@@ -1012,6 +1012,8 @@ exp	:
 			{ $$ = exp_nameop (ORIGIN, $3); }
 	|	LENGTH '(' NAME ')'
 			{ $$ = exp_nameop (LENGTH, $3); }
+	|	LOG2 '(' exp ')'
+			{ $$ = exp_unop (LOG2, $3); }
 	;
 
 
diff --git a/ld/ldlex.l b/ld/ldlex.l
index abe31c0..a64cf5b 100644
--- a/ld/ldlex.l
+++ b/ld/ldlex.l
@@ -259,6 +259,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([*?.$_a-zA-Z0-9\[\]\-\!\^\\]|::)*
 <EXPRESSION,BOTH,SCRIPT>"ALIGNOF"	{ RTOKEN(ALIGNOF); }
 <EXPRESSION,BOTH>"MAX"			{ RTOKEN(MAX_K); }
 <EXPRESSION,BOTH>"MIN"			{ RTOKEN(MIN_K); }
+<EXPRESSION,BOTH>"LOG2"			{ RTOKEN(LOG2); }
 <EXPRESSION,BOTH,SCRIPT>"ASSERT"	{ RTOKEN(ASSERT_K); }
 <BOTH,SCRIPT>"ENTRY"			{ RTOKEN(ENTRY);}
 <BOTH,SCRIPT,MRI>"EXTERN"		{ RTOKEN(EXTERN);}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]