Do global constants still have to be initialized with constant expressions? - global-variables

Since GLSL 4.20 const-qualified variables no longer have to be initialized by constant expressions. But when I actually try to define a global const-qualified variable initialized by a non-constant-expression, Mesa emits an error. Here's the example code:
#version 420
uniform vec2 v;
const float x=v.x;
out vec4 color;
void main()
{
color=vec4(x,v.y,0,1);
}
Here's how I test-compile (to avoid any OpenGL code):
$ glsl_compiler --version 420 test.frag
Info log for test.frag:
0:3(15): error: initializer of const variable `x' must be a constant expression
If I move const float x=v.x; line into the main function body, compilation ends successfully.
OTOH, nvidia driver, being (as usual) much more permissive, accepts the original code without warnings.
So, does GLSL 4.20+ actually prohibit non-constant-expression initializers of const-qualified variables in the global scope, or is this error a Mesa bug?

All versions of GLSL prohibit initializing a const qualified global variable with anything other than a constant expression (or for SPIR-V-bound GLSL, an expression involving constant expressions and specialization constants).
The only thing that changed in 4.20 regarding this was that, previously, any non-parameter variable declared const was restricted to initialization by constant expressions. 4.20 allowed function-local variables to be const while being initialized by non-constant expressions. But that's all.
Essentially, global const variables in GLSL are like C++11 constexpr variables. Local const variables are like C++ const variables.

Related

Why is a global vector of pointers (without objects) in C++ leaking in Valgrind when it won't let me use delete after new in two separated files?

So I have a struct:
typedef struct {
int x = 0;
} Command;
and global vectors:
vector<Command> cmdList = {}; vector<Event*> eventList = {};
I push_back, erase and clear the vector in another .cpp file. This gets pushed back into:
vector<Command> cmdsToExec = {}; inside per Event struct created. I use this to push_back:
eventList.push_back( new Event() ); eventList[int( eventList.size() ) - 1]->cmdsToExec = cmdList;
My problem A) these Event*s can't be erased with delete and B) is that Valgrind gives this error while trying to determine the size of the cmdsToExec:
==25096== Invalid read of size 8
==25096== at 0x113372: std::vector<Command, std::allocator<Command> >::size() const (stl_vector.h:919)
==25096== by 0x11C1C7: eventHandler::processEvent() (eventHandler.cpp:131)
==25096== by 0x124590: main (main.cpp:88)
==25096== Address 0x630a9e0 is 32 bytes inside a block of size 56 free'd
==25096== at 0x484BB6F: operator delete(void*, unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==25096== by 0x11C116: eventHandler::processEvent() (eventHandler.cpp:222)
==25096== by 0x124590: main (main.cpp:88)
==25096== Block was alloc'd at
==25096== at 0x4849013: operator new(unsigned long) (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==25096== by 0x11B4A5: eventHandler::createEvent() (eventHandler.cpp:58)
==25096== by 0x11B412: eventHandler::doState() (eventHandler.cpp:41)
==25096== by 0x124575: main (main.cpp:83)
Ive tracked it to the line:
while( int( eventList[0]->cmdsToExec.size() ) > 0 ) {
Im not trying to solve this specific problem, its more about how to properly delete and unallocate a dynamic pointer from a global vector of dynamic pointers. That being said there are no objects (and I want to keep it that way). Will I need a struct deconstructor (no pun intended)? Also I dont believe cmdList vector ever has a memory leak according to this error message, also as Im clearing it all at once.
My thoughts on fixing this are to place both global vectors into my main() function and pass them into the program from there. I thought it would be unnecessary to do this and would slow the program down. Thinking now, I guess it wouldn't.
My guess is that this is a problem related to the order of destruction of static/global objects.
C++ guarantees that for a given translation unit (i.e., a cpp source file) then statics/global objects get created in the order that they are defined, and they are destroyed in the reverse order.
C++ gives no guarantee between different translation units.
My recommendations are:
Avoid statics/globals. Move them to be class members if possible.
If you have any dependencies between statics/globals then put them all in the same source file so that you have control over the order of their creation and destruction.

Frama-c : Trouble understanding WP memory models

I'm looking for WP options/model that could allow me to prove basic C memory manipulations like :
memcpy : I've tried to prove this simple code :
struct header_src{
char t1;
char t2;
char t3;
char t4;
};
struct header_dest{
short t1;
short t2;
};
/*# requires 0<=n<=UINT_MAX;
# requires \valid(dest);
# requires \valid_read(src);
# assigns (dest)[0..n-1] \from (src)[0..n-1];
# assigns \result \from dest;
# ensures dest[0..n] == src[0..n];
# ensures \result == dest;
*/
void* Frama_C_memcpy(char *dest, const char *src, uint32_t n);
int main(void)
{
struct header_src p_header_src;
struct header_dest p_header_dest;
p_header_src.t1 = 'e';
p_header_src.t2 = 'b';
p_header_src.t3 = 'c';
p_header_src.t4 = 'd';
p_header_dest.t1 = 0x0000;
p_header_dest.t2 = 0x0000;
//# assert \valid(&p_header_dest);
Frama_C_memcpy((char*)&p_header_dest, (char*)&p_header_src, sizeof(struct header_src));
//# assert p_header_dest.t1 == 0x6265;
//# assert p_header_dest.t2 == 0x6463;
}
but the two last assert weren't verified by WP (with default prover Alt-Ergo). It can be proved thanks to Value analysis, but I mostly want to be able to prove the code not using abstract interpretation.
Cast pointer to int : Since I'm programming embedded code, I want to be able to specify something like:
#define MEMORY_ADDR 0x08000000
#define SOME_SIZE 10
struct some_struct {
uint8_t field1[SOME_SIZE];
uint32_t field2[SOME_SIZE];
}
// [...]
// some function body {
struct some_struct *p = (some_struct*)MEMORY_ADDR;
if(p == NULL) {
// Handle error
} else {
// Do something
}
// } body end
I've looked a little bit at WP's documentation and it seems that the version of frama-c that I use (Magnesium-20151002) has several memory model (Hoare, Typed , +cast, +ref, ...) but none of the given example were proved with any of the model above. It is explicitly said in the documentation that Typed model does not handle pointer-to-int casts. I've a lot of trouble to understand what's really going on under the hood with each wp-model. It would really help me if I was able to verify at least post-conditions of the memcpy function. Plus, I have seen this issue about void pointer that apparently are not very well handled by WP at least in the Magnesium version. I didn't tried another version of frama-c yet, but I think that newer version handle void pointer in a better way.
Thank you very much in advance for your suggestions !
memcpy
Reasoning about the result of memcpy (or Frama_C_memcpy) is out of range of the current WP plugin. The only memory model that would work in your case is Bytes (page 13 of the manual for Chlorine), but it is not implemented.
Independently, please note that your postcondition from Frama_C_memcpy is not what you want here. You are asserting the equality of the sets dest[0..n] and src[0..n]. First, you should stop at n-1. Second, and more importantly, this is far too weak, and is in fact not sufficient to prove the two assertions in the caller. What you want is a quantification on all bytes. See e.g. the predicate memcmp in Frama-C's stdlib, or the variant \forall int i; 0 <= i < n -> dest[i] == src[i];
By the way, this postcondition holds only if dest and src are properly separated, which your function does not require. Otherwise, you should write dest[i] == \at (src[i], Pre). And your requires are also too weak for another reason, as you only require the first character to be valid, not the n first ones.
Cast pointer to int
Basically, all current models implemented in WP are unable to reason on codes in which the memory is accessed with multiple incompatible types (through the use of unions or pointer casts). In some cases, such as Typed, the cast is detected syntactically, and a warning is issued to warn that the code cannot be analyzed. The Typed+Cast model is a variant of Typed in which some casts are accepted. The analysis is correct only if the pointer is re-cast into its original type before being used. The idea is to allow using some libc functions that require a cast to void*, but not much more.
Your example is again a bit different, because it is likely that MEMORY_ADDR is always addressed with type some_stuct. Would it be acceptable to change the code slightly, and change your function as taking a pointer to this type? This way, you would "hide" the cast to MEMORY_ADDR inside a function that would remain unproven.
I tried this example in the latest version of Frama-C (of course the format is modified a little bit).
for the memcpy case
Assertion 2 fails but assertion 3 is successfully proved (basically because the failure of assertion 2 leads to a False assumption, which proves everything).
So in fact both assertion cannot be proved, same as your problem.
This conclusion is sound because the memory models used in the wp plugin (as far as I know) has no assumption on the relation between fields in a struct, i.e. in header_src the first two fields are 8 bit chars, but they may not be nestedly organized in the physical memory like char[2]. Instead, there may be paddings between them (refer to wiki for detailed description). So when you try to copy bits in such a struct to another struct, Frama-C becomes completely confused and has no idea what you are doing.
As far as I am concerned, Frama-C does not support any approach to precisely control the memory layout, e.g. gcc's PACKED which forces the compiler to remove paddings.
I am facing the same problem, and the (not elegant at all) solution is, use arrays instead. Arrays are always nested, so if you try to copy a char[4] to a short[2], I think the assertion can be proved.
for the Cast pointer to int case
With memory model Typed+cast, the current version I am using (Chlorine-20180501) supports casting between pointers and uint64_t. You may want to try this version.
Moreover, it is strongly suggested to call Z3 and CVC4 through why3, whose performance is certainly better than Alt-Ergo.

Frama-C generates confusing assertions about pointer comparison

I'm getting assertions that don't make sense to me.
Code:
struct s {
int pred;
};
/*# assigns \result \from \nothing;
ensures \valid(\result);
*/
struct s *get(void);
int main(void)
{
return !get()->pred;
}
Frama-C output:
$ frama-c -val frama-ptr.c
[...]
frama-ptr.c:12:[kernel] warning: pointer comparison.
assert \pointer_comparable((void *)0, (void *)tmp->pred);
(tmp from get())
Am I doing something wrong or is it a bug in Frama-C?
This is not really a bug, although this behavior is not really satisfactory either. I recommend that you observe the analysis in the GUI (frama-c-gui -val frama-ptr.c), in particular the value of tmp->pred at line 12 in the Values tab.
Value before:
∈
{{ garbled mix of &{alloced_return_get}
(origin: Library function {c/ptrcmp.c:12}) }}
This is a very imprecise value, that has been generated because the return value of function get is a pointer. The Eva plugin generates a dummy variable (alloced_return_get), and fills it with dummy contents (garbled mix of &{alloced_return_get}). Even though the field pred is an integer, the analyzer assumes that (imprecise) pointers can also be present. This is why an alarm for pointer comparison is emitted.
There are at least two ways to avoid this:
use option -val-warn-undefined-pointer-comparison pointer, so that pointer comparison alarms are emitted only on comparisons involving lvalues with pointer type. The contents of the field pred will remain imprecise, though.
add a proper body to function get, possibly written using malloc, so that the field pred receives a more accurate value.
On a more general note, the Eva/Value plugin requires precise specifications for functions without a body; see section 7.2 of the manual. For functions that return pointers, you won't be able to write satisfactory specifications: you need to write allocates clauses, and those are currently not handled by Eva/Value. Thus, I suggest that you write a body for get.

Julia ccall outb - Problems with libc

I run the following ccall's:
status = ccall((:ioperm, "libc"), Int32, (Uint, Uint, Int32), 0x378, 5, 1)
ccall((:outb, "libc"), Void, (Uint8, Uint16), 0x00, 0x378)
After the second ccall I receive the following Error message:
ERROR: ccall: could not find function outb in library libc
in anonymous at no file
in include at ./boot.jl:245
in include_from_node1 at loading.jl:128
in process_options at ./client.jl:285
After some research and messing around I found the following information:
ioperm is in libc, but outb is not
However, both ioperm and outb are defined in the same header file <sys/io.h>
An equivalent version of C code compiles and runs smoothly.
outb in glibc, however on the system glibc is defined as libc
Same problem with full path names /lib/x86_64-linux-gnu/libc.so.6
EDIT:
Thanks for the insight #Employed Russian! I did not look closely enough to realize the extern declaration. Now, all of my above notes make total sense!
Great, we found that ioperm is a libc function that is declared in <sys/io.h>, and that outb is not in libc, but is defined in <sys/io.h> as a volatile assembly instruction.
Which library, or file path should I use?
Implementation of ccall.
However, both ioperm and outb are defined in the same header file <sys/io.h>
By "defined" you actually mean "declared". They are different. On my system:
extern int ioperm (unsigned long int __from, unsigned long int __num,
int __turn_on) __attribute__ ((__nothrow__ , __leaf__));
static __inline void
outb (unsigned char __value, unsigned short int __port)
{
__asm__ __volatile__ ("outb %b0,%w1": :"a" (__value), "Nd" (__port));
}
It should now be obvious why you can call ioperm but not outb.
Update 1
I am still lost as to how to correct the error.
You can't import outb from libc. You would have to provide your own native library, e.g.
void my_outb(unsigned char value, unsigned short port) {
outb(value, port);
}
and import my_outb from it. For symmetry, you should probably implement my_ioperm the same way, so you are importing both functions from the same native library.
Update 2
Making a library worked, but in terms of performance it is horrible.
I guess that's why the original is implemented as an inline function: you are only executing a single outb instruction, so the overhead of a function call is significant.
Unoptimized python does x5 better.
Probably by having that same outb instruction inlined into it.
Do you know if outb exist in some other library, not in libc
That is not going to help: you will still have a function call overhead. I am guessing that when you call the imported function from Julia, you probably execute a dlopen and dlsym call, which would impose an overhead of additional several 100s of instructions.
There is probably a way to "bind" the function dynamically once, and then use it repeatedly to make the call (thus avoiding repeated dlopen and dlsym). That should help.

GCC, linker-script: Variables that resolve to manually defined addresses?

I'll use a simple specific example to illustrate what I'm trying to do.
file main.c:
#include <stdio.h>
unsigned int X;
int main()
{
printf("&X = 0x%zX\r\n", &X);
return 0;
}
I want to know if it's possible (using a linker-script/gcc options) to manually specify an address for X at compile/link time, because I know it lies somewhere in memory, outside my executable.
I only want to know if this is possible, I know I can use a pointer (i.e. unsigned int*) to access a specific memory location (r/w) but that's not what I'm after.
What I'm after is making GCC generate code in which all accesses to global variables/static function variables are either done through a level of indirection, i.e. through a pointer (-fPIC not good enough because static global vars are not accessed via GOT) or their addresses can be manually specified (at link/compile time).
Thank you
What I'm after is making GCC generate code in which all accesses to
global variables/static function variables … their addresses can be
manually specified (at link/compile time).
You can specify the addresses of the .bss and .data sections (which contain the uninitialized and initialized variables respectively) with linker commands. The relative placement of the variables in the sections is up to the compiler/linker.
If you need only individual variables to be placed, this can be done by declaring them extern and specifying their addresses in a file, e. g. addresses.ld:
X = 0x12345678;
(note: spaces around = needed), which is added to the compiler/linker arguments:
cc main.c addresses.ld

Resources