From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Thomas Huth" <thuth@redhat.com>,
berrange@redhat.com, "David Hildenbrand" <david@redhat.com>,
"Cornelia Huck" <cohuck@redhat.com>,
"Richard Henderson" <richard.henderson@linaro.org>,
armbru@redhat.com, "Halil Pasic" <pasic@linux.ibm.com>,
"Christian Borntraeger" <borntraeger@de.ibm.com>,
qemu-s390x@nongnu.org, "Paolo Bonzini" <pbonzini@redhat.com>,
"Michael S. Tsirkin" <mst@redhat.com>,
"Gerd Hoffmann" <kraxel@redhat.com>,
"Samuel Thibault" <samuel.thibault@ens-lyon.org>,
"Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [PATCH 2/9] add qemu-modinfo utility
Date: Wed, 2 Jun 2021 11:17:20 +0200 [thread overview]
Message-ID: <20210602091727.1023563-3-kraxel@redhat.com> (raw)
In-Reply-To: <20210602091727.1023563-1-kraxel@redhat.com>
For now only dump metadata.
TODO:
* store in some file format (json?).
* make qemu parse it, replace hard-coded lists in util/module.c
* fix windows (seems to not have glob).
* do we need non-elf support?
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
qemu-modinfo.c | 182 +++++++++++++++++++++++++++++++++++++++++++++++++
meson.build | 3 +
2 files changed, 185 insertions(+)
create mode 100644 qemu-modinfo.c
diff --git a/qemu-modinfo.c b/qemu-modinfo.c
new file mode 100644
index 000000000000..ecd5f6c3adf2
--- /dev/null
+++ b/qemu-modinfo.c
@@ -0,0 +1,182 @@
+/*
+ * QEMU module parser
+ *
+ * read modules, find modinfo section, parse & store metadata.
+ *
+ * Copyright Red Hat, Inc. 2021
+ *
+ * Authors:
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+#include "qemu/osdep.h"
+#include "elf.h"
+#include <glob.h>
+
+#define Elf_Ehdr Elf64_Ehdr
+#define Elf_Shdr Elf64_Shdr
+#define ELFCLASS ELFCLASS64
+
+static const char *moddir = CONFIG_QEMU_MODDIR;
+static const char *dsosuf = CONFIG_HOST_DSOSUF;
+
+static void modinfo(const char *module, char *info, size_t size)
+{
+ size_t pos = 0, len;
+
+ fprintf(stderr, "%s\n", module);
+ do {
+ fprintf(stderr, " -> %s\n", info + pos);
+ len = strlen(info + pos) + 1;
+ pos += len;
+ } while (pos < size);
+}
+
+static void elf_read_section_hdr(FILE *fp, Elf_Ehdr *ehdr,
+ int section, Elf_Shdr *shdr)
+{
+ size_t pos, len;
+ int ret;
+
+ pos = ehdr->e_shoff + section * ehdr->e_shentsize;
+ len = MIN(ehdr->e_shentsize, sizeof(*shdr));
+
+ ret = fseek(fp, pos, SEEK_SET);
+ if (ret != 0) {
+ fprintf(stderr, "seek error\n");
+ exit(1);
+ }
+
+ memset(shdr, 0, sizeof(*shdr));
+ ret = fread(shdr, len, 1, fp);
+ if (ret != 1) {
+ fprintf(stderr, "read error\n");
+ exit(1);
+ }
+}
+
+static void *elf_read_section(FILE *fp, Elf_Ehdr *ehdr,
+ int section, size_t *size)
+{
+ Elf_Shdr shdr;
+ void *data;
+ int ret;
+
+ elf_read_section_hdr(fp, ehdr, section, &shdr);
+ if (shdr.sh_offset && shdr.sh_size) {
+ ret = fseek(fp, shdr.sh_offset, SEEK_SET);
+ if (ret != 0) {
+ fprintf(stderr, "seek error\n");
+ exit(1);
+ }
+
+ data = g_malloc(shdr.sh_size);
+ ret = fread(data, shdr.sh_size, 1, fp);
+ if (ret != 1) {
+ fprintf(stderr, "read error\n");
+ exit(1);
+ }
+ *size = shdr.sh_size;
+ } else {
+ data = NULL;
+ *size = 0;
+ }
+ return data;
+}
+
+static void elf_parse_module(const char *module)
+{
+ Elf_Ehdr ehdr;
+ Elf_Shdr shdr;
+ FILE *fp;
+ int ret, i;
+ char *str;
+ size_t str_size;
+ char *info;
+ size_t info_size;
+
+ fp = fopen(module, "r");
+ if (NULL == fp) {
+ fprintf(stderr, "open %s: %s\n", module, strerror(errno));
+ exit(1);
+ }
+
+ ret = fread(&ehdr, sizeof(ehdr), 1, fp);
+ if (ret != 1) {
+ fprintf(stderr, "read error (%s)\n", module);
+ exit(1);
+ }
+
+ if (ehdr.e_ident[EI_MAG0] != ELFMAG0 ||
+ ehdr.e_ident[EI_MAG1] != ELFMAG1 ||
+ ehdr.e_ident[EI_MAG2] != ELFMAG2 ||
+ ehdr.e_ident[EI_MAG3] != ELFMAG3) {
+ fprintf(stderr, "not an elf file (%s)\n", module);
+ exit(1);
+ }
+ if (ehdr.e_ident[EI_CLASS] != ELFCLASS64) {
+ fprintf(stderr, "elf class mismatch (%s)\n", module);
+ exit(1);
+ }
+ if (ehdr.e_shoff == 0) {
+ fprintf(stderr, "no section header (%s)\n", module);
+ exit(1);
+ }
+
+ /* read string table */
+ if (ehdr.e_shstrndx == 0) {
+ fprintf(stderr, "no section strings (%s)\n", module);
+ exit(1);
+ }
+ str = elf_read_section(fp, &ehdr, ehdr.e_shstrndx, &str_size);
+ if (NULL == str) {
+ fprintf(stderr, "no section strings (%s)\n", module);
+ exit(1);
+ }
+
+ /* find and read modinfo section */
+ info = NULL;
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ elf_read_section_hdr(fp, &ehdr, i, &shdr);
+ if (!shdr.sh_name) {
+ continue;
+ }
+ if (strcmp(str + shdr.sh_name, ".modinfo") == 0) {
+ info = elf_read_section(fp, &ehdr, i, &info_size);
+ }
+ }
+
+ if (info) {
+ modinfo(module, info, info_size);
+ }
+
+ fclose(fp);
+}
+
+int main(int argc, char **argv)
+{
+ char *pattern;
+ glob_t files;
+ int ret, i;
+
+ if (argc > 1) {
+ moddir = argv[1];
+ }
+
+ pattern = g_strdup_printf("%s/*%s", moddir, dsosuf);
+ ret = glob(pattern, 0, NULL, &files);
+ if (ret != 0) {
+ fprintf(stderr, "glob(%s) failed: %d\n", pattern, ret);
+ exit(1);
+ }
+
+ for (i = 0; i < files.gl_pathc; i++) {
+ elf_parse_module(files.gl_pathv[i]);
+ }
+
+ globfree(&files);
+ g_free(pattern);
+ return 0;
+}
diff --git a/meson.build b/meson.build
index a45f1a844f13..179e92aa7ae1 100644
--- a/meson.build
+++ b/meson.build
@@ -2358,6 +2358,9 @@ if xkbcommon.found()
dependencies: [qemuutil, xkbcommon], install: have_tools)
endif
+qemu_modinfo = executable('qemu-modinfo', files('qemu-modinfo.c') + genh,
+ dependencies: [glib], install: have_tools)
+
if have_tools
qemu_img = executable('qemu-img', [files('qemu-img.c'), hxdep],
dependencies: [authz, block, crypto, io, qom, qemuutil], install: true)
--
2.31.1
next prev parent reply other threads:[~2021-06-02 9:20 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-06-02 9:17 [PATCH 0/9] [RFC] store module metadata in .modinfo elf section Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 1/9] Add module metadata macros, add qxl module annotations Gerd Hoffmann
2021-06-02 9:17 ` Gerd Hoffmann [this message]
2021-06-02 9:17 ` [PATCH 3/9] virtio-gpu " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 4/9] chardev " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 5/9] audio " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 6/9] usb-redir " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 7/9] ccid " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 8/9] ui " Gerd Hoffmann
2021-06-02 9:17 ` [PATCH 9/9] s390x " Gerd Hoffmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20210602091727.1023563-3-kraxel@redhat.com \
--to=kraxel@redhat.com \
--cc=armbru@redhat.com \
--cc=berrange@redhat.com \
--cc=borntraeger@de.ibm.com \
--cc=cohuck@redhat.com \
--cc=david@redhat.com \
--cc=marcandre.lureau@redhat.com \
--cc=mst@redhat.com \
--cc=pasic@linux.ibm.com \
--cc=pbonzini@redhat.com \
--cc=qemu-devel@nongnu.org \
--cc=qemu-s390x@nongnu.org \
--cc=richard.henderson@linaro.org \
--cc=samuel.thibault@ens-lyon.org \
--cc=thuth@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).