I'm trying to print call stack from within a program. Unfortunately, call to glibc backtrace() returns me always only one record - address of current function. I'm working on sh4-linux, which probably causes the problem. I had no problems in printing it on x86 architecture.
Example code:
#include <string>
#include <iostream>
#include <execinfo.h>
const int maxCalls = 666;
void baz()
{
void *buffer[ maxCalls ];
int stackSize = backtrace( buffer, maxCalls );
char **symbols = backtrace_symbols( buffer, stackSize );
std::string str;
for( unsigned i = 0; i < stackSize; ++i )
{
str+= symbols[i];
}
free( symbols );
std::cout << str<< std::endl;
}
void bar()
{
baz();
}
void foo()
{
bar();
}
int main(int argc, char **argv)
{
foo();
return 0;
}
which was compiled by:
sh4-linux-g++ test.cpp -g -c -o test.o
sh4-linux-g++ test.o -g -rdynamic -o test
EDIT: Actually this code works fine. Probably some compiler flag causes this behavior in real project.
Compiler flags are: -g -O0 -pipe -fpermissive -frtti -fno-exceptions -ffunction-sections
Linker flags: -lpthread -g -rdynamic -Wl,-gc-sections -Wl,--start-group {Files here} -Wl,--end-group --verbose -Xlinker -lm
EDIT2: I found out which flag is the cause: -fno-exceptions. Can anyone tell me why? And if it can be repaired without skipping this flag?
EDIT3: Well, nevermind. It seems that I can actually omit this flag.
Try removing "stackSize = 1;"
A patch to glibc is needed. Look here.
As noted in the patch, user applications using backtrace need to be compiled with "-fexceptions". If you want full symbol resolution of addresses you need "-rdynamic" too.
The compiler may be inlining those functions. Could try recompiling with the -O0 option.
Related
I run an up to date debian testing (with kernel 4.19).
Helpers are not found on my system (but they exist in the header, Qt jumps to them)
#include "bpf/bpf.h"
int main (){
int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
return 0;
}
Compilation results in
undefined reference to `bpf_create_map(bpf_map_type, int, int, int, unsigned int)'
compiled with
g++ -c -pipe -g -std=gnu++1z -Wall -W -fPIC -DQT_QML_DEBUG -I. -I../../Qt/5.13.0/gcc_64/mkspecs/linux-g++ -o main.o main.cpp
g++ -lbpf -o server main.o
Same result with
g++ main.cpp -lbpf -o out
I have the libbpf-dev installed as well and i have the associated libraries (a and so).
What is wrong?
Update
even the following code won't work
#include <linux/bpf.h>
int main (){
//int r = bpf_create_map(BPF_MAP_TYPE_ARRAY,1,1,1,0);
bpf_attr attr = {};
attr.map_type = BPF_MAP_TYPE_ARRAY;
attr.key_size = 1;
attr.value_size = 1;
attr.max_entries = 1;
bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
return 0;
}
results in
error: 'bpf' was not declared in this scope
Update2:
BTW, key size is mandated to be 4 and not 1; but it is a point aside, that was unrelated to my problem here.
Namespace issue due to compiling in C++, you probably want:
extern "C" {
#include "bpf/bpf.h"
}
int main()...
Regarding your second error (error: 'bpf' was not declared in this scope), this is not directly related to libbpf, this is because there is no function simply called bpf() to actually perform the syscall. Instead you have to use the syscall number. For example, libbpf defines the following:
static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
unsigned int size)
{
return syscall(__NR_bpf, cmd, attr, size);
}
... and uses sys_bpf() after that, the same way you try to call bpf() in your sample.
For the record, “BPF helpers” often designates BPF functions that you call from within a BPF program, which is not the case here. Hence some confusion in the comments, I believe.
I am writing a program that calls an external string array from within a compiled static library.
When I compile and run the program in 64-bit, it works without issue. However, when I try to call the external array when compiling code in* 32-bit*, it give a Segmentation Fault when running main.
Here is the code:
Header declaration "hoenyB_lib.h:
#ifndef HONEYB_LIB_H_
#define HONEYB_LIB_H_
#include <string>
extern std::string honeyB_libs[];
#endif
Extern definition HoneyB_lib.cpp:
#include <string>
std::string honeyB_libs[] = { "libHoneyB.so", "libHoneyB3.so", "libHoneyB2.so", "" };
Extern use HoneyB_fcn.cpp:
deque<string> get_array()
{
deque<string> dst;
int i =0;
for(;;)
{
if(honeyB_libs[i] == "")
break;
else
{
dst.push_front(honeyB_libs[i]);
i++;
}
}
return dst;
}
The Makefile to compile this is as follows:
all:
$(CC) -c -Wall -fPIC source.cpp
$(CC) -g -c -fPIC honeyB_fcn.cpp
ar rcs libHB.a honeyB_fcn.o
g++ -g -c -fPIC honeyB_lib.cpp
g++ --whole-archive -shared -o libHoneyB.so source.o honeyB_lib.o libHB.a
g++ -L. -o main main.cpp -lHoneyB
This works without issue when main() is called. However, when I compile as 32-bit with the following:
all32:
$(CC) -m32 -c -Wall -fPIC source.cpp
$(CC) -m32 -g -c -fPIC honeyB_fcn.cpp
ar rcs libHB.a honeyB_fcn.o
g++ -m32 -g -c -fPIC honeyB_lib.cpp
g++ --whole-archive -m32 -shared -o libHoneyB.so source.o honeyB_lib.o libHB.a
g++ -m32 -L. -o main main.cpp -lHoneyB
The code give a Segmentation Fault. If I remove the call in honeyB_fct.cpp to honeyB_libs[], the code compiles and executes.
Does anybody have any idea why this fails for 32-bit, but works for 64?
Thanks in advance.
Order of initialization between different translation units is undefined. You have no guarantee that global variables in HoneyB_lib.cpp will be initialized before they are used in HoneyB_fcn.cpp. The only reason it worked for the 64-bit version is because you got lucky.
There are a couple workarounds:
Define the array in honeyB_lib.h, wrapped in an anonymous namespace to get around the ODR. Each TU that includes your header will have its own copy of the array.
Again, define the array in the header, but put it inside of a function that returns the array. The compiler should optimize it out everywhere, but if not you can make the array static in the scope of the function and return by reference (i.e. make it a singleton).
As a side note, I'd recommend a std::array instead of a raw array; this will let you do honeyB_libs.size() (or even for (auto&& lib : honeyB_libs) {...}) instead of relying on the "" sentinel value, which would clean up your get_array function a bit.
Thank you for the help. It appears that the problem had to do with the bit count of strings in 32-bit vs 64-bit. Changing honeyB_libs[] from a string array to a const char* array solved the issue.
honeyB_lib.h
extern const char* honeyB_libs[];
honeyB_lib.cpp
const char* honeyB_libs[] = { "libHoneyB.so", "libHoneyB3.so", "libHoneyB2.so", "" }
function.cpp
deque<string> get_array()
{
deque<string> dst;
string temp;
int i =0;
for(;;)
{
if(strlen(honeyB_libs[i]) == 0)
break;
else
{
temp = honeyB_libs[i];
dst.push_front(temp);
i++;
}
}
return dst;
}
Doing this allows my program to compile and run as 64-bit and 32-bit
I am having problems understanding the segmentation fault I receive when trying to run icpc-compiled programs.
A simple example consists of the following files:
// Filename: include/lib1.h
#include <string>
namespace Lib1 {
// Template initialization, T: int, double
template< typename T>
T function1( T x, T y );
// Give me the version
std::string VERSION(void);
}
// Filename: include/lib2.h
#include <string>
namespace Lib2 {
// Give me the version
std::string VERSION(void);
}
// Filename: src/main.cpp
#include <iostream>
#include <string>
#include "lib1.h"
#include "lib2.h"
int main( int argc, char* argv[] ) {
std::cout << "Lib1::VERSION() :" << Lib1::VERSION()
<< std::endl;
std::cout << "Lib2::VERSION() :" << Lib2::VERSION()
<< std::endl;
double x = 1., y = 2.;
std::cout << "Lib1::function1(x, y): "
<< Lib1::function1(x, y)
<< std::endl;
return 0;
}
// Filename: src/lib1/lib1.cpp
#include <string>
#include "lib1.h"
template< typename T >
T Lib1::function1( T x, T y ) {
return x * y;
}
std::string Lib1::VERSION(void) {
return std::string("v0.0.2");
}
// Instantiation for dynamic library
template double Lib1::function1(double, double);
template int Lib1::function1(int, int);
// Filename: src/lib2/lib2.cpp
#include <string>
#include "lib2.h"
std::string Lib2::VERSION(void) {
return std::string("v0.0.1");
}
In this simple, stupid example, when I compile the files using
clang++ -Wall -c -fPIC -I include -o liblib1.o src/lib1/lib1.cpp
clang++ -Wall -shared -o liblib1.so liblib1.o
clang++ -Wall -c -fPIC -I include -o liblib2.o src/lib2/lib2.cpp
clang++ -Wall -shared -o liblib2.so liblib2.o
clang++ -Wall -o main.out -I include -L ./ -llib1 -llib2 src/main.cpp
the program runs fine (provided that I modify my LD_LIBRARY_PATH environment variable properly. However, when I use
icpc -Wall -c -fPIC -I include -o liblib1.o src/lib1/lib1.cpp
icpc -Wall -shared -o liblib1.so liblib1.o
icpc -Wall -c -fPIC -I include -o liblib2.o src/lib2/lib2.cpp
icpc -Wall -shared -o liblib2.so liblib2.o
icpc -Wall -o main.out -I include -L ./ -llib1 -llib2 src/main.cpp
then the program gives me:
[1] 27397 segmentation fault (core dumped) LD_LIBRARY_PATH=./:$LD_LIBRARY_PATH ./main.out
I would appreciate if you helped me understand and solve this problem. When I did some research on the web, I came across some sources talking about memory access problems and such, but I am not doing anything fancy right now. Moreover, I tried using ddd (I am not fluent/good in gdb) and running the program there, but the program exists with the segfault immidiately after the program start. I cannot even trace the program (yes, prior to running ddd, I used -debug -g switches).
It happened to be the case that Intel Parallel Studio v16.0.3 has (known) issues for Ubuntu and Arch Linux platforms, and unfortunately these systems are not officially supported, either.
One fast workaround seems to be to downgrade to v16.0.2 for now.
I've read multiple posts here relating to dynamic libraries on os x and debugging with gdb. But I still can't figure out why I can't debug a simple test case.
The main issue is that when I start up GDB it never loads any shared libraries.
Update: I've tried this with GDB from macports, from homebrew, and built from source and the behavior is the same.
I have a class that I compile into a library.
Test.hpp
class Test {
public:
void set(int i);
void out() const;
private:
int i;
};
Test.cpp
#include "Test.hpp"
#include <iostream>
void Test::set(int ii) { i = ii; }
void Test::out() const {
auto j = i * 100;
std::cout << i << ", " << j << "\n";
++j;
std::cout << i << ", " << j << "\n";
}
I compile it and create a library with g++. Note: the behavior is the same with macports gcc and the gcc from xcode.
/opt/local/bin/g++-mp-4.8 -O0 -g -ggdb -Wall -c -std=c++11 -o Test.o Test.cpp
/opt/local/bin/g++-mp-4.8 -dynamiclib -o libTest.dylib Test.o
Then I test it with this simple main
#include "Test.hpp"
int main() {
Test t;
auto x = 4;
t.set(x);
t.out();
return 0;
}
This is compiled and linked with
/opt/local/bin/g++-mp-4.8 -O0 -g -ggdb -Wall -c -std=c++11 -o main.o main.cpp
/opt/local/bin/g++-mp-4.8 -L . -o testing main.o -lTest
Everything compiles and runs as expected. But when I try to debug this with gdb (installed from macports, or installed from source, the behavior is the same), I have problems.
As I step through main, if I call info sharedlibrary it always says "No shared libraries loaded at this time.", so it apparently never loads libTest.dylib. Therefore, I can't step into any of the Test member functions or create breakpoints anywhere in libTest.dylib.
Indeed ggdb installed from macports for some reason does not respect the DYLD_LIBRARY_PATH. However, if you "patch" your executable with the correct paths for the .dylibs you should be able to debug with ggdb. Take a look at this question and especially the answer by Akos Cz.
I am trying to create a baremetal c++ application for a cortex-M4 device. My toolchain is ARM-GCC
I have noticed that the code size has shot up by 300kb which is 30% of the available flash size. There is a whole truckload of stuff from the standard libraries that gets linked in bloating TEXT, DATA and BSS areas.
Can this be reduced?
The application is the venerable blinky program with a :
- Blinky.c containing the C routine to toggle a port pin in a while loop
- Main.cpp containing the main() and a simple class with a constructor
- Device startup file which does program loading and yields control to main()
The c file is compiled using gcc while the cpp is compiled using g++. The linker is invoked via g++ to automatically link in stdlibc++(with the assumption that only necessary object fies from the stdlibc++ will be linked in).
I even have -fno-rtti and -fno-exceptions as compile options to g++, but the savings are a pittiance.
By the way, the generated binary works file.
This is the Main.cpp
#include <iostream>
using namespace std;
extern "C" void Toggle_Pin(uint8_t Speed);
void *__dso_handle = (void *)NULL;
void __cxa_atexit(void (*Arg)(void *), void *Arg2, void *Arg3){}
void __cxa_guard_acquire(void){}
void __cxa_guard_release(void){}
void __aeabi_atexit(void (*Arg)(void *), void *Arg2, void *Arg3){}
class Computer
{
public:
uint32_t aa;
uint32_t bb;
Computer();
};
Computer::Computer()
{
aa=0;
bb=0;
for(uint8_t i=0;i < 10; i++)
{
Toggle_Pin((uint8_t)100);
}
}
Computer a;
int main(void)
{
a.aa = 10;
Toggle_Pin();
}
And these are my compilation options provided to g++.
-O0 -ffunction-sections -Wall -fno-rtti -fno-exceptions -mfloat-abi=softfp -Wa,-adhlns="$#.lst" -c -fmessage-length=0 -mfpu=fpv4-sp-d16 -MMD -MP -MF"$(#:%.o=%.d)" -MT"$(#:%.o=%.d) $#" -mcpu=cortex-m4 -mthumb -g3 -gdwarf-2 -o "$#" "$<"
Linker options provided to g++:
-T LinkerScript.ld" -nostartfiles -L"Path to libraries" -Wl,-Map,"Project.map" -mcpu=cortex-m4 -mthumb -g3 -gdwarf-2 -o "Project.elf" "#makefile.rsp" $(USER_OBJS) $(LIBS)
Remove part with
#include <iostream>
using namespace std;
you don't need it. I guess it adds extra global objects / variables and might leave some definitions in binary.
Also use -Os
-Os
Optimize for size. -Os enables all -O2 optimizations that do not typically increase code size. It also performs further optimizations designed to reduce code size.