Unusual segfault when using C ++ Std Lib on embedded Linux

Here is a 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 Microblaze, which is a 32-bit RISC software processor running on Xilinx FPGAs. Please do not delay, as many of your standard Linux knowledge will continue to be applied. The processor is configured as LSB with MMU, and the Linux build I use (PetaLinux, supplied by Xilinx) expects the same. I use the included GNU compiler; Microblaze appears to be officially supported by GCC.

The problem I am facing is that when stdlib needs to interact with an integer, it segfaults. Here's the conclusion:

 Hello World from C++ c=A Segmentation fault 

Note that char handles 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 C\n"); printf("c=%c\n", c); printf("i=%i\n", i); return 0; } 

...

 Hello World from C c=A i=7 

This makes me suspect a problem with the libstdc++.so.6.0.20 shared library. However, this library is supplied by Xilinx, so it must be correct. The output of the file this 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 

file output of my binary:

 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 also tried to statically link my binary using the -static flag, but the result was the same.

Here are the most suitable compiler and linker settings that I use, but I tried to change them to 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 a small continental version of the microblaze compiler.

I would really like to debug this, or at least look at coredump, but no coredump seems to be created when segfault happens and there is no gdb executable in the Microblaze Linux build. Maybe I missed something?

Thanks for taking the time to read this. Any thoughts?

+5
source share
1 answer

From what I could see after a little research, vivado is an HW development IDE [because they offer a trial period — so this is the HW devel they always want to charge for].

If you are using a standard Xilinx SDK, everything must be preconfigured. Otherwise, the HW designer launches the HW design, which has Microblaze.

From this, you may have to use petalinux to create a new boot, kernel, etc. images compatible.

You may need to rebuild libstdc++ from the source code, but I will do this as a last resort. For example, don't worry about it until you get gdb and get the test results.


Here are a few 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 call gdb (for example,):
In the target system:
gdbserver host:1534 /bin/myapp
About the development system:
petalinux-utils --gdb myapp followed by target remote 192.168.0.10:1534


I made some changes to the Makefile with annotations. I commented on some of the non-essential options. Note that I use the += operator to increment CFLAGS/CXXFLAGS gradually

The main idea here is to make an assembly with minimal deviations from the "standard" one. Add only verified key parameters. Assembly and testing. Add the parameters back one at a time (rebuild and check each time) until you find the parameter that causes the problem.

However, I have a strong suspicion that -fno-common is a source of problems. Also, to a lesser extent, I'm a little suspicious of -Wl,--as-needed

Should these options work? Of course, but xilinx / microblaze is not x86 ...

I added two command line variables:
DEBUG - generate for debugging using gdb
VERBOSE - show all 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 "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) 
+1
source

Source: https://habr.com/ru/post/1236071/


All Articles