Re:Pointers Are More Abstract Than You Might Expect in C
by nwmcsween on Monday July 02, 2018 @12:14PM
(#17442909)
> flag bits
That's sort of a processor specific implementation detail, IIRC you can access them via GNU extensions.
> SIMD vectors
Not having SIMD IMO is a feature as doing useful things will expose processor specific details, you can use SWAR to do some of SIMD.
Re:Pointers Are More Abstract Than You Might Expect in C
by jcranmer on Monday July 02, 2018 @01:06PM
(#17443419)
Exposing processor-specific details is the desired feature, not a bug. The people who want to program C for portable assembly do so because they want to take advantage of things they know about the architecture: the same source code isn't really portable across different architectures without #ifdef anyways.
Re:Pointers Are More Abstract Than You Might Expect in C
by p1esk on Monday July 02, 2018 @02:31PM
(#17444244)
But if you don't care about portability, and want more hardware control, you can do inline assembly, or something like Intel's AVX intrinsics.
Re:Pointers Are More Abstract Than You Might Expect in C
by trentnelson on Tuesday July 03, 2018 @01:12AM
(#17447705)
> Traps don't quite work the way you'd want in C [1]; there's no way to catch a trap that occurs in a specific region of code.
Ah, unless you're in NT land, which makes lexical scoping of traps very easy: https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285...
//
// Verify the guard page is working properly by wrapping an attempt to
// write to it in a structured exception handler that will catch the
// access violation trap.
//
// N.B. We only do this if we're not actively being debugged, as the
// traps get dispatched to the debugger engine first as part of
// the "first-pass" handling logic of the kernel.
//
if (!IsDebuggerPresent()) {
CaughtException = FALSE;
TRY_PROBE_MEMORY{
*Unusable = 1;
} CATCH_EXCEPTION_ACCESS_VIOLATION{
CaughtException = TRUE;
}
ASSERT(CaughtException);
}
The helper #defines: https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285..., e.g. #define TRY_TSX __try
#define TRY_AVX __try
#define TRY_AVX512 __try
#define TRY_AVX_ALIGNED __try
#define TRY_AVX_UNALIGNED __try
#define TRY_SSE42 __try
#define TRY_SSE42_ALIGNED __try
#define TRY_SSE42_UNALIGNED __try
#define TRY_PROBE_MEMORY __try
#define TRY_MAPPED_MEMORY_OP __try
#define CATCH_EXCEPTION_ILLEGAL_INSTRUCTION __except( \
GetExceptionCode() == EXCEPTION_ILLEGAL_INSTRUCTION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_EXCEPTION_ACCESS_VIOLATION __except( \
GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_STATUS_IN_PAGE_ERROR __except( \
GetExceptionCode() == STATUS_IN_PAGE_ERROR ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
#define CATCH_STATUS_IN_PAGE_ERROR_OR_ACCESS_VIOLATION __except( \
GetExceptionCode() == STATUS_IN_PAGE_ERROR || \
GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? \
EXCEPTION_EXECUTE_HANDLER : \
EXCEPTION_CONTINUE_SEARCH \
)
Also allows you to do fun things like this for testing if you can do an AVX512 op (although this is not the supported way of doing things): #pragma optimize("", off)
static
NOINLINE
VOID
CanWeUseAvx512(PBOOLEAN UseAvx512Pointer)
{
BOOLEAN UseAvx512 = TRUE;
TRY_AVX512 {
ZMMWORD Test1 = _mm512_set1_epi64(1);
ZMMWORD Test2 = _mm512_add_epi64(Test1, Test1);
UNREFERENCED_PARAMETER(Test2);
} CATCH_EXCEPTION_ILLEGAL_INSTRUCTION{
UseAvx512 = FALSE;
}
*UseAvx512Pointer = UseAvx512;
}
#pragma optimize("", on)
https://github.com/tpn/tracer/blob/0224d94b8d17fe74c39cec285...The structured exception handling protocol used by NT is really quite elegant.
The first obvious issue is that C is specified by an abstract machine that doesn't really correspond to actual hardware. There's no concept of segmented memory, or multiple address spaces in C. Traps don't quite work the way you'd want in C [1]; there's no way to catch a trap that occurs in a specific region of code. Worse, the abstract machine leans on a definition of undefined behavior in such a way that it's painful for programmers but not useful enough to make automatic security permissible. (Unsigned overflow, which is going to be a more common cause of overflows that lead to security vulnerabilities, is well-defined).
However, the more real problem with C is that it is outright missing hardware features that you'd like access to. Things like rotate instructions or wide multiply are easy enough to pattern match, so their lack isn't so devastating. But flag bits--particularly add with carry or checked overflow operations--aren't figured into at all. SIMD vectors have no conception. Returning multiple values via registers. Traps [1]. Coroutines. Multiple address spaces (especially important for GPUs).
[1] Admittedly, the OS is also to blame here: POSIX signals are a really atrocious way to handle machine-generated faults.