[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v6 1/4] xen: introduce SYMBOL



>>> On 21.01.19 at 06:24, <Stewart.Hildebrand@xxxxxxxxxxxxxxx> wrote:
> On Friday, January 18, 2019 6:05 PM, Stefano Stabellini wrote:
>> I don't think this is the case for MISRAC. C rules apply to C. Other
>> rules apply to assembly and linker scripts. This is something that
>> should be easy to check, and I hope that Stewart should be able to
>> confirm.
> 
> Would it help to provide a guarantee that during processing of one
> compilation unit, the compiler doesn't have visibility into other
> compilation units or object files?
> 
> With GCC, we have the luxury of being able to specify no link time
> optimization and no whole program optimization. This could also involve
> one of -fno-lto, -fno-whole-program, or both.
> 
> We should also specify to invoke the compiler separately for each .c file
> (i.e. don't do "gcc -c foo.c bar.c", rather they should be separate steps
> "gcc -c foo.c" and "gcc -c bar.c").

I don't see how use of whole program optimization matters here:
In order to do so, the compiler leverages information it has stored
in the object files originating from .c ones. Such information is
necessarily missing from object files resulting from assembly sources
or the symbols originating from linker scripts.

> Can we agree that this would give us a guarantee C land is separate from
> assembly and linker lands?
> 
> I have not investigated clang, but we should make sure we can provide this
> guarantee for clang as well.
> 
> With those guarantees in place, can we agree that what happens in an
> assembly source file is not subject to the potential undefined pointers to
> different objects behavior described in C99 section 6.5.6 and 6.5.8, and
> the "if and only if" clause in 6.5.9? (I'm not talking about inline
> assembly).

I simply don't know. Interfacing with other languages is, I'm
afraid, beyond the scope of the C spec.

>> Comparisons between pointers to different objects is undefined by the C
>> spec, and not allowed by MISRAC.
>> 
>> Casting pointers to integers and casting integers to pointers is
>> implementation-defined, which is not the same thing as undefined.
>> 
>> Specifically, casting integers to pointers and pointers to integers is
>> allowed by MISRAC with the caveat that we should avoid misaligned
>> pointers (char* are always allowed), and that a compatible pointer type
>> is used when accessing the object (char* is always compatible). Stewart
>> will send a longer explanation over the weekend.
>> 
>> I don't make up the rules, I am only trying to follow them :-)
> 
> I'll get to that in a bit, but first, it's time for another radical new
> idea. Let's call it approach number 4.
> 
> The undefined behavior and "if and only if" clause (C99 6.5.6/8/9) only
> pertain to the subtract/compare operators. So, if we don't use the
> subtract/compare operators in C land, we won't be subject to the undefined
> behavior. Let's move the pointer subtract/compare operations to assembly.
> Not inline assembly, but to a separate assembly source file.
> 
> We would write subroutines in assembly (callable from C) for each
> subtract/compare operation required. For example:
> char * subtract_ptr_ptr(char *, char *);
> char * subtract_ptr_int(char *, uintptr_t);
> int test_equal(char *, char *);
> 
> That could even open up the door for common operations like "_end - _start":
> size_t get_program_size(void);
> 
> If we can prove to the compiler that we're subtracting/comparing pointers
> to the same object, or one element past the last, then we're still OK to
> use the subtract/compare operators. Otherwise, call these functions.
> 
> This approach relies on being able to provide some or all of the
> guarantees discussed above.
> 
> Do you think this will prevent GCC from doing its code-breaking
> optimization in questions and help with MISRA C?

As per my earlier reply, I've yet to see proof of a "code-breaking
optimization" that actually matches our case(s). As to MISRA-C -
maybe; I simply can't tell. What I can tell though that in terms of
code uglification this new approach is not really better than what
was proposed before. Anyway - before thinking about the least
bad option of how to change our code, I'd like to be convinced
that we need to make changes in the first place.

> Lastly, back to the casts question (though it may be irrelevant if we
> choose the approach I just outlined): the C standard guarantees that you
> can reliably convert a void pointer to uintptr_t and back (C99 section
> 7.18.1.4). This is fully defined by the C standard: no unspecified,
> implementation-defined, or undefined behavior about that. It does not make
> the same guarantee for other pointer types. Rather, conversion between
> pointer types (other than void*) and integers is implementation defined
> (C99 section 6.3.2.3 paragraphs 5 and 6). Further, converting any pointer
> type (except function pointer types) to a "void *" and back is not lossy
> (C99 section 6.3.2.3 paragraph 1).

Ah yes, I see. Two caveats: It's the library specification of the spec,
and hence not directly applicable (as we simply have no library in the
hypervisor). And the two types are optional. But yes, I agree it helps
clarify the overall intent.

> So, let's say you have a "char *" that you want to convert to uintptr_t,
> you'd first have to convert to "void *".
> 
> char * im_a_char_ptr;
> uintptr_t im_a_uintptr_t;
> /* ... initialization ... */
> im_a_uintptr_t = (uintptr_t)(void*)im_a_char_ptr;
> im_a_char_ptr = (char*)(void*)im_a_uintptr_t;
> 
> It may not be pretty, and I fully sympathize with your resistance toward
> unnecessary casts, but we have a fully C99 standard compliant way to
> convert between uintptr_t and pointer types and back without loss, and
> without relying on unspecified, implementation-defined, or undefined
> behavior.

Except that, as was mentioned before, it remains unclear whether the
compiler may legitimately "look through" such casts and apply gained
knowledge to its "undefined behavior optimization".

> MISRA C advises that you shouldn't do such casting, but recognizes that it
> is necessary in some cases, so it gives guidelines for the case when an
> integer type is converted to a pointer type:
> 1. Take care to avoid misaligned pointers ("char *" will always be
>    aligned, assuming certain properties of the execution environment)
> 2. Ensure that a compatible pointer type is used when accessing the object
>    ("char *" is always guaranteed to be compatible)

And how would proof of, in particular, point 2 look like for a random
piece of code?

Jan


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.