diff --git a/ld/ChangeLog b/ld/ChangeLog index 74e5b4fe4f2..a7869c759f0 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,19 @@ +2020-10-16 Andrew Burgess + + * ldlang.c (lang_process): Add extra call to + lang_do_memory_regions, and pass parameter. + (lang_do_memory_regions): Add parameter, only define origin and + length when requested. Reindent. + * testsuite/ld-scripts/provide-10.d: New file. + * testsuite/ld-scripts/provide-10.map: New file. + * testsuite/ld-scripts/provide-11.d: New file. + * testsuite/ld-scripts/provide-11.map: New file. + * testsuite/ld-scripts/provide-12.d: New file. + * testsuite/ld-scripts/provide-12.map: New file. + * testsuite/ld-scripts/provide-9.d: New file. + * testsuite/ld-scripts/provide-9.map: New file. + * testsuite/ld-scripts/provide-9.t: New file. + 2020-10-16 Andrew Burgess * ld.texi (Options): Extend the description of --defsym. diff --git a/ld/ldlang.c b/ld/ldlang.c index 4249b3a045d..2073ac09ce4 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -98,7 +98,7 @@ static void lang_record_phdrs (void); static void lang_do_version_exports_section (void); static void lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *); -static void lang_do_memory_regions (void); +static void lang_do_memory_regions (bfd_boolean); /* Exported variables. */ const char *output_target; @@ -7909,13 +7909,22 @@ lang_process (void) if (!bfd_section_already_linked_table_init ()) einfo (_("%F%P: can not create hash table: %E\n")); + /* A first pass through the memory regions ensures that if any region + references a symbol for its origin or length then this symbol will be + added to the symbol table. Having these symbols in the symbol table + means that when we call open_input_bfds PROVIDE statements will + trigger to provide any needed symbols. The regions origins and + lengths are not assigned as a result of this call. */ + lang_do_memory_regions (FALSE); + /* Create a bfd for each input file. */ current_target = default_target; lang_statement_iteration++; open_input_bfds (statement_list.head, OPEN_BFD_NORMAL); - /* open_input_bfds also handles assignments, so we can give values - to symbolic origin/length now. */ - lang_do_memory_regions (); + + /* Now that open_input_bfds has processed assignments and provide + statements we can give values to symbolic origin/length now. */ + lang_do_memory_regions (TRUE); #if BFD_SUPPORTS_PLUGINS if (link_info.lto_plugin_active) @@ -9373,10 +9382,16 @@ lang_do_version_exports_section (void) lang_new_vers_node (greg, lreg), NULL); } -/* Evaluate LENGTH and ORIGIN parts of MEMORY spec */ +/* Evaluate LENGTH and ORIGIN parts of MEMORY spec. This is initially + called with UPDATE_REGIONS_P set to FALSE, in this case no errors are + thrown, however, references to symbols in the origin and length fields + will be pushed into the symbol table, this allows PROVIDE statements to + then provide these symbols. This function is called a second time with + UPDATE_REGIONS_P set to TRUE, this time the we update the actual region + data structures, and throw errors if missing symbols are encountered. */ static void -lang_do_memory_regions (void) +lang_do_memory_regions (bfd_boolean update_regions_p) { lang_memory_region_type *r = lang_memory_region_list; @@ -9385,24 +9400,30 @@ lang_do_memory_regions (void) if (r->origin_exp) { exp_fold_tree_no_dot (r->origin_exp); - if (expld.result.valid_p) - { - r->origin = expld.result.value; - r->current = r->origin; - } - else - einfo (_("%F%P: invalid origin for memory region %s\n"), - r->name_list.name); + if (update_regions_p) + { + if (expld.result.valid_p) + { + r->origin = expld.result.value; + r->current = r->origin; + } + else + einfo (_("%P: invalid origin for memory region %s\n"), + r->name_list.name); + } } if (r->length_exp) { exp_fold_tree_no_dot (r->length_exp); - if (expld.result.valid_p) - r->length = expld.result.value; - else - einfo (_("%F%P: invalid length for memory region %s\n"), - r->name_list.name); - } + if (update_regions_p) + { + if (expld.result.valid_p) + r->length = expld.result.value; + else + einfo (_("%P: invalid length for memory region %s\n"), + r->name_list.name); + } + } } } diff --git a/ld/testsuite/ld-scripts/provide-10.d b/ld/testsuite/ld-scripts/provide-10.d new file mode 100644 index 00000000000..7481a92bbbd --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-10.d @@ -0,0 +1,3 @@ +#source: provide-5.s +#ld: --defsym=mem_origin=0x300 --defsym=mem_length=0x400 -T provide-9.t +#map: provide-10.map diff --git a/ld/testsuite/ld-scripts/provide-10.map b/ld/testsuite/ld-scripts/provide-10.map new file mode 100644 index 00000000000..022b962b2d8 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-10.map @@ -0,0 +1,6 @@ +#... +Memory Configuration + +Name Origin Length Attributes +FOO 0x[0-9a-f]+300 +0x[0-9a-f]+400 +#pass diff --git a/ld/testsuite/ld-scripts/provide-11.d b/ld/testsuite/ld-scripts/provide-11.d new file mode 100644 index 00000000000..79bcfa62162 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-11.d @@ -0,0 +1,3 @@ +#source: provide-5.s +#ld: --defsym=mem_length=0x400 -T provide-9.t +#map: provide-11.map diff --git a/ld/testsuite/ld-scripts/provide-11.map b/ld/testsuite/ld-scripts/provide-11.map new file mode 100644 index 00000000000..71763123123 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-11.map @@ -0,0 +1,6 @@ +#... +Memory Configuration + +Name Origin Length Attributes +FOO 0x[0-9a-f]+100 +0x[0-9a-f]+400 +#pass diff --git a/ld/testsuite/ld-scripts/provide-12.d b/ld/testsuite/ld-scripts/provide-12.d new file mode 100644 index 00000000000..41d95900fd3 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-12.d @@ -0,0 +1,3 @@ +#source: provide-5.s +#ld: --defsym=mem_origin=0x300 -T provide-9.t +#map: provide-12.map diff --git a/ld/testsuite/ld-scripts/provide-12.map b/ld/testsuite/ld-scripts/provide-12.map new file mode 100644 index 00000000000..e76654b10fd --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-12.map @@ -0,0 +1,6 @@ +#... +Memory Configuration + +Name Origin Length Attributes +FOO 0x[0-9a-f]+300 +0x[0-9a-f]+200 +#pass diff --git a/ld/testsuite/ld-scripts/provide-9.d b/ld/testsuite/ld-scripts/provide-9.d new file mode 100644 index 00000000000..94dc02949b7 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-9.d @@ -0,0 +1,3 @@ +#source: provide-5.s +#ld: -T provide-9.t +#map: provide-9.map diff --git a/ld/testsuite/ld-scripts/provide-9.map b/ld/testsuite/ld-scripts/provide-9.map new file mode 100644 index 00000000000..e35e3e25157 --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-9.map @@ -0,0 +1,6 @@ +#... +Memory Configuration + +Name Origin Length Attributes +FOO 0x[0-9a-f]+100 +0x[0-9a-f]+200 +#pass diff --git a/ld/testsuite/ld-scripts/provide-9.t b/ld/testsuite/ld-scripts/provide-9.t new file mode 100644 index 00000000000..00d906aa80a --- /dev/null +++ b/ld/testsuite/ld-scripts/provide-9.t @@ -0,0 +1,25 @@ +PROVIDE (mem_origin = 0x100); +PROVIDE (mem_length = 0x200); + +MEMORY +{ + FOO : ORIGIN = mem_origin, LENGTH = mem_length +} + +SECTIONS +{ + .data : { + *(.data .data.*) + } >FOO + + .text : { + *(.text .text.*) + } >FOO + + .bss : { + *(.bss .bss.*) + } >FOO + + /DISCARD/ : { *(.*) } +} +