diff options
author | Alan Modra <amodra@gmail.com> | 2025-01-11 16:20:36 +1030 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2025-01-20 07:13:46 +1030 |
commit | cb6326b5ceb7cfc784003c05b90b351d78c755fd (patch) | |
tree | 7f9ee6febac9179e3bbea81799c7dc5c99edffdc /bfd/elf.c | |
parent | 354ed4d4a26da57cf2a2b9b463c4262b18c48021 (diff) | |
download | gdb-cb6326b5ceb7cfc784003c05b90b351d78c755fd.zip gdb-cb6326b5ceb7cfc784003c05b90b351d78c755fd.tar.gz gdb-cb6326b5ceb7cfc784003c05b90b351d78c755fd.tar.bz2 |
sec->alloced and freeing section contents
This modifies _bfd_elf_free_cached_info to unmap/free section
contents. To do that we need to *not* free sections where contents
are bfd_alloc'd or point to constant strings or somesuch. I've chosen
to implement this be adding another flag to struct bfd_section,
"alloced" to say the section contents can't be freed. Most of the
patch is about setting that flag in many places.
Diffstat (limited to 'bfd/elf.c')
-rw-r--r-- | bfd/elf.c | 26 |
1 files changed, 24 insertions, 2 deletions
@@ -3885,6 +3885,7 @@ bfd_elf_set_group_contents (bfd *abfd, asection *sec, void *failedptrarg) *failedptr = true; return; } + sec->alloced = 1; } loc = sec->contents + sec->size; @@ -10125,6 +10126,15 @@ _bfd_elf_free_cached_info (bfd *abfd) _bfd_dwarf2_cleanup_debug_info (abfd, &tdata->dwarf2_find_line_info); _bfd_dwarf1_cleanup_debug_info (abfd, &tdata->dwarf1_find_line_info); _bfd_stab_cleanup (abfd, &tdata->line_info); + for (asection *sec = abfd->sections; sec != NULL; sec = sec->next) + { + _bfd_elf_munmap_section_contents (sec, sec->contents); + if (!sec->alloced) + { + free (elf_section_data (sec)->this_hdr.contents); + elf_section_data (sec)->this_hdr.contents = NULL; + } + } free (tdata->symtab_hdr.contents); tdata->symtab_hdr.contents = NULL; } @@ -14090,6 +14100,7 @@ _bfd_elf_write_secondary_reloc_section (bfd *abfd, asection *sec) hdr->contents = bfd_alloc (abfd, hdr->sh_size); if (hdr->contents == NULL) continue; + relsec->alloced = 1; #if DEBUG_SECONDARY_RELOCS fprintf (stderr, "write %u secondary relocs for %s from %s\n", @@ -14235,6 +14246,7 @@ elf_mmap_section_contents (bfd *abfd, sec_ptr sec, bfd_byte **buf) } } #endif + /* FIXME: We should not get here if sec->alloced is set. */ bool ret = bfd_get_full_section_contents (abfd, sec, buf); if (ret && sec->mmapped_p) *buf = sec->contents; @@ -14262,14 +14274,23 @@ _bfd_elf_link_mmap_section_contents (bfd *abfd, sec_ptr sec, /* Munmap section contents. */ void -_bfd_elf_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED, - void *contents) +_bfd_elf_munmap_section_contents (asection *sec, void *contents) { /* NB: Since _bfd_elf_munmap_section_contents is called like free, CONTENTS may be NULL. */ if (contents == NULL) return; + if (sec->alloced + /* What a tangled web we weave with section contents. + FIXME: We shouldn't need to test anything but sec->alloced + here, but there are cases where a buffer is allocated for a + section but then another buffer is malloc'd anyway. eg. + trace through ld-elf/eh4 testcase on x86_64. */ + && (sec->contents == contents + || elf_section_data (sec)->this_hdr.contents == contents)) + return; + /* Don't leave pointers to data we are about to munmap or free. */ if (sec->contents == contents) sec->contents = NULL; @@ -14314,6 +14335,7 @@ _bfd_elf_link_munmap_section_contents (asection *sec ATTRIBUTE_UNUSED) abort (); sec->mmapped_p = 0; sec->contents = NULL; + elf_section_data (sec)->this_hdr.contents = NULL; elf_section_data (sec)->contents_addr = NULL; elf_section_data (sec)->contents_size = 0; } |