Zunächst einmal: Ich bin kein Experte, also entschuldigen Sie bitte alle Fehler, die ich versuche, mich zu erklären.Umzugsfehler beim Einfügen eines externen kompilierten SPARC-Linux-Moduls
Ich versuche, ein externes Linux-Modul für eine SPARC-Maschine mit Sparc-Linux-GCC-4.4.2
zu kompilieren. Die Version des Linux-Kernels ist 2.6.36.4-00037-g059aa91-dirty
. Es wurde mit einigen Dateien aus dem LEON
Prozessor gepatcht. Der Build-Flow wird mir zur Verfügung gestellt und verwendet LinuxBuild
, Buildroot
und Busybox
. Ich versuche ein 32-Bit-Betriebssystem zu erstellen.
Alles scheint zu funktionieren, aber nachdem ich das Modul kompilieren und versuchen Sie es mit dem SPARC-System zu insmod bekomme ich diesen Fehler:
module hellok: Unknown relocation: 6
Dieser Fehler von ~/linuxbuild-1.0.3/linux/linux-2.6-git/arch/sparc/kernel/module.c
kommt, werde ich das ganze Verfahren zum Zwecke bereitstellen der Vollständigkeit halber:
int apply_relocate_add(Elf_Shdr *sechdrs,
const char *strtab,
unsigned int symindex,
unsigned int relsec,
struct module *me)
{
unsigned int i;
Elf_Rela *rel = (void *)sechdrs[relsec].sh_addr;
Elf_Sym *sym;
u8 *location;
u32 *loc32;
for (i = 0; i < sechdrs[relsec].sh_size/sizeof(*rel); i++) {
Elf_Addr v;
/* This is where to make the change */
location = (u8 *)sechdrs[sechdrs[relsec].sh_info].sh_addr
+ rel[i].r_offset;
loc32 = (u32 *) location;
#ifdef CONFIG_SPARC64
BUG_ON(((u64)location >> (u64)32) != (u64)0);
#endif /* CONFIG_SPARC64 */
/* This is the symbol it is referring to. Note that all
undefined symbols have been resolved. */
sym = (Elf_Sym *)sechdrs[symindex].sh_addr
+ ELF_R_SYM(rel[i].r_info);
v = sym->st_value + rel[i].r_addend;
switch (ELF_R_TYPE(rel[i].r_info) & 0xff) {
#ifdef CONFIG_SPARC64
case R_SPARC_64:
location[0] = v >> 56;
location[1] = v >> 48;
location[2] = v >> 40;
location[3] = v >> 32;
location[4] = v >> 24;
location[5] = v >> 16;
location[6] = v >> 8;
location[7] = v >> 0;
break;
case R_SPARC_DISP32:
v -= (Elf_Addr) location;
*loc32 = v;
break;
case R_SPARC_WDISP19:
v -= (Elf_Addr) location;
*loc32 = (*loc32 & ~0x7ffff) |
((v >> 2) & 0x7ffff);
break;
case R_SPARC_OLO10:
*loc32 = (*loc32 & ~0x1fff) |
(((v & 0x3ff) +
(ELF_R_TYPE(rel[i].r_info) >> 8))
& 0x1fff);
break;
#endif /* CONFIG_SPARC64 */
case R_SPARC_32:
case R_SPARC_UA32:
location[0] = v >> 24;
location[1] = v >> 16;
location[2] = v >> 8;
location[3] = v >> 0;
break;
case R_SPARC_WDISP30:
v -= (Elf_Addr) location;
*loc32 = (*loc32 & ~0x3fffffff) |
((v >> 2) & 0x3fffffff);
break;
case R_SPARC_WDISP22:
v -= (Elf_Addr) location;
*loc32 = (*loc32 & ~0x3fffff) |
((v >> 2) & 0x3fffff);
break;
case R_SPARC_LO10:
*loc32 = (*loc32 & ~0x3ff) | (v & 0x3ff);
break;
case R_SPARC_HI22:
*loc32 = (*loc32 & ~0x3fffff) |
((v >> 10) & 0x3fffff);
break;
default:
printk(KERN_ERR "module %s: Unknown relocation: %x\n",
me->name,
(int) (ELF_R_TYPE(rel[i].r_info) & 0xff));
return -ENOEXEC;
};
}
return 0;
}
So verstehe ich das der Standardfall ist der, den ich fallen werde unter. ELF_R_TYPE(rel[i].r_info
(SPARC Relocations) Typen sind in meiner ~/linuxbuild-1.0.3/dist/buildroot/build-br/staging/usr/include/elf.h
-Datei definiert und einige sind wie folgt:
/* SPARC relocs. */
#define R_SPARC_NONE 0 /* No reloc */
#define R_SPARC_8 1 /* Direct 8 bit */
#define R_SPARC_16 2 /* Direct 16 bit */
#define R_SPARC_32 3 /* Direct 32 bit */
#define R_SPARC_DISP8 4 /* PC relative 8 bit */
#define R_SPARC_DISP16 5 /* PC relative 16 bit */
#define R_SPARC_DISP32 6 /* PC relative 32 bit */
#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */
#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */
#define R_SPARC_HI22 9 /* High 22 bit */
#define R_SPARC_22 10 /* Direct 22 bit */
#define R_SPARC_13 11 /* Direct 13 bit */
#define R_SPARC_LO10 12 /* Truncated 10 bit */
#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */
#define R_SPARC_GOT13 14 /* 13 bit GOT entry */
#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */
#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */
#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */
#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */
#define R_SPARC_COPY 19 /* Copy symbol at runtime */
#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */
#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */
#define R_SPARC_RELATIVE 22 /* Adjust by program base */
#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */
/* Additional Sparc64 relocs. */
...
So Relocation 6 entspricht R_SPARC_DISP32
aka PC
relativ 32 Bit. Dies ist in der module.c
Fallanweisung definiert, aber nur im 64-Bit-Abschnitt. Ich denke, entweder muss ich den Umzug selbst schreiben oder herausfinden, welche Umzugsflagge ich brauche, und die Flagge während der Zusammenstellung ändern. Ich verstehe nicht wirklich, was im Verlagerungscode vor sich geht, also bitte hilf mir herauszufinden, wie ich das beheben soll. Ich glaube nicht, dass ich das Betriebssystem als 64-Bit-System bauen kann, weil es das System zu durchbrechen scheint. Bitte helfen Sie mir, alternative Lösungen zu finden.
Ist es möglich, dass es mit der MMU zu tun hat? – Stuart
Ich denke nur laut nach, aber können Sie [Ziel] -objdump -r einige kompilierte Module von der Zielmaschine erstellen und herausfinden, welche Art von Umzügen sie verwenden? Und dann herausfinden, wo im Build-System der zu verwendende Typ gewählt wird? Wie sicher sind Sie, dass Ihr Build-System/Konfiguration/Header mit denen auf dem Rechner übereinstimmt? –
Welcher Leon Prozessor? Welche Distribution läuft - etwas von Gaisler oder etwas anderes? Hast du -m32 in deinen Build Flags? –