为arm32

时间:2016-01-06 06:47:48

标签: gcc linux-kernel embedded-linux

为arm32平台构建一个内核映像时,在最终链接中,错误为:

  

arm-eabi-ld -EL -p --no-undefined -X --build-id -o .tmp_vmlinux1 -T obj / KERNEL / arch / arm / kernel / vmlinux.lds arch / arm / kernel / head .o init / built-in.o --start-group usr / built-in.o arch / arm / vfp / built-in.o arch / arm / kernel / built-in.o arch / arm / mm / built -in.o arch / arm / common / built-in.o arch / arm / net / built-in.o arch / arm / crypto / built-in.o arch / arm / mach-sc / built-in.o kernel / built-in.o mm / built-in.o fs / built-in.o ipc / built-in.o security / built-in.o crypto / built-in.o block / built-in.o arch /arm/lib/lib.a lib / lib.a arch / arm / lib / built-in.o lib / built-in.o drivers / built-in.o sound / built-in.o firmware / built-in .o arch / arm / oprofile / built-in.o net / built-in.o --end-group   驱动程序/内置in.o:

     

未明确引用`__aeabi_ldivmod'

     

make [2]:*** [vmlinux]错误1

我知道原因是我使用arm32的64位divison不支持64位,并且使用do_div()可以摆脱__aeabi_ldivmod错误。我知道__aeabi_ldivmod是在libgcc.a中定义的,所以我在我的内核Makefile中添加了以下代码:

--- a/Makefile  
+++ b/Makefile  
@@ -677,6 +677,7 @@   
LDFLAGS_BUILD_ID = $(patsubst -Wl$(comma)%,%,\  
                          $(call cc-ldoption, -Wl$(comma)--build-id,))  
KBUILD_LDFLAGS_MODULE += $(LDFLAGS_BUILD_ID)  
LDFLAGS_vmlinux += $(LDFLAGS_BUILD_ID)  
+LDFLAGS_vmlinux += -L$(MY_LIBPATH) -lgcc  

但它仍然无法奏效,所以任何人都可以帮助解决我的问题:
1)为什么libgcc.a在内核构建中没有默认链接?
2)如何链接libgcc.a以修复链接错误?

[更新]

好的,我在OSDev wiki中找到了-lgcc的以下注释:

  

-lgcc
  传递-nodefaultlibs(由-nostdlib暗示)时禁用重要的libgcc库。编译器需要这个库进行许多操作,这些操作不能自行完成,或者更有效地放入共享函数中。 您必须在链接行末尾附近传递此库,在所有其他目标文件和库之后,或者链接器不会使用它并且您会收到奇怪的链接器错误

所以我将-L${MYLIB_PATH} -lgcc into硬编码到scripts / link-vmlinux.sh中:

--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -55,7 +55,7 @@ vmlinux_link()
        if [ "${SRCARCH}" != "um" ]; then
                ${LD} ${LDFLAGS} ${LDFLAGS_vmlinux} -o ${2}                  \
                        -T ${lds} ${KBUILD_VMLINUX_INIT}                     \
-                       --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1}
+                       --start-group ${KBUILD_VMLINUX_MAIN} --end-group ${1} -L${MYLIB_PATH} -lgcc
        else
                ${CC} ${CFLAGS_vmlinux} -o ${2}                              \
                        -Wl,-T,${lds} ${KBUILD_VMLINUX_INIT}                 \

然后构建没有__aeabi_ldivmod错误 虽然我想找到更好的修改,而不仅仅是编写代码并知道为什么内核没有链接libgcc默认。

1 个答案:

答案 0 :(得分:1)

不要编辑 scripts/link-vmlinux.sh,只编辑某些 Makefile。例如,如果您遇到此错误:

drivers/power/reset/msm-poweroff.c:249: undefined reference to `lge_set_restart_reason'

在linux内核源代码目录顶部运行cscope -R,然后找到lge_set_restart_reason的全局定义,在include/soc/qcom/lge/lge_handle_panic.h中找到文件定义

但是lge_handle_panic.h只有lge_set_restart_reason的定义,你需要lge_handle_panic.c,它有这个功能,长这样:

    void lge_set_restart_reason(unsigned int reason)
{
        writel_relaxed(reason, RESTART_REASON);
        if(use_hardreset) {
                qpnp_pon_set_restart_reason(map_imem_reboot_to_pmic(reason));
                qpnp_pon_system_pwr_off(PON_POWER_OFF_HARD_RESET);
        }
}

所以你需要编辑drivers/power/reset/Makefile来包含lge_handle_panic.o目标文件:

obj-$(CONFIG_POWER_RESET_MSM) += msm-poweroff.o lge_handle_panic.o

在自定义内核中,很多功能都是通过配置启用的,我的意思是:

#ifdef CONFIG_LGE_HANDLE_PANIC
static void __iomem *msm_timer0_base;

void __iomem *wdt_timer_get_timer0_base(void)
{
        return msm_timer0_base;
}

static void wdt_timer_set_timer0_base(void __iomem * iomem)
{
        msm_timer0_base = iomem;
}
#endif

如果再次出现此错误,您需要启用 CONFIG_LGE_HANDLE_PANIC 或任何配置,或者删除“ifdef”和“endif”(我不建议这样做)