diff options
-rw-r--r-- | ld/ChangeLog | 8 | ||||
-rw-r--r-- | ld/emultempl/pe.em | 123 | ||||
-rw-r--r-- | ld/pe-dll.c | 4 |
3 files changed, 99 insertions, 36 deletions
diff --git a/ld/ChangeLog b/ld/ChangeLog index 4a7494a..e9bb45d 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,11 @@ +2001-08-20 Alan Modra <amodra@bigpond.net.au> + + * pe-dll.c (pe_dll_fill_sections): Correct type of "relax" param + passed to lang_size_sections. + (pe_exe_fill_sections): Likewise. + * emultempl/pe.em (output_prev_sec_find): Copied from elf32.em. + (gld_${EMULATION_NAME}_place_orphan): Merge from elf32.em. + 2001-08-18 Alan Modra <amodra@bigpond.net.au> * emultempl/aix.em: Formatting fixes. diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em index 6519eae..fce661e 100644 --- a/ld/emultempl/pe.em +++ b/ld/emultempl/pe.em @@ -108,6 +108,8 @@ static void gld_${EMULATION_NAME}_after_open PARAMS ((void)); static void gld_${EMULATION_NAME}_before_parse PARAMS ((void)); static void gld_${EMULATION_NAME}_after_parse PARAMS ((void)); static void gld_${EMULATION_NAME}_before_allocation PARAMS ((void)); +static asection *output_prev_sec_find + PARAMS ((lang_output_section_statement_type *)); static boolean gld_${EMULATION_NAME}_place_orphan PARAMS ((lang_input_statement_type *, asection *)); static char *gld_${EMULATION_NAME}_get_script PARAMS ((int *)); @@ -1405,6 +1407,32 @@ gld_${EMULATION_NAME}_finish () } +/* Find the last output section before given output statement. + Used by place_orphan. */ + +static asection * +output_prev_sec_find (os) + lang_output_section_statement_type *os; +{ + asection *s = (asection *) NULL; + lang_statement_union_type *u; + lang_output_section_statement_type *lookup; + + for (u = lang_output_section_statement.head; + u != (lang_statement_union_type *) NULL; + u = lookup->next) + { + lookup = &u->output_section_statement; + if (lookup == os) + return s; + + if (lookup->bfd_section != NULL && lookup->bfd_section->owner != NULL) + s = lookup->bfd_section; + } + + return NULL; +} + /* Place an orphan section. We use this to put sections in a reasonable place in the file, and @@ -1455,9 +1483,12 @@ gld_${EMULATION_NAME}_place_orphan (file, s) lang_list_init (&add_child); if (os != NULL - && os->bfd_section != NULL - && ((s->flags ^ os->bfd_section->flags) & (SEC_LOAD | SEC_ALLOC)) == 0) + && (os->bfd_section == NULL + || ((s->flags ^ os->bfd_section->flags) + & (SEC_LOAD | SEC_ALLOC)) == 0)) { + /* We already have an output section statement with this + name, and its bfd section, if any, has compatible flags. */ lang_add_section (&add_child, s, os, file); } else @@ -1498,7 +1529,7 @@ gld_${EMULATION_NAME}_place_orphan (file, s) /* Choose a unique name for the section. This will be needed if the same section name appears in the input file with - different loadable or allocateable characteristics. */ + different loadable or allocatable characteristics. */ outsecname = xstrdup (hold_section_name); if (bfd_get_section_by_name (output_bfd, outsecname) != NULL) { @@ -1590,28 +1621,30 @@ gld_${EMULATION_NAME}_place_orphan (file, s) asection *snew, **pps; snew = os->bfd_section; - if (place->os->bfd_section != NULL || place->section != NULL) + + /* Shuffle the bfd section list to make the output file look + neater. This is really only cosmetic. */ + if (place->section == NULL) { - /* Shuffle the section to make the output file look neater. */ - if (place->section == NULL) - { -#if 0 - /* Finding the end of the list is a little tricky. We - make a wild stab at it by comparing section flags. */ - flagword first_flags = place->os->bfd_section->flags; - for (pps = &place->os->bfd_section->next; - *pps != NULL && (*pps)->flags == first_flags; - pps = &(*pps)->next) - ; - place->section = pps; -#else - /* Put orphans after the first section on the list. */ - place->section = &place->os->bfd_section->next; -#endif - } + asection *bfd_section = place->os->bfd_section; + + /* If the output statement hasn't been used to place + any input sections (and thus doesn't have an output + bfd_section), look for the closest prior output statement + having an output section. */ + if (bfd_section == NULL) + bfd_section = output_prev_sec_find (place->os); + + if (bfd_section != NULL && bfd_section != snew) + place->section = &bfd_section->next; + } + if (place->section != NULL) + { /* Unlink the section. */ - for (pps = &output_bfd->sections; *pps != snew; pps = &(*pps)->next) + for (pps = &output_bfd->sections; + *pps != snew; + pps = &(*pps)->next) ; *pps = snew->next; @@ -1619,21 +1652,43 @@ gld_${EMULATION_NAME}_place_orphan (file, s) snew->next = *place->section; *place->section = snew; } - place->section = &snew->next; /* Save the end of this list. */ - if (place->stmt == NULL) - { - /* Put the new statement list right at the head. */ - *add.tail = place->os->header.next; - place->os->header.next = add.head; - } - else + /* Save the end of this list. Further ophans of this type will + follow the one we've just added. */ + place->section = &snew->next; + + /* The following is non-cosmetic. We try to put the output + statements in some sort of reasonable order here, because + they determine the final load addresses of the orphan + sections. In addition, placing output statements in the + wrong order may require extra segments. For instance, + given a typical situation of all read-only sections placed + in one segment and following that a segment containing all + the read-write sections, we wouldn't want to place an orphan + read/write section before or amongst the read-only ones. */ + if (add.head != NULL) { - /* Put it after the last orphan statement we added. */ - *add.tail = *place->stmt; - *place->stmt = add.head; + if (place->stmt == NULL) + { + /* Put the new statement list right at the head. */ + *add.tail = place->os->header.next; + place->os->header.next = add.head; + } + else + { + /* Put it after the last orphan statement we added. */ + *add.tail = *place->stmt; + *place->stmt = add.head; + } + + /* Fix the global list pointer if we happened to tack our + new list at the tail. */ + if (*old->tail == add.head) + old->tail = add.tail; + + /* Save the end of this list. */ + place->stmt = add.tail; } - place->stmt = add.tail; /* Save the end of this list. */ } } diff --git a/ld/pe-dll.c b/ld/pe-dll.c index 1c9cb78..8bbd8fd 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -2361,7 +2361,7 @@ pe_dll_fill_sections (abfd, info) /* Resize the sections. */ lang_size_sections (stat_ptr->head, abs_output_section, - &stat_ptr->head, 0, (bfd_vma) 0, false); + &stat_ptr->head, 0, (bfd_vma) 0, NULL); /* Redo special stuff. */ ldemul_after_allocation (); @@ -2395,7 +2395,7 @@ pe_exe_fill_sections (abfd, info) /* Resize the sections. */ lang_size_sections (stat_ptr->head, abs_output_section, - &stat_ptr->head, 0, (bfd_vma) 0, false); + &stat_ptr->head, 0, (bfd_vma) 0, NULL); /* Redo special stuff. */ ldemul_after_allocation (); |