summaryrefslogtreecommitdiff
path: root/src/coredump/_UCD_access_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/coredump/_UCD_access_mem.c')
-rw-r--r--src/coredump/_UCD_access_mem.c109
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;
}