Linux kernel 插入外部交叉编译SPARC Linux模块时发生重新定位错误
首先:我不是专家,所以请原谅我在解释自己时犯的任何错误 我正在尝试使用SPARC-Linux kernel 插入外部交叉编译SPARC Linux模块时发生重新定位错误,linux-kernel,cross-compiling,kernel-module,sparc,relocation,Linux Kernel,Cross Compiling,Kernel Module,Sparc,Relocation,首先:我不是专家,所以请原谅我在解释自己时犯的任何错误 我正在尝试使用SPARC-Linux-GCC-4.4.2为SPARC机器交叉编译一个外部Linux模块。Linux内核的版本是2.6.36.4-00037-g059aa91-dirty。它已经用LEON处理器中的一些文件进行了修补。构建流提供给我,它使用LinuxBuild、Buildroot和Busybox。我正在尝试制作一个32位操作系统 一切似乎都正常,但在我编译模块并尝试将其insmod到SPARC系统后,我得到以下错误: modu
Linux-GCC-4.4.2
为SPARC机器交叉编译一个外部Linux模块。Linux内核的版本是2.6.36.4-00037-g059aa91-dirty
。它已经用LEON
处理器中的一些文件进行了修补。构建流提供给我,它使用LinuxBuild
、Buildroot
和Busybox
。我正在尝试制作一个32位操作系统
一切似乎都正常,但在我编译模块并尝试将其insmod到SPARC系统后,我得到以下错误:
module hellok: Unknown relocation: 6
此错误来自~/linuxbuild-1.0.3/linux/linux-2.6-git/arch/sparc/kernel/module.c
为了完整起见,我将提供整个方法:
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;
}
因此,重定位6对应于相对32位。这在
module.c
case语句中定义,但仅在64位部分下定义。我想我要么自己编写重新定位,要么弄清楚我需要什么样的重新定位标志,并在编译过程中更改标志。我真的不明白重新定位代码中发生了什么,所以请帮助我找出应该如何解决这个问题。我认为我无法将操作系统构建为64位,因为它似乎破坏了系统,所以请帮助我找到替代解决方案。对于Leon Linux配置(linuxbuild-1.0.1),我自己的模块也有同样的问题
我所做的是将代码的“case R_SPARC_DISP32”部分(4行)移到“#endif/*CONFIG_SPARC64*/”行之后
那是个坏家伙,哈利;-)但至少我现在可以安装模块了。。。
现在,当应用程序调用模块的例程时,我需要在用户端寻找副作用
所以,接下来
致以最良好的祝愿,
Karim这可能与MMU有关吗?只是想大声说出来,但是你能[target]-objdump-r从目标机器编译一些模块,并找出它们使用的是什么类型的重新定位吗?然后找出在构建系统中选择要使用的类型的位置?您对构建系统/配置/头文件与机器上的内容匹配有多大信心?哪个Leon处理器?正在运行哪个发行版-Gaisler发行的还是其他发行版?您的构建标志中是否有-m32?查看运行系统的/lib/modules下是否有任何(未使用的)内容,如果有,请执行以下操作:readelf-r something.ko | grep-o'r[^]*'| sort-u并比较系统上的内容和您构建的内容。您确定您使用的内核源与系统上的内核版本相同(即uname-a)吗?是否有一个/proc/config.gz可以提取并检查?在/lib/modules中没有任何内容。没有/proc/config.gz。我通过“makexconfig”构建了一些非定制模块,它们与我试图构建的模块具有相同的重新定位标志。我可以使用以下标志删除[.eh_frame]和重新定位错误:-fno-dwarf2-cfi-asm:Emit DWARF 2 unwind info as compiler generated“.eh_frame”部分,而不是使用GAS“.cfi_*”指令。用这个会不好吗?我也用了一段时间,但我觉得不舒服,因为我不能确定这是否合适。我认为-fno-dwarf2-dfi-asm标志更好,但不能肯定。
/* 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. */
...