2003-02-18 06:35:34

by Miles Bader

[permalink] [raw]
Subject: [PATCH] Enhance script/modpost to handle "_" prefixed symbols

The decision to do so is made by having mk_elfconfig look at the elf
machine-type. It would be better to actually examine a known symbol,
but that seems quite a bit more complicated.

diff -ruN -X../cludes linux-2.5.62-uc0.orig/scripts/mk_elfconfig.c linux-2.5.62-uc0/scripts/mk_elfconfig.c
--- linux-2.5.62-uc0.orig/scripts/mk_elfconfig.c 2003-02-18 10:13:36.000000000 +0900
+++ linux-2.5.62-uc0/scripts/mk_elfconfig.c 2003-02-18 14:44:52.000000000 +0900
@@ -3,11 +3,17 @@
#include <string.h>
#include <elf.h>

+/* Bogus old v850 magic number, used by old tools; it's not defined in most
+ <elf.h> files, so define it here. */
+#define EM_CYGNUS_V850 0x9080
+
int
main(int argc, char **argv)
{
unsigned char ei[EI_NIDENT];
union { short s; char c[2]; } endian_test;
+ Elf32_Half mach_type; /* 32- and 64-bit versions are the same. */
+ int host_little_endian;

if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
fprintf(stderr, "Error: input truncated\n");
@@ -45,13 +51,56 @@
}

endian_test.s = 0x0102;
- if (memcmp(endian_test.c, "\x01\x02", 2) == 0)
+ if (memcmp(endian_test.c, "\x01\x02", 2) == 0) {
printf("#define HOST_ELFDATA ELFDATA2MSB\n");
- else if (memcmp(endian_test.c, "\x02\x01", 2) == 0)
+ host_little_endian = 0;
+ } else if (memcmp(endian_test.c, "\x02\x01", 2) == 0) {
printf("#define HOST_ELFDATA ELFDATA2LSB\n");
- else
+ host_little_endian = 1;
+ } else
abort();

+ /* Read the rest of the elf header, and find out the machine type. */
+ if (ei[EI_CLASS] == ELFCLASS32) {
+ Elf32_Ehdr ehdr;
+ if (fread((char *)&ehdr + EI_NIDENT,
+ sizeof(Elf32_Ehdr) - EI_NIDENT,
+ 1, stdin) != 1)
+ {
+ fprintf(stderr, "Error: input truncated\n");
+ return 1;
+ }
+ mach_type = ehdr.e_machine;
+ } else {
+ Elf64_Ehdr ehdr;
+ if (fread((char *)&ehdr + EI_NIDENT,
+ sizeof(Elf64_Ehdr) - EI_NIDENT,
+ 1, stdin) != 1)
+ {
+ fprintf(stderr, "Error: input truncated\n");
+ return 1;
+ }
+ mach_type = ehdr.e_machine;
+ }
+
+ /* Make sure the machine-type is in host byte-order. */
+ if ((ei[EI_DATA] == ELFDATA2LSB) != host_little_endian)
+ mach_type =
+ ((mach_type >> 8) & 0xFF) | ((mach_type & 0xFF) << 8);
+
+ /* Now output any machine-type-specific definitions. */
+ switch (mach_type) {
+ case EM_V850:
+ case EM_CYGNUS_V850:
+ /* It would be nice to do this by actually examining an elf
+ symbol -- then it needn't be machine specific -- but
+ that seems a great deal more complicated. I don't think
+ many architectures have this stupid symbol prefix in elf
+ files anyway. */
+ printf ("#define KERNEL_SYMBOL_PREFIX \"_\"\n");
+ break;
+ }
+
return 0;
}

diff -ruN -X../cludes linux-2.5.62-uc0.orig/scripts/modpost.c linux-2.5.62-uc0/scripts/modpost.c
--- linux-2.5.62-uc0.orig/scripts/modpost.c 2003-02-18 10:13:36.000000000 +0900
+++ linux-2.5.62-uc0/scripts/modpost.c 2003-02-18 14:42:50.000000000 +0900
@@ -13,6 +13,12 @@

#include "modpost.h"

+/* Normally elf systems don't use any symbol prefix. */
+#ifndef KERNEL_SYMBOL_PREFIX
+#define KERNEL_SYMBOL_PREFIX ""
+#endif
+#define KERNEL_SYMBOL_PREFIX_LEN ((sizeof KERNEL_SYMBOL_PREFIX) - 1)
+
/* Are we using CONFIG_MODVERSIONS? */
int modversions = 0;
/* Do we have vmlinux? */
@@ -279,7 +285,7 @@
break;
case SHN_ABS:
/* CRC'd symbol */
- if (memcmp(symname, "__crc_", 6) == 0) {
+ if (memcmp(symname, KERNEL_SYMBOL_PREFIX "__crc_", 6) == 0) {
crc = (unsigned int) sym->st_value;
add_exported_symbol(symname+6, mod, &crc);
modversions = 1;
@@ -297,8 +303,35 @@
break;
default:
/* All exported symbols */
- if (memcmp(symname, "__ksymtab_", 10) == 0) {
- add_exported_symbol(symname+10, mod, NULL);
+ if (memcmp(symname, KERNEL_SYMBOL_PREFIX "__ksymtab_",
+ KERNEL_SYMBOL_PREFIX_LEN + 10) == 0)
+ {
+ const char *real_symname =
+ symname + KERNEL_SYMBOL_PREFIX_LEN + 10;
+
+ if (KERNEL_SYMBOL_PREFIX_LEN > 0) {
+ size_t len =
+ strlen(symname) - KERNEL_SYMBOL_PREFIX_LEN + 1;
+ static char *symname_buf = 0;
+ static size_t symname_buf_len = 0;
+
+ if (! symname_buf) {
+ symname_buf_len = len * 2;
+ symname_buf =
+ NOFAIL(malloc(symname_buf_len));
+ } else if (symname_buf_len < len) {
+ symname_buf_len = len * 2;
+ symname_buf =
+ NOFAIL(realloc(symname_buf,
+ symname_buf_len));
+ }
+
+ strcpy (symname_buf, KERNEL_SYMBOL_PREFIX);
+ strcat (symname_buf, real_symname);
+ real_symname = symname_buf;
+ }
+
+ add_exported_symbol(real_symname, mod, NULL);
}
break;
}


2003-02-19 19:18:05

by Kai Germaschewski

[permalink] [raw]
Subject: Re: [PATCH] Enhance script/modpost to handle "_" prefixed symbols

On Tue, 18 Feb 2003, Miles Bader wrote:

> The decision to do so is made by having mk_elfconfig look at the elf
> machine-type. It would be better to actually examine a known symbol,
> but that seems quite a bit more complicated.

Hmmh, the reason for mk_elfconfig existance was to avoid bit/endianness
independent parsing, not to put it in there. I put in the following
patch now, which is much simpler, yet should work just fine (untested);

--Kai


# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
# ChangeSet 1.992 -> 1.993
# scripts/modpost.c 1.7 -> 1.8
# scripts/Makefile 1.31 -> 1.32
# scripts/mk_elfconfig.c 1.1 -> 1.2
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/19 [email protected] 1.993
# kbuild: Handle MODULE_SYMBOL_PREFIX in module postprocessing
#
# Loosely based on a patch by Miles Bader, have modpost deal with
# weird archs (v850) which prefix their symbols with '_'.
#
# Modpost does not yet handle ppc64 "prefix function symbols with '.'"
# correctly, btw.
# --------------------------------------------
#
diff -Nru a/scripts/Makefile b/scripts/Makefile
--- a/scripts/Makefile Wed Feb 19 13:24:48 2003
+++ b/scripts/Makefile Wed Feb 19 13:24:48 2003
@@ -25,7 +25,7 @@
$(obj)/modpost.o $(obj)/file2alias.o: $(obj)/elfconfig.h

quiet_cmd_elfconfig = MKELF $@
- cmd_elfconfig = $(obj)/mk_elfconfig < $< > $@
+ cmd_elfconfig = $(obj)/mk_elfconfig $(ARCH) < $< > $@

$(obj)/elfconfig.h: $(obj)/empty.o $(obj)/mk_elfconfig FORCE
$(call if_changed,elfconfig)
diff -Nru a/scripts/mk_elfconfig.c b/scripts/mk_elfconfig.c
--- a/scripts/mk_elfconfig.c Wed Feb 19 13:24:48 2003
+++ b/scripts/mk_elfconfig.c Wed Feb 19 13:24:48 2003
@@ -9,6 +9,9 @@
unsigned char ei[EI_NIDENT];
union { short s; char c[2]; } endian_test;

+ if (argc != 2) {
+ fprintf(stderr, "Error: no arch\n");
+ }
if (fread(ei, 1, EI_NIDENT, stdin) != EI_NIDENT) {
fprintf(stderr, "Error: input truncated\n");
return 1;
@@ -51,6 +54,11 @@
printf("#define HOST_ELFDATA ELFDATA2LSB\n");
else
abort();
+
+ if (strcmp(argv[1], "v850") == 0)
+ printf("#define MODULE_SYMBOL_PREFIX \"_\"\n");
+ else
+ printf("#define MODULE_SYMBOL_PREFIX \"\"\n");

return 0;
}
diff -Nru a/scripts/modpost.c b/scripts/modpost.c
--- a/scripts/modpost.c Wed Feb 19 13:24:48 2003
+++ b/scripts/modpost.c Wed Feb 19 13:24:48 2003
@@ -265,6 +265,9 @@
munmap(info->hdr, info->size);
}

+#define CRC_PFX MODULE_SYMBOL_PREFIX "__crc_"
+#define KSYMTAB_PFX MODULE_SYMBOL_PREFIX "__ksymtab_"
+
void
handle_modversions(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname)
@@ -279,9 +282,10 @@
break;
case SHN_ABS:
/* CRC'd symbol */
- if (memcmp(symname, "__crc_", 6) == 0) {
+ if (memcmp(symname, CRC_PFX, strlen(CRC_PFX)) == 0) {
crc = (unsigned int) sym->st_value;
- add_exported_symbol(symname+6, mod, &crc);
+ add_exported_symbol(symname + strlen(CRC_PFX),
+ mod, &crc);
modversions = 1;
}
break;
@@ -290,15 +294,20 @@
if (ELF_ST_BIND(sym->st_info) != STB_GLOBAL)
break;

- s = alloc_symbol(symname);
- /* add to list */
- s->next = mod->unres;
- mod->unres = s;
+ if (memcmp(symname, MODULE_SYMBOL_PREFIX,
+ strlen(MODULE_SYMBOL_PREFIX)) == 0) {
+ s = alloc_symbol(symname +
+ strlen(MODULE_SYMBOL_PREFIX));
+ /* add to list */
+ s->next = mod->unres;
+ mod->unres = s;
+ }
break;
default:
/* All exported symbols */
- if (memcmp(symname, "__ksymtab_", 10) == 0) {
- add_exported_symbol(symname+10, mod, NULL);
+ if (memcmp(symname, KSYMTAB_PFX, strlen(KSYMTAB_PFX)) == 0) {
+ add_exported_symbol(symname + strlen(KSYMTAB_PFX),
+ mod, NULL);
}
break;
}

2003-02-20 01:58:48

by Miles Bader

[permalink] [raw]
Subject: Re: [PATCH] Enhance script/modpost to handle "_" prefixed symbols

Kai Germaschewski <[email protected]> writes:
> I put in the following patch now, which is much simpler, yet should
> work just fine (untested);

Yes, that seems to work fine (well, at least it doesn't spew lots of
warnings like the unmodified modpost did).

Thanks,

-Miles
--
P.S. All information contained in the above letter is false,
for reasons of military security.