7

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.

+0

Ist es möglich, dass es mit der MMU zu tun hat? – Stuart

+1

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? –

+0

Welcher Leon Prozessor? Welche Distribution läuft - etwas von Gaisler oder etwas anderes? Hast du -m32 in deinen Build Flags? –

Antwort

2

Ich habe genau das gleiche Problem mit meinem eigenen Modul, für eine Leon-Linux-Konfiguration (linuxbuild-1.0.1).

Was ich getan habe ist, dass ich den ‚Fall R_SPARC_DISP32‘ Teil des Codes (die 4 Zeilen) kurz nach der Linie bewegt ‚#endif/* CONFIG_SPARC64 * /‘

, dass einige schlechte Hack Harry ist ;-) aber zumindest kann ich jetzt das modul insmod ... Jetzt muss ich auf der benutzerlandseite nach seiten-effekten suchen, wenn apps die routinen des moduls aufrufen.

So wird fortgesetzt ...

Mit freundlichen Grüßen, Karim

+0

Ich habe das auch eine Zeit lang benutzt, aber ich fühlte mich nicht wohl, da ich nicht sicher sein konnte, dass das angemessen war. Ich denke, die -fno-dwarf2-dfi-asm-Flagge ist besser, kann aber nicht positiv sein. – Stuart