mirror of https://github.com/xemu-project/xemu.git
dump: update phys_base header field based on VMCOREINFO content
If the guest note is VMCOREINFO, try to get phys_base from it. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> Reviewed-by: Michael S. Tsirkin <mst@redhat.com> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
parent
903ef73496
commit
d9feb51772
|
@ -39,3 +39,11 @@ qemu dumps.
|
||||||
|
|
||||||
The note format/class must be of the target bitness and the size must
|
The note format/class must be of the target bitness and the size must
|
||||||
be less than 1Mb.
|
be less than 1Mb.
|
||||||
|
|
||||||
|
If the ELF note name is "VMCOREINFO", it is expected to be the Linux
|
||||||
|
vmcoreinfo note (see Documentation/ABI/testing/sysfs-kernel-vmcoreinfo
|
||||||
|
in Linux source). In this case, qemu dump code will read the content
|
||||||
|
as a key=value text file, looking for "NUMBER(phys_base)" key
|
||||||
|
value. The value is expected to be more accurate than architecture
|
||||||
|
guess of the value. This is useful for KASLR-enabled guest with
|
||||||
|
ancient tools not handling the VMCOREINFO note.
|
||||||
|
|
56
dump.c
56
dump.c
|
@ -779,6 +779,23 @@ static void get_note_sizes(DumpState *s, const void *note,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool note_name_equal(DumpState *s,
|
||||||
|
const uint8_t *note, const char *name)
|
||||||
|
{
|
||||||
|
int len = strlen(name) + 1;
|
||||||
|
uint64_t head_size, name_size;
|
||||||
|
|
||||||
|
get_note_sizes(s, note, &head_size, &name_size, NULL);
|
||||||
|
head_size = ROUND_UP(head_size, 4);
|
||||||
|
|
||||||
|
if (name_size != len ||
|
||||||
|
memcmp(note + head_size, "VMCOREINFO", len)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* write common header, sub header and elf note to vmcore */
|
/* write common header, sub header and elf note to vmcore */
|
||||||
static void create_header32(DumpState *s, Error **errp)
|
static void create_header32(DumpState *s, Error **errp)
|
||||||
{
|
{
|
||||||
|
@ -1553,6 +1570,39 @@ static int64_t dump_calculate_size(DumpState *s)
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vmcoreinfo_update_phys_base(DumpState *s)
|
||||||
|
{
|
||||||
|
uint64_t size, note_head_size, name_size, phys_base;
|
||||||
|
char **lines;
|
||||||
|
uint8_t *vmci;
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (!note_name_equal(s, s->guest_note, "VMCOREINFO")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
get_note_sizes(s, s->guest_note, ¬e_head_size, &name_size, &size);
|
||||||
|
note_head_size = ROUND_UP(note_head_size, 4);
|
||||||
|
|
||||||
|
vmci = s->guest_note + note_head_size + ROUND_UP(name_size, 4);
|
||||||
|
*(vmci + size) = '\0';
|
||||||
|
|
||||||
|
lines = g_strsplit((char *)vmci, "\n", -1);
|
||||||
|
for (i = 0; lines[i]; i++) {
|
||||||
|
if (g_str_has_prefix(lines[i], "NUMBER(phys_base)=")) {
|
||||||
|
if (qemu_strtou64(lines[i] + 18, NULL, 16,
|
||||||
|
&phys_base) < 0) {
|
||||||
|
warn_report("Failed to read NUMBER(phys_base)=");
|
||||||
|
} else {
|
||||||
|
s->dump_info.phys_base = phys_base;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev(lines);
|
||||||
|
}
|
||||||
|
|
||||||
static void dump_init(DumpState *s, int fd, bool has_format,
|
static void dump_init(DumpState *s, int fd, bool has_format,
|
||||||
DumpGuestMemoryFormat format, bool paging, bool has_filter,
|
DumpGuestMemoryFormat format, bool paging, bool has_filter,
|
||||||
int64_t begin, int64_t length, Error **errp)
|
int64_t begin, int64_t length, Error **errp)
|
||||||
|
@ -1636,8 +1686,9 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The goal of this block is to copy the guest note out of
|
* The goal of this block is to (a) update the previously guessed
|
||||||
* the guest. Failure to do so is not fatal for dumping.
|
* phys_base, (b) copy the guest note out of the guest.
|
||||||
|
* Failure to do so is not fatal for dumping.
|
||||||
*/
|
*/
|
||||||
if (vmci) {
|
if (vmci) {
|
||||||
uint64_t addr, note_head_size, name_size, desc_size;
|
uint64_t addr, note_head_size, name_size, desc_size;
|
||||||
|
@ -1670,6 +1721,7 @@ static void dump_init(DumpState *s, int fd, bool has_format,
|
||||||
g_free(s->guest_note);
|
g_free(s->guest_note);
|
||||||
s->guest_note = NULL;
|
s->guest_note = NULL;
|
||||||
} else {
|
} else {
|
||||||
|
vmcoreinfo_update_phys_base(s);
|
||||||
s->note_size += s->guest_note_size;
|
s->note_size += s->guest_note_size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue