Unusual segfault when using C++ Std Lib on embedded Linux
Here's some sample test code I'm trying to run on an embedded Linux system:
#include <iostream>
int main(int argc, char *argv[])
{
char c = 'A';
int i = 7;
std::cout << "Hello World from C++" << std::endl;
std::cout << "c=" << c << std::endl;
std::cout << "i=" << i << std::endl;
}
The embedded system is a Microblaze, which is a 32-bit RISC softcore processor running on a Xilinx FPGA. Please don't be put off by that, as a lot of your standard Linux knowledge will still apply. The processor is configured as LSB with an MMU, and the Linux build I'm using (PetaLinux, supplied by Xilinx) is expecting the same. I'm using the supplied GNU compiler; Microblaze appears to be officially supported in GCC.
The problem I'm having is that when the stdlib needs to interact with the integer, it segfaults. Here's the output:
Hello World from C++
c=A
Segmentation fault
Note that the char is handled fine. The C equivalent of this code also works fine:
#include <stdio.h>
int main(int argc, char *argv[])
{
char c = 'A';
int i = 7;
printf("Hello World from Cn");
printf("c=%cn", c);
printf("i=%in", i);
return 0;
}
...
Hello World from C
c=A
i=7
This leads me to suspect an issue with the shared library libstdc++.so.6.0.20
. That library is supplied by Xilinx though, so it should be correct. The file
output of that library is:
libstdc++.so.6.0.20: ELF 32-bit LSB shared object, Xilinx MicroBlaze 32-bit RISC, version 1 (SYSV), dynamically linked, not stripped
The file
output of my binary is:
cpptest: ELF 32-bit LSB executable, Xilinx MicroBlaze 32-bit RISC, version 1 (SYSV), dynamically linked, interpreter /lib/ld.so.1, for GNU/Linux 2.6.32, stripped
I've also tried statically linking my binary using the -static
flag, but the result was the same.
Here are the most relevant compiler and linker settings I'm using, but I've tried changing these with no avail.
CC=microblazeel-xilinx-linux-gnu-gcc
CXX=microblazeel-xilinx-linux-gnu-g++
CFLAGS= -O2 -fmessage-length=0 -fno-common -fno-builtin -Wall -feliminate-unused-debug-types
CPPFLAGS?=
CXXFLAGS= -O2 -fmessage-length=0 -fno-common -fno-builtin -Wall -feliminate-unused-debug-types
LDFLAGS=-Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed
To compile:
@$(CCACHE) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(CFLAGS) $< -o "$@"
To link:
@$(CXX) $(RELOBJECTS) $(LDFLAGS) $(EXT_LIBS) -o $(RELBINARY)
Note that microblazeel
refers to the little endian version of the microblaze compiler.
I would very much like to debug this or at least look at a coredump, but no coredump seems to be produced when the segfault happens, and there's no gdb
executable in the Microblaze Linux build. Maybe I'm missing something?
Thanks for taking your time to read this. Any thoughts?
From what I could see after a bit of research, vivado
is the HW development IDE [because they offer a trial period--so it's the HW devel, which they always want to charge for].
If you're using the standard SDK board from Xilinx, everything should be preconfigured. Otherwise, a HW designer produces a HW design that has Microblaze in it.
From that, you may have to use petalinux to generate a new boot, kernel, etc. image that is compatible.
You may need to rebuild libstdc++
from source, but I'd do that as a last resort. For example, don't bother with it, until you've got gdb
working and have test results.
Here are some petalinux PDF files:
http://www.xilinx.com/support/documentation/sw_manuals/petalinux2013_10/ug977-petalinux-getting-started.pdf
http://www.xilinx.com/support/documentation/sw_manuals/petalinux2013_10/ug981-petalinux-application-development-debug.pdf
The development guide shows how to invoke gdb (eg):
On the target system:
gdbserver host:1534 /bin/myapp
On the development system:
petalinux-utils --gdb myapp
followed by target remote 192.168.0.10:1534
I've done some editing on your Makefile with annotations. I've commented out some of the non-essential options. Note that I'm using the +=
operator to build up CFLAGS/CXXFLAGS
gradually
The basic idea here is to do a build with minimum deviations from "standard". Add only proven essential options. Build and test. Add back the options one-by-one [rebuild and test each time] until you find the option that is causing the problem.
I do, however, have a strong suspicion about -fno-common
being a source of problems. Also, to a lesser extent, I'm a bit suspicious of -Wl,--as-needed
Should these options work? Sure, but xilinx/microblaze ain't no x86 ...
I've added two command line make variables:
DEBUG
-- generate for debug with gdb
VERBOSE
-- show everything about the build process
For example, try make <whatever> DEBUG=1 VERBOSE=1
CC = microblazeel-xilinx-linux-gnu-gcc
CXX = microblazeel-xilinx-linux-gnu-g++
CPPFLAGS ?=
CMFLAGS += -Wall -Werror
CMFLAGS += -fmessage-length=0
# compile for gdb session
# NOTES:
# (1) -gdwarf-2 may or may not be the the right option for microblaze
# (2) based on doc for -feliminate-unused-debug* petalinux/microblaze may want
# stabs format
ifdef DEBUG
CMFLAGS += -gdwarf-2
CMFLAGS += -O0
# compile for normal build
#else
CMFLAGS += -O2
CMFLAGS += -feliminate-unused-debug-types
endif
# NOTE: I used to use "@" on commands, but now I leave it off -- debug or not
# sure it's "ugly" but you can get used to it pretty quickly--YMMV
ifndef VERBOSE
Q :=
else
###Q := @
Q :=
endif
# let compiler/linker tell you _everything_:
# (1) configure options when tool was built
# (2) library search paths
# (3) linker scripts being used
ifdef VERBOSE
CMFLAGS += -v
LDFLAGS += -Wl,--verbose=2
endif
CMFLAGS += -fno-builtin
# NOTE: I'd _really_ leave this off as it may confuse c++ std as "<<" calls
# _M_insert (which is in the library, which is almost certainly _not_ using
# -fno-common)
###CMFLAGS += -fno-common
# NOTE: I'm also suspicious of this a little bit because the c++ lib may have
# some "weak" symbols that the c library doesn't
###LDFLAGS += -Wl,--as-needed
# NOTE: this seems harmless enough, but you can comment it out to see if it
# helps
LDFLAGS += -Wl,--hash-style=gnu
# NOTE: an optimization only
ifndef DEBUG
LDFLAGS += -Wl,-O1
endif
CFLAGS += $(CMFLAGS)
CXXFLAGS += $(CMFLAGS)
# NOTES:
# (1) leave this off for now -- doesn't save _that_ much and adds complexity
# to the build
# (2) IMO, I _never_ use it and I erase/uninstall it on any system I
# administrate (or just ensure the build doesn't use it by removing it
# from $PATH)--YMMV
###XCCACHE = $(CCACHE)
# to compile
$(Q)$(XCCACHE) $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(CFLAGS) $< -o "$@"
# to link
$(Q)$(CXX) $(RELOBJECTS) $(LDFLAGS) $(EXT_LIBS) -o $(RELBINARY)
链接地址: http://www.djcxy.com/p/86968.html
上一篇: 连字符应该逃脱吗?