pthread_cancel is broken on Mac OS X (it only works if the thread
you want to kill calls pthread_testcancel, which is never the situation
when you need async cancelation).
Anyway async cancelation is risky, it may leave bc_ctx in an inconsistent state.
So rather than doing using pthread_cancel (or pthread_kill+siglongjmp)
just insert the timeout checks into the JITed code directly.
These are inserted in each loop, if the loop's tripcount is unknown, or
higher than a threshold. They are also inserted after a certain amount
of APIcalls are made (even in absence of loops).
Note that 'loop' in this sense is not LLVM's notion of a natural loop,
it is simply a BB which is reachable both directly and via a backedge.
For example this doesn't contain natural loops but contains backedges (and a
potential infinite loop):
int foo(int a)
{
int x=4;
if (a == 42)
goto head2;
head:
x++;
head2:
if (a >= 2) {
x += 3;
goto head;
} else if (a >= 0) {
x += 9;
goto head;
}
return x;
}
Common function prototypes must be added only once per Module, otherwise LLVM autorenames
them, and we get llvm.bswap.i326 instead of llvm.bswap.i32, which is of course
not valid and the verifier rejects.
On 32-bit targets LLVM emits libcalls for 64-bit operations.
Make sure these libcalls actually map to our own functions, and not to 0.
Also reject any other libcall we don't know about instead of mapping to 0 and crashing.
gcc 3.4.6 doesn't support atomic builtins required by LLVM for multithreaded
mode.
So make the minimum version 4.1.3, since: 4.0 is buggy for ClamAV itself, and
4.1.1, 4.1.2 are buggy when compiling LLVM.
On gcc 3.4.6 clamav will use the interpreter now.