This patch adds support for adding NT_FILE note in the ELF coredump. It follows what's defined in readelf. Let me know if there is any issue with the patch. The patch is attached in plaintext below
Thanks, Kyle --------- >From 3c42074f9e99e6b5ca840b9ee9e965fb69122ef1 Mon Sep 17 00:00:00 2001 From: Kyle ZENG <jkjh1jk...@gmail.com> Date: Mon, 11 Jan 2021 21:54:09 -0700 Subject: [PATCH] add NT_FILE note for ELF core dump Signed-off-by: Kyle ZENG <jkjh1jk...@gmail.com> --- include/elf.h | 1 + linux-user/elfload.c | 92 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/include/elf.h b/include/elf.h index 7a418ee..f701fd9 100644 --- a/include/elf.h +++ b/include/elf.h @@ -1645,6 +1645,7 @@ typedef struct elf64_shdr { #define NT_TASKSTRUCT 4 #define NT_AUXV 6 #define NT_PRXFPREG 0x46e62b7f /* copied from gdb5.1/include/elf/common.h */ +#define NT_FILE 0x46494c45 /* copied from gdb/include/elf/common.h */ #define NT_S390_GS_CB 0x30b /* s390 guarded storage registers */ #define NT_S390_VXRS_HIGH 0x30a /* s390 vector registers 16-31 */ #define NT_S390_VXRS_LOW 0x309 /* s390 vector registers 0-15 (lower half) */ diff --git a/linux-user/elfload.c b/linux-user/elfload.c index a640507..c095c0c 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -3317,6 +3317,13 @@ struct target_elf_prpsinfo { char pr_psargs[ELF_PRARGSZ]; /* initial part of arg list */ }; +struct target_ntfile_entry { + abi_ulong vm_start; + abi_ulong vm_end; + abi_ulong page_offset; + char *path; +}; + /* Here is the structure in which status of each thread is captured. */ struct elf_thread_status { QTAILQ_ENTRY(elf_thread_status) ets_link; @@ -3677,6 +3684,84 @@ static void fill_auxv_note(struct memelfnote *note, const TaskState *ts) } } +static void fill_ntfile_note(struct memelfnote *note, TaskState *ts) +{ + GSList *map_info = read_self_maps(); + GSList *s; + int count = 0; + int data_size = sizeof(abi_long)*2; // reserve space for num_map_entry and page_size + struct target_ntfile_entry *entries = NULL; + + // grab memory mapping first + for (s = map_info; s; s = g_slist_next(s)) { + MapInfo *e = (MapInfo *) s->data; + + if (h2g_valid(e->start)) { + unsigned long min = e->start; + unsigned long max = e->end; + int flags = page_get_flags(h2g(min)); + const char *path; + + max = h2g_valid(max - 1) ? + max : (uintptr_t) g2h(GUEST_ADDR_MAX) + 1; + + if (page_check_range(h2g(min), max - min, flags) == -1) { + continue; + } + + if (h2g(min) == ts->info->stack_limit) { + path = "[stack]"; + } else { + path = e->path; + } + + count++; + entries = realloc(entries, sizeof(struct target_ntfile_entry)*count); + struct target_ntfile_entry *entry = &entries[count-1]; + memset(entry, 0, sizeof(*entry)); + + data_size += sizeof(abi_long)*3 + strlen(path) + 1; + entry->vm_start = h2g(min); + entry->vm_end = h2g(max - 1) + 1; + entry->page_offset = e->offset; + entry->path = strdup(path); + } + } + + // prepare the memory mapping in NT_FILE format + char *ptr; + int idx = 0; + ptr = (char *)g_malloc0(data_size); + abi_long *long_ptr = (abi_long *)ptr; + + // memory mappings + long_ptr[idx++] = count; // number of map entries + long_ptr[idx++] = TARGET_PAGE_SIZE; // target page size + for(int i=0; i<count; i++) { + struct target_ntfile_entry *entry = &entries[i]; + long_ptr[idx++] = entry->vm_start; + long_ptr[idx++] = entry->vm_end; + long_ptr[idx++] = entry->page_offset; + } + + // path names + idx *= sizeof(abi_long); + for(int i=0; i<count; i++) { + struct target_ntfile_entry *entry = &entries[i]; + int path_size = strlen(entry->path); + strcpy(&ptr[idx], entry->path); + idx += path_size + 1; + free(entry->path); + } + + // write it out + fill_note(note, "CORE", NT_FILE, data_size, ptr); + + // cleanup + free(entries); + free_self_maps(map_info); +} + /* * Constructs name of coredump file. We have following convention * for the name: @@ -3807,7 +3892,7 @@ static void init_note_info(struct elf_note_info *info) static int fill_note_info(struct elf_note_info *info, long signr, const CPUArchState *env) { -#define NUMNOTES 3 +#define NUMNOTES 4 CPUState *cpu = env_cpu((CPUArchState *)env); TaskState *ts = (TaskState *)cpu->opaque; int i; @@ -3824,7 +3909,7 @@ static int fill_note_info(struct elf_note_info *info, /* * First fill in status (and registers) of current thread - * including process info & aux vector. + * including process info, aux vector & memory mapping. */ fill_prstatus(info->prstatus, ts, signr); elf_core_copy_regs(&info->prstatus->pr_reg, env); @@ -3834,7 +3919,8 @@ static int fill_note_info(struct elf_note_info *info, fill_note(&info->notes[1], "CORE", NT_PRPSINFO, sizeof (*info->psinfo), info->psinfo); fill_auxv_note(&info->notes[2], ts); - info->numnote = 3; + fill_ntfile_note(&info->notes[3], ts); + info->numnote = NUMNOTES; info->notes_size = 0; for (i = 0; i < info->numnote; i++) -- 2.17.1