mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
* ldlex.l (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): New tokens.
* ldgram.y (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): New tokens. (exp): Add DATA_SEGMENT_ALIGN (exp, exp) and DATA_SEGMENT_END (exp). * ldexp.c (exp_data_seg): New variable. (exp_print_token): Handle DATA_SEGMENT_ALIGN and DATA_SEGMENT_END. (fold_binary): Handle DATA_SEGMENT_ALIGN. (exp_fold_tree): Handle DATA_SEGMENT_END. Pass allocation_done when recursing instead of hardcoding lang_allocating_phase_enum. * ldexp.h (exp_data_seg): New. * ldlang.c (lang_size_sections_1): Renamed from lang_size_sections. (lang_size_sections): New. * ld.texinfo (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): Document. * scripttempl/elf.sc: Use DATA_SEGMENT_ALIGN and DATA_SEGMENT_END if COMMONPAGESIZE is defined. * emulparams/elf_i386.sh (COMMONPAGESIZE): Set to 4K. * emulparams/elf32_sparc.sh (COMMONPAGESIZE): Set to 8K. * emulparams/elf64_sparc.sh (COMMONPAGESIZE): Set to 8K. * emulparams/elf64alpha.sh (COMMONPAGESIZE): Set to 8K. * emulparams/elf64_ia64.sh (COMMONPAGESIZE): Set to 16K for shared libraries only.
This commit is contained in:
parent
d2c1cacb1e
commit
2d20f7bf67
24
ld/ChangeLog
24
ld/ChangeLog
@ -1,3 +1,27 @@
|
||||
2002-02-12 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* ldlex.l (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): New tokens.
|
||||
* ldgram.y (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): New tokens.
|
||||
(exp): Add DATA_SEGMENT_ALIGN (exp, exp) and DATA_SEGMENT_END (exp).
|
||||
* ldexp.c (exp_data_seg): New variable.
|
||||
(exp_print_token): Handle DATA_SEGMENT_ALIGN and DATA_SEGMENT_END.
|
||||
(fold_binary): Handle DATA_SEGMENT_ALIGN.
|
||||
(exp_fold_tree): Handle DATA_SEGMENT_END.
|
||||
Pass allocation_done when recursing instead of hardcoding
|
||||
lang_allocating_phase_enum.
|
||||
* ldexp.h (exp_data_seg): New.
|
||||
* ldlang.c (lang_size_sections_1): Renamed from lang_size_sections.
|
||||
(lang_size_sections): New.
|
||||
* ld.texinfo (DATA_SEGMENT_ALIGN, DATA_SEGMENT_END): Document.
|
||||
* scripttempl/elf.sc: Use DATA_SEGMENT_ALIGN and DATA_SEGMENT_END
|
||||
if COMMONPAGESIZE is defined.
|
||||
* emulparams/elf_i386.sh (COMMONPAGESIZE): Set to 4K.
|
||||
* emulparams/elf32_sparc.sh (COMMONPAGESIZE): Set to 8K.
|
||||
* emulparams/elf64_sparc.sh (COMMONPAGESIZE): Set to 8K.
|
||||
* emulparams/elf64alpha.sh (COMMONPAGESIZE): Set to 8K.
|
||||
* emulparams/elf64_ia64.sh (COMMONPAGESIZE): Set to 16K for shared
|
||||
libraries only.
|
||||
|
||||
2002-02-11 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* Makefile.in: Regenerate.
|
||||
|
@ -2,6 +2,7 @@ SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-sparc"
|
||||
TEXT_START_ADDR=0x10000
|
||||
MAXPAGESIZE=0x10000
|
||||
COMMONPAGESIZE=0x2000
|
||||
NONPAGED_TEXT_START_ADDR=0x10000
|
||||
ALIGNMENT=8
|
||||
ARCH=sparc
|
||||
|
@ -7,6 +7,10 @@ OUTPUT_FORMAT="elf64-ia64-little"
|
||||
ARCH=ia64
|
||||
MACHINE=
|
||||
MAXPAGESIZE=0x10000
|
||||
if test -n "$CREATE_SHLIB"; then
|
||||
# Optimize shared libraries for 16K page size
|
||||
COMMONPAGESIZE=0x4000
|
||||
fi
|
||||
TEXT_START_ADDR="0x4000000000000000"
|
||||
DATA_ADDR="0x6000000000000000 + (. & (${MAXPAGESIZE} - 1))"
|
||||
GENERATE_SHLIB_SCRIPT=yes
|
||||
|
@ -3,6 +3,7 @@ ELFSIZE=64
|
||||
TEMPLATE_NAME=elf32
|
||||
OUTPUT_FORMAT="elf64-sparc"
|
||||
MAXPAGESIZE=0x100000
|
||||
COMMONPAGESIZE=0x2000
|
||||
ARCH="sparc:v9"
|
||||
MACHINE=
|
||||
DATA_PLT=
|
||||
|
@ -5,6 +5,7 @@ TEMPLATE_NAME=elf32
|
||||
OUTPUT_FORMAT="elf64-alpha"
|
||||
TEXT_START_ADDR="0x120000000"
|
||||
MAXPAGESIZE=0x10000
|
||||
COMMONPAGESIZE=0x2000
|
||||
NONPAGED_TEXT_START_ADDR="0x120000000"
|
||||
ARCH=alpha
|
||||
MACHINE=
|
||||
|
@ -2,6 +2,7 @@ SCRIPT_NAME=elf
|
||||
OUTPUT_FORMAT="elf32-i386"
|
||||
TEXT_START_ADDR=0x08048000
|
||||
MAXPAGESIZE=0x1000
|
||||
COMMONPAGESIZE=0x1000
|
||||
NONPAGED_TEXT_START_ADDR=0x08048000
|
||||
ARCH=i386
|
||||
MACHINE=
|
||||
|
@ -4159,6 +4159,45 @@ This is a synonym for @code{ALIGN}, for compatibility with older linker
|
||||
scripts. It is most often seen when setting the address of an output
|
||||
section.
|
||||
|
||||
@item DATA_SEGMENT_ALIGN(@var{maxpagesize}, @var{commonpagesize})
|
||||
@kindex DATA_SEGMENT_ALIGN(@var{maxpagesize}, @var{commonpagesize})
|
||||
This is equivalent to either
|
||||
@smallexample
|
||||
(ALIGN(@var{maxpagesize}) + (. & (@var{maxpagesize} - 1)))
|
||||
@end smallexample
|
||||
or
|
||||
@smallexample
|
||||
(ALIGN(@var{maxpagesize}) + (. & (@var{maxpagesize} - @var{commonpagesize})))
|
||||
@end smallexample
|
||||
@noindent
|
||||
depending on whether the latter uses fewer @var{commonpagesize} sized pages
|
||||
for the data segment (area between the result of this expression and
|
||||
@code{DATA_SEGMENT_END}) than the former or not.
|
||||
If the latter form is used, it means @var{commonpagesize} bytes of runtime
|
||||
memory will be saved at the expense of up to @var{commonpagesize} wasted
|
||||
bytes in the on-disk file.
|
||||
|
||||
This expression can only be used directly in @code{SECTIONS} commands, not in
|
||||
any output section descriptions and only once in the linker script.
|
||||
@var{commonpagesize} should be less or equal to @var{maxpagesize} and should
|
||||
be the system page size the object wants to be optimized for (while still
|
||||
working on system page sizes up to @var{maxpagesize}).
|
||||
|
||||
@noindent
|
||||
Example:
|
||||
@smallexample
|
||||
. = DATA_SEGMENT_ALIGN(0x10000, 0x2000);
|
||||
@end smallexample
|
||||
|
||||
@item DATA_SEGMENT_END(@var{exp})
|
||||
@kindex DATA_SEGMENT_END(@var{exp})
|
||||
This defines the end of data segment for @code{DATA_SEGMENT_ALIGN}
|
||||
evaluation purposes.
|
||||
|
||||
@smallexample
|
||||
. = DATA_SEGMENT_END(.);
|
||||
@end smallexample
|
||||
|
||||
@item DEFINED(@var{symbol})
|
||||
@kindex DEFINED(@var{symbol})
|
||||
@cindex symbol defaults
|
||||
|
50
ld/ldexp.c
50
ld/ldexp.c
@ -64,6 +64,8 @@ static etree_value_type exp_fold_tree_no_dot
|
||||
lang_output_section_statement_type *current_section,
|
||||
lang_phase_type allocation_done));
|
||||
|
||||
struct exp_data_seg exp_data_seg;
|
||||
|
||||
static void
|
||||
exp_print_token (code)
|
||||
token_code_type code;
|
||||
@ -114,6 +116,8 @@ exp_print_token (code)
|
||||
{ LOADADDR, "LOADADDR" },
|
||||
{ MAX_K, "MAX_K" },
|
||||
{ REL, "relocateable" },
|
||||
{ DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
|
||||
{ DATA_SEGMENT_END, "DATA_SEGMENT_END" }
|
||||
};
|
||||
unsigned int idx;
|
||||
|
||||
@ -314,6 +318,33 @@ fold_binary (tree, current_section, allocation_done, dot, dotp)
|
||||
result = other;
|
||||
break;
|
||||
|
||||
case DATA_SEGMENT_ALIGN:
|
||||
if (allocation_done != lang_first_phase_enum
|
||||
&& current_section == abs_output_section
|
||||
&& (exp_data_seg.phase == exp_dataseg_none
|
||||
|| exp_data_seg.phase == exp_dataseg_adjust
|
||||
|| allocation_done != lang_allocating_phase_enum))
|
||||
{
|
||||
bfd_vma maxpage = result.value;
|
||||
|
||||
result.value = ALIGN_N (dot, maxpage);
|
||||
if (exp_data_seg.phase != exp_dataseg_adjust)
|
||||
{
|
||||
result.value += dot & (maxpage - 1);
|
||||
if (allocation_done == lang_allocating_phase_enum)
|
||||
{
|
||||
exp_data_seg.phase = exp_dataseg_align_seen;
|
||||
exp_data_seg.base = result.value;
|
||||
exp_data_seg.pagesize = other.value;
|
||||
}
|
||||
}
|
||||
else if (other.value < maxpage)
|
||||
result.value += dot & (maxpage - other.value);
|
||||
}
|
||||
else
|
||||
result.valid_p = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ();
|
||||
}
|
||||
@ -578,6 +609,23 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
|
||||
result.valid_p = false;
|
||||
break;
|
||||
|
||||
case DATA_SEGMENT_END:
|
||||
if (allocation_done != lang_first_phase_enum
|
||||
&& current_section == abs_output_section
|
||||
&& (exp_data_seg.phase == exp_dataseg_align_seen
|
||||
|| exp_data_seg.phase == exp_dataseg_adjust
|
||||
|| allocation_done != lang_allocating_phase_enum))
|
||||
{
|
||||
if (exp_data_seg.phase == exp_dataseg_align_seen)
|
||||
{
|
||||
exp_data_seg.phase = exp_dataseg_end_seen;
|
||||
exp_data_seg.end = result.value;
|
||||
}
|
||||
}
|
||||
else
|
||||
result.valid_p = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
FAIL ();
|
||||
break;
|
||||
@ -615,7 +663,7 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
|
||||
{
|
||||
result = exp_fold_tree (tree->assign.src,
|
||||
current_section,
|
||||
lang_allocating_phase_enum, dot,
|
||||
allocation_done, dot,
|
||||
dotp);
|
||||
if (! result.valid_p)
|
||||
einfo (_("%F%S invalid assignment to location counter\n"));
|
||||
|
10
ld/ldexp.h
10
ld/ldexp.h
@ -88,6 +88,16 @@ typedef union etree_union {
|
||||
} assert_s;
|
||||
} etree_type;
|
||||
|
||||
extern struct exp_data_seg {
|
||||
enum {
|
||||
exp_dataseg_none,
|
||||
exp_dataseg_align_seen,
|
||||
exp_dataseg_end_seen,
|
||||
exp_dataseg_adjust
|
||||
} phase;
|
||||
bfd_vma base, end, pagesize;
|
||||
} exp_data_seg;
|
||||
|
||||
etree_type *exp_intop PARAMS ((bfd_vma));
|
||||
etree_type *exp_relop PARAMS ((asection *, bfd_vma));
|
||||
etree_value_type invalid PARAMS ((void));
|
||||
|
@ -122,7 +122,7 @@ static int error_index;
|
||||
%token END
|
||||
%left <token> '('
|
||||
%token <token> ALIGN_K BLOCK BIND QUAD SQUAD LONG SHORT BYTE
|
||||
%token SECTIONS PHDRS SORT
|
||||
%token SECTIONS PHDRS SORT DATA_SEGMENT_ALIGN DATA_SEGMENT_END
|
||||
%token '{' '}'
|
||||
%token SIZEOF_HEADERS OUTPUT_FORMAT FORCE_COMMON_ALLOCATION OUTPUT_ARCH
|
||||
%token INHIBIT_COMMON_ALLOCATION
|
||||
@ -795,6 +795,10 @@ exp :
|
||||
{ $$ = exp_unop(ABSOLUTE, $3); }
|
||||
| ALIGN_K '(' exp ')'
|
||||
{ $$ = exp_unop(ALIGN_K,$3); }
|
||||
| DATA_SEGMENT_ALIGN '(' exp ',' exp ')'
|
||||
{ $$ = exp_binop (DATA_SEGMENT_ALIGN, $3, $5); }
|
||||
| DATA_SEGMENT_END '(' exp ')'
|
||||
{ $$ = exp_unop(DATA_SEGMENT_END, $3); }
|
||||
| BLOCK '(' exp ')'
|
||||
{ $$ = exp_unop(ALIGN_K,$3); }
|
||||
| NAME
|
||||
|
71
ld/ldlang.c
71
ld/ldlang.c
@ -150,6 +150,9 @@ static void lang_check_section_addresses PARAMS ((void));
|
||||
static void os_region_check
|
||||
PARAMS ((lang_output_section_statement_type *,
|
||||
struct memory_region_struct *, etree_type *, bfd_vma));
|
||||
static bfd_vma lang_size_sections_1
|
||||
PARAMS ((lang_statement_union_type *, lang_output_section_statement_type *,
|
||||
lang_statement_union_type **, fill_type, bfd_vma, boolean *));
|
||||
|
||||
typedef void (*callback_t) PARAMS ((lang_wild_statement_type *,
|
||||
struct wildcard_list *,
|
||||
@ -2823,8 +2826,8 @@ os_region_check (os, region, tree, base)
|
||||
|
||||
/* Set the sizes for all the output sections. */
|
||||
|
||||
bfd_vma
|
||||
lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
static bfd_vma
|
||||
lang_size_sections_1 (s, output_section_statement, prev, fill, dot, relax)
|
||||
lang_statement_union_type *s;
|
||||
lang_output_section_statement_type *output_section_statement;
|
||||
lang_statement_union_type **prev;
|
||||
@ -2949,8 +2952,8 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
os->bfd_section->output_offset = 0;
|
||||
}
|
||||
|
||||
lang_size_sections (os->children.head, os, &os->children.head,
|
||||
os->fill, dot, relax);
|
||||
lang_size_sections_1 (os->children.head, os, &os->children.head,
|
||||
os->fill, dot, relax);
|
||||
|
||||
/* Put the section within the requested block size, or
|
||||
align at the block boundary. */
|
||||
@ -3018,10 +3021,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
break;
|
||||
|
||||
case lang_constructors_statement_enum:
|
||||
dot = lang_size_sections (constructor_list.head,
|
||||
output_section_statement,
|
||||
&s->wild_statement.children.head,
|
||||
fill, dot, relax);
|
||||
dot = lang_size_sections_1 (constructor_list.head,
|
||||
output_section_statement,
|
||||
&s->wild_statement.children.head,
|
||||
fill, dot, relax);
|
||||
break;
|
||||
|
||||
case lang_data_statement_enum:
|
||||
@ -3082,10 +3085,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
|
||||
case lang_wild_statement_enum:
|
||||
|
||||
dot = lang_size_sections (s->wild_statement.children.head,
|
||||
output_section_statement,
|
||||
&s->wild_statement.children.head,
|
||||
fill, dot, relax);
|
||||
dot = lang_size_sections_1 (s->wild_statement.children.head,
|
||||
output_section_statement,
|
||||
&s->wild_statement.children.head,
|
||||
fill, dot, relax);
|
||||
|
||||
break;
|
||||
|
||||
@ -3180,10 +3183,10 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
break;
|
||||
|
||||
case lang_group_statement_enum:
|
||||
dot = lang_size_sections (s->group_statement.children.head,
|
||||
output_section_statement,
|
||||
&s->group_statement.children.head,
|
||||
fill, dot, relax);
|
||||
dot = lang_size_sections_1 (s->group_statement.children.head,
|
||||
output_section_statement,
|
||||
&s->group_statement.children.head,
|
||||
fill, dot, relax);
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -3199,6 +3202,42 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
return dot;
|
||||
}
|
||||
|
||||
bfd_vma
|
||||
lang_size_sections (s, output_section_statement, prev, fill, dot, relax)
|
||||
lang_statement_union_type *s;
|
||||
lang_output_section_statement_type *output_section_statement;
|
||||
lang_statement_union_type **prev;
|
||||
fill_type fill;
|
||||
bfd_vma dot;
|
||||
boolean *relax;
|
||||
{
|
||||
bfd_vma result;
|
||||
|
||||
exp_data_seg.phase = exp_dataseg_none;
|
||||
result = lang_size_sections_1 (s, output_section_statement, prev, fill,
|
||||
dot, relax);
|
||||
if (exp_data_seg.phase == exp_dataseg_end_seen)
|
||||
{
|
||||
/* If DATA_SEGMENT_ALIGN DATA_SEGMENT_END pair was seen, check whether
|
||||
a page could be saved in the data segment. */
|
||||
bfd_vma first, last;
|
||||
|
||||
first = -exp_data_seg.base & (exp_data_seg.pagesize - 1);
|
||||
last = exp_data_seg.end & (exp_data_seg.pagesize - 1);
|
||||
if (first && last
|
||||
&& ((exp_data_seg.base & ~(exp_data_seg.pagesize - 1))
|
||||
!= (exp_data_seg.end & ~(exp_data_seg.pagesize - 1)))
|
||||
&& first + last <= exp_data_seg.pagesize)
|
||||
{
|
||||
exp_data_seg.phase = exp_dataseg_adjust;
|
||||
result = lang_size_sections_1 (s, output_section_statement, prev,
|
||||
fill, dot, relax);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bfd_vma
|
||||
lang_do_assignments (s, output_section_statement, fill, dot)
|
||||
lang_statement_union_type *s;
|
||||
|
@ -239,6 +239,8 @@ V_IDENTIFIER [*?.$_a-zA-Z]([*?.$_a-zA-Z0-9]|::)*
|
||||
<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_END" { RTOKEN(DATA_SEGMENT_END);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"ADDR" { RTOKEN(ADDR);}
|
||||
<EXPRESSION,BOTH,SCRIPT>"LOADADDR" { RTOKEN(LOADADDR);}
|
||||
<EXPRESSION,BOTH>"MAX" { RTOKEN(MAX_K); }
|
||||
|
@ -70,6 +70,10 @@ if [ -z "$MACHINE" ]; then OUTPUT_ARCH=${ARCH}; else OUTPUT_ARCH=${ARCH}:${MACHI
|
||||
test -z "${ELFSIZE}" && ELFSIZE=32
|
||||
test -z "${ALIGNMENT}" && ALIGNMENT="${ELFSIZE} / 8"
|
||||
test "$LD_FLAG" = "N" && DATA_ADDR=.
|
||||
DATA_SEGMENT_ALIGN="ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))"
|
||||
if [ -n "${COMMONPAGESIZE}" ]; then
|
||||
DATA_SEGMENT_ALIGN="DATA_SEGMENT_ALIGN(${MAXPAGESIZE}, ${COMMONPAGESIZE})"
|
||||
fi
|
||||
INTERP=".interp ${RELOCATING-0} : { *(.interp) }"
|
||||
PLT=".plt ${RELOCATING-0} : { *(.plt) }"
|
||||
DYNAMIC=".dynamic ${RELOCATING-0} : { *(.dynamic) }"
|
||||
@ -269,8 +273,8 @@ cat <<EOF
|
||||
|
||||
/* Adjust the address for the data segment. We want to adjust up to
|
||||
the same address within the page on the next page up. */
|
||||
${CREATE_SHLIB-${RELOCATING+. = ${DATA_ADDR-ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))};}}
|
||||
${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-ALIGN(${MAXPAGESIZE}) + (. & (${MAXPAGESIZE} - 1))};}}
|
||||
${CREATE_SHLIB-${RELOCATING+. = ${DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
|
||||
${CREATE_SHLIB+${RELOCATING+. = ${SHLIB_DATA_ADDR-${DATA_SEGMENT_ALIGN}};}}
|
||||
|
||||
.data ${RELOCATING-0} :
|
||||
{
|
||||
@ -316,6 +320,7 @@ cat <<EOF
|
||||
${RELOCATING+_end = .;}
|
||||
${RELOCATING+${OTHER_BSS_END_SYMBOLS}}
|
||||
${RELOCATING+PROVIDE (end = .);}
|
||||
${COMMONPAGESIZE+${RELOCATING+. = DATA_SEGMENT_END (.);}}
|
||||
|
||||
/* Stabs debugging sections. */
|
||||
.stab 0 : { *(.stab) }
|
||||
|
Loading…
Reference in New Issue
Block a user