我做的是busybox-1.24.1
arm-linux-gnueabi-gcc 4.7.3
我的linux内核是4.4.3
在编译linux内核时已经选择了支持eabi
但是还是出现了:
VFS: Mounted root (jffs2 filesystem) on device 31:3.
Freeing unused kernel memory: 208K (c06c2000 - c06f6000)
Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000004
在linux中搜索内核代码 exitcode=0x00000004 这个退出代码 表示的非法指令!!
于是在网上搜索,发现是busybox编译成了armv5t架构我的s3c2440是armv4t不能使用armv5t架构的指令,所以出现了非法指令错误:
——————原帖——————————————
动态库的搜索路径先后顺序:
1、编译目标代码时指定的动态库搜索路径:在编译的时候,可以指定-Wl,-rpath=你的路径
2、环境变量LD_LIBRARY_PATH指定的动态库搜索路径;
3、配置文件/etc/ld.so.conf中指定的动态库搜索路径(我移植的根文件系统,ld.so.conf在/etc目录下的,而且指定搜索路径位/lib)
4、默认的动态库搜索路径/lib
5、默认的动态库搜索路径 /usr/lib
明白这些了,若我们运行的应用程序找不到库那么可以有很多种解决途径~!
1、编译的时候加上-Wl,-rpath=。。。。
2、使用export LD_LIBRARY_PATH=….
3、将路径追加到/etc/ld.so.conf中
4、将so拷贝到/lib目录下
5、将so拷贝到/usr/lib目录下
我们知道动态库的搜索顺序后,下面就需要获得适合自己目标板cpu体系的库,或获得库源码用交叉工具链编译自己的库
这里我从crosstools 4.3.2 中获得库 然后cp到开发板根文件系统的/lib 目录下
在交叉工具链下 /usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib 目录下
用 readelf -A 命令 看 某库文件体系结构信息如下
Attribute Section: aeabi
File Attributes
Tag_CPU_name: “4T”
Tag_CPU_arch: v4T
Tag_ARM_ISA_use: Yes
Tag_ABI_PCS_wchar_t: 4
Tag_ABI_FP_denormal: Needed
Tag_ABI_FP_exceptions: Needed
Tag_ABI_FP_number_model: IEEE 754
Tag_ABI_align_needed: 8-byte
Tag_ABI_align_preserved: 8-byte, except leaf SP
Tag_ABI_enum_size: int
上述体系符正是s3c2440的架构,故我们应当把这个库文件cp到/lib 下
而在工具链下存放有三个库
usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/armv4t/lib/ (armv4)
usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/lib/ (armv5)
usr/local/arm/4.3.2/arm-none-linux-gnueabi/libc/thumb2/lib (armv5)
上面库所属的cpu体系,可以通过readelf -A 命令 查看该目录下的任意一个库文件 例如:readelf -A libc.so.6
用readelf -d 命令可以查看,可执行文件所依赖的动态库,如果某个文件依赖libc.so.6 我们也许不能仅仅把其链接和库文件cp到/lib下
readelf -d libc.so.6 来看
Dynamic section at offset 0x11ff18 contains 25 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [ld-linux.so.3]
0x0000000e (SONAME) Library soname: [libc.so.6]
0x0000000c (INIT) 0x14e18
0x0000001a (FINI_ARRAY) 0x1266f4
0x0000001c (FINI_ARRAYSZ) 4 (bytes)
0x00000004 (HASH) 0x11ad30
0x6ffffef5 (GNU_HASH) 0x194
0x00000005 (STRTAB) 0xbd6c
0x00000006 (SYMTAB) 0x3a1c
0x0000000a (STRSZ) 21853 (bytes)
还依赖ld-linux.so.3 库。因此我们要把库文件及其所依赖的库文件统统cp到/lib下才可以。cp完成后可以运行一下动态编译的application 是不是不再报错了!
查资料可以发现在/etc/ld.so.conf 文件可以设置动态库的路径。
按下述步骤更新配置后应用程序就按此路径搜索库:
1。rm -f /etc/ld.so.cache
2。vim /etc/ld.so.config,在其中加入你新的libs的目录 (在其加入动态库的路径)
3。用“ldconfig -f etc/ld.so.conf -C etc/ld.so.cache”生成一个新的ld.so.cache
但是我用上述方法生成ld.so.cache 后会提示 -/bin/sh: XXX: not found
无法找到动态库。具体原因现在还没有找到。
另外交叉链 arm-none-linux-gnueabi-gcc 默认编译armV5体系
arm-none-linux-gnueabi-gcc -march=armv4t -o hello -static hello.c 加上-march=armv4t 才可在2440上运行,否则提示Illegal instruction。
为了方便以后编译程序模块,要想个法子才行,友善的做法很好,就是建立带参数的脚本代替gcc,脚本是另外一个名字,叫arm-linux-gcc!脚本内容如下
exec arm-none-linux-gnueabi-gcc -march=armv4t $*
g++也类似。其他工具ar阿ld阿统统建立符号链接。最后加入搜索路径方便使用。
————————————————————————
按照这种方法还是不能成功编译出来的还是 V5架构
于是在网上又看到一篇很好的贴
————————原帖——————————————
最近在学习和做项目的时候需要搭建s3c2440的环境,遇到了一些问题(非法指令)和大家分享一下修正错误的过程。
一、我先介绍一下我们的实验环境:
内核版本:kernel-2.6.27-android_ok
编绎器:arm-2010q1-202-arm-none-linux-gnueabi
硬件:(S3C2440) 支持armv4t 指令,
busybox版本:busybox-1.17.0
我们这次实验的kernel相对来说版本不算老,编译可就是非常新的了。
他支持ARMV7,就是cortex-A8,A9系列的。
而我们的硬件s3c2440 只有armv4t的指令集。
二、问题的出现:
我们用新的编译器编译出来的uboot,kernel均能正常执行。
当我们用它来编译busybox,并且生成静态busybox的时候,有时候执行正常,
有时候执行就不正常。不正常的时候出现如下提示:
Illegal instruction
这个错误表明我们的程序执行了不正确的指令。
一般这种情况是因为我们编译起编译出了较高版本的ARM指令造成的。
三、排错
排错1:让编译器编译出支持s3c2440 的armv4t,在网络上查询得知增加 “-march=armv4t”选项即可。
于是在busybox make menuconfig 中编译选项中加入了上述参数,见下图
增加 -march=armv4t
残酷的事实验证后,结果发现还是不行。
这是为什么,我们该怎么做?有两个问题困扰着我:
1.出现的非法指令是在哪,是什么指令?
2.所加入的参数到底有没有起作用?
排错二:
现来寻找上述第一个问题的答案,
由于在交叉编译过程中产生了非法指令,故在执行过程中会产生异常,我们进入到内核的非法指令异常去看看。
于是到内核 (arch/arm/kernel/traps.c) 中找到相关的异常处理函数(do_undefinstr)
其中部分代码为:
if (user_debug & UDBG_UNDEFINED)
{
printk(KERN_INFO “%s (%d): undefined instruction: pc=%p\n”, current->comm,
task_pid_nr(current), pc);
dump_instr(regs);
}
通过上面的代码我们如果
CONFIG_DEBUG_USER 定义了,并且user_debug设置了参数,应该可以看到系统打印是哪个程序产生了异常。
通过kernel的.config文件发现 CONFIG_DEBUG_USER已经定义了。
user_debug是一个命令行参数。
好了我们可以通过uboot打开:
打开的方法为在U-boot bootargs 添加 user_debug=1;
(egs: setenv bootargs console=ttySAC0,115200 user_debug=1 saveenv );
在LINUX再次执行程序,发现在原先的出现“指令错误”的上方多出了两条具体的错误信息。
打印出非法指令信息
以上图片中,是执行mdev(mdev,是busybox的子程序)时出错。 pc=000ca8b4,是指mdev的ca8b4处有个非法指令。
接下来从busybox中找出次指令:
进入busybox目录 ,输入命令(arm-none-linux-gnueabi-objdump -D busybox > bu.S 意思为将生的目标文件的汇编代码dump 到 bu.S 文件中) ,
打开bu.S(命令:vim bu.S) 文件,根据出现“指令错误”上面两条具体指令错误位置信息可以找到非法指令指置,我们查到该位置为clz指令:
在ARM官方网上息查询得知clz指令相关信息:(http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0204ic/Cihjgjed.html)
clz 指令体系结构:
此 ARM 指令可用于 ARMv5 及更高版本。
此 32 位 Thumb 指令可用于 ARMv6T2 及更高版本。
此指令无 16 位 Thumb 版本。
我们最终找到出现非法指令的位置,以及是什么指令。
好,接下来,我们需要第二步,回到busybox本身:
我们想把编译过程中的参数给打印出来,通过查看busybox中的Makefile,得知由quiet_决定,我们在编译busybox时加入选项参数V=1(egs: make V=1);
通过编译过程所打印的信息知所加的选项参数在编译的时候起了作用,但在链接生成静态库的时候并没有起到作用。
虽然知道在make menuconfig 加了相关参数(-march=armv4t),编译器并没有去执行这条语句,可能的原因是:我们所加的参数的格式不正确,或其它原因等)。于是我们就想找一种能解决此问题的方法。下面给出一种针对上述问题的解决的方案:
为了以防万一,我们手动将编译链接的地方都增加了 (-march=armv4t )
我们可在busybox 中的Makefile.flags 中找到静态链接的位置以及编译的位置:
将:
ifeq ( (CONFIGSTATIC),y)CFLAGSbusybox+=−staticendif修改为:ifeq( (CONFIG_STATIC),y)CFLAGS_busybox += -static -march=armv4t
endif
将:
CPPFLAGS += (callcc−option,−std=gnu99,)修改为:CPPFLAGS+= (call cc-option,-std=gnu99 -march=armv4t,)
再进行编译就生成了我们所需指令版本的目标文件了。
相关软件下载地址:交叉编译器:arm-2010q1-202-arm-none-linux-gnueabi下载地址:
http://www.codesourcery.com/sgpp/lite/arm/portal/release1293 具体为Recommended Packagesbusybox-1.17.0下载地址:http://www.busybox.net/
————————————————————————
按照这个方法仍然没有解决
subingxi@ubuntu:/work/busybox-1.24.1 arm−linux−gnueabi−readelf−AbusyboxAttributeSection:aeabiFileAttributesTagCPUname:“5T”TagCPUarch:v5TTagARMISAuse:YesTagTHUMBISAuse:Thumb−1TagABIPCSwchart:4TagABIFProunding:NeededTagABIFPdenormal:NeededTagABIFPexceptions:NeededTagABIFPnumbermodel:IEEE754TagABIalignneeded:8−byteTagABIalignpreserved:8−byte,exceptleafSPTagABIenumsize:intsubingxi@ubuntu:/work/busybox−1.24.1
于是我想到看看编译工具的信息
subingxi@ubuntu:/work/busybox-1.24.1 arm−linux−gnueabi−gcc−vUsingbuilt−inspecs.COLLECTGCC=arm−linux−gnueabi−gccCOLLECTLTOWRAPPER=/usr/lib/gcc−cross/arm−linux−gnueabi/4.7/lto−wrapperTarget:arm−linux−gnueabiConfiguredwith:../src/configure−v–with−pkgversion=′Ubuntu/Linaro4.7.3−12ubuntu1′–with−bugurl=file:///usr/share/doc/gcc−4.7/README.Bugs–enable−languages=c,c++,go,fortran,objc,obj−c++–prefix=/usr–program−suffix=−4.7–enable−shared–enable−linker−build−id–libexecdir=/usr/lib–without−included−gettext–enable−threads=posix–with−gxx−include−dir=/usr/arm−linux−gnueabi/include/c++/4.7.3–libdir=/usr/lib–enable−nls–with−sysroot=/–enable−clocale=gnu–enable−libstdcxx−debug–enable−gnu−unique−object–disable−libmudflap–disable−libitm–enable−plugin–with−system−zlib–enable−objc−gc–with−cloog–enable−cloog−backend=ppl–disable−cloog−version−check–disable−ppl−version−check–enable−multiarch–enable−multilib–disable−sjlj−exceptions–with−arch=armv5t–with−float=soft–disable−werror–enable−checking=release–build=i686−linux−gnu–host=i686−linux−gnu–target=arm−linux−gnueabi–program−prefix=arm−linux−gnueabi−–includedir=/usr/arm−linux−gnueabi/includeThreadmodel:posixgccversion4.7.3(Ubuntu/Linaro4.7.3−12ubuntu1)subingxi@ubuntu:/work/busybox−1.24.1 arm-linux-gnueabi-readelf -A busybox
在其中我看到 –with-arch=armv5t 默认配置就是armv5t
还是没有办法修改,最后只有卸载掉arm-linux-gnueabi
安装arm-none-linux-gnueabi-gcc
再按照第一个贴的方法,成功!!