diff options
Diffstat (limited to 'bfd')
-rw-r--r-- | bfd/ChangeLog | 6 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 38 |
2 files changed, 44 insertions, 0 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index b8eced6..5a1cbd3 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,9 @@ +2006-10-20 Richard Sandiford <richard@codesourcery.com> + + * elfxx-mips.c (_bfd_mips_elf_additional_program_headers): Allocate + a PT_NULL header for dynamic objects. + (_bfd_mips_elf_modify_segment_map): Add it. + 2006-10-19 Mei Ligang <ligang@sunnorth.com.cn> * elf32-score.c (score_elf_rel_dyn_section): Replace diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index 33b0e43..639a065 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -9169,6 +9169,12 @@ _bfd_mips_elf_additional_program_headers (bfd *abfd, && bfd_get_section_by_name (abfd, ".mdebug")) ++ret; + /* Allocate a PT_NULL header in dynamic objects. See + _bfd_mips_elf_modify_segment_map for details. */ + if (!SGI_COMPAT (abfd) + && bfd_get_section_by_name (abfd, ".dynamic")) + ++ret; + return ret; } @@ -9377,6 +9383,38 @@ _bfd_mips_elf_modify_segment_map (bfd *abfd, } } + /* Allocate a spare program header in dynamic objects so that tools + like the prelinker can add an extra PT_LOAD entry. + + If the prelinker needs to make room for a new PT_LOAD entry, its + standard procedure is to move the first (read-only) sections into + the new (writable) segment. However, the MIPS ABI requires + .dynamic to be in a read-only segment, and the section will often + start within sizeof (ElfNN_Phdr) bytes of the last program header. + + Although the prelinker could in principle move .dynamic to a + writable segment, it seems better to allocate a spare program + header instead, and avoid the need to move any sections. + There is a long tradition of allocating spare dynamic tags, + so allocating a spare program header seems like a natural + extension. */ + if (!SGI_COMPAT (abfd) + && bfd_get_section_by_name (abfd, ".dynamic")) + { + for (pm = &elf_tdata (abfd)->segment_map; *pm != NULL; pm = &(*pm)->next) + if ((*pm)->p_type == PT_NULL) + break; + if (*pm == NULL) + { + m = bfd_zalloc (abfd, sizeof (*m)); + if (m == NULL) + return FALSE; + + m->p_type = PT_NULL; + *pm = m; + } + } + return TRUE; } |