To enable attaching to externally launched QEMU, we need to be able to reverse engineer a guest XML config based on the argv for a PID in /proc * src/qemu/qemu_command.c, src/qemu/qemu_command.h: Add qemuParseCommandLinePid which extracts QEMU config from argv in /proc, given a PID number --- src/qemu/qemu_command.c | 106 +++++++++++++++++++++++++++++++++++++++++++++++ src/qemu/qemu_command.h | 5 ++ 2 files changed, 111 insertions(+), 0 deletions(-) diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e711f0e..dbc9e0c 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -6604,3 +6604,109 @@ cleanup: return def; } + + +static int qemuParseProcFileStrings(unsigned long long pid, + const char *name, + const char ***list) +{ + char *path = NULL; + int ret = -1; + char *data = NULL; + ssize_t len; + char *tmp; + size_t nstr = 0; + const char **str = NULL; + int i; + + if (virAsprintf(&path, "/proc/%llu/%s", pid, name) < 0) { + virReportOOMError(); + goto cleanup; + } + + if ((len = virFileReadAll(path, 1024*128, &data)) < 0) + goto cleanup; + + tmp = data; + while (tmp < (data + len)) { + if (VIR_EXPAND_N(str, nstr, 1) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (!(str[nstr-1] = strdup(tmp))) { + virReportOOMError(); + goto cleanup; + } + /* Skip arg */ + tmp += strlen(tmp); + /* Skip \0 separator */ + tmp++; + } + + if (VIR_EXPAND_N(str, nstr, 1) < 0) { + virReportOOMError(); + goto cleanup; + } + + str[nstr-1] = NULL; + + ret = nstr-1; + *list = str; + +cleanup: + if (ret < 0) { + for (i = 0 ; str && str[i] ; i++) + VIR_FREE(str[i]); + VIR_FREE(str); + } + VIR_FREE(data); + VIR_FREE(path); + return ret; +} + +virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps, + unsigned long long pid, + char **pidfile, + virDomainChrSourceDefPtr *monConfig, + bool *monJSON) +{ + virDomainDefPtr def = NULL; + const char **progargv = NULL; + const char **progenv = NULL; + char *exepath = NULL; + char *emulator; + int i; + + if (qemuParseProcFileStrings(pid, "cmdline", &progargv) < 0 || + qemuParseProcFileStrings(pid, "environ", &progenv) < 0) + goto cleanup; + + if (!(def = qemuParseCommandLine(caps, progenv, progargv, + pidfile, monConfig, monJSON))) + goto cleanup; + + if (virAsprintf(&exepath, "/proc/%llu/exe", pid) < 0) { + virReportOOMError(); + goto cleanup; + } + + if (virFileResolveLink(exepath, &emulator) < 0) { + virReportSystemError(errno, + _("Unable to resolve %s for pid %llu"), + exepath, pid); + goto cleanup; + } + VIR_FREE(def->emulator); + def->emulator = emulator; + +cleanup: + VIR_FREE(exepath); + for (i = 0 ; progargv && progargv[i] ; i++) + VIR_FREE(progargv[i]); + VIR_FREE(progargv); + for (i = 0 ; progenv && progenv[i] ; i++) + VIR_FREE(progenv[i]); + VIR_FREE(progenv); + return def; +} diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h index 89502b7..928b53e 100644 --- a/src/qemu/qemu_command.h +++ b/src/qemu/qemu_command.h @@ -151,6 +151,11 @@ virDomainDefPtr qemuParseCommandLineString(virCapsPtr caps, char **pidfile, virDomainChrSourceDefPtr *monConfig, bool *monJSON); +virDomainDefPtr qemuParseCommandLinePid(virCapsPtr caps, + unsigned long long pid, + char **pidfile, + virDomainChrSourceDefPtr *monConfig, + bool *monJSON); int qemuDomainAssignPCIAddresses(virDomainDefPtr def); qemuDomainPCIAddressSetPtr qemuDomainPCIAddressSetCreate(virDomainDefPtr def); -- 1.7.4.4 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list