aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/elf-bfd.h4
-rw-r--r--bfd/elf.c71
-rw-r--r--bfd/elfxx-target.h5
-rw-r--r--bfd/elfxx-x86.h2
-rw-r--r--include/bfdlink.h3
-rw-r--r--ld/emultempl/elf.em1
-rw-r--r--ld/ldelf.c3
-rw-r--r--ld/testsuite/ld-elf/elf.exp4
-rw-r--r--ld/testsuite/ld-elf/header.d2
-rw-r--r--ld/testsuite/ld-elf/linux-x86.exp36
-rw-r--r--ld/testsuite/ld-elf/p_align-1.c25
-rw-r--r--ld/testsuite/ld-elf/page-size-1.d4
-rw-r--r--ld/testsuite/ld-elf/pr26936.d2
-rw-r--r--ld/testsuite/ld-elf/seg.d2
-rw-r--r--ld/testsuite/ld-pru/pru_irq_map-1.d4
-rw-r--r--ld/testsuite/ld-pru/pru_irq_map-2.d2
-rw-r--r--ld/testsuite/ld-scripts/pr23571.d2
-rw-r--r--ld/testsuite/ld-scripts/rgn-at5.d2
18 files changed, 162 insertions, 12 deletions
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 19abd59..896aa08 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -945,6 +945,10 @@ struct elf_backend_data
/* The value of commonpagesize to use when -z relro for this backend. */
bfd_vma relropagesize;
+ /* The p_align value for this backend. If it is set, p_align of
+ PT_LOAD alignment will be to p_align by default. */
+ bfd_vma p_align;
+
/* The BFD flags applied to sections created for dynamic linking. */
flagword dynamic_sec_flags;
diff --git a/bfd/elf.c b/bfd/elf.c
index 7e8a2ec..1003bd2 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -5407,6 +5407,8 @@ assign_file_positions_for_load_sections (bfd *abfd,
Elf_Internal_Phdr *p;
file_ptr off; /* Octets. */
bfd_size_type maxpagesize;
+ bfd_size_type p_align;
+ bool p_align_p = false;
unsigned int alloc, actual;
unsigned int i, j;
struct elf_segment_map **sorted_seg_map;
@@ -5491,6 +5493,7 @@ assign_file_positions_for_load_sections (bfd *abfd,
qsort (sorted_seg_map, alloc, sizeof (*sorted_seg_map),
elf_sort_segments);
+ p_align = bed->p_align;
maxpagesize = 1;
if ((abfd->flags & D_PAGED) != 0)
{
@@ -5561,6 +5564,15 @@ assign_file_positions_for_load_sections (bfd *abfd,
segment. */
if (m->p_align_valid)
maxpagesize = m->p_align;
+ else if (p_align != 0
+ && (link_info == NULL
+ || !link_info->maxpagesize_is_set))
+ /* Set p_align to the default p_align value while laying
+ out segments aligning to the maximum page size or the
+ largest section alignment. The run-time loader can
+ align segments to the default p_align value or the
+ maximum page size, depending on system page size. */
+ p_align_p = true;
p->p_align = maxpagesize;
}
@@ -5598,7 +5610,22 @@ assign_file_positions_for_load_sections (bfd *abfd,
}
align = (bfd_size_type) 1 << align_power;
if (align < maxpagesize)
- align = maxpagesize;
+ {
+ /* If a section requires alignment higher than the
+ default p_align value, don't set p_align to the
+ default p_align value. */
+ if (align > p_align)
+ p_align_p = false;
+ align = maxpagesize;
+ }
+ else
+ {
+ /* If a section requires alignment higher than the
+ maximum page size, set p_align to the section
+ alignment. */
+ p_align_p = true;
+ p_align = align;
+ }
}
for (i = 0; i < m->count; i++)
@@ -5977,6 +6004,9 @@ assign_file_positions_for_load_sections (bfd *abfd,
print_segment_map (m);
}
}
+
+ if (p_align_p)
+ p->p_align = p_align;
}
}
@@ -7484,6 +7514,40 @@ rewrite_elf_program_header (bfd *ibfd, bfd *obfd, bfd_vma maxpagesize)
return true;
}
+/* Return true if p_align in the ELF program header in ABFD is valid. */
+
+static bool
+elf_is_p_align_valid (bfd *abfd)
+{
+ unsigned int i;
+ Elf_Internal_Phdr *segment;
+ unsigned int num_segments;
+ const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+ bfd_size_type maxpagesize = bed->maxpagesize;
+ bfd_size_type p_align = bed->p_align;
+
+ /* Return true if the default p_align value isn't set or the maximum
+ page size is the same as the minimum page size. */
+ if (p_align == 0 || maxpagesize == bed->minpagesize)
+ return true;
+
+ /* When the default p_align value is set, p_align may be set to the
+ default p_align value while segments are aligned to the maximum
+ page size. In this case, the input p_align will be ignored and
+ the maximum page size will be used to align the output segments. */
+ segment = elf_tdata (abfd)->phdr;
+ num_segments = elf_elfheader (abfd)->e_phnum;
+ for (i = 0; i < num_segments; i++, segment++)
+ if (segment->p_type == PT_LOAD
+ && (segment->p_align != p_align
+ || vma_page_aligned_bias (segment->p_vaddr,
+ segment->p_offset,
+ maxpagesize) != 0))
+ return true;
+
+ return false;
+}
+
/* Copy ELF program header information. */
static bool
@@ -7498,6 +7562,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
unsigned int num_segments;
bool phdr_included = false;
bool p_paddr_valid;
+ bool p_palign_valid;
unsigned int opb = bfd_octets_per_byte (ibfd, NULL);
iehdr = elf_elfheader (ibfd);
@@ -7518,6 +7583,8 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
break;
}
+ p_palign_valid = elf_is_p_align_valid (ibfd);
+
for (i = 0, segment = elf_tdata (ibfd)->phdr;
i < num_segments;
i++, segment++)
@@ -7560,7 +7627,7 @@ copy_elf_program_header (bfd *ibfd, bfd *obfd)
map->p_paddr = segment->p_paddr;
map->p_paddr_valid = p_paddr_valid;
map->p_align = segment->p_align;
- map->p_align_valid = 1;
+ map->p_align_valid = p_palign_valid;
map->p_vaddr_offset = 0;
if (map->p_type == PT_GNU_RELRO
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index b9af578..360b056 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -400,6 +400,10 @@
# error ELF_MINPAGESIZE > ELF_RELROPAGESIZE
#endif
+#ifndef ELF_P_ALIGN
+#define ELF_P_ALIGN 0
+#endif
+
#ifndef ELF_DYNAMIC_SEC_FLAGS
/* Note that we set the SEC_IN_MEMORY flag for these sections. */
#define ELF_DYNAMIC_SEC_FLAGS \
@@ -813,6 +817,7 @@ static const struct elf_backend_data elfNN_bed =
ELF_MINPAGESIZE, /* minpagesize */
ELF_COMMONPAGESIZE, /* commonpagesize */
ELF_RELROPAGESIZE, /* commonpagesize to use with -z relro */
+ ELF_P_ALIGN, /* p_align */
ELF_DYNAMIC_SEC_FLAGS, /* dynamic_sec_flags */
elf_backend_arch_data,
elf_info_to_howto,
diff --git a/bfd/elfxx-x86.h b/bfd/elfxx-x86.h
index eedb162..25791af 100644
--- a/bfd/elfxx-x86.h
+++ b/bfd/elfxx-x86.h
@@ -755,6 +755,8 @@ extern void _bfd_x86_elf_link_report_relative_reloc
#define elf_backend_fixup_gnu_properties \
_bfd_x86_elf_link_fixup_gnu_properties
+#define ELF_P_ALIGN ELF_MINPAGESIZE
+
/* Return true if H is a __start_SECNAME/__stop_SECNAME symbol for the
SECNAME section which has been garbage collected by --gc-sections
-z start-stop-gc. */
diff --git a/include/bfdlink.h b/include/bfdlink.h
index 6a61d7e..01f57c2 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -525,6 +525,9 @@ struct bfd_link_info
/* TRUE if all symbol names should be unique. */
unsigned int unique_symbol : 1;
+ /* TRUE if maxpagesize is set on command-line. */
+ unsigned int maxpagesize_is_set : 1;
+
/* Char that may appear as the first char of a symbol, but should be
skipped (like symbol_leading_char) when looking up symbols in
wrap_hash. Used by PowerPC Linux for 'dot' symbols. */
diff --git a/ld/emultempl/elf.em b/ld/emultempl/elf.em
index 9c8e792..5977526 100644
--- a/ld/emultempl/elf.em
+++ b/ld/emultempl/elf.em
@@ -721,6 +721,7 @@ fragment <<EOF
|| (link_info.maxpagesize & (link_info.maxpagesize - 1)) != 0)
einfo (_("%F%P: invalid maximum page size \`%s'\n"),
optarg + 14);
+ link_info.maxpagesize_is_set = true;
}
else if (startswith (optarg, "common-page-size="))
{
diff --git a/ld/ldelf.c b/ld/ldelf.c
index 00caa6b..d15f027 100644
--- a/ld/ldelf.c
+++ b/ld/ldelf.c
@@ -72,6 +72,9 @@ ldelf_after_parse (void)
link_info.dynamic_undefined_weak = 0;
}
after_parse_default ();
+ if (link_info.commonpagesize > link_info.maxpagesize)
+ einfo (_("%F%P: common page size (0x%v) > maximum page size (0x%v)\n"),
+ link_info.commonpagesize, link_info.maxpagesize);
}
/* Handle the generation of DT_NEEDED tags. */
diff --git a/ld/testsuite/ld-elf/elf.exp b/ld/testsuite/ld-elf/elf.exp
index 119908c..16128c2 100644
--- a/ld/testsuite/ld-elf/elf.exp
+++ b/ld/testsuite/ld-elf/elf.exp
@@ -365,7 +365,7 @@ if { [istarget *-*-linux*]
run_ld_link_exec_tests [list \
[list \
"Run mbind2a" \
- "$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000" \
+ "$NOPIE_LDFLAGS -Wl,-z,common-page-size=0x4000,-z,max-page-size=0x4000" \
"" \
{ mbind2a.s mbind2b.c } \
"mbind2a" \
@@ -374,7 +374,7 @@ if { [istarget *-*-linux*]
] \
[list \
"Run mbind2b" \
- "-static -Wl,-z,common-page-size=0x4000" \
+ "-static -Wl,-z,common-page-size=0x4000,-z,max-page-size=0x4000" \
"" \
{ mbind2a.s mbind2b.c } \
"mbind2b" \
diff --git a/ld/testsuite/ld-elf/header.d b/ld/testsuite/ld-elf/header.d
index c4d174a..67f0c98 100644
--- a/ld/testsuite/ld-elf/header.d
+++ b/ld/testsuite/ld-elf/header.d
@@ -1,5 +1,5 @@
# target: *-*-linux* *-*-gnu* *-*-vxworks arm*-*-uclinuxfdpiceabi
-# ld: -T header.t -z max-page-size=0x100
+# ld: -T header.t -z max-page-size=0x100 -z common-page-size=0x100
# objdump: -hpw
#...
diff --git a/ld/testsuite/ld-elf/linux-x86.exp b/ld/testsuite/ld-elf/linux-x86.exp
index f48c196..2e0cbd3 100644
--- a/ld/testsuite/ld-elf/linux-x86.exp
+++ b/ld/testsuite/ld-elf/linux-x86.exp
@@ -185,6 +185,42 @@ run_ld_link_exec_tests [list \
"" \
"tmpdir/indirect-extern-access-2.so" \
] \
+ [list \
+ "Run p_align-1a without PIE" \
+ "$NOPIE_LDFLAGS" \
+ "" \
+ { p_align-1.c } \
+ "p_align-1a" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run p_align-1b with PIE" \
+ "-pie" \
+ "" \
+ { p_align-1.c } \
+ "p_align-1b" \
+ "pass.out" \
+ "-fpie" \
+ ] \
+ [list \
+ "Run p_align-1c with -Wl,-z,max-page-size=0x1000 without PIE" \
+ "$NOPIE_LDFLAGS -Wl,-z,max-page-size=0x1000" \
+ "" \
+ { p_align-1.c } \
+ "p_align-1c" \
+ "pass.out" \
+ "$NOPIE_CFLAGS" \
+ ] \
+ [list \
+ "Run p_align-1d with -Wl,-z,max-page-size=0x1000 with PIE" \
+ "-pie -Wl,-z,max-page-size=0x1000" \
+ "" \
+ { p_align-1.c } \
+ "p_align-1d" \
+ "pass.out" \
+ "-fpie" \
+ ] \
]
proc elfedit_test { options test output } {
diff --git a/ld/testsuite/ld-elf/p_align-1.c b/ld/testsuite/ld-elf/p_align-1.c
new file mode 100644
index 0000000..6579cd7
--- /dev/null
+++ b/ld/testsuite/ld-elf/p_align-1.c
@@ -0,0 +1,25 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#ifndef ALIGN
+# define ALIGN 0x800000
+#endif
+
+int
+__attribute__ ((weak))
+is_aligned (void *p, int align)
+{
+ return (((uintptr_t) p) & (align - 1)) == 0;
+}
+
+int foo __attribute__ ((aligned (ALIGN))) = 1;
+
+int
+main (void)
+{
+ if (!is_aligned (&foo, ALIGN))
+ abort ();
+ printf ("PASS\n");
+ return 0;
+}
diff --git a/ld/testsuite/ld-elf/page-size-1.d b/ld/testsuite/ld-elf/page-size-1.d
new file mode 100644
index 0000000..04d2153
--- /dev/null
+++ b/ld/testsuite/ld-elf/page-size-1.d
@@ -0,0 +1,4 @@
+#source: dummy.s
+#ld: -z common-page-size=0x4000 -z max-page-size=0x1000
+#error: common page size \(0x4000\) > maximum page size \(0x1000\)
+#target: *-*-linux-gnu *-*-gnu* arm*-*-uclinuxfdpiceabi
diff --git a/ld/testsuite/ld-elf/pr26936.d b/ld/testsuite/ld-elf/pr26936.d
index 0a2831d..c479f47 100644
--- a/ld/testsuite/ld-elf/pr26936.d
+++ b/ld/testsuite/ld-elf/pr26936.d
@@ -2,7 +2,7 @@
#source: pr26936b.s
#source: pr26936c.s
#as: --gen-debug
-#ld: -z noseparate-code -Ttext-segment 0x10000 -z max-page-size=0x1000
+#ld: -z noseparate-code -Ttext-segment 0x10000 -z max-page-size=0x1000 -z common-page-size=0x1000
#readelf: -wL -W
#target: [check_shared_lib_support]
# Assembly source file for the HPPA assembler is renamed and modifed by
diff --git a/ld/testsuite/ld-elf/seg.d b/ld/testsuite/ld-elf/seg.d
index 3ff7aba..9dce11e 100644
--- a/ld/testsuite/ld-elf/seg.d
+++ b/ld/testsuite/ld-elf/seg.d
@@ -1,6 +1,6 @@
#target: *-*-linux* *-*-gnu* *-*-vxworks arm*-*-uclinuxfdpiceabi
#source: seg.s
-#ld: -T seg.t -z max-page-size=0x1000
+#ld: -T seg.t -z max-page-size=0x1000 -z common-page-size=0x1000
#readelf: -l --wide
#...
diff --git a/ld/testsuite/ld-pru/pru_irq_map-1.d b/ld/testsuite/ld-pru/pru_irq_map-1.d
index bbdf5b6..2538f4c 100644
--- a/ld/testsuite/ld-pru/pru_irq_map-1.d
+++ b/ld/testsuite/ld-pru/pru_irq_map-1.d
@@ -1,4 +1,4 @@
-#name: pru_irq_map special section for host
+#name: pru_irq_map special section for host 1
#source: pru_irq_map.s
#ld: --defsym=__HEAP_SIZE=0 --defsym=__STACK_SIZE=0
#readelf: -l --wide
@@ -9,7 +9,7 @@
Program Headers:
+Type +Offset +VirtAddr +PhysAddr +FileSiz +MemSiz +Flg +Align
+LOAD +0x[0-9a-f]+ 0x0+ 0x0+ 0x0+8 0x0+8 RW 0x1
- +LOAD +0x[0-9a-f]+ 0x20+ 0x20+ 0x0+4 0x0+4 R E 0x1
+ +LOAD +0x[0-9a-f]+ 0x20+ 0x20+ 0x0+4 0x0+4 R E 0x4
Section to Segment mapping:
+Segment Sections...
diff --git a/ld/testsuite/ld-pru/pru_irq_map-2.d b/ld/testsuite/ld-pru/pru_irq_map-2.d
index 3166595..d6c583f 100644
--- a/ld/testsuite/ld-pru/pru_irq_map-2.d
+++ b/ld/testsuite/ld-pru/pru_irq_map-2.d
@@ -1,4 +1,4 @@
-#name: pru_irq_map special section for host
+#name: pru_irq_map special section for host 2
#source: pru_irq_map.s
#ld: --defsym=__HEAP_SIZE=0 --defsym=__STACK_SIZE=0
#readelf: -S --wide
diff --git a/ld/testsuite/ld-scripts/pr23571.d b/ld/testsuite/ld-scripts/pr23571.d
index adf4796..45b4059 100644
--- a/ld/testsuite/ld-scripts/pr23571.d
+++ b/ld/testsuite/ld-scripts/pr23571.d
@@ -1,5 +1,5 @@
#source: align2a.s
-#ld: -T pr23571.t -z common-page-size=0x1000
+#ld: -T pr23571.t -z common-page-size=0x1000 -z max-page-size=0x1000
#objdump: -h -w
.*: +file format .*
diff --git a/ld/testsuite/ld-scripts/rgn-at5.d b/ld/testsuite/ld-scripts/rgn-at5.d
index 767285c..e9ab081 100644
--- a/ld/testsuite/ld-scripts/rgn-at5.d
+++ b/ld/testsuite/ld-scripts/rgn-at5.d
@@ -1,6 +1,6 @@
# name: rgn-at5
# source: rgn-at5.s
-# ld: -T rgn-at5.t -z max-page-size=0x1000
+# ld: -T rgn-at5.t -z max-page-size=0x1000 -z common-page-size=0x1000
# objdump: -w -h
# target: *-*-linux* *-*-gnu* arm*-*-uclinuxfdpiceabi
# xfail: rx-*-*