Prima di tutto: non sono un esperto, quindi scusate eventuali errori che cerco di spiegare.Errore di rilocazione durante l'inserimento di un modulo Linux SPARC esterno cross-compilato
Sto tentando di compilare un modulo Linux esterno per una macchina SPARC utilizzando Sparc-Linux-GCC-4.4.2
. La versione del kernel Linux è 2.6.36.4-00037-g059aa91-dirty
. È stato corretto con alcuni file dal processore LEON
. Il flusso di generazione viene fornito a me e utilizza LinuxBuild
, Buildroot
e Busybox
. Sto cercando di creare un sistema operativo a 32 bit.
Tutto sembra funzionare, ma dopo compilo il modulo e cerco di insmod al sistema SPARC ottengo questo errore:
module hellok: Unknown relocation: 6
Questo errore viene da ~/linuxbuild-1.0.3/linux/linux-2.6-git/arch/sparc/kernel/module.c
Mi impegno a fornire l'intero metodo per il bene di completezza:
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;
}
quindi capisco il caso di default è quella che sto cadendo sotto. ELF_R_TYPE(rel[i].r_info
(SPARC) Relocations tipi sono definiti nel mio file ~/linuxbuild-1.0.3/dist/buildroot/build-br/staging/usr/include/elf.h
e alcuni sono i seguenti:
/* 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. */
...
Così delocalizzazione 6 corrisponde a R_SPARC_DISP32
aka PC
relativa a 32 bit. Questo è definito nell'istruzione case module.c
, ma solo nella sezione 64-bit. Penso di dover scrivere il trasferimento da solo o di capire quale flag di riposizionamento ho bisogno e cambiare il flag durante la compilazione. Non capisco veramente cosa stia succedendo nel codice di delocalizzazione, quindi per favore aiutami a capire come dovrei risolvere questo problema. Non penso di poter costruire il sistema operativo come 64-bit perché sembra rompere il sistema, quindi per favore aiutami a trovare soluzioni alternative.
E 'possibile che si ha a che fare con la MMU? – Stuart
Stai solo pensando ad alta voce, ma puoi [target] -objdump -r alcuni moduli compilati dalla macchina di destinazione e capire che tipo di rilocazioni stanno usando? E poi capire dove nel sistema di costruzione viene scelto il tipo da usare? Sei sicuro che il tuo sistema di costruzione/configurazione/intestazioni corrisponde a quello che c'è sulla macchina? –
Quale processore Leon? Quale distribuzione è in esecuzione - qualcosa da Gaisler o qualcos'altro? Hai -m32 nei tuoi flag di compilazione? –