diff --git a/ld/ChangeLog b/ld/ChangeLog index 5993a1aafa..250435eed7 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,4 +1,31 @@ +Fri Jan 2 20:15:37 1998 Michael Meissner + + * ldgram.y (attributes_opt): Pass region pointer to + lang_set_flags, not ®ion->flags. + + * ldlang.c (lang_memory_default): New function to figure out a + default memory region for a section if it was not specified. + (lang_memory_region_lookup): Zero flags, not_flags field. + (lang_map{,_flags}): Print attribute flags in memory map. + (lang_size_sections): Call lang_memory_default to get default + memory region. + (lang_set_flags): Implement attribute flags for real. Take new + argument to give the flags we are to skip for this region. + + * ldlang.h (memory_region_struct): Add not_flags field, make both + flags fields flagword type. + (lang_output_section_state): Make flags field flagword type. + (lang_set_flags): Update prototype to match new calling sequence. + (lang_memory_region_default): Add prototype. + start-sanitize-d30v + * emulparams/d30v{_e,_o,elf}.sh ({TEXT,DATA,EMEM}_DEF_SECTION): + Define whether or not the region gets default sections, and if so, + what sections. + + * scripttempl/elfd30v.sc (MEMORY): Set up which of the regions get + default sections. + Thu Jan 1 22:58:04 1998 Michael Meissner * scripttempl/elfd30v.sc (.eh_frame): Link into the data section. diff --git a/ld/emulparams/d30v_e.sh b/ld/emulparams/d30v_e.sh new file mode 100644 index 0000000000..193d36ab15 --- /dev/null +++ b/ld/emulparams/d30v_e.sh @@ -0,0 +1,18 @@ +MACHINE= +SCRIPT_NAME=elfd30v +OUTPUT_FORMAT="elf32-d30v" +TEXT_START_ADDR=0x00000000 +DATA_START_ADDR=0x20000000 +EMEM_START_ADDR=0x80000000 +STACK_START_ADDR=0x20008000 +TEXT_SIZE=64K +DATA_SIZE=32K +EMEM_SIZE=8M +TEXT_MEMORY=emem +DATA_MEMORY=emem +BSS_MEMORY=emem +TEXT_DEF_SECTION="" +DATA_DEF_SECTION="" +EMEM_DEF_SECTION="(rwx)" +ARCH=d30v +EMBEDDED=t diff --git a/ld/emulparams/d30v_o.sh b/ld/emulparams/d30v_o.sh new file mode 100644 index 0000000000..038621c3d3 --- /dev/null +++ b/ld/emulparams/d30v_o.sh @@ -0,0 +1,18 @@ +MACHINE= +SCRIPT_NAME=elfd30v +OUTPUT_FORMAT="elf32-d30v" +TEXT_START_ADDR=0x00000000 +DATA_START_ADDR=0x20000000 +EMEM_START_ADDR=0x80000000 +STACK_START_ADDR=0x20008000 +TEXT_SIZE=64K +DATA_SIZE=32K +EMEM_SIZE=8M +TEXT_MEMORY=text +DATA_MEMORY=data +BSS_MEMORY=data +TEXT_DEF_SECTION="(x)" +DATA_DEF_SECTION="(rw)" +EMEM_DEF_SECTION="" +ARCH=d30v +EMBEDDED=t diff --git a/ld/emulparams/d30velf.sh b/ld/emulparams/d30velf.sh new file mode 100644 index 0000000000..038621c3d3 --- /dev/null +++ b/ld/emulparams/d30velf.sh @@ -0,0 +1,18 @@ +MACHINE= +SCRIPT_NAME=elfd30v +OUTPUT_FORMAT="elf32-d30v" +TEXT_START_ADDR=0x00000000 +DATA_START_ADDR=0x20000000 +EMEM_START_ADDR=0x80000000 +STACK_START_ADDR=0x20008000 +TEXT_SIZE=64K +DATA_SIZE=32K +EMEM_SIZE=8M +TEXT_MEMORY=text +DATA_MEMORY=data +BSS_MEMORY=data +TEXT_DEF_SECTION="(x)" +DATA_DEF_SECTION="(rw)" +EMEM_DEF_SECTION="" +ARCH=d30v +EMBEDDED=t diff --git a/ld/ldlang.c b/ld/ldlang.c index b66efbb723..b364f9dea0 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -128,6 +128,7 @@ static bfd_vma size_input_section lang_output_section_statement_type *output_section_statement, fill_type fill, bfd_vma dot, boolean relax)); static void lang_finish PARAMS ((void)); +static void ignore_bfd_errors PARAMS ((const char *, ...)); static void lang_check PARAMS ((void)); static void lang_common PARAMS ((void)); static boolean lang_one_common PARAMS ((struct bfd_link_hash_entry *, PTR)); @@ -412,7 +413,6 @@ lang_memory_region_type * lang_memory_region_lookup (name) CONST char *CONST name; { - lang_memory_region_type *p; for (p = lang_memory_region_list; @@ -451,6 +451,8 @@ lang_memory_region_lookup (name) *lang_memory_region_list_tail = new; lang_memory_region_list_tail = &new->next; new->origin = 0; + new->flags = 0; + new->not_flags = 0; new->length = ~(bfd_size_type)0; new->current = 0; new->had_full_message = false; @@ -460,6 +462,31 @@ lang_memory_region_lookup (name) } +lang_memory_region_type * +lang_memory_default (section) + asection *section; +{ + lang_memory_region_type *p; + + flagword sec_flags = section->flags; + + /* Override SEC_DATA to mean a writable section. */ + if (sec_flags & (SEC_ALLOC | SEC_READONLY | SEC_CODE) == SEC_ALLOC) + sec_flags |= SEC_DATA; + + for (p = lang_memory_region_list; + p != (lang_memory_region_type *) NULL; + p = p->next) + { + if ((p->flags & sec_flags) != 0 + && (p->not_flags & sec_flags) == 0) + { + return p; + } + } + return lang_memory_region_lookup ("*default*"); +} + lang_output_section_statement_type * lang_output_section_find (name) CONST char *CONST name; @@ -518,14 +545,34 @@ lang_output_section_statement_lookup (name) return lookup; } +static void +lang_map_flags (flag) + flagword flag; +{ + if (flag & SEC_ALLOC) + minfo ("a"); + + if (flag & SEC_CODE) + minfo ("x"); + + if (flag & SEC_READONLY) + minfo ("r"); + + if (flag & SEC_DATA) + minfo ("w"); + + if (flag & SEC_LOAD) + minfo ("l"); +} + void lang_map () { lang_memory_region_type *m; minfo ("\nMemory Configuration\n\n"); - fprintf (config.map_file, "%-16s %-18s %-18s\n", - "Name", "Origin", "Length"); + fprintf (config.map_file, "%-16s %-18s %-18s %s\n", + "Name", "Origin", "Length", "Attributes"); for (m = lang_memory_region_list; m != (lang_memory_region_type *) NULL; @@ -545,7 +592,26 @@ lang_map () ++len; } - minfo ("0x%V\n", m->length); + minfo ("0x%V", m->length); + if (m->flags || m->not_flags) + { +#ifndef BFD64 + minfo (" "); +#endif + if (m->flags) + { + print_space (); + lang_map_flags (m->flags); + } + + if (m->not_flags) + { + minfo (" !"); + lang_map_flags (m->not_flags); + } + } + + print_nl (); } fprintf (config.map_file, "\nLinker script and memory map\n\n"); @@ -2101,7 +2167,7 @@ lang_size_sections (s, output_section_statement, prev, fill, dot, relax) */ if (os->region == (lang_memory_region_type *) NULL) { - os->region = lang_memory_region_lookup ("*default*"); + os->region = lang_memory_default (os->bfd_section); } dot = os->region->current; if (os->section_alignment == -1) @@ -2630,6 +2696,20 @@ lang_finish () } } +/* This is a small function used when we want to ignore errors from + BFD. */ + +static void +#ifdef ANSI_PROTOTYPES +ignore_bfd_errors (const char *s, ...) +#else +ignore_bfd_errors (s) + const char *s; +#endif +{ + /* Don't do anything. */ +} + /* Check that the architecture of all the input files is compatible with the output file. Also call the backend to let it do any other checking that is needed. */ @@ -2649,13 +2729,31 @@ lang_check () compatible = bfd_arch_get_compatible (input_bfd, output_bfd); if (compatible == NULL) - einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n", - bfd_printable_name (input_bfd), input_bfd, - bfd_printable_name (output_bfd)); - - else if (! bfd_merge_private_bfd_data (input_bfd, output_bfd)) { - einfo ("%E%X: failed to merge target specific data of file %B\n", input_bfd); + if (command_line.warn_mismatch) + einfo ("%P: warning: %s architecture of input file `%B' is incompatible with %s output\n", + bfd_printable_name (input_bfd), input_bfd, + bfd_printable_name (output_bfd)); + } + else + { + bfd_error_handler_type pfn; + + /* If we aren't supposed to warn about mismatched input + files, temporarily set the BFD error handler to a + function which will do nothing. We still want to call + bfd_merge_private_bfd_data, since it may set up + information which is needed in the output file. */ + if (! command_line.warn_mismatch) + pfn = bfd_set_error_handler (ignore_bfd_errors); + if (! bfd_merge_private_bfd_data (input_bfd, output_bfd)) + { + if (command_line.warn_mismatch) + einfo ("%E%X: failed to merge target specific data of file %B\n", + input_bfd); + } + if (! command_line.warn_mismatch) + bfd_set_error_handler (pfn); } } } @@ -2853,36 +2951,41 @@ lang_place_orphans () void lang_set_flags (ptr, flags) - int *ptr; + lang_memory_region_type *ptr; CONST char *flags; { - boolean state = false; + flagword *ptr_flags = &ptr->flags; - *ptr = 0; + ptr->flags = ptr->not_flags = 0; while (*flags) { - if (*flags == '!') - { - state = false; - flags++; - } - else - state = true; switch (*flags) { - case 'R': - /* ptr->flag_read = state; */ + case '!': + ptr_flags = (ptr_flags == &ptr->flags) ? &ptr->not_flags : &ptr->flags; break; - case 'W': - /* ptr->flag_write = state; */ + + case 'A': case 'a': + *ptr_flags |= SEC_ALLOC; break; - case 'X': - /* ptr->flag_executable= state;*/ + + case 'R': case 'r': + *ptr_flags |= SEC_READONLY; break; - case 'L': - case 'I': - /* ptr->flag_loadable= state;*/ + + case 'W': case 'w': + *ptr_flags |= SEC_DATA; break; + + case 'X': case 'x': + *ptr_flags |= SEC_CODE; + break; + + case 'L': case 'l': + case 'I': case 'i': + *ptr_flags |= SEC_LOAD; + break; + default: einfo ("%P%F: invalid syntax in flags\n"); break;