diff options
author | Stephen Webb <swebb@blackberry.com> | 2022-07-23 22:30:23 -0400 |
---|---|---|
committer | Stephen M. Webb <stephen.webb@bregmasoft.ca> | 2022-07-26 21:44:26 -0400 |
commit | e96db56e586ad7a1c8d27593382b365f775a398f (patch) | |
tree | ab6bcc10a8504204d1f52b379d2ddc7cb1efb1ff /src/coredump/_UCD_elf_map_image.c | |
parent | 10e093db21b73e98ba8485b4b0696d330bf8dfdf (diff) | |
download | libunwind-e96db56e586ad7a1c8d27593382b365f775a398f.tar.gz |
Stop assuming .text and .eh_frame segment
The coredump remote was architected on the assumption that the .text and
.eh_frame sections were mapped onto the same segment, and that that segment was
always the first PT_LOAD segment in an ELF file. Well, that was never a valid
assumption, and moderns releases of various toolchains have started splitting
the PT_LOAD segments for security reasons.
This change implements an M:N mapping of PT_LOAD segments in a coredump file to
backing ELF files and calculates and adjusts offsets appropriately. Because the
backing files get mapped in a lot of file I/O operations have been replaced with
simple memory reads. Once a backing file is memory mapped is stays mapped until
the address space is destroyed.
The ucd_*.[ch] files contain only functions that should not be exposed through
the public API so they;re not mangled using the UB naming schedule because I
just bring myself to write code with undefined behaviour.
Reformatted some of the changed files using `astyle --style=gnu` for internal
consistency withing the file.
Fixes #363
Diffstat (limited to 'src/coredump/_UCD_elf_map_image.c')
-rw-r--r-- | src/coredump/_UCD_elf_map_image.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/src/coredump/_UCD_elf_map_image.c b/src/coredump/_UCD_elf_map_image.c index 99fd25e8..ea36745a 100644 --- a/src/coredump/_UCD_elf_map_image.c +++ b/src/coredump/_UCD_elf_map_image.c @@ -29,13 +29,14 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "_UCD_lib.h" #include "_UCD_internal.h" +#include "ucd_file_table.h" static coredump_phdr_t * CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) { struct elf_image *ei = &ui->edi.ei; - if (phdr->backing_fd < 0) + if (phdr->p_backing_file_index == ucd_file_no_index) { /* Note: coredump file contains only phdr->p_filesz bytes. * We want to map bigger area (phdr->p_memsz bytes) to make sure @@ -45,6 +46,7 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) ei->image = mmap(NULL, phdr->p_memsz, PROT_READ, MAP_PRIVATE, ui->coredump_fd, phdr->p_offset); if (ei->image == MAP_FAILED) { + Debug(0, "error %d in mmap(): %s\n", errno, strerror(errno)); ei->image = NULL; return NULL; } @@ -56,21 +58,19 @@ CD_elf_map_image(struct UCD_info *ui, coredump_phdr_t *phdr) munmap(remainder_base, remainder_len); } } else { - /* We have a backing file for this segment. - * This file is always longer than phdr->p_memsz, - * and if phdr->p_filesz !=0, first phdr->p_filesz bytes in coredump - * are the same as first bytes in the file. (Thus no need to map coredump) - * We map the entire file: - * unwinding may need data which is past phdr->p_memsz bytes. - */ + ucd_file_t *ucd_file = ucd_file_table_at(&ui->ucd_file_table, phdr->p_backing_file_index); + if (ucd_file == NULL) + { + Debug(0, "error retrieving backing file for index %d\n", phdr->p_backing_file_index); + return NULL; + } /* addr, length, prot, flags, fd, fd_offset */ - ei->image = mmap(NULL, phdr->backing_filesize, PROT_READ, MAP_PRIVATE, phdr->backing_fd, 0); - if (ei->image == MAP_FAILED) + ei->image = ucd_file_map (ucd_file); + if (ei->image == NULL) { - ei->image = NULL; return NULL; } - ei->size = phdr->backing_filesize; + ei->size = ucd_file->size; } /* Check ELF header for sanity */ |