EABI和OABI

EABI和OABI

作者:曹忠明,華清遠見嵌入式學院講師。

相信很多學習嵌入式linux的人都碰到過這樣一個問題:

初學linux的時候大家都用的工具鏈版本多是3.4.5或3.4.2,名字爲arm-linux-gcc或arm-softfloat-linux-gnu-gcc,可突然有一天發現這幾個版本的編譯器無法編譯最新的內核了,並且發現人們都換了工具鏈了(arm-none-linux-gnueabi-gcc),怎麼辦,換唄。於是也都換成了這個工具鏈,編譯內核,製作跟文件系統,按部就班的做,和以前沒什麼區別,很多人甚至想這些操作我都做爛了,閉着眼睛都能完成,一切和以前也沒什麼區別。可是緊接着問題來了,當內核啓動到最後階段掛載文件系統是出現如下錯誤:

kernel panic:attempted to kill init

或者什麼錯誤都不提示,只是永遠進入不了終端。

這是什麼問題呢,答案是大家需要在內核配置的時候選擇上如下內容:

make menuconfig
        Kernel Features --->
                [*] Use the ARM EABI to compile the kernel
                [*] Allow old ABI binaries to run with this kernel (EXPERIMENTAL)

選上這兩項重新編譯內核,發現上面提到的問題就解決了,爲什麼呢,這兩個選項是什麼東西呢。在這裏得提到幾個概念:

ABI:application binary interface
        OABI:old application binary interface
        EABI:extended application binary interface

但上面兩項選中後在內核的配置文件.config中CONFIG_AEABI和CONFIG_OABI_COMPAT會被設置爲“y”,CONFIG_AEABI表示現在內核爲EABI,CONFIG_OABI_COMPAT表示兼容OABI。

爲什麼這兩個選項會影響到我們的系統啓動呢。

這兩個選項可以選擇任意一個也可以都選。這裏涉及到兩個結構sys_call_table和sys_oabi_call_table,這兩個表是一個內核的跳轉表,存放的是系統調用的指針。當CONFIG_AEABI和CONFIG_OABI_COMPAT都選中的時候,當應用程序使用OABI的是時候調用sys_oabi_call_table中的系統調用,應用程序使用EABI時使用sys_call_table中的系統調用。而如果只選CONFIG_AEABI則使用sys_call_table。兩個都不選則使用sys_call_table。應爲CONFIG_OABI_COMPAT對CONFIG_AEABI有依賴關係所以不能只選擇CONFIG_OABI_COMPAT。

可以參考如下代碼

arch/arm/kernel/entry-common.S
        #if defined(CONFIG_OABI_COMPAT)

        /*
                * If we have CONFIG_OABI_COMPAT then we need to look at the swi
                * value to determine if it is an EABI or an old ABI call.
                */
        #ifdef CONFIG_ARM_THUMB
                tst r8, #PSR_T_BIT
                movne    r10, #0         @ no thumb OABI emulation
                ldreq        r10, [lr, #-4]        @ get SWI instruction
        #else
                ldr    r10, [lr, #-4]        @ get SWI instruction
            A710( and ip, r10, #0x0f000000        @ check for SWI )
            A710( teq ip, #0x0f000000 )
            A710( bne .Larm710bug )
        #endif
        #ifdef CONFIG_CPU_ENDIAN_BE8
                rev    r10, r10        @ little endian instruction
        #endif
        #elif defined(CONFIG_AEABI)
                /*
                * Pure EABI user space always put syscall number into scno (r7).
                */
            A710( ldr      ip, [lr, #-4]        @ get SWI instruction )
            A710( and    ip, ip, #0x0f000000        @ check for SWI )
            A710( teq      ip, #0x0f000000 )
            A710( bne    .Larm710bug )
        #elif defined(CONFIG_ARM_THUMB)
                /* Legacy ABI only, possibly thumb mode. */
                tst r8, #PSR_T_BIT        @ this is SPSR from save_user_regs
                addne    scno, r7, #__NR_SYSCALL_BASE        @ put OS number in
                ldreq    scno, [lr, #-4]
        #else
                /* Legacy ABI only. */
                ldr    scno, [lr, #-4] @ get SWI instruction
            A710( and    ip, scno, #0x0f000000        @ check for SWI )
            A710( teq    ip, #0x0f000000 )
            A710( bne    .Larm710bug )
        #endif
        #ifdef CONFIG_ALIGNMENT_TRAP
                ldr    ip, __cr_alignment
                ldr    ip, [ip]
                mcr    p15, 0, ip, c1, c0        @ update control register
        #endif
                enable_irq
                get_thread_info tsk
                adr tbl, sys_call_table        @ load syscall table pointer
                ldr    ip, [tsk, #TI_FLAGS]        @ check for syscall tracing
        #if defined(CONFIG_OABI_COMPAT)
                /*
                * If the swi argument is zero, this is an EABI call and we do nothing.
                *
                * If this is an old ABI call, get the syscall number into scno and
                * get the old ABI syscall table address.
                */
                bics r10, r10, #0xff000000
                eorne    scno, r10, #__NR_OABI_SYSCALL_BASE
                ldrne      tbl, =sys_oabi_call_table
        #elif !defined(CONFIG_AEABI)
                bic    scno, scno, #0xff000000    @ mask off SWI op-code
                eor    scno, scno, #__NR_SYSCALL_BASE @ check OS number
        #endif

發佈了67 篇原創文章 · 獲贊 9 · 訪問量 32萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章