diff options
Diffstat (limited to 'ld')
-rw-r--r-- | ld/ChangeLog | 23 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 2 | ||||
-rw-r--r-- | ld/emultempl/pep.em | 2 | ||||
-rw-r--r-- | ld/ldexp.c | 20 | ||||
-rw-r--r-- | ld/ldexp.h | 4 | ||||
-rw-r--r-- | ld/ldlang.c | 48 | ||||
-rw-r--r-- | ld/ldlang.h | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/align.exp | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/pr23571.d | 10 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/pr23571.t | 11 |
10 files changed, 88 insertions, 40 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 5488c85..96232df 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,26 @@ +2018-08-26 Alan Modra <amodra@gmail.com> + + PR 23571 + * ldlang.h (section_alignment): Make it an expression tree. + (subsection_alignment): Likewise. + * ldlang.c (topower): Delete. + (output_section_statement_newfunc): Adjust initialization. + (init_os): Evaluate section_alignment. + (lang_size_sections_1): Likewise. + (size_input_section): Evaluate subsection_alignment. + (lang_enter_output_section_statement): Don't evaluate here. + (lang_new_phdr): Use exp_get_vma rather than exp_get_value_int. + * ldexp.h (exp_get_value_int): Delete. + (exp_get_power): Declare. + * ldexp.c (exp_get_value_int): Delete. + (exp_get_power): New function. + * emultempl/pe.em (place_orphan): Build expression for section + alignment. + * emultempl/pep.em (place_orphan): Likewise. + * testsuite/ld-scripts/pr23571.d, + * testsuite/ld-scripts/pr23571.t: New test. + * testsuite/ld-scripts/align.exp: Run it. + 2018-08-24 Chenghua Xu <paul.hua.gm@gmail.com> * testsuite/ld-mips-elf/mips-elf-flags.exp diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 463b854..663d4ce 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -2165,7 +2165,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, &add_child); if (bfd_link_relocatable (&link_info)) { - os->section_alignment = s->alignment_power; + os->section_alignment = exp_intop (1U << s->alignment_power); os->bfd_section->alignment_power = s->alignment_power; } } diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em index 1a7394e..1dc1664 100644 --- a/ld/emultempl/pep.em +++ b/ld/emultempl/pep.em @@ -1962,7 +1962,7 @@ gld_${EMULATION_NAME}_place_orphan (asection *s, &add_child); if (bfd_link_relocatable (&link_info)) { - os->section_alignment = s->alignment_power; + os->section_alignment = exp_intop (1U << s->alignment_power); os->bfd_section->alignment_power = s->alignment_power; } } @@ -1523,10 +1523,26 @@ exp_get_vma (etree_type *tree, bfd_vma def, char *name) return def; } +/* Return the smallest non-negative integer such that two raised to + that power is at least as large as the vma evaluated at TREE, if + TREE is a non-NULL expression that can be resolved. If TREE is + NULL or cannot be resolved, return -1. */ + int -exp_get_value_int (etree_type *tree, int def, char *name) +exp_get_power (etree_type *tree, char *name) { - return exp_get_vma (tree, def, name); + bfd_vma x = exp_get_vma (tree, -1, name); + bfd_vma p2; + int n; + + if (x == (bfd_vma) -1) + return -1; + + for (n = 0, p2 = 1; p2 < x; ++n, p2 <<= 1) + if (p2 == 0) + break; + + return n; } fill_type * @@ -229,8 +229,8 @@ void exp_print_tree (etree_type *); bfd_vma exp_get_vma (etree_type *, bfd_vma, char *); -int exp_get_value_int - (etree_type *, int, char *); +int exp_get_power + (etree_type *, char *); fill_type *exp_get_fill (etree_type *, fill_type *, char *); bfd_vma exp_get_abs_int diff --git a/ld/ldlang.c b/ld/ldlang.c index 350baf2..8878ccd 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -1199,8 +1199,8 @@ output_section_statement_newfunc (struct bfd_hash_entry *entry, ret = (struct out_section_hash_entry *) entry; memset (&ret->s, 0, sizeof (ret->s)); ret->s.header.type = lang_output_section_statement_enum; - ret->s.output_section_statement.subsection_alignment = -1; - ret->s.output_section_statement.section_alignment = -1; + ret->s.output_section_statement.subsection_alignment = NULL; + ret->s.output_section_statement.section_alignment = NULL; ret->s.output_section_statement.block_value = 1; lang_list_init (&ret->s.output_section_statement.children); lang_statement_append (stat_ptr, &ret->s, &ret->s.header.next); @@ -2193,8 +2193,9 @@ init_os (lang_output_section_statement_type *s, flagword flags) exp_init_os (s->load_base); /* If supplied an alignment, set it. */ - if (s->section_alignment != -1) - s->bfd_section->alignment_power = s->section_alignment; + if (s->section_alignment != NULL) + s->bfd_section->alignment_power = exp_get_power (s->section_alignment, + "section alignment"); } /* Make sure that all output sections mentioned in an expression are @@ -4706,8 +4707,10 @@ size_input_section is greater than any seen before, then record it too. Perform the alignment by inserting a magic 'padding' statement. */ - if (output_section_statement->subsection_alignment != -1) - i->alignment_power = output_section_statement->subsection_alignment; + if (output_section_statement->subsection_alignment != NULL) + i->alignment_power + = exp_get_power (output_section_statement->subsection_alignment, + "subsection alignment"); if (o->alignment_power < i->alignment_power) o->alignment_power = i->alignment_power; @@ -5147,7 +5150,8 @@ lang_size_sections_1 section_alignment = os->bfd_section->alignment_power; } else - section_alignment = os->section_alignment; + section_alignment = exp_get_power (os->section_alignment, + "section alignment"); /* Align to what the section needs. */ if (section_alignment > 0) @@ -5225,7 +5229,8 @@ lang_size_sections_1 only align according to the value in the output statement. */ if (os->lma_region != os->region) - section_alignment = os->section_alignment; + section_alignment = exp_get_power (os->section_alignment, + "section alignment"); if (section_alignment > 0) lma = align_power (lma, section_alignment); } @@ -6673,25 +6678,6 @@ lang_add_output (const char *name, int from_script) } } -static int -topower (int x) -{ - unsigned int i = 1; - int l; - - if (x < 0) - return -1; - - for (l = 0; l < 32; l++) - { - if (i >= (unsigned int) x) - return l; - i <<= 1; - } - - return 0; -} - lang_output_section_statement_type * lang_enter_output_section_statement (const char *output_section_statement_name, etree_type *address_exp, @@ -6727,10 +6713,8 @@ lang_enter_output_section_statement (const char *output_section_statement_name, einfo (_("%F%P:%pS: error: align with input and explicit align specified\n"), NULL); - os->subsection_alignment = - topower (exp_get_value_int (subalign, -1, "subsection alignment")); - os->section_alignment = - topower (exp_get_value_int (align, -1, "section alignment")); + os->subsection_alignment = subalign; + os->section_alignment = align; os->load_base = ebase; return os; @@ -7748,7 +7732,7 @@ lang_new_phdr (const char *name, n = (struct lang_phdr *) stat_alloc (sizeof (struct lang_phdr)); n->next = NULL; n->name = name; - n->type = exp_get_value_int (type, 0, "program header type"); + n->type = exp_get_vma (type, 0, "program header type"); n->filehdr = filehdr; n->phdrs = phdrs; n->at = at; diff --git a/ld/ldlang.h b/ld/ldlang.h index 3d66169..dfac0b1 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -143,6 +143,8 @@ typedef struct lang_output_section_statement_struct fill_type *fill; union etree_union *addr_tree; union etree_union *load_base; + union etree_union *section_alignment; + union etree_union *subsection_alignment; /* If non-null, an expression to evaluate after setting the section's size. The expression is evaluated inside REGION (above) with '.' @@ -153,8 +155,6 @@ typedef struct lang_output_section_statement_struct lang_output_section_phdr_list *phdrs; unsigned int block_value; - int subsection_alignment; /* Alignment of components. */ - int section_alignment; /* Alignment of start of section. */ int constraint; flagword flags; enum section_type sectype; diff --git a/ld/testsuite/ld-scripts/align.exp b/ld/testsuite/ld-scripts/align.exp index f9523d2..25d4f6d 100644 --- a/ld/testsuite/ld-scripts/align.exp +++ b/ld/testsuite/ld-scripts/align.exp @@ -53,3 +53,7 @@ if ![is_aout_format] { } run_dump_test align2c set LDFLAGS "$saved_LDFLAGS" + +if { [is_elf_format] && ![is_generic_elf] } { + run_dump_test pr23571 +} diff --git a/ld/testsuite/ld-scripts/pr23571.d b/ld/testsuite/ld-scripts/pr23571.d new file mode 100644 index 0000000..adf4796 --- /dev/null +++ b/ld/testsuite/ld-scripts/pr23571.d @@ -0,0 +1,10 @@ +#source: align2a.s +#ld: -T pr23571.t -z common-page-size=0x1000 +#objdump: -h -w + +.*: +file format .* + +Sections: +Idx Name +Size +VMA +LMA +File off +Algn +Flags + +0 \.text +[0-9a-f]* +0+1000 +0+1000 .* + +1 \.data +[0-9a-f]* +0+2000 +0+2000 +[0-9a-f]* +2\*\*12 .* diff --git a/ld/testsuite/ld-scripts/pr23571.t b/ld/testsuite/ld-scripts/pr23571.t new file mode 100644 index 0000000..290cdf5 --- /dev/null +++ b/ld/testsuite/ld-scripts/pr23571.t @@ -0,0 +1,11 @@ +SECTIONS +{ + .text CONSTANT(COMMONPAGESIZE) : { + *(.text) + } + + .data : ALIGN(CONSTANT(COMMONPAGESIZE)) { + *(.data) + } + /DISCARD/ : {*(*)} +} |