非平凡的hello world cross building的Makefile导致Raspberry上的segemnation错误

时间:2014-10-06 16:16:45

标签: c++ makefile raspberry-pi cross-compiling toolchain

两个更新 - 请参阅本文末尾:

在两个不眠之夜后,我决定(第一次)直接请求你的支持。

问题
当我尝试为Raspberry(RPI)进行交叉编译时,我的intel ubuntu上的代码安静,导致代码以分段错误运行时错误结束,当我在RPI上运行时

直接在目标RPI上编译的相同代码工作得很好。源代码变得很大,等待在RPI上编译它,因此我想加速我的Ubuntu上的编译。

解决方案
1)按照http://elinux.org/RPi_Kernel_Compilation的步骤进行操作 2)从我的目标RPI复制“rootfs”,包括/ lib / usr / opt
3)修改原始项目Makefile以指向目标库并包含
4)享受快速编译


结果
在第4点失败。
我可以编译工作内核,模块和普通的Hello World应用程序
我可以编译我的项目并在RPI上运行它 - 它启动但总是失败一段时间后分段出错。很可能在首次使用alsa lib之后 的备注
我在我的项目中使用了两个外部库 - > -lasound -lconfig ++ -lconfig和单独文件中的几个自己的类。

这是我的标准Makefile,它在RPI上生成工作代码

CCC=g++
CXX=g++
RM=rm -f
WARNINGS=-W -Wall -Waggregate-return \
-Wcast-align -Wcast-qual -Wshadow \
-Wwrite-strings -Wno-unused-variable -Wno-unused-parameter
CPPFLAGS=-c -Wall -O3 -DFIXED_POINT=16 -DDEBUG=1 $(WARNINGS) -DREAL_FASTFIR -DFAST_FILT_UTIL 
CFLAGS=-c 
LDFLAGS=-g -Wall
LDLIBS=-lasound  -lconfig++ -lconfig -lc -lm
SRCS=spectrum.cpp kiss_fft.c kiss_fftr.c oled.cpp mibridge.cpp
//OBJS=$(subst .c,.o,$(SRCS))
OBJS=spectrum.o kiss_fft.o kiss_fftr.o oled.o mibridge.o
all: spectrum
spectrum: $(OBJS)
    $(CXX) $(LDFLAGS) -o spectrum $(OBJS) $(LDLIBS) 
depend: .depend
.depend: $(SRCS)
    rm -f ./.depend
    $(CXX) $(CPPFLAGS) $(CFLAGS) -MM $^>>./.depend;
clean:
    #touch *
    $(RM) $(OBJS)
    $(RM) *~ .dependtool
    $(RM) spectrum
print-%:
    @echo '$*=$($*)'
include .depend

...这是我想用于交叉编译的(有问题的)Makefile:

TOOLCHAIN_PREFIX=$(HOME)/development/raspberry/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-

SYSROOT=$(HOME)/development/raspberry/rootfs
CROSS_DIR=$(HOME)/development/raspberry/rootfs

CXX    = $(TOOLCHAIN_PREFIX)g++
CC     = $(TOOLCHAIN_PREFIX)gcc
LD     = $(TOOLCHAIN_PREFIX)g++

RM=rm -f

INCLUDEDIR = ./ 
INCLUDEDIR += $(CROSS_DIR)/usr/include \
              $(CROSS_DIR)/usr/include/arm-linux-gnueabihf 


LIBRARYDIR= $(CROSS_DIR)/lib \
            $(CROSS_DIR)/lib/arm-linux-gnueabihf \
            $(CROSS_DIR)/usr/lib/arm-linux-gnueabihf \
            $(CROSS_DIR)/opt/vc/lib 

XLINK_LIBDIR= $(CROSS_DIR)/lib \
              $(CROSS_DIR)/lib/arm-linux-gnueabihf \
              $(CROSS_DIR)/usr/lib/arm-linux-gnueabihf \
              $(CROSS_DIR)/opt/vc/lib       

LIBRARY=  asound  config++ config      


INCDIR   = $(patsubst %,-I%,$(INCLUDEDIR))
LIBDIR   = $(patsubst %,-L%,$(LIBRARYDIR))
LIB      = $(patsubst %,-l%,$(LIBRARY))
XLINKDIR = $(patsubst %,-Xlinker -rpath-link=%,$(XLINK_LIBDIR))


WARNINGS=-W -Wall -Waggregate-return -Wcast-align -Wcast-qual -Wshadow -Wwrite-strings -Wno-unused-variable -Wno-unused-parameter -Wno-sequence-point -Wno-unused-but-set-variable -Wno-cast-align


OPT=-c -Wall -O3 -DFIXED_POINT=16 -DDEBUG=1 -DREAL_FASTFIR -DFAST_FILT_UTIL    
OPT += -Ofast -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s
CFLAGS=-c -mfloat-abi=hard


CXXFLAGS= $(OPT) $(WARNINGS) $(INCDIR) 
LDFLAGS= $(LIBDIR) $(LIB) $(XLINKDIR) -lc -lm 

SRCS=spectrum.cpp kiss_fft.c kiss_fftr.c oled.cpp mibridge.cpp
OBJS=spectrum.o kiss_fft.o kiss_fftr.o oled.o mibridge.o


all: spectrum

spectrum: $(OBJS)
        $(CXX) --sysroot=$(SYSROOT) $(LDFLAGS) $(OBJS) -o spectrum

depend: .depend

.depend: $(SRCS)
        rm -f ./.depend
        $(CXX) $(CXXFLAGS) $(CFLAGS) -MM $^>>./.depend;        

clean:
        #touch *
        $(RM) $(OBJS)
        $(RM) *~ .dependtool
        $(RM) spectrum

print-%:
        @echo '$*=$($*)'

include .depend

我能看到的唯一区别是gcc版本:
在Ubuntu:

gcc version 4.8.3 20140106 (prerelease) (crosstool-NG linaro-1.13.1-4.8-2014.01 - Linaro GCC 2013.11)* 

关于RPI:

gcc version 4.6.3 (Debian 4.6.3-14+rpi1)* 

然而,简单的“Hello World”和我应用程序中的前十几个源代码行工作正常 另一个观察:
RPI上的bin代码大小为:59906
来自cross的bin代码大小为:121254
看起来链接器混合了什么?


编辑: 添加结果objdump -x
有一些差异,我试图在以下两个转储中选择:

分段错误可执行文件已得到:

spectrum:     file format elf32-little
architecture: UNKNOWN!, flags 0x00000112:
...

Dynamic Section:
...
  NEEDED               libc.so.6
  NEEDED               libgcc_s.so.1
...
SYMBOL TABLE:
...
00000000 l    d  .ARM.attributes        00000000              .ARM.attributes
00000000 l    df *ABS*  00000000              /home/peter/development/raspberry/rootfs/usr/lib/arm-linux-gnueabihf/crt1.o

RPI版本有许多相似之处,但这些是我能想到的一些差异:

spectrum:     file format elf32-littlearm
architecture: arm, flags 0x00000112:
...
Dynamic Section:
...
  NEEDED               libm.so.6
  NEEDED               libc.so.6
  NEEDED               libgcc_s.so.1
  NEEDED               libpthread.so.0
...
Version References: 
...  
  required from libm.so.6:       <---- mising in the cross-compiled version
    0x0d696914 0x00 02 GLIBC_2.4
private flags = 5000002: [Version5 EABI] [has entry point]
...

在RPI原生(工作)版本中更有趣的是完全缺少对它的引用 crt1.o,crti.o,crtn.o,

如果您建议objdump中的任何特定条目,它将帮助我找到更多有用的信息。

编辑2 根据@yegorich的推荐,我尝试了 strace 并没有找到任何特别有用的提示。 但是我尝试调试 - 只是为了查看分段的来源。 1.使用-g -ggdb编译 2.运行gdb我的应用程序 结果如下:

Program received signal SIGSEGV, Segmentation fault.
0x0000d490 in demux(short*, short*, short*, CONFIG&) () at spectrum.cpp:530
530            if (PrgCfg.Sound_Channels[0] == 'M') { 

没什么特别的。相同的代码使用本机编译的代码运行,没有任何问题。 我在代码中做了一些更改,然后代码在另一点崩溃 - 没有“任何”可行的原因。

然后我添加了一些“debug”printf,其中一个变量改变了它的值,在范围内我对此值没有任何作用。对我来说,一个明确的信号表明内存已被我的代码“损坏”。

现在我必须找到 - 有史以来最严重的错误。

我仍然不明白为什么如果用原生g ++编译代码就不会发生这种情况。 有什么想法吗?


非常感谢您方提出的任何建议 谢谢。
彼得

0 个答案:

没有答案