This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
RFC: Add -z text-start-addr=ADDR to ELF linker
- From: "H.J. Lu" <hongjiu dot lu at intel dot com>
- To: binutils at sources dot redhat dot com
- Date: Mon, 12 Jan 2009 11:29:46 -0800
- Subject: RFC: Add -z text-start-addr=ADDR to ELF linker
- Reply-to: "H.J. Lu" <hjl dot tools at gmail dot com>
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