diff options
Diffstat (limited to 'src/coredump/_UCD_access_mem.c')
-rw-r--r-- | src/coredump/_UCD_access_mem.c | 109 |
1 files changed, 58 insertions, 51 deletions
diff --git a/src/coredump/_UCD_access_mem.c b/src/coredump/_UCD_access_mem.c index 1fdbd128..cdfc6220 100644 --- a/src/coredump/_UCD_access_mem.c +++ b/src/coredump/_UCD_access_mem.c @@ -23,76 +23,83 @@ 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" int -_UCD_access_mem(unw_addr_space_t as, unw_word_t addr, unw_word_t *val, - int write, void *arg) +_UCD_access_mem (unw_addr_space_t as, + unw_word_t addr, + unw_word_t *val, + int write, + void *arg) { if (write) { - Debug(0, "write is not supported\n"); + Debug (0, "write is not supported\n"); return -UNW_EINVAL; } struct UCD_info *ui = arg; - unw_word_t addr_last = addr + sizeof(*val)-1; - coredump_phdr_t *phdr; + unw_word_t addr_last = addr + sizeof (*val) - 1; + unsigned i; + for (i = 0; i < ui->phdrs_count; i++) { - phdr = &ui->phdrs[i]; - if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) + coredump_phdr_t *phdr = &ui->phdrs[i]; + + /* First check the (in-memory) backup file image. */ + if (phdr->p_backing_file_index != ucd_file_no_index) { - goto found; - } - } - Debug(1, "addr 0x%llx is unmapped\n", (unsigned long long)addr); - return -UNW_EINVAL; + ucd_file_t *ucd_file = ucd_file_table_at (&ui->ucd_file_table, phdr->p_backing_file_index); - found: ; + if (ucd_file == NULL) + { + Debug (0, "invalid backing file index for phdr[%d]\n", i); + return -UNW_EINVAL; + } - const char *filename UNUSED; - off_t fileofs; - int fd; - if (addr_last >= phdr->p_vaddr + phdr->p_filesz) - { - /* This part of mapped address space is not present in coredump file */ - /* Do we have it in the backup file? */ - if (phdr->backing_fd < 0) + off_t image_offset = addr - phdr->p_vaddr; + + if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + ucd_file->size) + { + memcpy (val, ucd_file->image + image_offset, sizeof (*val)); + Debug (16, "%#010llx <- [addr:%#010llx file:%s]\n", + (unsigned long long) (*val), + (unsigned long long)image_offset, + ucd_file->filename); + return UNW_ESUCCESS; + } + } + + /* Next, check the on-disk corefile. */ + if (phdr->p_vaddr <= addr && addr_last < phdr->p_vaddr + phdr->p_memsz) { - Debug(1, "access to not-present data in phdr[%d]: addr:0x%llx\n", - i, (unsigned long long)addr - ); - return -UNW_EINVAL; + off_t fileofs = phdr->p_offset + (addr - phdr->p_vaddr); + + if (lseek (ui->coredump_fd, fileofs, SEEK_SET) != fileofs) + { + Debug (0, "error %d in lseek(\"%s\", %lld): %s\n", + errno, ui->coredump_filename, (long long)fileofs, strerror (errno)); + return -UNW_EINVAL; + } + + if (read (ui->coredump_fd, val, sizeof (*val)) != sizeof (*val)) + { + Debug (0, "error %d in read(\"%s\", %lld): %s\n", + errno, ui->coredump_filename, (long long)sizeof (*val), strerror (errno)); + return -UNW_EINVAL; + } + + Debug (16, "0x%llx <- [addr:0x%llx fileofs:0x%llx file:%s]\n", + (unsigned long long) (*val), + (unsigned long long)addr, + (unsigned long long)fileofs, + ui->coredump_filename); + return UNW_ESUCCESS; } - filename = phdr->backing_filename; - fileofs = addr - phdr->p_vaddr; - fd = phdr->backing_fd; - goto read; } - filename = ui->coredump_filename; - fileofs = phdr->p_offset + (addr - phdr->p_vaddr); - fd = ui->coredump_fd; - read: - if (lseek(fd, fileofs, SEEK_SET) != fileofs) - goto read_error; - if (read(fd, val, sizeof(*val)) != sizeof(*val)) - goto read_error; - - Debug(1, "0x%llx <- [addr:0x%llx fileofs:0x%llx]\n", - (unsigned long long)(*val), - (unsigned long long)addr, - (unsigned long long)fileofs - ); - return 0; - - read_error: - Debug(1, "access out of file: addr:0x%llx fileofs:%llx file:'%s'\n", - (unsigned long long)addr, - (unsigned long long)fileofs, - filename - ); + Debug (0, "addr %#010llx is unmapped\n", (unsigned long long)addr); return -UNW_EINVAL; } |