Cmake flags for debugging don't seem to be useful in valgrind? - cmake

Ok, so I have this Qt application I'm attempting to debug;
upon running valgrind on it and redirecting output to a file, I see many some 'definitely lost' blocks that look something like this, which make me sad:
==24357== 24 bytes in 1 blocks are definitely lost in loss record 150 of 508
==24357== at 0x4C2C56F: malloc (vg_replace_malloc.c:267)
==24357== by 0x76ED3CA: FcPatternCreate (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
==24357== by 0x76EB3CD: FcFontRenderPrepare (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
==24357== by 0x76EB66C: FcFontMatch (in /usr/lib/x86_64-linux-gnu/libfontconfig.so.1.4.4)
==24357== by 0x57163D7: QFontDatabase::load(QFontPrivate const*, int) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x56F3586: QFontPrivate::engineForScript(int) const (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x5728482: ??? (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x573B73D: QTextLine::layout_helper(int) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x573D5A4: QTextLayout::endLayout() (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x58F33CE: QLineControl::updateDisplayText(bool) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x58F36C6: QLineControl::init(QString const&) (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
==24357== by 0x58EC720: ??? (in /usr/lib/x86_64-linux-gnu/libQtGui.so.4.8.1)
I'm not very good with valgrind, but as far as I can tell, this trace doesn't come back to my source files, right? In fact, nowhere in the full valgrind report (with the -v switch) do my source files appear, except for in main() where I declare the QApplication.
Then can I assume I'm not compiling my project with CMake correctly? Hopefully that's the problem, because the valgrind report doesn't seem too helpful to me right now..
Now then, in my CmakeLists.txt, I'm (attempting) to compile the project with debug flags like so:
set(CMAKE_CXX_FLAGS_DEBUG "-g3 -ggdb -O0")
is this a proper way of doing this?
Am I doing something wrong here?
Thanks, and sorry for such a long question! :/

The usual procedure is to set CMAKE_BUILD_TYPE variable to Debug, Release, or etc. during configuration stage. This can be achieved by using -D flag for command-line cmake tool, or by modifying appropriate field in GUI.
If you wish to pass extra flags to the compiler, just set CMAKE_CXX_FLAGS the same way as you set CMAKE_BUILD_TYPE.
As you see, this doesn't invovles modifying any of CMakeLists.txt files, but CMakeCache.txt in your build dir.

Related

Weak function definitions for interrupt vector in a static library are preferred over strong ones

Introduction
arm-none-eabi-gcc version 10.3-2021.10 20210824
device: nordic nRF52840/nRF52832/nRF52833
library affected: Nordic NRF5 SDK 17.1.0 - custom build system (CMake)
I wrote the CMake build system for Nordic NRF5 SDK (natively it only supports makefiles). The build system has a executable (application) and multiple underlying static libraries. The dependencies go like this:
application
...
- NordicAl (abstraction layer)
- nrf5_sdk
...
//root/CMakeLists.txt
add_executable(application)
...
add_subdirectory(lib/NordicAl)
...
target_link_libraries(application PRIVATE
nordic_al
...)
....
//root/lib/NordicAl/CMakeLists.txt
add_library(nordic_al)
...
add_subdirectory(lib/nrf5_sdk)
target_link_libraries(nordic_al PRIVATE
nrf5_sdk
...)
...
//root/lib/NordicAl/lib/nrf5_sdk/CMakeLists.txt
add_library(nrf5_sdk)
...
target_sources(nrf5_sdk PRIVATE
...
${NRF5_SDK_ROOT}/modules/nrfx/mdk/gcc_startup_${PLATFORM_MCU_FAMILY}.S
${NRF5_SDK_ROOT}/components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c
)
Problem
I have created a custom C hard-fault handler on top of the Nordic nRF5 SDK. It works with the previous build system (makefile build system). It must be noted that the previous build system does not create the static libraries, as does the new CMake system. It just links everything unconditionally.
In the perfect world, the user of the SDK (i.e., I) should define a callback (HardFault_c_handler) and it will be called by the interrupt vector in case of a hard-fault.
In the nRF5 SDK library, a startup file (modules/nrfx/mdk/gcc_startup_nrf52840.S) is included in the target nrf5_sdk (static library). The relevant code for this problem:
__isr_vector:
.long __StackTop /* Top of Stack */
.long Reset_Handler
.long NMI_Handler
.long HardFault_Handler
...
.weak HardFault_Handler
.type HardFault_Handler, %function
HardFault_Handler:
b .
.size HardFault_Handler, . - HardFault_Handler
Additionally, there is a strong defition of HardFault_Handler in a c file that should take precedence over this weak definition. The file (components/libraries/hardfault/nrf52/handler/hardfault_handler_gcc.c) contains:
extern void HardFault_c_handler(uint32_t *);
void HardFault_Handler(void) __attribute__(( naked ));
void HardFault_Handler(void)
{
__ASM volatile(
...
" .ltorg \n"
: : "X"(HardFault_c_handler)
);
}
The code from the c file should be called by the MCU in a case of the hard-fault, but it does not.
My question is why? How to make it prefer the strong function? My thinking now, although I am not sure. Because this callback, i.e., HardFault_Handler, is not referenced in the main application (or before getting to the startup file) the linker does not need to resolve it. Only when it sees this symbol in the startup file it looks for it, and because this is a static library it only looks for the first occurrence.
Things I tried
removing static libraries, this fixes the problem,
separating weak definition of the HardFault_Handler into separate assembly file, this makes the linker link the function from the file that appears first, using -Wl,-trace-symbol=HardFault_Handler I see that the linker only looks for the first occurence and than stops (irrelevant of weak and strong).
putting c file before the startup file in the sources, does not change the result.
Edit
My linker flags:
-mcpu=cortex-m4
-mfloat-abi=hard
-mfpu=fpv4-sp-d16
-mthumb
-mabi=aapcs
-ffreestanding
-fno-common
-finline-small-functions
-findirect-inlining
-fstack-protector-strong
-ffunction-sections
-fdata-sections
-Wl,--gc-sections
--specs=nano.specs
I figured out, as I am using CMake, that I can supply OBJECT keyword with the add_library() function. In that case the keyword works as expected. Take note that object library linked to another object library does not work properly. And the underlying object library must, also, be included in the top-most (non-object library) target.

Duplicate Symbols when removing Preprocessor code

Noob build question.
When I change this;
#define NOTIFICATION_PLAYBACK_STATE_CHANGED #"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED"
to this;
NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED = #"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED";
I get this:
ld: 752 duplicate symbols for architecture armv7
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Sample of the 752 duplicates:
duplicate symbol _NOTIFICATION_PLAYBACK_STATE_CHANGED in:
/Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRemoteRecordManager.o
/Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRegisterAcceptTermsViewController.o
duplicate symbol _NOTIFICATION_PLAYBACK_STATE_CHANGED in:
/Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCRemoteRecordManager.o
/Users/myname/Library/Developer/Xcode/DerivedData/MyApp-hazegevzmypmbtbnalpiwebrhaea/Build/Intermediates/MyApp.build/Debug-iphoneos/MyApp.build/Objects-normal/armv7/SCStreamingVideoViewController.o
(A search for this particular duplicate symbol returns nothing outside of the class's own .h and .m files.)
There are many other places in the code where I have replaced such a #define with a constant without objections during the build.
Can someone take a guess at what's happening here (or advise me what information I would need to post for a guess to be possible)?
Is trawling through the code replacing #defines where they have been used to create constants (leaving stuff like debug/release defs untouched) a dumb thing to do, i.e. should I be doing this differently (if at all)?
You seem to have these constants defined in a header file. The header file is imported into multiple other files; the definition is thus repeated across all those files. Multiple definitions using the same name are not allowed.
What you want to do instead is to declare the constant in the header:
extern NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED;
extern indicates to the compiler "this is a name I'm going to use, but the storage and definition for it is elsewhere; let the linker handle that".
Then, in a file that imports the header, but is not itself imported anywhere, you define the string:
NSString * const NOTIFICATION_PLAYBACK_STATE_CHANGED = #"SC_NOTIFICATION_PLAYBACK_STATE_CHANGED";
The linker will find this definition, and all the copies of the extern declarations, and tie them together to be the same thing.
(It may interest you to see what errors you get if you omit each of these pieces in turn. You'll get a compiler error in one case, and a linker error in the other.)

g++ compile multiple files

I'got a problem with compiling linking of a program with multiple files by g++ (I usually use vstudio, but...).
If I use only main.cpp (and include appropriate header files for openCV), everything is ok with
g++ main.cpp -o main -I"C:\OpenCV2.1\include\opencv" -L"C:\OpenCV2.1\lib"
-lcxcore210 -lcv210 -lhighgui210
If I have main.cpp and some otherfile.cpp (both need openCV) and use
g++ main.cpp otherfile.cpp -o main -I"C:\OpenCV2.1\include\opencv"
-L"C:\OpenCV2.1\lib" -lcxcore210 -lcv210 -lhighgui210
it simply doesn't work and I got
c:/mingw/bin/../lib/gcc/mingw32/4.5.0/../../../../mingw32/bin/ld.exe: warning: a
uto-importing has been activated without --enable-auto-import specified on the c
ommand line.
This should work unless it involves constant data structures referencing symbols
from auto-imported DLLs.
C:\Users\ONDEJM~1\AppData\Local\Temp\ccNisCoC.o:main.cpp:(.text+0x16d0): undefin
ed reference to `cv::Mat::Mat(_IplImage const*, bool)'
C:\Users\ONDEJM~1\AppData\Local\Temp\ccNisCoC.o:main.cpp:(.text+0x16f1): undefin
ed reference to `cv::FAST(cv::Mat const&, std::vector<cv::KeyPoint, std::allocat
or<cv::KeyPoint> >&, int, bool)'
C:\Users\ONDEJM~1\AppData\Local\Temp\ccNisCoC.o:main.cpp:(.text$_ZN2cv3Mat7relea
seEv[cv::Mat::release()]+0x3f): undefined reference to `cv::fastFree(void*)'
collect2: ld returned 1 exit status
What am I doing wrong?
Pass "-Wl,--enable-auto-import" to g++. Read ld's documentation about this.
Hm, it seems that I made a silly mistake... solution is simple: just recompile all openCV binarries by g++ and everything will be ok!

In an ELF file, how does the address for _start get detemined?

I've been reading the ELF specification and cannot figure out where the program entry point and _start address come from.
It seems like they should have to be in a pretty consistent place, but I made a few trivial programs, and _start is always in a different place.
Can anyone clarify?
The _start symbol may be defined in any object file. Normally it is generated automatically (it corresponds to main in C). You can generate it yourself, for instance in an assembler source file:
.globl _start
_start:
// assembly here
When the linker has processed all object files it looks for the _start symbol and puts its value in the e_entry field of the elf header. The loader takes the address from this field and makes a call to it after it has finished loading all sections in memory and is ready to execute the file.
Take a look at the linker script ld is using:
ld -verbose
The format is documented at: https://sourceware.org/binutils/docs-2.25/ld/Scripts.html
It determines basically everything about how the executable will be generated.
On Binutils 2.24 Ubuntu 14.04 64-bit, it contains the line:
ENTRY(_start)
which sets the entry point to the _start symbol (goes to the ELF header as mentioned by ctn)
And then:
. = SEGMENT_START("text-segment", 0x400000) + SIZEOF_HEADERS;
which sets the address of the first headers to 0x400000 + SIZEOF_HEADERS.
I have modified that address to 0x800000, passed my custom script with ld -T and it worked: readelf -s says that _start is at that address.
Another way to change it is to use the -Ttext-segment=0x800000 option.
The reason for using 0x400000 = 4Mb = getconf PAGE_SIZE is to start at the beginning of the second page as asked at: Why is the ELF execution entry point virtual address of the form 0x80xxxxx and not zero 0x0?
A question describes how to set _start from the command line: Why is the ELF entry point 0x8048000 not changeable with the "ld -e" option?
SIZEOF_HEADERS is the size of the ELF + program headers, which are at the beginning of the ELF file. That data gets loaded into the very beginning of the virtual memory space by Linux (TODO why?) In a minimal Linux x86-64 hello world with 2 program headers it is worth 0xb0, so that the _start symbol comes at 0x4000b0.
I'm not sure but try this link http://www.docstoc.com/docs/23942105/UNIX-ELF-File-Format
at page 8 it is shown where the entry point is if it is executable. Basically you need to calculate the offset and you got it.
Make sure to remember the little endianness of x86 ( i guess you use it) and reorder if you read bytewise edit: or maybe not i'm not quit sure about this to be honest.

Linking with libpng & zlib?

I'm trying to compile a project that uses both libjpeg and libpng. I know that libpng needs zlib, so I compiled all the three independently and put them (libjpeg.a, libpng.a and libz.a) on a folder called linrel32. What I execute then is:
g++ -Llinrel32/ program.cpp otherfile.cpp -o linrel32/executable -Izlib/ -Ilpng140/ -Ijpeg/ -lpthread -lX11 -O2 -DLINUX -s -lz -lpng -ljpeg
So I include the three libraries. Still, the linker complains:
linrel32//libpng.a(png.o): In function `png_calculate_crc':
png.c:(.text+0x97d): undefined reference to `crc32'
linrel32//libpng.a(png.o): In function `png_reset_crc':
png.c:(.text+0x9be): undefined reference to `crc32'
linrel32//libpng.a(png.o): In function `png_reset_zstream':
png.c:(.text+0x537): undefined reference to `inflateReset'
linrel32//libpng.a(pngread.o): In function `png_read_destroy':
pngread.c:(.text+0x6f4): undefined reference to `inflateEnd'
linrel32//libpng.a(pngread.o): In function `png_read_row':
pngread.c:(.text+0x1267): undefined reference to `inflate'
linrel32//libpng.a(pngread.o): In function `png_create_read_struct_2':
(... you get the idea :D)
collect2: ld returned 1 exit status
I know the missing functions are from zlib, and I'm adding zlib there. Opened libz.a and it seems to have a good structure. Recompiled it, everything looks fine. But it is not...
I don't know, is likely that the problem is trivial, and what I need is to sleep for a while. But still, if you could help me to figure out this thing ...
You need to rearrange the order of the libraries:
-lpng -ljpeg -lz
What is happening is that the linker has special rules on how it treats static libraries. What it does is that it only includes a .o from inside the .a if the .o is needed to satisfy a reference.
Furthermore, it handles static archives in the order in which they appear on the link line.
So, your code does not directly call any functions in zlib. So when the linker handles -lz first, there are not yet any calls to it so it doesn't pull in any of zlib.
Next, when the linker handles libpng, it sees that there are calls to it from your code. So it pulls the code from libpng and since it makes calls to zlib, now there are references to the zlib functions.
Now you come to the end of your libraries and there are unsatisfied calls which causes your error.
So, if libhigh.a makes use of liblow.a, you must have -lhigh before -llow in your link order.
you probably need to surround the zlib and png headers with extern "C", e.g.:
extern "C" {
#include <zlib.h>
}