En primer lugar: no soy un experto, así que disculpe cualquier error que haga tratando de explicarme.Error de reubicación al insertar el módulo de SPARC Linux externo compilado cruzado
Estoy tratando de realizar una compilación cruzada de un módulo externo de Linux para una máquina SPARC utilizando Sparc- Linux-GCC-4.4.2
. La versión del kernel de Linux es 2.6.36.4-00037-g059aa91-dirty
. Se ha corregido con algunos archivos del procesador LEON
. El flujo de compilación se me proporciona y usa LinuxBuild
, Buildroot
y Busybox
. Estoy tratando de hacer un sistema operativo de 32 bits.
Todo parece funcionar pero después de compilar el módulo y trato de insmodéelo al sistema SPARC me sale este error:
module hellok: Unknown relocation: 6
Este error proviene de ~/linuxbuild-1.0.3/linux/linux-2.6-git/arch/sparc/kernel/module.c
que proporcionará todo el método por el bien de exhaustividad:
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;
}
por lo que entiendo el caso de que el defecto es el que estoy cayendo debajo. ELF_R_TYPE(rel[i].r_info
(SPARC) Movimientos tipos se definen en mi archivo ~/linuxbuild-1.0.3/dist/buildroot/build-br/staging/usr/include/elf.h
y algunos son los siguientes:
/* 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. */
...
Así reubicación 6 corresponde a R_SPARC_DISP32
aka PC
relativa de 32 bits. Esto se define en la declaración de caso module.c
, pero solo en la sección de 64 bits. Creo que o bien debo escribir el traslado yo mismo o averiguar qué bandera de reubicación necesito y cambiar el indicador durante la compilación. Realmente no entiendo qué está pasando en el código de reubicación, así que por favor ayúdame a descubrir cómo debo solucionar esto. No creo que pueda construir el sistema operativo como de 64 bits porque parece romper el sistema, así que ayúdenme a encontrar soluciones alternativas.
¿Es posible que esto tiene que ver con la MMU? – Stuart
Solo pensando en voz alta, pero ¿puede [objetivo] -objdump -r algunos módulos compilados de la máquina de destino y averiguar qué tipo de reubicaciones están utilizando? Y luego, ¿en qué parte del sistema de compilación se elige el tipo que se utilizará? ¿Qué tan seguro está de que su sistema de construcción/configuración/encabezados coincida con lo que hay en la máquina? –
¿Qué procesador Leon? ¿Qué distribución se está ejecutando, algo de Gaisler o algo más? ¿Tienes -m32 en tus banderas de construcción? –