[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH v4 2/3] elf-ops.h: Map into memory the ELF to load
From: |
Stefano Garzarella |
Subject: |
[Qemu-devel] [PATCH v4 2/3] elf-ops.h: Map into memory the ELF to load |
Date: |
Wed, 24 Jul 2019 16:31:04 +0200 |
In order to reduce the memory footprint we map into memory
the ELF to load using g_mapped_file_new_from_fd() instead of
reading each sections. In this way we can share the ELF pages
between multiple instances of QEMU.
Suggested-by: Dr. David Alan Gilbert <address@hidden>
Suggested-by: Paolo Bonzini <address@hidden>
Signed-off-by: Stefano Garzarella <address@hidden>
---
v4:
- fix the missing of g_mapped_file_unref() in the success case [Paolo]
- fix the rom_add_elf_program() comment [Paolo]
v3:
- renamed 'GMappedFile *gmf' in 'GMappedFile *mapped_filed' for readability.
- passed the GMappedFile* to rom_add_elf_program() to correctly handle the
reference count. [Paolo]
- set 'data' pointer only if 'file_size > 0' as the original behaviour
[check-qtest-ppc64 fails without it]
v2:
- used g_mapped_file_new_from_fd() with 'writeble' set to 'true',
since we can modify the mapped buffer. [Paolo, Peter]
---
include/hw/elf_ops.h | 71 ++++++++++++++++++++++++++------------------
1 file changed, 42 insertions(+), 29 deletions(-)
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h
index fede37ee9c..1496d7e753 100644
--- a/include/hw/elf_ops.h
+++ b/include/hw/elf_ops.h
@@ -323,8 +323,9 @@ static int glue(load_elf, SZ)(const char *name, int fd,
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
int size, i, total_size;
- elf_word mem_size, file_size;
+ elf_word mem_size, file_size, data_offset;
uint64_t addr, low = (uint64_t)-1, high = 0;
+ GMappedFile *mapped_file = NULL;
uint8_t *data = NULL;
char label[128];
int ret = ELF_LOAD_FAILED;
@@ -409,20 +410,32 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
}
+ /*
+ * Since we want to be able to modify the mapped buffer, we set the
+ * 'writeble' parameter to 'true'. Modifications to the buffer are not
+ * written back to the file.
+ */
+ mapped_file = g_mapped_file_new_from_fd(fd, true, NULL);
+ if (!mapped_file) {
+ goto fail;
+ }
+
total_size = 0;
for(i = 0; i < ehdr.e_phnum; i++) {
ph = &phdr[i];
if (ph->p_type == PT_LOAD) {
mem_size = ph->p_memsz; /* Size of the ROM */
file_size = ph->p_filesz; /* Size of the allocated data */
- data = g_malloc0(file_size);
- if (ph->p_filesz > 0) {
- if (lseek(fd, ph->p_offset, SEEK_SET) < 0) {
- goto fail;
- }
- if (read(fd, data, file_size) != file_size) {
+ data_offset = ph->p_offset; /* Offset where the data is located */
+
+ if (file_size > 0) {
+ if (g_mapped_file_get_length(mapped_file) <
+ file_size + data_offset) {
goto fail;
}
+
+ data = (uint8_t *)g_mapped_file_get_contents(mapped_file);
+ data += data_offset;
}
/* The ELF spec is somewhat vague about the purpose of the
@@ -513,25 +526,25 @@ static int glue(load_elf, SZ)(const char *name, int fd,
*pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
}
- if (mem_size == 0) {
- /* Some ELF files really do have segments of zero size;
- * just ignore them rather than trying to create empty
- * ROM blobs, because the zero-length blob can falsely
- * trigger the overlapping-ROM-blobs check.
- */
- g_free(data);
- } else {
+ /* Some ELF files really do have segments of zero size;
+ * just ignore them rather than trying to create empty
+ * ROM blobs, because the zero-length blob can falsely
+ * trigger the overlapping-ROM-blobs check.
+ */
+ if (mem_size != 0) {
if (load_rom) {
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
- /* rom_add_elf_program() seize the ownership of 'data' */
- rom_add_elf_program(label, NULL, data, file_size, mem_size,
- addr, as);
+ /*
+ * rom_add_elf_program() takes its own reference to
+ * 'mapped_file'.
+ */
+ rom_add_elf_program(label, mapped_file, data, file_size,
+ mem_size, addr, as);
} else {
address_space_write(as ? as : &address_space_memory,
addr, MEMTXATTRS_UNSPECIFIED,
data, file_size);
- g_free(data);
}
}
@@ -547,14 +560,16 @@ static int glue(load_elf, SZ)(const char *name, int fd,
struct elf_note *nhdr = NULL;
file_size = ph->p_filesz; /* Size of the range of ELF notes */
- data = g_malloc0(file_size);
- if (ph->p_filesz > 0) {
- if (lseek(fd, ph->p_offset, SEEK_SET) < 0) {
- goto fail;
- }
- if (read(fd, data, file_size) != file_size) {
+ data_offset = ph->p_offset; /* Offset where the notes are located
*/
+
+ if (file_size > 0) {
+ if (g_mapped_file_get_length(mapped_file) <
+ file_size + data_offset) {
goto fail;
}
+
+ data = (uint8_t *)g_mapped_file_get_contents(mapped_file);
+ data += data_offset;
}
/*
@@ -570,19 +585,17 @@ static int glue(load_elf, SZ)(const char *name, int fd,
sizeof(struct elf_note) == sizeof(struct elf64_note);
elf_note_fn((void *)nhdr, (void *)&ph->p_align, is64);
}
- g_free(data);
data = NULL;
}
}
- g_free(phdr);
if (lowaddr)
*lowaddr = (uint64_t)(elf_sword)low;
if (highaddr)
*highaddr = (uint64_t)(elf_sword)high;
- return total_size;
+ ret = total_size;
fail:
- g_free(data);
+ g_mapped_file_unref(mapped_file);
g_free(phdr);
return ret;
}
--
2.20.1
- [Qemu-devel] [PATCH v4 0/3] pc: mmap kernel (ELF image) and initrd, Stefano Garzarella, 2019/07/24
- [Qemu-devel] [PATCH v4 1/3] loader: Handle memory-mapped ELFs, Stefano Garzarella, 2019/07/24
- [Qemu-devel] [PATCH v4 2/3] elf-ops.h: Map into memory the ELF to load,
Stefano Garzarella <=
- [Qemu-devel] [PATCH v4 3/3] hw/i386/pc: Map into memory the initrd, Stefano Garzarella, 2019/07/24
- Re: [Qemu-devel] [PATCH v4 0/3] pc: mmap kernel (ELF image) and initrd, Paolo Bonzini, 2019/07/24
- Re: [Qemu-devel] [PATCH v4 0/3] pc: mmap kernel (ELF image) and initrd, Dr. David Alan Gilbert, 2019/07/24
- Re: [Qemu-devel] [PATCH v4 0/3] pc: mmap kernel (ELF image) and initrd, Montes, Julio, 2019/07/24