diff options
-rw-r--r-- | ld/ChangeLog | 14 | ||||
-rw-r--r-- | ld/ldexp.c | 21 | ||||
-rw-r--r-- | ld/ldgram.y | 4 | ||||
-rw-r--r-- | ld/ldlang.c | 36 | ||||
-rw-r--r-- | ld/ldlang.h | 2 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/memory.t | 3 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/memory_sym.t | 36 | ||||
-rw-r--r-- | ld/testsuite/ld-scripts/script.exp | 21 |
9 files changed, 132 insertions, 12 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 5a97e32..c61baae 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,17 @@ +2015-01-28 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + PR 4643 + * ldexp.c (fold_name): Fold LENGTH only after + lang_first_phase_enum. + * ldgram.y (memory_spec): Don't evaluate ORIGIN and LENGTH + rightaway. + * ldlang.h (struct memory_region_struct): Add origin_exp and + length_exp fields. + * ldlang.c (lang_do_memory_regions): New. + (lang_memory_region_lookup): Initialize origin_exp and + length_exp fields. + (lang_process): Call lang_do_memory_regions. + 2015-01-20 Andrew Burgess <andrew.burgess@embecosm.com> * ldlang.c (print_assignment): Only evaluate the expression for a @@ -828,15 +828,18 @@ fold_name (etree_type *tree) case LENGTH: { - lang_memory_region_type *mem; - - mem = lang_memory_region_lookup (tree->name.name, FALSE); - if (mem != NULL) - new_number (mem->length); - else - einfo (_("%F%S: undefined MEMORY region `%s'" - " referenced in expression\n"), - tree, tree->name.name); + if (expld.phase != lang_first_phase_enum) + { + lang_memory_region_type *mem; + + mem = lang_memory_region_lookup (tree->name.name, FALSE); + if (mem != NULL) + new_number (mem->length); + else + einfo (_("%F%S: undefined MEMORY region `%s'" + " referenced in expression\n"), + tree, tree->name.name); + } } break; diff --git a/ld/ldgram.y b/ld/ldgram.y index 736f77d..f46aa9e 100644 --- a/ld/ldgram.y +++ b/ld/ldgram.y @@ -817,7 +817,7 @@ memory_spec: NAME origin_spec: ORIGIN '=' mustbe_exp { - region->origin = exp_get_vma ($3, 0, "origin"); + region->origin_exp = $3; region->current = region->origin; } ; @@ -825,7 +825,7 @@ origin_spec: length_spec: LENGTH '=' mustbe_exp { - region->length = exp_get_vma ($3, -1, "length"); + region->length_exp = $3; } ; diff --git a/ld/ldlang.c b/ld/ldlang.c index 3ea22c2..5344e5e 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -85,6 +85,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); /* Exported variables. */ const char *output_target; @@ -1305,7 +1306,9 @@ lang_memory_region_lookup (const char *const name, bfd_boolean create) new_region->name_list.name = xstrdup (name); new_region->name_list.next = NULL; new_region->next = NULL; + new_region->origin_exp = NULL; new_region->origin = 0; + new_region->length_exp = NULL; new_region->length = ~(bfd_size_type) 0; new_region->current = 0; new_region->last_os = NULL; @@ -6707,6 +6710,8 @@ lang_process (void) /* PR 13683: We must rerun the assignments prior to running garbage collection in order to make sure that all symbol aliases are resolved. */ lang_do_assignments (lang_mark_phase_enum); + + lang_do_memory_regions(); expld.phase = lang_first_phase_enum; /* Size up the common data. */ @@ -7970,6 +7975,37 @@ lang_do_version_exports_section (void) lang_new_vers_node (greg, lreg), NULL); } +/* Evaluate LENGTH and ORIGIN parts of MEMORY spec */ + +static void +lang_do_memory_regions (void) +{ + lang_memory_region_type *r = lang_memory_region_list; + + for (; r != NULL; r = r->next) + { + 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 (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); + } + } +} + void lang_add_unique (const char *name) { diff --git a/ld/ldlang.h b/ld/ldlang.h index 48d7e4e..69d21a7 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -55,8 +55,10 @@ typedef struct memory_region_struct { lang_memory_region_name name_list; struct memory_region_struct *next; + union etree_union *origin_exp; bfd_vma origin; bfd_size_type length; + union etree_union *length_exp; bfd_vma current; union lang_statement_union *last_os; flagword flags; diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 21cf40e..4746f14 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2015-01-28 Senthil Kumar Selvaraj <senthil_kumar.selvaraj@atmel.com> + + * ld-scripts/memory.t: Define new symbol tred. + * ld-scripts/memory_sym.t: New. + * ld-scripts/script.exp: Perform MEMORY with symbols test, and + conditionally check values of linker symbols. + 2015-01-20 Andrew Burgess <andrew.burgess@embecosm.com> * ld-scripts/provide-4-map.d: Update expected output. diff --git a/ld/testsuite/ld-scripts/memory.t b/ld/testsuite/ld-scripts/memory.t index 129bd7c..937394f 100644 --- a/ld/testsuite/ld-scripts/memory.t +++ b/ld/testsuite/ld-scripts/memory.t @@ -29,5 +29,6 @@ SECTIONS data_end = .; } >DATAMEM - fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM); + fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM); + tred = ORIGIN(TEXTMEM) + LENGTH(TEXTMEM); } diff --git a/ld/testsuite/ld-scripts/memory_sym.t b/ld/testsuite/ld-scripts/memory_sym.t new file mode 100644 index 0000000..4ccec55 --- /dev/null +++ b/ld/testsuite/ld-scripts/memory_sym.t @@ -0,0 +1,36 @@ +TXT_ORIGIN = 0x100; +TXT_LENGTH = 32K; +MEMORY +{ + R_TEXTMEM (ARX) : ORIGIN = TXT_ORIGIN, LENGTH = TXT_LENGTH + R_DATAMEM (AW) : org = DATA_ORIGIN, l = DATA_LENGTH +} + +REGION_ALIAS ("A_TEXTMEM", R_TEXTMEM); +REGION_ALIAS ("A_DATAMEM", R_DATAMEM); + +REGION_ALIAS ("TEXTMEM", A_TEXTMEM); +REGION_ALIAS ("DATAMEM", A_DATAMEM); + +SECTIONS +{ + . = 0; + .text : + { + text_start = ORIGIN (TEXTMEM); + *(.text) + *(.pr) + text_end = .; + } > TEXTMEM + + data_start = ORIGIN (DATAMEM); + .data : + { + *(.data) + *(.rw) + data_end = .; + } >DATAMEM + + fred = ORIGIN(DATAMEM) + LENGTH(DATAMEM); + tred = ORIGIN(TEXTMEM) + LENGTH(TEXTMEM); +} diff --git a/ld/testsuite/ld-scripts/script.exp b/ld/testsuite/ld-scripts/script.exp index cee706f..6ab04ec 100644 --- a/ld/testsuite/ld-scripts/script.exp +++ b/ld/testsuite/ld-scripts/script.exp @@ -66,6 +66,13 @@ proc check_script { } { set passes 0 } + if {[info exists nm_output(tred)] \ + && $nm_output(tred) != (0x100 + 0x8000)} { + send_log "tred == $nm_output(tred)\n" + verbose "tred == $nm_output(tred)" + set passes 0 + } + if {$nm_output(text_end) < $text_end \ || $nm_output(text_end) > 0x110} { send_log "text_end == $nm_output(text_end)\n" @@ -79,6 +86,13 @@ proc check_script { } { set passes 0 } + if {[info exists nm_output(fred)] \ + && $nm_output(fred) != (0x1000 + 0x10000)} { + send_log "fred == $nm_output(fred)\n" + verbose "fred == $nm_output(fred)" + set passes 0 + } + if {$nm_output(data_end) < $data_end \ || $nm_output(data_end) > 0x1010} { send_log "data_end == $nm_output(data_end)\n" @@ -126,6 +140,13 @@ if ![ld_simple_link $ld tmpdir/script "$flags -T $srcdir/$subdir/memory.t tmpdir check_script } +set testname "MEMORY with symbols" +if ![ld_simple_link $ld tmpdir/script "$flags -defsym DATA_ORIGIN=0x1000 -defsym DATA_LENGTH=0x10000 -T $srcdir/$subdir/memory_sym.t tmpdir/script.o"] { + fail $testname +} else { + check_script +} + set test_script_list [lsort [glob $srcdir/$subdir/region-alias-*.t]] foreach test_script $test_script_list { |