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]

RFC: Add -z text-start-addr=ADDR to ELF linker


Hi,

Sometimes, we want to load the ELF executable in a different address from
the default.  This patch adds -z text-start-addr=ADDR to ELF linker. If it
is acceptable, I will submit a complete patch with some testcases.

Thanks.


H.J.
---
Index: ld/emultempl/elf32.em
===================================================================
--- ld/emultempl/elf32.em	(revision 4759)
+++ ld/emultempl/elf32.em	(working copy)
@@ -2162,7 +2162,8 @@ fragment <<EOF
 	    einfo (_("%P%F: invalid maxium page size \`%s'\n"),
 		   optarg + 14);
 	  ASSERT (default_target != NULL);
-	  bfd_emul_set_maxpagesize (default_target, config.maxpagesize);
+	  bfd_emul_set_constant (default_target, maxpagesize,
+				 config.maxpagesize);
 	}
       else if (CONST_STRNEQ (optarg, "common-page-size="))
 	{
@@ -2173,8 +2174,20 @@ fragment <<EOF
 	    einfo (_("%P%F: invalid common page size \`%s'\n"),
 		   optarg + 17);
 	  ASSERT (default_target != NULL);
-	  bfd_emul_set_commonpagesize (default_target,
-				       config.commonpagesize);
+	  bfd_emul_set_constant (default_target, commonpagesize,
+				 config.commonpagesize);
+	}
+      else if (CONST_STRNEQ (optarg, "text-start-addr="))
+	{
+	  char *end;
+	  config.text_start_addr = strtoul (optarg + 16, &end, 0);
+	  if (*end
+	      || (config.text_start_addr == (bfd_vma) -1))
+	    einfo (_("%P%F: invalid text start address\`%s'\n"),
+		   optarg + 16);
+	  ASSERT (default_target != NULL);
+	  bfd_emul_set_constant (default_target, text_start_addr,
+				 config.text_start_addr);
 	}
       /* What about the other Solaris -z options? FIXME.  */
       break;
@@ -2277,6 +2290,8 @@ fragment <<EOF
   fprintf (file, _("\
   -z common-page-size=SIZE    Set common page size to SIZE\n"));
   fprintf (file, _("\
+  -z text-start-addr=ADDR     Set text start address to ADDR\n"));
+  fprintf (file, _("\
   -z KEYWORD                  Ignored for Solaris compatibility\n"));
 EOF
 fi
Index: ld/ld.h
===================================================================
--- ld/ld.h	(revision 4759)
+++ ld/ld.h	(working copy)
@@ -300,6 +300,9 @@ typedef struct {
 
   /* The common page size for ELF.  */
   bfd_vma commonpagesize;
+
+  /* The first byte of the text segment for ELF.  */
+  bfd_vma text_start_addr;
 } ld_config_type;
 
 extern ld_config_type config;
Index: ld/emulparams/elf_i386_ldso.sh
===================================================================
--- ld/emulparams/elf_i386_ldso.sh	(revision 4759)
+++ ld/emulparams/elf_i386_ldso.sh	(working copy)
@@ -1,7 +1,7 @@
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
 NO_RELA_RELOCS=yes
-TEXT_START_ADDR=0x08048000
+TEXT_START_ADDR="CONSTANT (TEXT_START_ADDR)"
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 ARCH=i386
 MACHINE=
Index: ld/emulparams/elf_i386.sh
===================================================================
--- ld/emulparams/elf_i386.sh	(revision 4759)
+++ ld/emulparams/elf_i386.sh	(working copy)
@@ -1,7 +1,7 @@
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386"
 NO_RELA_RELOCS=yes
-TEXT_START_ADDR=0x08048000
+TEXT_START_ADDR="CONSTANT (TEXT_START_ADDR)"
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH=i386
Index: ld/emulparams/elf_i386_vxworks.sh
===================================================================
--- ld/emulparams/elf_i386_vxworks.sh	(revision 4759)
+++ ld/emulparams/elf_i386_vxworks.sh	(working copy)
@@ -1,7 +1,7 @@
 SCRIPT_NAME=elf
 OUTPUT_FORMAT="elf32-i386-vxworks"
 NO_RELA_RELOCS=yes
-TEXT_START_ADDR=0x08048000
+TEXT_START_ADDR="CONSTANT (TEXT_START_ADDR)"
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH=i386
Index: ld/emulparams/elf_x86_64.sh
===================================================================
--- ld/emulparams/elf_x86_64.sh	(revision 4759)
+++ ld/emulparams/elf_x86_64.sh	(working copy)
@@ -2,7 +2,7 @@ SCRIPT_NAME=elf
 ELFSIZE=64
 OUTPUT_FORMAT="elf64-x86-64"
 NO_REL_RELOCS=yes
-TEXT_START_ADDR=0x400000
+TEXT_START_ADDR="CONSTANT (TEXT_START_ADDR)"
 MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
 COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
 ARCH="i386:x86-64"
Index: ld/ldexp.c
===================================================================
--- ld/ldexp.c	(revision 4759)
+++ ld/ldexp.c	(working copy)
@@ -482,6 +482,8 @@ fold_trinary (etree_type *tree)
 static void
 fold_name (etree_type *tree)
 {
+  enum bfd_emul_constant constant;
+
   memset (&expld.result, 0, sizeof (expld.result));
 
   switch (tree->type.node_code)
@@ -673,12 +675,15 @@ fold_name (etree_type *tree)
 
     case CONSTANT:
       if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
-	new_abs (bfd_emul_get_maxpagesize (default_target));
+	constant = maxpagesize;
       else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
-	new_abs (bfd_emul_get_commonpagesize (default_target));
+	constant = commonpagesize;
+      else if (strcmp (tree->name.name, "TEXT_START_ADDR") == 0)
+	constant = text_start_addr;
       else
 	einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
 	       tree->name.name);
+      new_abs (bfd_emul_get_constant (default_target, constant));
       break;
 
     default:
Index: ld/ld.texinfo
===================================================================
--- ld/ld.texinfo	(revision 4942)
+++ ld/ld.texinfo	(working copy)
@@ -1049,6 +1049,9 @@ Set the emulation maximum page size to @
 @item common-page-size=@var{value}
 Set the emulation common page size to @var{value}.
 
+@item text-start-addr=@var{value}
+Set the first byte of the text segment to @var{value}.
+
 @end table
 
 Other keywords are ignored for Solaris compatibility.
Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h	(revision 4942)
+++ bfd/elf-bfd.h	(working copy)
@@ -629,6 +629,9 @@ struct elf_backend_data
   /* The common page size for this backend.  */
   bfd_vma commonpagesize;
 
+  /* The first byte of the text segment for this backend.  */
+  bfd_vma text_start_addr;
+
   /* The BFD flags applied to sections created for dynamic linking.  */
   flagword dynamic_sec_flags;
 
Index: bfd/elfxx-target.h
===================================================================
--- bfd/elfxx-target.h	(revision 4759)
+++ bfd/elfxx-target.h	(working copy)
@@ -320,6 +320,10 @@
 # error ELF_MINPAGESIZE > ELF_COMMONPAGESIZE
 #endif
 
+#ifndef ELF_TEXT_START_ADDR
+#define ELF_TEXT_START_ADDR ((bfd_vma) -1)
+#endif
+
 #ifndef ELF_DYNAMIC_SEC_FLAGS
 /* Note that we set the SEC_IN_MEMORY flag for these sections.  */
 #define ELF_DYNAMIC_SEC_FLAGS			\
@@ -631,6 +635,7 @@ static struct elf_backend_data elfNN_bed
   ELF_MAXPAGESIZE,		/* maxpagesize */
   ELF_MINPAGESIZE,		/* minpagesize */
   ELF_COMMONPAGESIZE,		/* commonpagesize */
+  ELF_TEXT_START_ADDR,		/* text_start_addr */
   ELF_DYNAMIC_SEC_FLAGS,	/* dynamic_sec_flags */
   elf_info_to_howto,
   elf_info_to_howto_rel,
Index: bfd/elf64-x86-64.c
===================================================================
--- bfd/elf64-x86-64.c	(revision 4942)
+++ bfd/elf64-x86-64.c	(working copy)
@@ -3850,6 +3850,7 @@ static const struct bfd_elf_special_sect
 #define ELF_MAXPAGESIZE			    0x200000
 #define ELF_MINPAGESIZE			    0x1000
 #define ELF_COMMONPAGESIZE		    0x1000
+#define ELF_TEXT_START_ADDR		    0x400000
 
 #define elf_backend_can_gc_sections	    1
 #define elf_backend_can_refcount	    1
Index: bfd/bfd.c
===================================================================
--- bfd/bfd.c	(revision 4759)
+++ bfd/bfd.c	(working copy)
@@ -1685,37 +1685,59 @@ bfd_preserve_finish (bfd *abfd ATTRIBUTE
 }
 
 /*
+  Supported linker emulation constants.
+
+.enum bfd_emul_constant
+.  {
+.    maxpagesize,	{* maximum page size *}
+.    commonpagesize,	{* common page size *}
+.    text_start_addr	{* the first byte of the text segment *}
+.  };
+.
+*/
+ 
+/*
 FUNCTION
-	bfd_emul_get_maxpagesize
+	bfd_emul_get_constant
 
 SYNOPSIS
- 	bfd_vma bfd_emul_get_maxpagesize (const char *);
+ 	bfd_vma bfd_emul_get_constant
+	  (const char *emul, enum bfd_emul_constant constant);
 
 DESCRIPTION
-	Returns the maximum page size, in bytes, as determined by
-	emulation.
+	Returns the value of constant, CONSTANT, as determined by
+	emulation, EMUL.  If EMUL isn't ELF, abort.
 
-RETURNS
-	Returns the maximum page size in bytes for ELF, abort
-	otherwise.
 */
 
 bfd_vma
-bfd_emul_get_maxpagesize (const char *emul)
+bfd_emul_get_constant (const char *emul, enum bfd_emul_constant constant)
 {
   const bfd_target *target;
 
   target = bfd_find_target (emul, NULL);
   if (target != NULL
       && target->flavour == bfd_target_elf_flavour)
-    return xvec_get_elf_backend_data (target)->maxpagesize;
+    {
+      switch (constant)
+	{
+	case maxpagesize:
+	  return xvec_get_elf_backend_data (target)->maxpagesize;
+	case commonpagesize:
+	  return xvec_get_elf_backend_data (target)->commonpagesize;
+	case text_start_addr:
+	  if (xvec_get_elf_backend_data (target)->text_start_addr
+	      != (bfd_vma) -1)
+	    return xvec_get_elf_backend_data (target)->text_start_addr;
+	}
+    }
 
   abort ();
   return 0;
 }
 
 static void
-bfd_elf_set_pagesize (const bfd_target *target, bfd_vma size,
+bfd_elf_set_constant (const bfd_target *target, bfd_vma value,
 		      int offset, const bfd_target *orig_target)
 {
   if (target->flavour == bfd_target_elf_flavour)
@@ -1723,92 +1745,65 @@ bfd_elf_set_pagesize (const bfd_target *
       const struct elf_backend_data *bed;
 
       bed = xvec_get_elf_backend_data (target);
-      *((bfd_vma *) ((char *) bed + offset)) = size;
+      *((bfd_vma *) ((char *) bed + offset)) = value;
     }
 
   if (target->alternative_target
       && target->alternative_target != orig_target)
-    bfd_elf_set_pagesize (target->alternative_target, size, offset,
+    bfd_elf_set_constant (target->alternative_target, value, offset,
 			  orig_target);
 }
 
 /*
 FUNCTION
-	bfd_emul_set_maxpagesize
-
-SYNOPSIS
- 	void bfd_emul_set_maxpagesize (const char *, bfd_vma);
-
-DESCRIPTION
-	For ELF, set the maximum page size for the emulation.  It is
-	a no-op for other formats.
-
-*/
-
-void
-bfd_emul_set_maxpagesize (const char *emul, bfd_vma size)
-{
-  const bfd_target *target;
-
-  target = bfd_find_target (emul, NULL);
-  if (target)
-    bfd_elf_set_pagesize (target, size,
-			  offsetof (struct elf_backend_data,
-				    maxpagesize), target);
-}
-
-/*
-FUNCTION
-	bfd_emul_get_commonpagesize
+	bfd_emul_set_constant
 
 SYNOPSIS
- 	bfd_vma bfd_emul_get_commonpagesize (const char *);
+ 	void bfd_emul_set_constant
+	  (const char *emul, enum bfd_emul_constant constant,
+	   bfd_vma value);
 
 DESCRIPTION
-	Returns the common page size, in bytes, as determined by
-	emulation.
-
-RETURNS
-	Returns the common page size in bytes for ELF, abort otherwise.
-*/
-
-bfd_vma
-bfd_emul_get_commonpagesize (const char *emul)
-{
-  const bfd_target *target;
-
-  target = bfd_find_target (emul, NULL);
-  if (target != NULL
-      && target->flavour == bfd_target_elf_flavour)
-    return xvec_get_elf_backend_data (target)->commonpagesize;
-
-  abort ();
-  return 0;
-}
-
-/*
-FUNCTION
-	bfd_emul_set_commonpagesize
-
-SYNOPSIS
- 	void bfd_emul_set_commonpagesize (const char *, bfd_vma);
+	Returns the value of constant, CONSTANT, as determined by
+	emulation, EMUL.  If EMUL isn't ELF, abort.
 
 DESCRIPTION
-	For ELF, set the common page size for the emulation.  It is
-	a no-op for other formats.
+	For ELF, set the value of constant, CONSTANT, for emulation,
+	EMUL.  It is a no-op if EMUL isn't ELF.
 
 */
 
 void
-bfd_emul_set_commonpagesize (const char *emul, bfd_vma size)
+bfd_emul_set_constant (const char *emul, enum bfd_emul_constant constant,
+		       bfd_vma value)
 {
   const bfd_target *target;
 
   target = bfd_find_target (emul, NULL);
   if (target)
-    bfd_elf_set_pagesize (target, size,
-			  offsetof (struct elf_backend_data,
-				    commonpagesize), target);
+    {
+      int offset;
+
+      switch (constant)
+	{
+	case maxpagesize:
+	  offset = offsetof (struct elf_backend_data,
+			     maxpagesize);
+	  break;
+	case commonpagesize:
+	  offset = offsetof (struct elf_backend_data,
+			     commonpagesize);
+	  break;
+	case text_start_addr:
+	  offset = offsetof (struct elf_backend_data,
+			     text_start_addr);
+	  break;
+	default:
+	  abort ();
+	  break;
+	}
+      bfd_elf_set_constant (target, value, offset, target);
+    }
 }
 
 /*
Index: bfd/elf32-i386.c
===================================================================
--- bfd/elf32-i386.c	(revision 4942)
+++ bfd/elf32-i386.c	(working copy)
@@ -4047,6 +4047,7 @@ elf_i386_hash_symbol (struct elf_link_ha
 #define ELF_ARCH			bfd_arch_i386
 #define ELF_MACHINE_CODE		EM_386
 #define ELF_MAXPAGESIZE			0x1000
+#define ELF_TEXT_START_ADDR		0x08048000
 
 #define elf_backend_can_gc_sections	1
 #define elf_backend_can_refcount	1


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