This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
PATCH: Getting MAXPAGESIZE from ELF_MAXPAGESIZE
On Sat, May 21, 2005 at 10:43:09PM -0700, H. J. Lu wrote:
> On Sat, May 21, 2005 at 09:50:02PM -0400, Ian Lance Taylor wrote:
> > "H. J. Lu" <hjl@lucon.org> writes:
> >
> > > I found a need to change ELF_MAXPAGESIZE at the command line. I can
> > > add a new option like -z page-size=128M. The problem is I have to
> > > update the linker script also. I'd like to modify the linker to
> > > get MAXPAGESIZE from ELF_MAXPAGESIZE in bfd. MAXPAGESIZE will be
> > > treated as a special read only symbol like '.'. At least, we don't
> > > need to set MAXPAGESIZE in linker.
> >
> > I think it might be nicer if we didn't introduce yet another magic
> > symbol name in the linker script language. How about making it a
> > function: MAXPAGESIZE()?
> >
> > What should it return for a non-ELF target?
>
> Since that will be ELF specific, how about adding ELF_CONSTANT (xxx)
> where xxx can be MAXPAGESIZE, ....?
>
>
Here is the patch. If this patch is approved, I will submit a patch
to support "-z max-page-size=xxxx" and "-z commone-page-size=xxx".
H.J.
----
bfd/
2005-05-22 H.J. Lu <hongjiu.lu@intel.com>
* bfd.c (bfd_get_maxpagesize): New.
(bfd_get_commonpagesize): New.
* bfd-in2.h: Regenerated.
* elf-bfd.h (elf_backend_data): Add commonpagesize.
(xvec_get_elf_backend_data): New.
(get_elf_backend_data): Use it.
* elf.c (map_sections_to_segments): Accept a pointer to
struct bfd_link_info. Call bfd_get_maxpagesize to get the
maximum page size.
(elf_sort_sections): Likewise.
(assign_file_positions_for_segments): Likewise.
(assign_file_positions_except_relocs): Likewise.
* elf64-x86-64.c (ELF_COMMONPAGESIZE): New.
* elfxx-ia64.c (ELF_COMMONPAGESIZE): New.
* elfxx-target.h (ELF_COMMONPAGESIZE): New.
(elfNN_bed): Initialize commonpagesize with ELF_COMMONPAGESIZE.
ld/
2005-05-22 H.J. Lu <hongjiu.lu@intel.com>
* emulparams/elf64_ia64.sh (MAXPAGESIZE): Set to
"CONSTANT (MAXPAGESIZE)"
(COMMONPAGESIZE): Set to "CONSTANT (COMMONPAGESIZE)".
* emulparams/elf_i386.sh: Likewise.
* emulparams/elf_x86_64.sh: Likewise.
* ldemul.c (ldemul_target_name): New.
* ldemul.h (ldemul_target_name): Likewise.
* ldexp.c: Include "ldfile.h" and "ldemul.h".
(exp_print_token): Add "CONSTANT".
(fold_name): Handle CONSTANT.
* ldgram.y: Add CONSTANT.
* ldlex.l: Likewise.
--- binutils/bfd/bfd.c.page 2005-05-21 23:03:20.000000000 -0700
+++ binutils/bfd/bfd.c 2005-05-22 09:59:15.000000000 -0700
@@ -1500,3 +1500,134 @@ bfd_preserve_finish (bfd *abfd ATTRIBUTE
objalloc. */
bfd_hash_table_free (&preserve->section_htab);
}
+
+/*
+FUNCTION
+ bfd_get_maxpagesize
+
+SYNOPSIS
+ bfd_vma bfd_get_maxpagesize
+ (struct bfd_link_info *, bfd *, const char *);
+
+DESCRIPTION
+ Returns the object file maximum page size, in bits, as
+ determined by the object file's link info, emulation, format.
+ For ELF, this information is included in the header.
+
+RETURNS
+ Returns the maximum page size in bytes if known, <<0>>
+ otherwise.
+*/
+
+bfd_vma
+bfd_get_maxpagesize (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ bfd *abfd, const char *emul)
+{
+ static bfd_vma size;
+ const struct elf_backend_data *bed;
+
+ if (size)
+ return size;
+
+ bed = NULL;
+ if (emul == NULL
+ || strcmp (abfd->xvec->name, emul) == 0)
+ {
+ if (abfd->xvec->flavour == bfd_target_elf_flavour)
+ bed = get_elf_backend_data (abfd);
+ }
+ else if (emul != NULL)
+ {
+ const bfd_target * const *target;
+
+ /* Find the maximum page size for this emulation. */
+ for (target = bfd_target_vector; *target != NULL; target++)
+ if (strcmp ((*target)->name, emul) == 0)
+ {
+ if ((*target)->flavour == bfd_target_elf_flavour)
+ bed = xvec_get_elf_backend_data (*target);
+ break;
+ }
+ }
+
+ if (bed != NULL)
+ size = bed->maxpagesize;
+ else
+ {
+ if (emul != NULL)
+ (*_bfd_error_handler) (_("bfd_get_maxpagesize: Unsupported output emulation `%s` for format `%s'"),
+ emul, abfd->xvec->name);
+ else
+ (*_bfd_error_handler) (_("bfd_get_maxpagesize: Unsupported output format `%s'"),
+ abfd->xvec->name);
+
+ abort ();
+ }
+
+ return size;
+}
+
+/*
+FUNCTION
+ bfd_get_commonpagesize
+
+SYNOPSIS
+ bfd_vma bfd_get_commonpagesize
+ (struct bfd_link_info *, bfd *, const char *);
+
+DESCRIPTION
+ Returns the object file common page size, in bits, as
+ determined by the object file's link info, emulation, format.
+ For ELF, this information is included in the header.
+
+RETURNS
+ Returns the common page size in bytes if known, <<0>> otherwise.
+*/
+
+bfd_vma
+bfd_get_commonpagesize (struct bfd_link_info *info ATTRIBUTE_UNUSED,
+ bfd *abfd, const char *emul)
+{
+ static bfd_vma size;
+ const struct elf_backend_data *bed;
+
+ if (size)
+ return size;
+
+ bed = NULL;
+ if (emul == NULL
+ || strcmp (abfd->xvec->name, emul) == 0)
+ {
+ if (abfd->xvec->flavour == bfd_target_elf_flavour)
+ bed = get_elf_backend_data (abfd);
+ }
+ else if (emul != NULL)
+ {
+ const bfd_target * const *target;
+
+ /* Find the common page size for this emulation. */
+ for (target = bfd_target_vector; *target != NULL; target++)
+ if (strcmp ((*target)->name, emul) == 0)
+ {
+ if ((*target)->flavour == bfd_target_elf_flavour)
+ bed = xvec_get_elf_backend_data (*target);
+ break;
+ }
+ }
+
+ if (bed != NULL)
+ size = bed->commonpagesize;
+ else
+ {
+ if (emul != NULL)
+ (*_bfd_error_handler) (_("bfd_get_commonpagesize: Unsupported output emulation `%s` for format `%s'"),
+ emul, abfd->xvec->name);
+ else
+ (*_bfd_error_handler) (_("bfd_get_commonpagesize: Unsupported output format `%s'"),
+ abfd->xvec->name);
+
+ abort ();
+ }
+
+ return size;
+}
--- binutils/bfd/elf-bfd.h.page 2005-05-21 14:52:20.000000000 -0700
+++ binutils/bfd/elf-bfd.h 2005-05-22 07:34:52.000000000 -0700
@@ -564,6 +564,9 @@ struct elf_backend_data
pages at least this large. May be smaller than maxpagesize. */
bfd_vma minpagesize;
+ /* The common page size for this backend. */
+ bfd_vma commonpagesize;
+
/* The BFD flags applied to sections created for dynamic linking. */
flagword dynamic_sec_flags;
@@ -1133,8 +1136,11 @@ struct bfd_elf_section_data
&& (sec)->sec_info_type != ELF_INFO_TYPE_MERGE \
&& (sec)->sec_info_type != ELF_INFO_TYPE_JUST_SYMS)
+#define xvec_get_elf_backend_data(xvec) \
+ ((const struct elf_backend_data *) (xvec)->backend_data)
+
#define get_elf_backend_data(abfd) \
- ((const struct elf_backend_data *) (abfd)->xvec->backend_data)
+ xvec_get_elf_backend_data ((abfd)->xvec)
/* This struct is used to pass information to routines called via
elf_link_hash_traverse which must return failure. */
--- binutils/bfd/elf.c.page 2005-05-19 06:51:54.000000000 -0700
+++ binutils/bfd/elf.c 2005-05-22 07:55:21.000000000 -0700
@@ -3568,7 +3568,7 @@ _bfd_elf_make_dynamic_segment (bfd *abfd
/* Set up a mapping from BFD sections to program segments. */
static bfd_boolean
-map_sections_to_segments (bfd *abfd)
+map_sections_to_segments (bfd *abfd, struct bfd_link_info *link_info)
{
asection **sections = NULL;
asection *s;
@@ -3660,7 +3660,7 @@ map_sections_to_segments (bfd *abfd)
last_hdr = NULL;
last_size = 0;
phdr_index = 0;
- maxpagesize = get_elf_backend_data (abfd)->maxpagesize;
+ maxpagesize = bfd_get_maxpagesize (link_info, abfd, NULL);
writable = FALSE;
dynsec = bfd_get_section_by_name (abfd, ".dynamic");
if (dynsec != NULL
@@ -3999,10 +3999,11 @@ elf_sort_sections (const void *arg1, con
the page size.'' */
/* In other words, something like:
- vma_offset = m->sections[0]->vma % bed->maxpagesize;
- off_offset = off % bed->maxpagesize;
+ maxpagesize = bfd_get_maxpagesize (info, abfd, NULL);
+ vma_offset = m->sections[0]->vma % maxpagesize;
+ off_offset = off % maxpagesize;
if (vma_offset < off_offset)
- adjustment = vma_offset + bed->maxpagesize - off_offset;
+ adjustment = vma_offset + maxpagesize - off_offset;
else
adjustment = vma_offset - off_offset;
@@ -4031,10 +4032,11 @@ assign_file_positions_for_segments (bfd
bfd_vma phdrs_vaddr, phdrs_paddr;
Elf_Internal_Phdr *p;
bfd_size_type amt;
+ bfd_vma maxpagesize;
if (elf_tdata (abfd)->segment_map == NULL)
{
- if (! map_sections_to_segments (abfd))
+ if (! map_sections_to_segments (abfd, link_info))
return FALSE;
}
else
@@ -4113,6 +4115,8 @@ assign_file_positions_for_segments (bfd
off = bed->s->sizeof_ehdr;
off += alloc * bed->s->sizeof_phdr;
+ maxpagesize = bfd_get_maxpagesize (link_info, abfd, NULL);
+
filehdr_vaddr = 0;
filehdr_paddr = 0;
phdrs_vaddr = 0;
@@ -4164,8 +4168,8 @@ assign_file_positions_for_segments (bfd
}
align = (bfd_size_type) 1 << align_power;
- if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > align)
- align = bed->maxpagesize;
+ if ((abfd->flags & D_PAGED) != 0 && maxpagesize > align)
+ align = maxpagesize;
adjust = vma_page_aligned_bias (m->sections[0]->vma, off, align);
off += adjust;
@@ -4220,7 +4224,7 @@ assign_file_positions_for_segments (bfd
if (p->p_type == PT_LOAD
&& (abfd->flags & D_PAGED) != 0)
- p->p_align = bed->maxpagesize;
+ p->p_align = maxpagesize;
else if (m->count == 0)
p->p_align = 1 << bed->s->log_file_align;
else
@@ -4292,7 +4296,7 @@ assign_file_positions_for_segments (bfd
phdrs_paddr = p->p_paddr;
}
else
- phdrs_vaddr = bed->maxpagesize + bed->s->sizeof_ehdr;
+ phdrs_vaddr = maxpagesize + bed->s->sizeof_ehdr;
}
p->p_filesz += alloc * bed->s->sizeof_phdr;
@@ -4351,8 +4355,9 @@ assign_file_positions_for_segments (bfd
/* The section VMA must equal the file position
modulo the page size. */
bfd_size_type page = align;
- if ((abfd->flags & D_PAGED) != 0 && bed->maxpagesize > page)
- page = bed->maxpagesize;
+ if ((abfd->flags & D_PAGED) != 0
+ && maxpagesize > page)
+ page = maxpagesize;
adjust = vma_page_aligned_bias (sec->vma,
p->p_vaddr + p->p_memsz,
page);
@@ -4716,6 +4721,7 @@ assign_file_positions_except_relocs (bfd
{
unsigned int i;
Elf_Internal_Shdr **hdrpp;
+ bfd_vma maxpagesize;
/* Assign file positions for the loaded sections based on the
assignment of sections to segments. */
@@ -4723,6 +4729,7 @@ assign_file_positions_except_relocs (bfd
return FALSE;
/* Assign file positions for the other sections. */
+ maxpagesize = bfd_get_maxpagesize (link_info, abfd, NULL);
off = elf_tdata (abfd)->next_file_pos;
for (i = 1, hdrpp = i_shdrpp + 1; i < num_sec; i++, hdrpp++)
@@ -4743,7 +4750,7 @@ assign_file_positions_except_relocs (bfd
: hdr->bfd_section->name)));
if ((abfd->flags & D_PAGED) != 0)
off += vma_page_aligned_bias (hdr->sh_addr, off,
- bed->maxpagesize);
+ maxpagesize);
else
off += vma_page_aligned_bias (hdr->sh_addr, off,
hdr->sh_addralign);
--- binutils/bfd/elf64-x86-64.c.page 2005-05-17 09:56:52.000000000 -0700
+++ binutils/bfd/elf64-x86-64.c 2005-05-22 08:26:31.000000000 -0700
@@ -2844,6 +2844,7 @@ elf64_x86_64_section_from_shdr (bfd *abf
#define ELF_ARCH bfd_arch_i386
#define ELF_MACHINE_CODE EM_X86_64
#define ELF_MAXPAGESIZE 0x100000
+#define ELF_COMMONPAGESIZE 0x1000
#define elf_backend_can_gc_sections 1
#define elf_backend_can_refcount 1
--- binutils/bfd/elfxx-ia64.c.page 2005-05-22 09:12:47.000000000 -0700
+++ binutils/bfd/elfxx-ia64.c 2005-05-22 08:28:17.000000000 -0700
@@ -5241,6 +5241,7 @@ elfNN_hpux_backend_symbol_processing (bf
#define ELF_MACHINE_ALT1 1999 /* EAS2.3 */
#define ELF_MACHINE_ALT2 1998 /* EAS2.2 */
#define ELF_MAXPAGESIZE 0x10000 /* 64KB */
+#define ELF_COMMONPAGESIZE 0x4000 /* 16KB */
#define elf_backend_section_from_shdr \
elfNN_ia64_section_from_shdr
@@ -5346,7 +5347,8 @@ elfNN_hpux_backend_symbol_processing (bf
#define elf_backend_want_p_paddr_set_to_zero 1
#undef ELF_MAXPAGESIZE
-#define ELF_MAXPAGESIZE 0x1000 /* 1K */
+#define ELF_MAXPAGESIZE 0x1000 /* 4K */
+#undef ELF_COMMONPAGESIZE
#undef elfNN_bed
#define elfNN_bed elfNN_ia64_hpux_bed
--- binutils/bfd/elfxx-target.h.page 2005-05-07 06:42:05.000000000 -0700
+++ binutils/bfd/elfxx-target.h 2005-05-21 23:05:57.000000000 -0700
@@ -284,6 +284,10 @@
#define ELF_MINPAGESIZE ELF_MAXPAGESIZE
#endif
+#ifndef ELF_COMMONPAGESIZE
+#define ELF_COMMONPAGESIZE ELF_MAXPAGESIZE
+#endif
+
#ifndef ELF_DYNAMIC_SEC_FLAGS
/* Note that we set the SEC_IN_MEMORY flag for these sections. */
#define ELF_DYNAMIC_SEC_FLAGS \
@@ -524,6 +528,7 @@ static const struct elf_backend_data elf
ELF_MACHINE_CODE, /* elf_machine_code */
ELF_MAXPAGESIZE, /* maxpagesize */
ELF_MINPAGESIZE, /* minpagesize */
+ ELF_COMMONPAGESIZE, /* commonpagesize */
ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */
elf_info_to_howto,
elf_info_to_howto_rel,
--- binutils/ld/emulparams/elf64_ia64.sh.page 2004-10-21 09:13:02.000000000 -0700
+++ binutils/ld/emulparams/elf64_ia64.sh 2005-05-22 09:41:25.000000000 -0700
@@ -6,12 +6,12 @@ EXTRA_EM_FILE=ia64elf
OUTPUT_FORMAT="elf64-ia64-little"
ARCH=ia64
MACHINE=
-MAXPAGESIZE=0x10000
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
# FIXME: It interferes with linker relaxation. Disable it until it is
# fixed.
if test "0" = "1" -a -n "$CREATE_SHLIB"; then
# Optimize shared libraries for 16K page size
- COMMONPAGESIZE=0x4000
+ COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
fi
TEXT_START_ADDR="0x4000000000000000"
DATA_ADDR="0x6000000000000000 + (. & (${MAXPAGESIZE} - 1))"
--- binutils/ld/emulparams/elf_i386.sh.page 2004-05-13 19:14:20.000000000 -0700
+++ binutils/ld/emulparams/elf_i386.sh 2005-05-22 09:40:26.000000000 -0700
@@ -1,8 +1,8 @@
SCRIPT_NAME=elf
OUTPUT_FORMAT="elf32-i386"
TEXT_START_ADDR=0x08048000
-MAXPAGESIZE=0x1000
-COMMONPAGESIZE=0x1000
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
NONPAGED_TEXT_START_ADDR=0x08048000
ARCH=i386
MACHINE=
--- binutils/ld/emulparams/elf_x86_64.sh.page 2004-05-13 19:14:20.000000000 -0700
+++ binutils/ld/emulparams/elf_x86_64.sh 2005-05-22 09:40:34.000000000 -0700
@@ -2,8 +2,8 @@ SCRIPT_NAME=elf
ELFSIZE=64
OUTPUT_FORMAT="elf64-x86-64"
TEXT_START_ADDR=0x400000
-MAXPAGESIZE=0x100000
-COMMONPAGESIZE=0x1000
+MAXPAGESIZE="CONSTANT (MAXPAGESIZE)"
+COMMONPAGESIZE="CONSTANT (COMMONPAGESIZE)"
NONPAGED_TEXT_START_ADDR=0x400000
ARCH="i386:x86-64"
MACHINE=
--- binutils/ld/ldemul.c.page 2005-05-12 06:34:15.000000000 -0700
+++ binutils/ld/ldemul.c 2005-05-22 00:08:41.000000000 -0700
@@ -194,6 +194,12 @@ ldemul_default_target (int argc ATTRIBUT
return ld_emulation->target_name;
}
+char *
+ldemul_target_name (void)
+{
+ return ld_emulation->target_name;
+}
+
void
after_parse_default (void)
{
--- binutils/ld/ldemul.h.page 2005-03-14 08:08:53.000000000 -0800
+++ binutils/ld/ldemul.h 2005-05-22 00:09:12.000000000 -0700
@@ -87,6 +87,8 @@ extern int ldemul_find_potential_librar
(char *, struct lang_input_statement_struct *);
extern struct bfd_elf_version_expr *ldemul_new_vers_pattern
(struct bfd_elf_version_expr *);
+extern char *ldemul_target_name
+ (void);
typedef struct ld_emulation_xfer_struct {
/* Run before parsing the command line and script file.
--- binutils/ld/ldexp.c.page 2005-05-17 09:57:49.000000000 -0700
+++ binutils/ld/ldexp.c 2005-05-22 07:42:40.000000000 -0700
@@ -38,6 +38,8 @@
#include "ldexp.h"
#include <ldgram.h>
#include "ldlang.h"
+#include "ldfile.h"
+#include "ldemul.h"
#include "libiberty.h"
#include "safe-ctype.h"
@@ -107,6 +109,7 @@ exp_print_token (token_code_type code, i
{ SIZEOF, "SIZEOF" },
{ ADDR, "ADDR" },
{ LOADADDR, "LOADADDR" },
+ { CONSTANT, "CONSTANT" },
{ MAX_K, "MAX_K" },
{ REL, "relocatable" },
{ DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
@@ -704,6 +707,23 @@ fold_name (etree_type *tree,
}
break;
+ case CONSTANT:
+ if (allocation_done != lang_first_phase_enum)
+ {
+ if (strcmp (tree->name.name, "MAXPAGESIZE") == 0)
+ result = new_abs (bfd_get_maxpagesize (&link_info,
+ output_bfd,
+ ldemul_target_name ()));
+ else if (strcmp (tree->name.name, "COMMONPAGESIZE") == 0)
+ result = new_abs (bfd_get_commonpagesize (&link_info,
+ output_bfd,
+ ldemul_target_name ()));
+ else
+ einfo (_("%F%S: unknown constant `%s' referenced in expression\n"),
+ tree->name.name);
+ }
+ break;
+
default:
FAIL ();
break;
--- binutils/ld/ldgram.y.page 2005-05-12 06:34:16.000000000 -0700
+++ binutils/ld/ldgram.y 2005-05-21 23:01:43.000000000 -0700
@@ -153,6 +153,7 @@ static int error_index;
%token GLOBAL LOCAL VERSIONK INPUT_VERSION_SCRIPT
%token KEEP ONLY_IF_RO ONLY_IF_RW SPECIAL
%token EXCLUDE_FILE
+%token CONSTANT
%type <versyms> vers_defns
%type <versnode> vers_tag
%type <deflist> verdep
@@ -843,6 +844,8 @@ exp :
{ $$ = exp_nameop (ADDR,$3); }
| LOADADDR '(' NAME ')'
{ $$ = exp_nameop (LOADADDR,$3); }
+ | CONSTANT '(' NAME ')'
+ { $$ = exp_nameop (CONSTANT,$3); }
| ABSOLUTE '(' exp ')'
{ $$ = exp_unop (ABSOLUTE, $3); }
| ALIGN_K '(' exp ')'
--- binutils/ld/ldlex.l.page 2005-05-12 06:34:17.000000000 -0700
+++ binutils/ld/ldlex.l 2005-05-21 23:01:55.000000000 -0700
@@ -315,6 +315,7 @@ V_IDENTIFIER [*?.$_a-zA-Z\[\]\-\!\^\\]([
<EXPRESSION,BOTH,SCRIPT>"PROVIDE" { RTOKEN(PROVIDE); }
<EXPRESSION,BOTH,SCRIPT>"KEEP" { RTOKEN(KEEP); }
<EXPRESSION,BOTH,SCRIPT>"EXCLUDE_FILE" { RTOKEN(EXCLUDE_FILE); }
+<EXPRESSION,BOTH,SCRIPT>"CONSTANT" { RTOKEN(CONSTANT);}
<MRI>"#".*\n? { ++ lineno; }
<MRI>"\n" { ++ lineno; RTOKEN(NEWLINE); }
<MRI>"*".* { /* Mri comment line */ }