Various fixes:
- add .github repo lockdown config - better handle missing symbols in elf-ops - protect fcntl64 with #ifdef - remove unused macros from test - fix handling of /proc/self/maps - avoid BAD_SHIFT in x80 softfloat - properly terminate on .hex EOF - fix configure probe on windows cross build - fix %r12 guest_base initialization -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl6MnMIACgkQ+9DbCVqe KkQmYQf9EvffSO3rsazTR4fairuzKipnLaQor9LuwusV5CbESwC9BQiUt3G5Q/Ue cvBI9Lvwp0v2q0F/nLgRiomI+ZyOgxBNElAmX5YBiO9sKn+O/lIUSbEJvuglEl2F 4sfnwLH3tXsIe+7N5R/NSS4VkOpMebIRBHQUNHZgg00KJuhRrK8Ikl/XW7RiqHrM bK2BmxgWRtx63JDGZDKVSsDIkY8dhCmlWIDyXaspaYUrU7kAoxoD6YwM4armIYat TkYeZxEAXRn5e9ln/hXg4sUd348Hhw4arCHqsOplPk8BQ9psw98o/TuHnvJ1CX1q G1Ci9LcGBhvaz8yoImzhiczykwCiiw== =PXy6 -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-misc-fixes-070420-1' into staging Various fixes: - add .github repo lockdown config - better handle missing symbols in elf-ops - protect fcntl64 with #ifdef - remove unused macros from test - fix handling of /proc/self/maps - avoid BAD_SHIFT in x80 softfloat - properly terminate on .hex EOF - fix configure probe on windows cross build - fix %r12 guest_base initialization # gpg: Signature made Tue 07 Apr 2020 16:31:14 BST # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-misc-fixes-070420-1: tcg/i386: Fix %r12 guest_base initialization configure: Add -Werror to PIE probe hw/core: properly terminate loading .hex on EOF record linux-user: clean-up padding on /proc/self/maps linux-user: factor out reading of /proc/self/maps softfloat: Fix BAD_SHIFT from normalizeFloatx80Subnormal gdbstub: fix compiler complaining target/xtensa: add FIXME for translation memory leak linux-user: more debug for init_guest_space tests/tcg: remove extraneous pasting macros linux-user: protect fcntl64 with an #ifdef elf-ops: bail out if we have no function symbols .github: Enable repo-lockdown bot to refuse GitHub pull requests Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
e715f7b77e
34
.github/lockdown.yml
vendored
Normal file
34
.github/lockdown.yml
vendored
Normal file
@ -0,0 +1,34 @@
|
||||
# Configuration for Repo Lockdown - https://github.com/dessant/repo-lockdown
|
||||
|
||||
# Close issues and pull requests
|
||||
close: true
|
||||
|
||||
# Lock issues and pull requests
|
||||
lock: true
|
||||
|
||||
issues:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's master
|
||||
repostories hosted on https://git.qemu.org/git/qemu.git.
|
||||
The project does not process issues filed on GitHub.
|
||||
|
||||
The project issues are tracked on Launchpad:
|
||||
https://bugs.launchpad.net/qemu
|
||||
|
||||
QEMU welcomes bug report contributions. You can file new ones on:
|
||||
https://bugs.launchpad.net/qemu/+filebug
|
||||
|
||||
pulls:
|
||||
comment: |
|
||||
Thank you for your interest in the QEMU project.
|
||||
|
||||
This repository is a read-only mirror of the project's master
|
||||
repostories hosted on https://git.qemu.org/git/qemu.git.
|
||||
The project does not process merge requests filed on GitHub.
|
||||
|
||||
QEMU welcomes contributions of code (either fixing bugs or adding new
|
||||
functionality). However, we get a lot of patches, and so we have some
|
||||
guidelines about contributing on the project website:
|
||||
https://www.qemu.org/contribute/
|
@ -2834,6 +2834,7 @@ M: Alex Bennée <alex.bennee@linaro.org>
|
||||
M: Fam Zheng <fam@euphon.net>
|
||||
R: Philippe Mathieu-Daudé <philmd@redhat.com>
|
||||
S: Maintained
|
||||
F: .github/lockdown.yml
|
||||
F: .travis.yml
|
||||
F: scripts/travis/
|
||||
F: .shippable.yml
|
||||
|
4
configure
vendored
4
configure
vendored
@ -2119,7 +2119,7 @@ if compile_prog "-Werror -fno-pie" "-no-pie"; then
|
||||
fi
|
||||
|
||||
if test "$static" = "yes"; then
|
||||
if test "$pie" != "no" && compile_prog "-fPIE -DPIE" "-static-pie"; then
|
||||
if test "$pie" != "no" && compile_prog "-Werror -fPIE -DPIE" "-static-pie"; then
|
||||
QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="-static-pie $QEMU_LDFLAGS"
|
||||
pie="yes"
|
||||
@ -2132,7 +2132,7 @@ if test "$static" = "yes"; then
|
||||
elif test "$pie" = "no"; then
|
||||
QEMU_CFLAGS="$CFLAGS_NOPIE $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="$LDFLAGS_NOPIE $QEMU_LDFLAGS"
|
||||
elif compile_prog "-fPIE -DPIE" "-pie"; then
|
||||
elif compile_prog "-Werror -fPIE -DPIE" "-pie"; then
|
||||
QEMU_CFLAGS="-fPIE -DPIE $QEMU_CFLAGS"
|
||||
QEMU_LDFLAGS="-pie $QEMU_LDFLAGS"
|
||||
pie="yes"
|
||||
|
@ -5856,6 +5856,9 @@ static floatx80 addFloatx80Sigs(floatx80 a, floatx80 b, flag zSign,
|
||||
zSig1 = 0;
|
||||
zSig0 = aSig + bSig;
|
||||
if ( aExp == 0 ) {
|
||||
if (zSig0 == 0) {
|
||||
return packFloatx80(zSign, 0, 0);
|
||||
}
|
||||
normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
|
||||
goto roundAndPack;
|
||||
}
|
||||
|
@ -2060,8 +2060,8 @@ static void handle_query_thread_extra(GdbCmdContext *gdb_ctx, void *user_ctx)
|
||||
/* Print the CPU model and name in multiprocess mode */
|
||||
ObjectClass *oc = object_get_class(OBJECT(cpu));
|
||||
const char *cpu_model = object_class_get_name(oc);
|
||||
g_autofree char *cpu_name;
|
||||
cpu_name = object_get_canonical_path_component(OBJECT(cpu));
|
||||
g_autofree char *cpu_name =
|
||||
object_get_canonical_path_component(OBJECT(cpu));
|
||||
g_string_printf(rs, "%s %s [%s]", cpu_model, cpu_name,
|
||||
cpu->halted ? "halted " : "running");
|
||||
} else {
|
||||
|
@ -1447,6 +1447,7 @@ typedef struct {
|
||||
uint32_t current_rom_index;
|
||||
uint32_t rom_start_address;
|
||||
AddressSpace *as;
|
||||
bool complete;
|
||||
} HexParser;
|
||||
|
||||
/* return size or -1 if error */
|
||||
@ -1484,6 +1485,7 @@ static int handle_record_type(HexParser *parser)
|
||||
parser->current_rom_index,
|
||||
parser->rom_start_address, parser->as);
|
||||
}
|
||||
parser->complete = true;
|
||||
return parser->total_size;
|
||||
case EXT_SEG_ADDR_RECORD:
|
||||
case EXT_LINEAR_ADDR_RECORD:
|
||||
@ -1548,11 +1550,12 @@ static int parse_hex_blob(const char *filename, hwaddr *addr, uint8_t *hex_blob,
|
||||
.bin_buf = g_malloc(hex_blob_size),
|
||||
.start_addr = addr,
|
||||
.as = as,
|
||||
.complete = false
|
||||
};
|
||||
|
||||
rom_transaction_begin();
|
||||
|
||||
for (; hex_blob < end; ++hex_blob) {
|
||||
for (; hex_blob < end && !parser.complete; ++hex_blob) {
|
||||
switch (*hex_blob) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
|
@ -104,19 +104,21 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1)
|
||||
: ((sym0->st_value > sym1->st_value) ? 1 : 0);
|
||||
}
|
||||
|
||||
static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
int clear_lsb, symbol_fn_t sym_cb)
|
||||
static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
int clear_lsb, symbol_fn_t sym_cb)
|
||||
{
|
||||
struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
|
||||
struct elf_sym *syms = NULL;
|
||||
struct elf_shdr *symtab, *strtab;
|
||||
g_autofree struct elf_shdr *shdr_table = NULL;
|
||||
g_autofree struct elf_sym *syms = NULL;
|
||||
g_autofree char *str = NULL;
|
||||
struct syminfo *s;
|
||||
int nsyms, i;
|
||||
char *str = NULL;
|
||||
|
||||
shdr_table = load_at(fd, ehdr->e_shoff,
|
||||
sizeof(struct elf_shdr) * ehdr->e_shnum);
|
||||
if (!shdr_table)
|
||||
return -1;
|
||||
if (!shdr_table) {
|
||||
return ;
|
||||
}
|
||||
|
||||
if (must_swab) {
|
||||
for (i = 0; i < ehdr->e_shnum; i++) {
|
||||
@ -125,23 +127,25 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
}
|
||||
|
||||
symtab = glue(find_section, SZ)(shdr_table, ehdr->e_shnum, SHT_SYMTAB);
|
||||
if (!symtab)
|
||||
goto fail;
|
||||
if (!symtab) {
|
||||
return;
|
||||
}
|
||||
syms = load_at(fd, symtab->sh_offset, symtab->sh_size);
|
||||
if (!syms)
|
||||
goto fail;
|
||||
if (!syms) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsyms = symtab->sh_size / sizeof(struct elf_sym);
|
||||
|
||||
/* String table */
|
||||
if (symtab->sh_link >= ehdr->e_shnum) {
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
strtab = &shdr_table[symtab->sh_link];
|
||||
|
||||
str = load_at(fd, strtab->sh_offset, strtab->sh_size);
|
||||
if (!str) {
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
@ -170,8 +174,13 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
}
|
||||
i++;
|
||||
}
|
||||
syms = g_realloc(syms, nsyms * sizeof(*syms));
|
||||
|
||||
/* check we have symbols left */
|
||||
if (nsyms == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
syms = g_realloc(syms, nsyms * sizeof(*syms));
|
||||
qsort(syms, nsyms, sizeof(*syms), glue(symcmp, SZ));
|
||||
for (i = 0; i < nsyms - 1; i++) {
|
||||
if (syms[i].st_size == 0) {
|
||||
@ -182,18 +191,11 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
/* Commit */
|
||||
s = g_malloc0(sizeof(*s));
|
||||
s->lookup_symbol = glue(lookup_symbol, SZ);
|
||||
glue(s->disas_symtab.elf, SZ) = syms;
|
||||
glue(s->disas_symtab.elf, SZ) = g_steal_pointer(&syms);
|
||||
s->disas_num_syms = nsyms;
|
||||
s->disas_strtab = str;
|
||||
s->disas_strtab = g_steal_pointer(&str);
|
||||
s->next = syminfos;
|
||||
syminfos = s;
|
||||
g_free(shdr_table);
|
||||
return 0;
|
||||
fail:
|
||||
g_free(syms);
|
||||
g_free(str);
|
||||
g_free(shdr_table);
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int glue(elf_reloc, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
|
||||
|
44
include/qemu/selfmap.h
Normal file
44
include/qemu/selfmap.h
Normal file
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Utility functions to read our own memory map
|
||||
*
|
||||
* Copyright (c) 2020 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#ifndef _SELFMAP_H_
|
||||
#define _SELFMAP_H_
|
||||
|
||||
typedef struct {
|
||||
unsigned long start;
|
||||
unsigned long end;
|
||||
|
||||
/* flags */
|
||||
bool is_read;
|
||||
bool is_write;
|
||||
bool is_exec;
|
||||
bool is_priv;
|
||||
|
||||
unsigned long offset;
|
||||
gchar *dev;
|
||||
uint64_t inode;
|
||||
gchar *path;
|
||||
} MapInfo;
|
||||
|
||||
|
||||
/**
|
||||
* read_self_maps:
|
||||
*
|
||||
* Read /proc/self/maps and return a list of MapInfo structures.
|
||||
*/
|
||||
GSList *read_self_maps(void);
|
||||
|
||||
/**
|
||||
* free_self_maps:
|
||||
* @info: a GSlist
|
||||
*
|
||||
* Free a list of MapInfo structures.
|
||||
*/
|
||||
void free_self_maps(GSList *info);
|
||||
|
||||
#endif /* _SELFMAP_H_ */
|
@ -2172,6 +2172,8 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||
|
||||
/* Check to see if the address is valid. */
|
||||
if (host_start && real_start != current_start) {
|
||||
qemu_log_mask(CPU_LOG_PAGE, "invalid %lx && %lx != %lx\n",
|
||||
host_start, real_start, current_start);
|
||||
goto try_again;
|
||||
}
|
||||
|
||||
@ -2240,7 +2242,11 @@ unsigned long init_guest_space(unsigned long host_start,
|
||||
* probably a bad strategy if not, which means we got here
|
||||
* because of trouble with ARM commpage setup.
|
||||
*/
|
||||
munmap((void *)real_start, real_size);
|
||||
if (munmap((void *)real_start, real_size) != 0) {
|
||||
error_report("%s: failed to unmap %lx:%lx (%s)", __func__,
|
||||
real_start, real_size, strerror(errno));
|
||||
abort();
|
||||
}
|
||||
current_start += align;
|
||||
if (host_start == current_start) {
|
||||
/* Theoretically possible if host doesn't have any suitably
|
||||
|
@ -117,6 +117,7 @@
|
||||
|
||||
#include "qemu.h"
|
||||
#include "qemu/guest-random.h"
|
||||
#include "qemu/selfmap.h"
|
||||
#include "user/syscall-trace.h"
|
||||
#include "qapi/error.h"
|
||||
#include "fd-trans.h"
|
||||
@ -7232,58 +7233,61 @@ static int open_self_maps(void *cpu_env, int fd)
|
||||
{
|
||||
CPUState *cpu = env_cpu((CPUArchState *)cpu_env);
|
||||
TaskState *ts = cpu->opaque;
|
||||
FILE *fp;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
ssize_t read;
|
||||
GSList *map_info = read_self_maps();
|
||||
GSList *s;
|
||||
int count;
|
||||
|
||||
fp = fopen("/proc/self/maps", "r");
|
||||
if (fp == NULL) {
|
||||
return -1;
|
||||
}
|
||||
for (s = map_info; s; s = g_slist_next(s)) {
|
||||
MapInfo *e = (MapInfo *) s->data;
|
||||
|
||||
while ((read = getline(&line, &len, fp)) != -1) {
|
||||
int fields, dev_maj, dev_min, inode;
|
||||
uint64_t min, max, offset;
|
||||
char flag_r, flag_w, flag_x, flag_p;
|
||||
char path[512] = "";
|
||||
fields = sscanf(line, "%"PRIx64"-%"PRIx64" %c%c%c%c %"PRIx64" %x:%x %d"
|
||||
" %512s", &min, &max, &flag_r, &flag_w, &flag_x,
|
||||
&flag_p, &offset, &dev_maj, &dev_min, &inode, path);
|
||||
|
||||
if ((fields < 10) || (fields > 11)) {
|
||||
continue;
|
||||
}
|
||||
if (h2g_valid(min)) {
|
||||
if (h2g_valid(e->start)) {
|
||||
unsigned long min = e->start;
|
||||
unsigned long max = e->end;
|
||||
int flags = page_get_flags(h2g(min));
|
||||
max = h2g_valid(max - 1) ? max : (uintptr_t)g2h(GUEST_ADDR_MAX) + 1;
|
||||
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) {
|
||||
pstrcpy(path, sizeof(path), " [stack]");
|
||||
path = "[stack]";
|
||||
} else {
|
||||
path = e->path;
|
||||
}
|
||||
|
||||
count = dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
|
||||
" %c%c%c%c %08" PRIx64 " %s %"PRId64,
|
||||
h2g(min), h2g(max - 1) + 1,
|
||||
e->is_read ? 'r' : '-',
|
||||
e->is_write ? 'w' : '-',
|
||||
e->is_exec ? 'x' : '-',
|
||||
e->is_priv ? 'p' : '-',
|
||||
(uint64_t) e->offset, e->dev, e->inode);
|
||||
if (path) {
|
||||
dprintf(fd, "%*s%s\n", 73 - count, "", path);
|
||||
} else {
|
||||
dprintf(fd, "\n");
|
||||
}
|
||||
dprintf(fd, TARGET_ABI_FMT_ptr "-" TARGET_ABI_FMT_ptr
|
||||
" %c%c%c%c %08" PRIx64 " %02x:%02x %d %s%s\n",
|
||||
h2g(min), h2g(max - 1) + 1, flag_r, flag_w,
|
||||
flag_x, flag_p, offset, dev_maj, dev_min, inode,
|
||||
path[0] ? " " : "", path);
|
||||
}
|
||||
}
|
||||
|
||||
free_self_maps(map_info);
|
||||
|
||||
#ifdef TARGET_VSYSCALL_PAGE
|
||||
/*
|
||||
* We only support execution from the vsyscall page.
|
||||
* This is as if CONFIG_LEGACY_VSYSCALL_XONLY=y from v5.3.
|
||||
*/
|
||||
dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
|
||||
" --xp 00000000 00:00 0 [vsyscall]\n",
|
||||
TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
|
||||
count = dprintf(fd, TARGET_FMT_lx "-" TARGET_FMT_lx
|
||||
" --xp 00000000 00:00 0",
|
||||
TARGET_VSYSCALL_PAGE, TARGET_VSYSCALL_PAGE + TARGET_PAGE_SIZE);
|
||||
dprintf(fd, "%*s%s\n", 73 - count, "", "[vsyscall]");
|
||||
#endif
|
||||
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -11331,11 +11335,11 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
This is a hint, so ignoring and returning success is ok. */
|
||||
return 0;
|
||||
#endif
|
||||
#if TARGET_ABI_BITS == 32
|
||||
#ifdef TARGET_NR_fcntl64
|
||||
case TARGET_NR_fcntl64:
|
||||
{
|
||||
int cmd;
|
||||
struct flock64 fl;
|
||||
int cmd;
|
||||
struct flock64 fl;
|
||||
from_flock64_fn *copyfrom = copy_from_user_flock64;
|
||||
to_flock64_fn *copyto = copy_to_user_flock64;
|
||||
|
||||
@ -11346,7 +11350,7 @@ static abi_long do_syscall1(void *cpu_env, int num, abi_long arg1,
|
||||
}
|
||||
#endif
|
||||
|
||||
cmd = target_to_host_fcntl_cmd(arg2);
|
||||
cmd = target_to_host_fcntl_cmd(arg2);
|
||||
if (cmd == -TARGET_EINVAL) {
|
||||
return cmd;
|
||||
}
|
||||
|
@ -1174,6 +1174,11 @@ static void xtensa_tr_init_disas_context(DisasContextBase *dcbase,
|
||||
dc->callinc = ((tb_flags & XTENSA_TBFLAG_CALLINC_MASK) >>
|
||||
XTENSA_TBFLAG_CALLINC_SHIFT);
|
||||
|
||||
/*
|
||||
* FIXME: This will leak when a failed instruction load or similar
|
||||
* event causes us to longjump out of the translation loop and
|
||||
* hence not clean-up in xtensa_tr_tb_stop
|
||||
*/
|
||||
if (dc->config->isa) {
|
||||
dc->insnbuf = xtensa_insnbuf_alloc(dc->config->isa);
|
||||
dc->slotbuf = xtensa_insnbuf_alloc(dc->config->isa);
|
||||
|
@ -3737,7 +3737,7 @@ static void tcg_target_qemu_prologue(TCGContext *s)
|
||||
} else {
|
||||
/* Choose R12 because, as a base, it requires a SIB byte. */
|
||||
x86_guest_base_index = TCG_REG_R12;
|
||||
tcg_out_mov(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base);
|
||||
tcg_out_movi(s, TCG_TYPE_PTR, x86_guest_base_index, guest_base);
|
||||
tcg_regset_set_reg(s->reserved_regs, x86_guest_base_index);
|
||||
}
|
||||
}
|
||||
|
@ -41,10 +41,7 @@
|
||||
#define XEN_ELFNOTE_PHYS32_ENTRY 18
|
||||
|
||||
#define __ASM_FORM(x) x
|
||||
#define __ASM_FORM_RAW(x) x
|
||||
#define __ASM_FORM_COMMA(x) x,
|
||||
#define __ASM_SEL(a,b) __ASM_FORM(b)
|
||||
#define __ASM_SEL_RAW(a,b) __ASM_FORM_RAW(b)
|
||||
#define __ASM_SEL(a,b) __ASM_FORM(b)
|
||||
#define _ASM_PTR __ASM_SEL(.long, .quad)
|
||||
|
||||
ELFNOTE(Xen, XEN_ELFNOTE_VIRT_BASE, _ASM_PTR 0x100000)
|
||||
|
@ -63,3 +63,4 @@ util-obj-y += guest-random.o
|
||||
util-obj-$(CONFIG_GIO) += dbus.o
|
||||
dbus.o-cflags = $(GIO_CFLAGS)
|
||||
dbus.o-libs = $(GIO_LIBS)
|
||||
util-obj-$(CONFIG_USER_ONLY) += selfmap.o
|
||||
|
78
util/selfmap.c
Normal file
78
util/selfmap.c
Normal file
@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Utility function to get QEMU's own process map
|
||||
*
|
||||
* Copyright (c) 2020 Linaro Ltd
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "qemu/selfmap.h"
|
||||
|
||||
GSList *read_self_maps(void)
|
||||
{
|
||||
gchar *maps;
|
||||
GSList *map_info = NULL;
|
||||
|
||||
if (g_file_get_contents("/proc/self/maps", &maps, NULL, NULL)) {
|
||||
gchar **lines = g_strsplit(maps, "\n", 0);
|
||||
int i, entries = g_strv_length(lines);
|
||||
|
||||
for (i = 0; i < entries; i++) {
|
||||
gchar **fields = g_strsplit(lines[i], " ", 6);
|
||||
if (g_strv_length(fields) > 4) {
|
||||
MapInfo *e = g_new0(MapInfo, 1);
|
||||
int errors;
|
||||
const char *end;
|
||||
|
||||
errors = qemu_strtoul(fields[0], &end, 16, &e->start);
|
||||
errors += qemu_strtoul(end + 1, NULL, 16, &e->end);
|
||||
|
||||
e->is_read = fields[1][0] == 'r';
|
||||
e->is_write = fields[1][1] == 'w';
|
||||
e->is_exec = fields[1][2] == 'x';
|
||||
e->is_priv = fields[1][3] == 'p';
|
||||
|
||||
errors += qemu_strtoul(fields[2], NULL, 16, &e->offset);
|
||||
e->dev = g_strdup(fields[3]);
|
||||
errors += qemu_strtou64(fields[4], NULL, 10, &e->inode);
|
||||
|
||||
/*
|
||||
* The last field may have leading spaces which we
|
||||
* need to strip.
|
||||
*/
|
||||
if (g_strv_length(fields) == 6) {
|
||||
e->path = g_strdup(g_strchug(fields[5]));
|
||||
}
|
||||
map_info = g_slist_prepend(map_info, e);
|
||||
}
|
||||
|
||||
g_strfreev(fields);
|
||||
}
|
||||
g_strfreev(lines);
|
||||
g_free(maps);
|
||||
}
|
||||
|
||||
/* ensure the map data is in the same order we collected it */
|
||||
return g_slist_reverse(map_info);
|
||||
}
|
||||
|
||||
/**
|
||||
* free_self_maps:
|
||||
* @info: a GSlist
|
||||
*
|
||||
* Free a list of MapInfo structures.
|
||||
*/
|
||||
static void free_info(gpointer data)
|
||||
{
|
||||
MapInfo *e = (MapInfo *) data;
|
||||
g_free(e->dev);
|
||||
g_free(e->path);
|
||||
g_free(e);
|
||||
}
|
||||
|
||||
void free_self_maps(GSList *info)
|
||||
{
|
||||
g_slist_free_full(info, &free_info);
|
||||
}
|
Loading…
Reference in New Issue
Block a user