Michal Suchanek 9cd1e1
From: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 9cd1e1
Date: Wed, 7 Feb 2018 15:16:04 +0100
Michal Kubecek 00fe0a
Subject: Add ksym-provides tool.
Michal Suchanek 9cd1e1
Michal Suchanek 9cd1e1
References: bsc#1077692
Michal Suchanek 9cd1e1
Patch-mainline: no, not needed
Michal Suchanek 9cd1e1
Michal Suchanek 9cd1e1
Signed-off-by: Michal Suchanek <msuchanek@suse.de>
Michal Suchanek 9cd1e1
---
Michal Kubecek a3b9ca
 scripts/mod/Makefile        |   6 +-
Michal Kubecek a3b9ca
 scripts/mod/ksym-provides.c | 124 ++++++++++++++++++++++++++++++++++++
Michal Suchanek 9cd1e1
 2 files changed, 129 insertions(+), 1 deletion(-)
Michal Suchanek 9cd1e1
 create mode 100644 scripts/mod/ksym-provides.c
Michal Suchanek 9cd1e1
Michal Suchanek 9cd1e1
--- a/scripts/mod/Makefile
Michal Suchanek 9cd1e1
+++ b/scripts/mod/Makefile
Michal Kubecek 42fc05
@@ -2,11 +2,15 @@
Michal Suchanek 9cd1e1
 OBJECT_FILES_NON_STANDARD := y
Michal Kubecek 42fc05
 CFLAGS_REMOVE_empty.o += $(CC_FLAGS_LTO)
Michal Suchanek 9cd1e1
 
Michal Kubecek 6a3065
-hostprogs-always-y	+= modpost mk_elfconfig
Michal Kubecek 6a3065
+hostprogs-always-y	+= modpost mk_elfconfig ksym-provides
Michal Kubecek 6a3065
 always-y		+= empty.o
Michal Suchanek 9cd1e1
 
Michal Suchanek 9cd1e1
 modpost-objs	:= modpost.o file2alias.o sumversion.o
Michal Suchanek 9cd1e1
 
Michal Suchanek 9cd1e1
+ksym-provides-objs	:= ksym-provides.o
Michal Suchanek 9cd1e1
+
Michal Kubecek a3b9ca
+HOSTLDLIBS_ksym-provides := -lelf
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
 devicetable-offsets-file := devicetable-offsets.h
Michal Suchanek 9cd1e1
 
Michal Suchanek 9cd1e1
 $(obj)/$(devicetable-offsets-file): $(obj)/devicetable-offsets.s FORCE
Michal Suchanek 9cd1e1
--- /dev/null
Michal Suchanek 9cd1e1
+++ b/scripts/mod/ksym-provides.c
Michal Suchanek 9cd1e1
@@ -0,0 +1,124 @@
Michal Suchanek 9cd1e1
+#include <stdio.h>
Michal Suchanek 9cd1e1
+#include <sys/types.h>
Michal Suchanek 9cd1e1
+#include <sys/stat.h>
Michal Suchanek 9cd1e1
+#include <fcntl.h>
Michal Suchanek 9cd1e1
+#include <unistd.h>
Michal Suchanek 9cd1e1
+#include <gelf.h>
Michal Suchanek 9cd1e1
+#include <string.h>
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+int main(int argc, char *argv[])
Michal Suchanek 9cd1e1
+{
Michal Suchanek 9cd1e1
+	int fd;
Michal Suchanek 9cd1e1
+	Elf *elf;
Michal Suchanek 9cd1e1
+	Elf_Scn *scn;
Michal Suchanek 9cd1e1
+	GElf_Shdr shdr;
Michal Suchanek 9cd1e1
+	size_t strndx;
Michal Suchanek 9cd1e1
+	int ndx;
Michal Suchanek 9cd1e1
+	Elf_Data *symdata, *data;
Michal Suchanek 9cd1e1
+	GElf_Sym sym;
Michal Suchanek 9cd1e1
+	char *name;
Michal Suchanek 9cd1e1
+	const char * flavor = argv[1];
Michal Suchanek 9cd1e1
+	const char * prefix = "__crc_";
Michal Suchanek 9cd1e1
+	size_t prefixlen = strlen(prefix);
Michal Suchanek 9cd1e1
+	const char * symformat = "ksym(%s:%s) = %lx\n";
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	if (argc != 3) {
Michal Suchanek 9cd1e1
+		fprintf(stderr, "Usage: %s <flavor> <filename>\n", argv[0]);
Michal Suchanek 9cd1e1
+		return 1;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	if (elf_version(EV_CURRENT) == EV_NONE) {
Michal Suchanek 9cd1e1
+		fprintf(stderr, "libelf initialization failed: %s\n",
Michal Suchanek 9cd1e1
+			elf_errmsg(-1));
Michal Suchanek 9cd1e1
+		return 1;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	fd = open(argv[2], O_RDONLY);
Michal Suchanek 9cd1e1
+	if (fd < 0) {
Michal Suchanek 9cd1e1
+		perror("open failed");
Michal Suchanek 9cd1e1
+		return 1;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	elf = elf_begin(fd, ELF_C_READ, NULL);
Michal Suchanek 9cd1e1
+	if (!elf) {
Michal Suchanek 9cd1e1
+		fprintf(stderr, "elf_begin failed: %s\n", elf_errmsg(-1));
Michal Suchanek 9cd1e1
+		goto err_close;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	scn = NULL;
Michal Suchanek 9cd1e1
+	while ((scn = elf_nextscn(elf, scn)) != NULL) {
Michal Suchanek 9cd1e1
+		if (!gelf_getshdr(scn, &shdr)) {
Michal Suchanek 9cd1e1
+			fprintf(stderr, "gelf_getshdr failed: %s\n",
Michal Suchanek 9cd1e1
+				elf_errmsg(-1));
Michal Suchanek 9cd1e1
+			goto err_end;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		if (shdr.sh_type == SHT_SYMTAB)
Michal Suchanek 9cd1e1
+			break;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+	if (!scn) {
Michal Suchanek 9cd1e1
+		fputs("symbol table not found\n", stderr);
Michal Suchanek 9cd1e1
+		goto err_end;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+	strndx = shdr.sh_link;
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	symdata = elf_getdata(scn, NULL);
Michal Suchanek 9cd1e1
+	if (!symdata) {
Michal Suchanek 9cd1e1
+		fprintf(stderr, "elf_getdata failed: %s\n", elf_errmsg(-1));
Michal Suchanek 9cd1e1
+		goto err_end;
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	for (ndx = 0; gelf_getsym(symdata, ndx, &sym) != NULL; ++ndx) {
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		name = elf_strptr(elf, strndx, sym.st_name);
Michal Suchanek 9cd1e1
+		if (!name) {
Michal Suchanek 9cd1e1
+			fprintf(stderr, "elf_strptr failed: %s\n",
Michal Suchanek 9cd1e1
+				elf_errmsg(-1));
Michal Suchanek 9cd1e1
+			goto err_end;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+		if (strncmp(prefix, name, prefixlen))
Michal Suchanek 9cd1e1
+			continue;
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		if (sym.st_shndx >= SHN_LORESERVE) {
Michal Suchanek 9cd1e1
+			printf(symformat, flavor, name + prefixlen,
Michal Suchanek 9cd1e1
+				sym.st_value);
Michal Suchanek 9cd1e1
+			continue;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		scn = elf_getscn(elf, sym.st_shndx);
Michal Suchanek 9cd1e1
+		if (!scn) {
Michal Suchanek 9cd1e1
+			fprintf(stderr, "elf_getscn failed: %s\n",
Michal Suchanek 9cd1e1
+				elf_errmsg(-1));
Michal Suchanek 9cd1e1
+			goto err_end;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+		if (!gelf_getshdr(scn, &shdr)) {
Michal Suchanek 9cd1e1
+			fprintf(stderr, "gelf_getshdr failed: %s\n",
Michal Suchanek 9cd1e1
+				elf_errmsg(-1));
Michal Suchanek 9cd1e1
+			goto err_end;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		if (shdr.sh_type != SHT_PROGBITS)
Michal Suchanek 9cd1e1
+			continue;
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+		data = elf_getdata_rawchunk(
Michal Suchanek 9cd1e1
+			elf, shdr.sh_offset + sym.st_value - shdr.sh_addr,
Michal Suchanek 9cd1e1
+			sizeof(GElf_Word), ELF_T_WORD);
Michal Suchanek 9cd1e1
+		if (!data) {
Michal Suchanek 9cd1e1
+			fprintf(stderr, "elf_getdata_rawchunk failed: %s\n",
Michal Suchanek 9cd1e1
+				elf_errmsg(-1));
Michal Suchanek 9cd1e1
+			goto err_end;
Michal Suchanek 9cd1e1
+		}
Michal Suchanek 9cd1e1
+		printf(symformat, flavor, name + prefixlen,
Michal Suchanek 9cd1e1
+		       (unsigned long) *(GElf_Word*)data->d_buf);
Michal Suchanek 9cd1e1
+	}
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+	elf_end(elf);
Michal Suchanek 9cd1e1
+	close(fd);
Michal Suchanek 9cd1e1
+	return 0;
Michal Suchanek 9cd1e1
+
Michal Suchanek 9cd1e1
+ err_end:
Michal Suchanek 9cd1e1
+	elf_end(elf);
Michal Suchanek 9cd1e1
+ err_close:
Michal Suchanek 9cd1e1
+	close(fd);
Michal Suchanek 9cd1e1
+	return 1;
Michal Suchanek 9cd1e1
+}