I have turned on the ld option --fatal-warning in the linux kernel. How can I generate a simple linker warning to test this feature?
#include<stdio.h>
int main()
{
printf("Run !!");
static const char warning[] __attribute__((section(".gnu.warning.printf")))="My sweet linker warning";
return 0;
}
Save this as test.c
If you build this using:
gcc -Wl,--fatal-warnings test.c -o my_exe
You should receive your linker warning and it would not prepare "my_exe"
Now try:
gcc -Wl,--no-fatal-warnings test.c -o my_exe
In this case, warning will be reported as it is but it wont be treated as error and it will prepare "my_exe" for you.
I am not sure what exactly you meant by "turned on", but if you are seeing above behavior then I guess you are good.
If you are doing something with kernel source then you will need to replace printf with any function name you already have in source( also change .gnu.warning section name )
Thank you all for your suggestions. I went through the makefile, and found some linker flags that were suppressing warnings. I just removed them to generate ld warnings.
Related
I have compiled a c++ code using g++ -std=c++11 -o main main.cpp -pthread and it compiled fine however if I compile the same code using gcc -std=c++11 -o main main.cpp -pthread it does not compile and throws error. The program uses threading which properly taken care of using -pthread option while compiling. For the reference I am attaching the code below. Any help is highly appreciated.
#include <iostream>
#include <thread>
class foo
{
public:
void bar(int loop_num)
{
for (int i = 0; i < loop_num; ++i) {
std::cout << "Thread executing\n";
++n;
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
}
int n = 0;
};
int main()
{
int n = 0;
foo f;
std::thread t1(&foo::bar, &f, 5);
t1.join();
}
If you’ve written C++ code with GCC, you’ll know that you need to use the program g++, both for compilation and linking. For multi-module programs, this means every .cpp file gets compiled with g++, and then the entire program must be linked separately using g++. If you try to link the program using gcc, it will almost work, but you’ll get a lot of “undefined reference” errors, like this:
test.cpp:(.text+0x11): undefined reference to `std::cout'
The need to use g++ to link the entire program causes trouble when you have a very complicated build process you don’t have full control of. For instance, I’m trying to link C++ code with Mercury, and I have to use the Mercury linker, which in turn calls gcc.
So just a quick tip: If you are forced to use gcc to link the program, just add the library “stdc++”, as you would any other library, and it will work. That is, add the option “-lstdc++” to your GCC linker command line. For example:
g++ -c hello.cpp
gcc -lstdc++ -o hello hello.o
I assume the error you get looks something like this:
/tmp/ccUKAq0K.o: In function `main':
main.cpp:(.text+0x59): undefined reference to `std::thread::join()'
/tmp/ccUKAq0K.o: In function `__static_initialization_and_destruction_0(int, int)':
main.cpp:(.text+0xb6): undefined reference to `std::ios_base::Init::Init()'
main.cpp:(.text+0xcb): undefined reference to `std::ios_base::Init::~Init()'
/tmp/ccUKAq0K.o: In function `std::thread::~thread()':
main.cpp:(.text._ZNSt6threadD2Ev[_ZNSt6threadD5Ev]+0x1d): undefined reference to `std::terminate()'
(And so on.)
C++ programs which use the standard library (so most of them) need to be linked using g++, not gcc. Only the g++ compiler driver links in most of the standard library. The gcc compiler driver compiles C++ programs, just like g++, but when the linker is invoked, the program is treated as a C program, which usually leads to linker errors.
Try adding the -lrt flag after the pthread one.
I'd like to use a single (cross-)compiler to compile code for different ARM calling conventions: since I always want to use floating point and NEON instructions, I just want to select the hard-float calling convention or the soft-float (softfp) calling convention.
My compiler defaults to hard-float, but it supports both architectures that I need:
$ arm-linux-gnueabihf-gcc -print-multi-lib
.;
arm-linux-gnueabi;#marm#march=armv4t#mfloat-abi=soft
$
When I compile with the default parameters:
$ arm-linux-gnueabihf-g++ -Wall -o hello_world_armhf hello_world.cpp
It succeeds without any errors.
If I compile with the parameters returned by -print-multi-lib:
$ arm-linux-gnueabihf-g++ -marm -march=armv4t -mfloat-abi=soft -Wall -o hello_world hello_world.cpp
It again compiles without error (By the way, how can I test that the resultant code is hard- or soft-float?)
Unfortunately, if I try this:
$ arm-linux-gnueabihf-g++ -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -Wall -o hello_world hello_world.cpp
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: error: hello_world uses VFP register arguments, /tmp/ccwvfDJo.o does not
[...]/gcc/bin/../lib/gcc/arm-linux-gnueabihf/4.7.3/../../../../arm-linux-gnueabihf/bin/ld: failed to merge target specific data of file /tmp/ccwvfDJo.o
collect2: error: ld returned 1 exit status
$
I've tested some other permutations of the parameters, but it seems that anything other than the combination shown by -print-multi-lib results in an error.
I've read ARM compilation error, VFP registered used by executable, not object file but the problem there was that some parts of the binary were soft- and some were hard-float. I have a single C++ file to compile...
What parameter(s) I miss to be able to compile with -march=armv7-a -mthumb-interwork -mfloat-abi=softfp -mfpu=neon?
How is it possible that the error is about VFP register arguments while I explicitly have -mfloat-abi=softfp in the command line which prohibits VFP register arguments?
Thanks!
For the records, hello_world.cpp contains the following:
#include <iostream>
int main()
{
std::cout << "Hello, world!" << std::endl;
return 0;
}
You need another compiler with corresponding multilib support.
You can check multilib support with next command.
arm-none-eabi-gcc -print-multi-lib
.;
thumb;#mthumb
fpu;#mfloat-abi=hard
armv6-m;#mthumb#march=armv6s-m
armv7-m;#mthumb#march=armv7-m
armv7e-m;#mthumb#march=armv7e-m
armv7-ar/thumb;#mthumb#march=armv7
cortex-m7;#mthumb#mcpu=cortex-m7
armv7e-m/softfp;#mthumb#march=armv7e-m#mfloat-abi=softfp#mfpu=fpv4-sp-d16
armv7e-m/fpu;#mthumb#march=armv7e-m#mfloat-abi=hard#mfpu=fpv4-sp-d16
armv7-ar/thumb/softfp;#mthumb#march=armv7#mfloat-abi=softfp#mfpu=vfpv3-d16
armv7-ar/thumb/fpu;#mthumb#march=armv7#mfloat-abi=hard#mfpu=vfpv3-d16
cortex-m7/softfp/fpv5-sp-d16;#mthumb#mcpu=cortex-m7#mfloat-abi=softfp#mfpu=fpv5-sp-d16
cortex-m7/softfp/fpv5-d16;#mthumb#mcpu=cortex-m7#mfloat-abi=softfp#mfpu=fpv5-d16
cortex-m7/fpu/fpv5-sp-d16;#mthumb#mcpu=cortex-m7#mfloat-abi=hard#mfpu=fpv5-sp-d16
cortex-m7/fpu/fpv5-d16;#mthumb#mcpu=cortex-m7#mfloat-abi=hard#mfpu=fpv5-d16
https://stackoverflow.com/questions/37418986/how-to-interpret-the-output-of-gcc-print-multi-lib
How to interpret the output of gcc -print-multi-lib
With this configuration gcc -mfloat-abi=hard not only will build your files using FPU instructions but also link them with corresponding libs, avoiding "X uses VFP register arguments, Y does not" error.
The above-mentioned -print-multi-lib output produced by gcc with this patch and --with-multilib-list=armv6-m,armv7,armv7-m,armv7e-m,armv7-r,armv7-a,cortex-m7 configuration option.
If you are interested in building your own gcc with Cortex-A series multilib support, just use --with-multilib-list=aprofile configuration option for any arm*-*-* target without any patches (at list with gcc-6.2.0).
As per Linaro FAQ if your compiler prints arm-linux-gnueabi;#marm#march=armv4t#mfloat-abi=soft then you can only use -march=armv4t. If you want to use -march=armv7-a you need to build compiler yourself.
Following link could be helpful in building yourself GCC ARM Builds
I am using gcc 4.5 to compile a Linux kernel module. I just noticed that I have some code that looks like this:
#define NODE_ID "string_here"
int foot(int a) {
/* snip */
NODE_ID;
NODE_ID;
/* snip */
return 0;
}
I have these two no-effect statements, and the compiler never generates a warning telling me about them. Why is this? I wonder if there's other statements like this floating in my project that I haven't found.
It does warn you, you just weren't listening -- as #Mat said in the comments, you need to enable the -Wall option, and it will warn you:
$ gcc test.c -c -Wall
test.c: In function ‘foot’:
test.c:5:5: warning: statement with no effect
test.c:6:5: warning: statement with no effect
Or, you can just enable the -Wunused-value option for just this warning, but I highly recommend using -Wall, which includes this and many other useful warnings. You can also enable -Wextra and -pedantic for even more, but these sometimes give false positives for code which is perfectly fine, adding extra noise to your build process. So use them judiciously.
When I try to build the following program:
#include <stdio.h>
int main(void)
{
printf("hello world\n");
return 0;
}
On OS X 10.6.4, with the following flags:
gcc -static -o blah blah.c
It returns this:
ld: library not found for -lcrt0.o
collect2: ld returned 1 exit status
Has anyone else encountered this, or is it something that noone else has been affected with yet? Any fixes?
Thanks
This won’t work. From the man page for gcc:
This option will not work on Mac OS X unless all libraries (including libgcc.a) have also been compiled with -static. Since neither a static version of libSystem.dylib nor crt0.o are provided, this option is not useful to most people.
Per Nate's answer, a completely static application is apparently not possible - see also man ld:
-static Produces a mach-o file that does not use the dyld. Only used building the kernel.
The problem in linking with static libraries is that, if both a static and a dynamic version of a library are found in the same directory, the dynamic version will be taken in preference. Three ways of avoiding this are:
Do not attempt to find them via the -L and -l options; instead, specify the full paths, to the libraries you want to use, on the compiler or linker command line.
$ g++ -Wall -Werror -o hi /usr/local/lib/libboost_unit_test_framework.a hi.cpp
Create a separate directory, containing symbolic links to the static libraries, use the -L option to have this directory searched first, and use the -l option to specify the libraries you want to use.
$ g++ -Wall -Werror -L ./staticBoostLib -l boost_unit_test_framework -o hi hi.cpp
Instead of creating a link of the same name in a different directory, create a link of a different name in the same directory, and specify that name in a -l argument.
$ g++ -Wall -Werror -l boost_unit_test_framework_static -o hi hi.cpp
You may also try LLVM LLD linker - I did prebuilt version for my two major OSes - https://github.com/VerKnowSys/Sofin-llds
This one allows me to link for exmple: "Qemu" properly - which is impossible with ld preinstalled by Apple.
And last one is - to build GCC yourself with libstdc++ (don't).
I've been on a crusade lately to eliminate warnings from our code and have become more familiar with GCC warning flags (such as -Wall, -Wno-<warning to disable>, -fdiagnostics-show-option, etc.). However I haven't been able to figure out how to disable (or even control) linker warnings. The most common linker warning that I was getting is of the following form:
ld: warning: <some symbol> has different visibility (default) in
<path/to/library.a> and (hidden) in <path/to/my/class.o>
The reason I was getting this was because the library I was using was built using the default visibility while my application is built with hidden visibility. I've fixed this by rebuilding the library with hidden visibility.
My question though is: how would I suppress that warning if I wanted to? It's not something that I need to do now that I've figured out how to fix it but I'm still curious as to how you'd suppress that particular warning — or any linker warnings in general?
Using the -fdiagnostics-show-option for any of the C/C++/linker flags doesn't say where that warning comes from like with other compiler warnings.
Actually, you can't disable a GCC linker warning, as it's stored in a specific section of the binary library you're linking with. (The section is called .gnu.warning.symbol)
You can however mute it, like this (this is extracted from libc-symbols.h):
Without it:
#include <sys/stat.h>
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
Gives:
$ gcc a.c
/tmp/cc0TGjC8.o: in function « main »:
a.c:(.text+0xf): WARNING: lchmod is not implemented and will always fail
With disabling:
#include <sys/stat.h>
/* We want the .gnu.warning.SYMBOL section to be unallocated. */
#define __make_section_unallocated(section_string) \
__asm__ (".section " section_string "\n\t.previous");
/* When a reference to SYMBOL is encountered, the linker will emit a
warning message MSG. */
#define silent_warning(symbol) \
__make_section_unallocated (".gnu.warning." #symbol)
silent_warning(lchmod)
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
gives:
$ gcc a.c
/tmp/cc195eKj.o: in function « main »:
a.c:(.text+0xf): WARNING:
With hiding:
#include <sys/stat.h>
#define __hide_section_warning(section_string) \
__asm__ (".section " section_string "\n.string \"\rHello world! \"\n\t.previous");
/* If you want to hide the linker's output */
#define hide_warning(symbol) \
__hide_section_warning (".gnu.warning." #symbol)
hide_warning(lchmod)
int main()
{
lchmod("/path/to/whatever", 0666);
return 0;
}
gives:
$ gcc a.c
/tmp/cc195eKj.o: in function « main »:
Hello world!
Obviously, in that case, replace Hello world! either by multiple space or some advertisement for your wonderful project.
Unfortunately ld does not appear to have any intrinsic way of suppressing specific options. One thing that I found useful was limiting the number of duplicate warnings by passing -Wl,--warn-once to g++ (or you can pass --warn-once directly to ld).