summaryrefslogtreecommitdiff
path: root/src/coredump/_UCD_elf_map_image.c
diff options
context:
space:
mode:
authorStephen Webb <swebb@blackberry.com>2022-07-23 22:30:23 -0400
committerStephen M. Webb <stephen.webb@bregmasoft.ca>2022-07-26 21:44:26 -0400
commite96db56e586ad7a1c8d27593382b365f775a398f (patch)
treeab6bcc10a8504204d1f52b379d2ddc7cb1efb1ff /src/coredump/_UCD_elf_map_image.c
parent10e093db21b73e98ba8485b4b0696d330bf8dfdf (diff)
downloadlibunwind-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.c24
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 */