GCC fortified function documentation - gcc

I'm trying to find information on what is required for implementing fortified functions in GCC for libc.
From what I understand the __builtin__*_chk variants are for compile-time checks but if GCC can't determine buffer sizes he will replace the call with the __*_chk version if they exist.
Is the above assertion correct? If so where can I find documentation on what is required by GCC in libc to tie together a function to it's runtime __*_chk version when FORTIFY_SOURCE=1|2?
Thanks

Fortification is mostly implemented in Glibc via GCC's __builtin_constant_p and __builtin_object_size intrinsics. E.g. here's definition of memset from /usr/include/string.h:
__fortify_function void *
__NTH (memset (void *__dest, int __ch, size_t __len))
{
if (__builtin_constant_p (__len) && __len == 0
&& (!__builtin_constant_p (__ch) || __ch != 0))
{
__warn_memset_zero_len ();
return __dest;
}
return __builtin___memset_chk (__dest, __ch, __len, __bos0 (__dest));
}
__builtin___memset_chk is simply expanded by GCC to a call to memset_chk (also defined in libc.so).
GCC knows about *_chk functions but only uses this knowledge to perform optimizations (dead code removal, folding, etc.), not for verification.

Related

Does MSP430 GCC support newer C++ standards? (like 11, 14, 17)

I'm writing some code that would greatly benefit from the concise syntax of lambdas, which were introduced with C++ 11. Is this supported by the compiler?
How do I specify the compiler flags when compiling using Energia or embedXcode?
As of February 2018, up to C++14 is supported with some limitations:
http://processors.wiki.ti.com/index.php/C%2B%2B_Support_in_TI_Compilers
There isn't much about this topic on the TI site, or, at least, I don't know enough C++ to give you a detailed and precise response.
The implementation of the embedded ABI is described in this document that is mainly a derivation of the Itanium C++ ABI. It explains nothing about the implementation of lambdas nor the auto, keyword (or probably I'm not able to derive this information from the documentation).
Thus I decided to directly test in Energia. Apparently the g++ version is 4.6.3, thus it should support both.
And in fact (from a compilation point of view, I don't have my MSP here to test the code) it can compile something like:
// In template.hpp
#ifndef TEMPLATE_HPP_
#define TEMPLATE_HPP_
template<class T>
T func(T a) {
auto c = [&](int n) { return n + a; };
return c(0);
}
#endif /* TEMPLATE_HPP_ */
// in the sketch main
#include "template.hpp"
void setup() { int b = func<int>(0); }
void loop() { }
(the template works only if in an header, in the main sketch raises an error). To compile this sketch I had to modify one internal file of the editor. The maximum supported standard seems to be -std=c++0x, and the compilation flags are in the file:
$ENERGIA_ROOT/hardware/energia/msp430/platform.txt
in my setup the root is in /opt/energia. Inside that file I modified line 32 (compiler.cpp.flags) and added the option. Notice that -std=c++11 is not supported (raises an error).
compiler.cpp.flags=-std=c++0x -c -g -O2 {compiler.mlarge_flag} {compiler.warning_flags} -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD
Unfortunately I have zero experience with embedXcode :\
Mimic std::function
std::function is not provided, thus you have to write some sort of class that mimics it. Something like:
// callback.hpp
#ifndef CALLBACK_HPP_
#define CALLBACK_HPP_
template <class RET, class ARG>
class Callback {
RET (*_f)(ARG);
public:
Callback() : _f(0) { };
Callback(RET (*f)(ARG)) : _f(f) { };
bool is_set() const { return (_f) ? true : false; }
RET operator()(ARG a) const { return is_set() ? _f(a) : 0; }
};
#endif /* CALLBACK_HPP_ */
// sketch
#include "callback.hpp"
// | !! empty capture!
void setup() { // V
auto clb = Callback<int, char>([](char c) { return (int)c; });
if (clb.is_set())
auto b = clb('a');
}
void loop() {}
may do the work, and it uses a simple trick:
The closure type for a lambda-expression with no lambda-capture has a public non-virtual non-explicit const conversion function to pointer to function having the same parameter and return types as the closure type’s function call operator. [C++11 standard 5.1.2]
As soon as you leave the capture empty, you are assured to have a "conversion" to a function pointer, thus you can store it without issues. The code I have written:
requires a first template RET that is the returned type
requires a second template ARG that is one argument for the callback. In the majority of the case you may consider to use void* as common argument (cast a struct pointer in a void pointer and use it as argument, to counter-cast in the function, the operation costs nothing)
implements two constructors: the empty constructor initialize the function pointer to NULL, while the second directly assigns the callback. Notice that the copy constructor is missing, you need to implement it.
implements a method to call the function (overloading the operator ()) and to check if the callback actually exists.
Again: this stuff compiles with no warnings, but I don't know if it works on the MSP430, since I cannot test it (it works on a common amd64 linux system).

Clang compilation error: "variable 'array' with variably modified type cannot be captured in lambda expression

In the code listed below, "LambdaTest" fails with the following error on Clang only:
shared/LambdaTest.cpp:8:31: error: variable 'array' with variably
modified type cannot be captured in a lambda expression
auto myLambdaFunction = [&array]()
^
shared/LambdaTest.cpp:7:9: note: 'array' declared here
int array[length];
The function "LambdaTest2" which passes the array as a parameter instead of capturing compiles fine on G++/Clang.
// Compiles with G++ but fails in Clang
void LambdaTest(int length)
{
int array[length];
auto myLambdaFunction = [&array]()
{
array[0] = 2;
};
myLambdaFunction();
}
// Compiles OK with G++ and Clang
void LambdaTest2(int length)
{
int array[length];
auto myLambdaFunction = [](int* myarray)
{
myarray[0] = 2;
};
myLambdaFunction(array);
}
Two questions:
What does the compiler error message "variable 'array' with variably modified type cannot be captured in a lambda expression" mean?
Why does LambdaTest fail to compile on Clang and not G++?
Thanks in advance.
COMPILER VERSIONS:
*G++ version 4.6.3
*clang version 3.5.0.210790
int array[length]; is not allowed in Standard C++. The dimension of an array must be known at compile-time.
What you are seeing is typical for non-standard features: they conflict with standard features at some point. The reason this isn't standard is because nobody has been able to make a satisfactory proposal that resolves those conflicts. Instead, each compiler has done their own thing.
You will have to either stop using the non-standard feature, or live with what a compiler happens to do with it.
VLA (Variable-length array) is not officially supported in C++.
You can instead use std::vector like so:
void LambdaTest(int length)
{
std::vector<int> array(length);
auto myLambdaFunction = [&array]()
{
array[0] = 2;
};
myLambdaFunction();
}
Thanks to both answers above for pointing out that VLAs are non-standard. Now I know what to search for.
Here are more are related links to the subject.
Why aren't variable-length arrays part of the C++ standard?
Why no VLAS in C++

Can GCC issue a warning when 0 is passed as an argument?

I have been told that you could add some special instruction to your code to make GCC issue a warning when it detects that 0 is being passed as an argument (which means, when it is possible at compile-time).
I have looked for it but haven’t been able to find it. Is this true?
There is a function attribute you can use to warn on null pointers:
void foo(void *data) __attribute__((nonnull));
int main(void)
{
foo(0);
return 0;
}
$ gcc -Wall -c t.c
t.c: In function ‘main’:
t.c:5:5: warning: null argument where non-null required (argument 1) [-Wnonnull]
I'm not aware of anything built-in to check for 0 for integer types though.
You might find something that suits your need in the various BUILD_BUG_* macros from the Linux kernel though. They're in include/linux/kernel.h. (Cross-referenced here.)

GCC Compile-time checking of constant function inputs

I want to use gcc to do some compile-time checking on function inputs if the compiler knows that they are constants.
I have a solution that very almost works, and as far as I can see, it should work.
Note: __builtin_constant_p(expression) is supposed to returns whether an expression is known to be a constant at compile time.
Assuming we want to check whether port<2 when calling uart(port), the following code should work:
#include <stdio.h>
void _uart(int port) {
printf("port is %d", port);
}
#define uart(port) \
static_assert(__builtin_constant_p(port)? port<2: 1, "parameter port must be < 2"); \
_uart(port)
int main(void) {
int x=1;
uart(x);
}
This works when calling uart(). Unfortunately, it doesn't quite work for non-constant x. For some reason static_assert can't handle the case where x is not a constant, even though in theory __builtin_constant_p() won't even pass it a constant. The error message I get is:
c:\>gcc a.cpp -std=c++0x -Os
a.cpp: In function 'int main()':
a.cpp:13: error: 'x' cannot appear in a constant-expression
Any ideas?
Your code works with g++ (GCC) 4.8.2.
- but not with optimization, as you correctly noted.
If only we could use
static_assert(__builtin_choose_expr(__builtin_constant_p(port), \
port<2, 1), "parameter port must be < 2")
- but unfortunately the __builtin_choose_expr construct is currently only available for C.
However, there is a C++ patch which sadly didn't make it into the release yet.
You can try the trick used in the Linux kernel:
What is ":-!!" in C code?
The (somewhat horrible) Linux kernel macro is less strict about what kinds of expressions are allowed in the parameter.

Overloading conflict with vector types __m128, __m256 in GCC

I've started playing around with AVX instructions on the new Intel's Sandy Bridge processor. I'm using GCC 4.5.2, TDM-GCC 64bit build of MinGW64.
I want to overload operator<< for ostream to be able to print out the vector types __m256, __m128 etc to the console. But I'm running into an overloading conflict. The 2nd function in the following code produces an error "conflicts with previous declaration void f(__vector(8) float)":
void f(__m128 v) {
cout << 4;
}
void f(__m256 v) {
cout << 8;
}
It seems that the compiler cannot distinguish between the two types and consideres them both f(float __vector).
Is there a way around this? I haven't been able to find anything online. Any help is greatly appreciated.
I accidentally stumbled upon the answer when having a similar problem with function templates. In this case, the GCC error message actually suggested a solution:
add -fabi-version=4 compiler option.
This solves my problem, and hopefully doesn't cause any issues when linking the standard libraries.
One can read more about ABI (Application Binary Interface) and GCC at ABI Policy and Guidelines and ABI specification. ABI specifies how the functions names are mangled when the code is compiled into object files. Apparently, ABI version 3 used by GCC by default cannot distinguish between the various vector types.
I was unsatisfied with the solution of changing compiler ABI flags to solve this, so I went looking for a different solution. It seems they encountered this issue in writing the Eigen library - see this source file for details http://eigen.tuxfamily.org/dox-devel/SSE_2PacketMath_8h_source.html
My solution to this is a slightly tweaked version of theirs:
template <typename T, unsigned RegisterSize>
struct Register
{
using ValueType = T;
enum { Size = RegisterSize };
inline operator T&() { return myValue; }
inline operator const T&() const { return myValue; }
inline Register() {}
inline Register(const T & v) : myValue(v) {} // Not explicit
inline Register & operator=(const T & v)
{
myValue = v;
return *this;
}
T myValue;
};
using Register4 = Register<__m128, 4u>;
using Register8 = Register<__m256, 8u>;
// Could provide more declarations for __m128d, __m128i, etc. if needed
Using the above, you can overload on Register4, Register8, etc. or produce template functions taking Registers without running into linking issues and without changing ABI settings.

Resources