Fixture 147

instruction substitution

C · 6 functions · 4 lanes · 24 of 24 function-lanes behave identically

All 4 lanes recompile and return the same results as the original.

Instruction substitution: the second pass every obfuscator runs after flattening. Each primitive arithmetic operation is replaced by a longer sequence of cheaper ones that computes the same function:

x + y == (x ^ y) + 2 * (x & y) (sum of "carry-less add" + carries) x - y == x + ~y + 1 (two's complement definition) x ^ y == (x | y) - (x & y) x & y == (x + y) - (x | y) x | y == (x + y) - (x & y) x * 23 == (x << 4) + (x << 2) + (x << 1) + x

Every identity above is exact over the full uint32_t ring — they are not approximations that happen to work for small values — so the expansions are safe to apply to arbitrary fuzz input, and any deviation the differential reports is the decompiler's, not the identity's.

Why this breaks decompilers: an expression simplifier has to decide whether (x ^ y) + ((x & y) << 1) is "really" an addition. If it declines, the output is unreadable but correct; if it accepts, it must apply the rewrite only where it is actually valid — the near-miss (x ^ y) + (x & y) is NOT x + y, and neither is (x ^ y) + ((x | y) << 1). Pattern matchers keyed on shape rather than semantics fire on all three and produce a decompilation that reads like clean arithmetic and computes the wrong number. Type recovery is attacked at the same time: the bitwise operands look like flags/masks, so a plausible-looking unsigned flags type is inferred for what is an integer.

No undefined behaviour: everything is unsigned, all shift counts are literal and below 32, buffer lengths are validated against a small constant bound.

tests/decompiler_fixtures/src/147_instruction_substitution.c source
#include <stdint.h>

/* Instruction substitution: the second pass every obfuscator runs after
 * flattening. Each primitive arithmetic operation is replaced by a longer
 * sequence of cheaper ones that computes the same function:
 *
 *     x + y  ==  (x ^ y) + 2 * (x & y)        (sum of "carry-less add" + carries)
 *     x - y  ==  x + ~y + 1                   (two's complement definition)
 *     x ^ y  ==  (x | y) - (x & y)
 *     x & y  ==  (x + y) - (x | y)
 *     x | y  ==  (x + y) - (x & y)
 *     x * 23 ==  (x << 4) + (x << 2) + (x << 1) + x
 *
 * Every identity above is exact over the full uint32_t ring — they are not
 * approximations that happen to work for small values — so the expansions are
 * safe to apply to arbitrary fuzz input, and any deviation the differential
 * reports is the decompiler's, not the identity's.
 *
 * Why this breaks decompilers: an expression simplifier has to decide whether
 * `(x ^ y) + ((x & y) << 1)` is "really" an addition. If it declines, the
 * output is unreadable but correct; if it accepts, it must apply the rewrite
 * only where it is actually valid — the near-miss `(x ^ y) + (x & y)` is NOT
 * `x + y`, and neither is `(x ^ y) + ((x | y) << 1)`. Pattern matchers keyed on
 * shape rather than semantics fire on all three and produce a decompilation
 * that reads like clean arithmetic and computes the wrong number. Type recovery
 * is attacked at the same time: the bitwise operands look like flags/masks, so
 * a plausible-looking `unsigned flags` type is inferred for what is an integer.
 *
 * No undefined behaviour: everything is unsigned, all shift counts are literal
 * and below 32, buffer lengths are validated against a small constant bound.
 */

#define ISUB147_MAX_BYTES 16

static uint32_t isub147_add(uint32_t x, uint32_t y) {
    return (x ^ y) + ((x & y) << 1);
}

static uint32_t isub147_sub(uint32_t x, uint32_t y) {
    return isub147_add(x, isub147_add(~y, 1u));
}

static uint32_t isub147_xor(uint32_t x, uint32_t y) {
    return (x | y) - (x & y);
}

static uint32_t isub147_and(uint32_t x, uint32_t y) {
    return isub147_sub(isub147_add(x, y), x | y);
}

static uint32_t isub147_or(uint32_t x, uint32_t y) {
    return isub147_sub(isub147_add(x, y), x & y);
}

/* Plain addition, expanded twice: the outer add is itself substituted, so the
 * carry chain appears as nested xor/and/shift instead of one instruction. */
__attribute__((noinline)) uint32_t
substituted_add(uint32_t x, uint32_t y) {
    return isub147_add(isub147_add(x, y), 0u);
}

/* Subtraction routed through the two's-complement identity. Note the negation
 * itself is substituted, so no unary minus survives in the source. */
__attribute__((noinline)) uint32_t
substituted_sub(uint32_t x, uint32_t y) {
    return isub147_sub(x, y);
}

/* All three bitwise primitives expressed through their arithmetic duals, then
 * recombined. The result is `(x ^ y) ^ ((x & y) | ...)` for concrete inputs but
 * is written entirely in terms of + and -. */
__attribute__((noinline)) uint32_t
substituted_bitops(uint32_t x, uint32_t y) {
    uint32_t a = isub147_xor(x, y);
    uint32_t b = isub147_and(x, y);
    uint32_t c = isub147_or(x, y);
    return isub147_add(isub147_xor(a, b), isub147_sub(c, b));
}

/* Multiplication by a constant as a shift-add chain, with each add substituted.
 * A decompiler that recognises the shift-add ladder must recover `* 23`; one
 * that recognises it wrongly recovers a different constant, which the
 * differential separates on the very first vector. */
__attribute__((noinline)) uint32_t
substituted_multiply(uint32_t x) {
    uint32_t s4 = x << 4;
    uint32_t s2 = x << 2;
    uint32_t s1 = x << 1;
    return isub147_add(isub147_add(s4, s2), isub147_add(s1, x));
}

/* Negation with no `-` in sight. Signed extremes are safe because the whole
 * computation happens in uint32_t. */
__attribute__((noinline)) int32_t
substituted_negate(int32_t value) {
    return (int32_t)isub147_add(~(uint32_t)value, 1u);
}

/* A byte-wise checksum whose every operation is substituted, so the loop body
 * expands to roughly twenty instructions with no recognisable accumulator
 * update. `length` is validated against a small constant bound. */
__attribute__((noinline)) uint32_t
substituted_checksum(uint8_t *data, int32_t length) {
    int32_t index;
    uint32_t acc = 0x811C9DC5u;

    if (data == 0 || length < 0 || length > ISUB147_MAX_BYTES) {
        return 0u;
    }

    for (index = 0; index < length; ++index) {
        uint32_t byte = (uint32_t)data[index];
        acc = isub147_xor(acc, byte);
        acc = isub147_add(isub147_add(acc << 1, acc << 4), isub147_add(acc << 7, acc));
    }
    return isub147_sub(acc, (uint32_t)length);
}

Recovered C

Generated by glaurung decompile --style decbench at b47f6b43. baseline.json records the result after recompiling the C and calling it beside the original with seeded inputs.

clang -O0

6/6
substituted_add pass 11 lines
// glaurung: substituted_add @ 0x1100
uint32_t substituted_add(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int ret;
    unsigned int var0;
    // x86-64 prologue: save rbp, frame 16 bytes
    var0 = isub147_add(arg0, arg1);
    ret = isub147_add(var0, 0);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_bitops pass 31 lines
// glaurung: substituted_bitops @ 0x11b0
uint32_t substituted_bitops(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    extern unsigned int isub147_and(unsigned int, unsigned int);
    extern unsigned int isub147_or(unsigned int, unsigned int);
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    extern unsigned int isub147_xor(unsigned int, unsigned int);
    unsigned int a;
    unsigned int b;
    unsigned int c;
    int local_18;
    unsigned int ret;
    unsigned int var0;
    unsigned int var2;
    unsigned int var4;
    unsigned int var6;
    unsigned int var8;
    // x86-64 prologue: save rbp, frame 32 bytes
    var0 = isub147_xor(arg0, arg1);
    a = var0;
    var2 = isub147_and(arg0, arg1);
    b = var2;
    var4 = isub147_or(arg0, arg1);
    c = var4;
    var6 = isub147_xor(a, b);
    local_18 = var6;
    var8 = isub147_sub(c, b);
    ret = isub147_add((unsigned long)((unsigned int)(local_18)), var8);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_checksum pass 44 lines
// glaurung: substituted_checksum @ 0x1320
uint32_t substituted_checksum(uint8_t * arg0, int32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    extern unsigned int isub147_xor(unsigned int, unsigned int);
    unsigned int acc;
    int index;
    unsigned int byte;
    int local_24;
    int local_4;
    unsigned int var12;
    unsigned int var16;
    unsigned int var18;
    unsigned int var23;
    unsigned int var6;
    // x86-64 prologue: save rbp, frame 48 bytes
    acc = -0x7ee3623bLL;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    for (index = 0; (index < arg1); index++) {
        byte = (unsigned char)(arg0[index]);
        var6 = isub147_xor(acc, byte);
        acc = var6;
        var12 = isub147_add((unsigned long)((unsigned int)((acc << 1))), (unsigned long)((unsigned int)((acc << 4))));
        local_24 = var12;
        var16 = isub147_add((unsigned long)((unsigned int)((acc << 7))), acc);
        var18 = isub147_add((unsigned long)((unsigned int)(local_24)), var16);
        acc = var18;
    }
    var23 = isub147_sub(acc, (unsigned long)((unsigned int)(arg1)));
    local_4 = var23;
    // x86-64 epilogue: restore rbp
    return (unsigned int)(local_4);
}
substituted_multiply pass 21 lines
// glaurung: substituted_multiply @ 0x12a0
uint32_t substituted_multiply(uint32_t arg0) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int s4;
    unsigned int s2;
    unsigned int s1;
    int local_14;
    unsigned int ret;
    unsigned int var11;
    unsigned int var9;
    // x86-64 prologue: save rbp, frame 32 bytes
    s4 = (arg0 << 4);
    s2 = (arg0 << 2);
    s1 = (arg0 << 1);
    var9 = isub147_add(s4, s2);
    local_14 = var9;
    var11 = isub147_add(s1, arg0);
    ret = isub147_add((unsigned long)((unsigned int)(local_14)), var11);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_negate pass 9 lines
// glaurung: substituted_negate @ 0x12f0
int32_t substituted_negate(int32_t arg0) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int ret;
    // x86-64 prologue: save rbp, frame 16 bytes
    ret = isub147_add((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) ^ -1))), 1);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_sub pass 9 lines
// glaurung: substituted_sub @ 0x1150
uint32_t substituted_sub(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    unsigned int ret;
    // x86-64 prologue: save rbp, frame 16 bytes
    ret = isub147_sub(arg0, arg1);
    // x86-64 epilogue: restore rbp
    return ret;
}

clang -O2

6/6
substituted_add pass 4 lines
// glaurung: substituted_add @ 0x1100
uint32_t substituted_add(uint32_t arg0, uint32_t arg1) {
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)(arg1) ^ arg0))) + ((unsigned long)((unsigned int)((arg1 & arg0))) * 2)));
}
substituted_bitops pass 27 lines
// glaurung: substituted_bitops @ 0x1130
uint32_t substituted_bitops(uint32_t arg0, uint32_t arg1) {
    unsigned int b;
    unsigned int c;
    unsigned int a;
    long var10;
    int var19;
    long var2;
    int var31;
    long var40;
    int var49;
    long var5;
    long var56;
    long var8;
    var2 = (unsigned long)((unsigned int)((arg1 ^ arg0)));
    var5 = (unsigned long)((unsigned int)((arg1 & arg0)));
    var8 = (unsigned long)((unsigned int)((var2 + (var5 * 2))));
    var10 = (unsigned long)((unsigned int)((arg1 | arg0)));
    var19 = ((unsigned int)(((~(unsigned long)((unsigned int)((var10 + var10)))) & 2)) + (unsigned int)(((unsigned long)((unsigned int)(var10)) ^ -2)));
    b = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var19)) ^ var8))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var19)) & var8))) * 2))));
    var31 = ((unsigned int)(((~(unsigned long)((unsigned int)((var5 + var5)))) & 2)) + (unsigned int)((var5 ^ -2)));
    c = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) ^ var8))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var31)) & var8))) * 2))));
    var40 = (unsigned long)((unsigned int)((var2 ^ b)));
    var49 = ((unsigned int)(((~(unsigned long)((unsigned int)((b + b)))) & 2)) + (unsigned int)((b ^ -2)));
    var56 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var49)) ^ c))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var49)) & c))) * 2))));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var56)) ^ var40))) + ((unsigned long)((unsigned int)((var40 & var56))) * 2)));
}
substituted_checksum pass 43 lines
// glaurung: substituted_checksum @ 0x11e0
uint32_t substituted_checksum(uint8_t * arg0, int32_t arg1) {
    int index;
    unsigned int acc;
    unsigned int byte;
    long ret;
    long var12;
    long var15;
    long var2;
    long var22;
    long var28;
    long var29;
    long var3;
    int var43;
    long var8;
    ret = 0;
    if ((arg0 == 0)) {
        return ret;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return ret;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var2 = 0x811c9dc5;
    } else {
        var3 = (unsigned long)((unsigned int)(arg1));
        index = 0;
        var8 = 0x811c9dc5;
        do {
            acc = (unsigned long)((unsigned int)(((unsigned int)((unsigned char)(*(char *)(((long)arg0 + index)))) ^ var8)));
            var12 = (unsigned long)((unsigned int)((acc + acc)));
            var15 = (unsigned long)((unsigned int)((acc << 7)));
            var22 = (unsigned long)((unsigned int)((acc << 4)));
            var28 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var22)) ^ var12))) + ((unsigned long)((unsigned int)((var22 & var12))) * 2))));
            var29 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) ^ acc))) + ((unsigned long)((unsigned int)((var15 & acc))) * 2))));
            var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var29)) ^ var28))) + ((unsigned long)((unsigned int)((var29 & var28))) * 2))));
            index = (index + 1);
            var8 = var2;
        } while ((var3 != index));
    }
    var43 = ((unsigned int)(((~(unsigned long)((unsigned int)((arg1 + arg1)))) & 2)) + (unsigned int)(((unsigned long)((unsigned int)(arg1)) ^ -2)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var2)) ^ (unsigned long)((unsigned int)(var43))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var43)) & var2))) * 2)));
}
substituted_multiply pass 16 lines
// glaurung: substituted_multiply @ 0x11a0
uint32_t substituted_multiply(uint32_t arg0) {
    unsigned int s2;
    unsigned int s1;
    unsigned int s4;
    long var1;
    long var14;
    long var15;
    long var8;
    s2 = (unsigned long)((unsigned int)((arg0 * 4)));
    var1 = (unsigned long)((unsigned int)((arg0 + arg0)));
    var8 = (unsigned long)((unsigned int)((arg0 << 4)));
    var14 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((s2 ^ var8))) + ((unsigned long)((unsigned int)((var8 & s2))) * 2))));
    var15 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var1)) ^ arg0))) + ((unsigned long)((unsigned int)((var1 & arg0))) * 2))));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var15)) ^ var14))) + ((unsigned long)((unsigned int)((var15 & var14))) * 2)));
}
substituted_negate pass 4 lines
// glaurung: substituted_negate @ 0x11d0
int32_t substituted_negate(int32_t arg0) {
    return (unsigned int)(((unsigned long)((unsigned int)(((~(unsigned long)((unsigned int)((arg0 + arg0)))) & 2))) + (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(arg0)) ^ -2)))));
}
substituted_sub pass 6 lines
// glaurung: substituted_sub @ 0x1110
uint32_t substituted_sub(uint32_t arg0, uint32_t arg1) {
    int var8;
    var8 = ((unsigned int)(((~(unsigned long)((unsigned int)((arg1 + arg1)))) & 2)) + (unsigned int)((arg1 ^ -2)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) ^ arg0))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var8)) & arg0))) * 2)));
}

gcc -O0

6/6
substituted_add pass 11 lines
// glaurung: substituted_add @ 0x11d6
uint32_t substituted_add(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int ret;
    unsigned int var2;
    // x86-64 prologue: save rbp, frame 8 bytes
    var2 = isub147_add(arg0, arg1);
    ret = isub147_add(var2, 0);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_bitops pass 31 lines
// glaurung: substituted_bitops @ 0x1228
uint32_t substituted_bitops(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    extern unsigned int isub147_and(unsigned int, unsigned int);
    extern unsigned int isub147_or(unsigned int, unsigned int);
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    extern unsigned int isub147_xor(unsigned int, unsigned int);
    unsigned int a;
    unsigned int b;
    unsigned int c;
    unsigned int ret;
    unsigned int var10;
    unsigned int var14;
    long var16;
    unsigned int var19;
    unsigned int var2;
    unsigned int var6;
    // x86-64 prologue: save rbp, frame 8 bytes
    var2 = isub147_xor(arg0, arg1);
    a = var2;
    var6 = isub147_and(arg0, arg1);
    b = var6;
    var10 = isub147_or(arg0, arg1);
    c = var10;
    var14 = isub147_sub(c, b);
    var16 = (unsigned long)(var14);
    var19 = isub147_xor(a, b);
    ret = isub147_add(var19, (unsigned long)((unsigned int)(var16)));
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_checksum pass 42 lines
// glaurung: substituted_checksum @ 0x131b
uint32_t substituted_checksum(uint8_t * arg0, int32_t arg1) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    extern unsigned int isub147_xor(unsigned int, unsigned int);
    unsigned int acc;
    int index;
    unsigned int byte;
    unsigned int ret;
    unsigned int var10;
    unsigned int var17;
    long var19;
    unsigned int var27;
    unsigned int var29;
    // x86-64 prologue: save rbp, frame 8 bytes
    acc = -0x7ee3623bLL;
    if ((arg0 == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((long)(arg1) < 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    if (((((unsigned long)((unsigned int)(arg1)) == 16) | ((long)(arg1) < 16)) == 0)) {
        // x86-64 epilogue: restore rbp
        return 0;
    }
    for (index = 0; (index < arg1); index++) {
        byte = (unsigned char)(((unsigned int)((unsigned char)(arg0[index])) & 255));
        var10 = isub147_xor(acc, byte);
        acc = var10;
        var17 = isub147_add((unsigned long)((unsigned int)((acc << 7))), acc);
        var19 = (unsigned long)(var17);
        var27 = isub147_add((unsigned long)((unsigned int)((acc + acc))), (unsigned long)((unsigned int)((acc << 4))));
        var29 = isub147_add(var27, (unsigned long)((unsigned int)(var19)));
        acc = var29;
    }
    ret = isub147_sub(acc, (unsigned long)((unsigned int)(arg1)));
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_multiply pass 21 lines
// glaurung: substituted_multiply @ 0x12a0
uint32_t substituted_multiply(uint32_t arg0) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int s4;
    unsigned int s2;
    unsigned int s1;
    unsigned int ret;
    unsigned int var11;
    long var13;
    unsigned int var16;
    // x86-64 prologue: save rbp, frame 8 bytes
    s4 = (arg0 << 4);
    s2 = (arg0 << 2);
    s1 = (arg0 + arg0);
    var11 = isub147_add(s1, arg0);
    var13 = (unsigned long)(var11);
    var16 = isub147_add(s4, s2);
    ret = isub147_add(var16, (unsigned long)((unsigned int)(var13)));
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_negate pass 9 lines
// glaurung: substituted_negate @ 0x12f9
int32_t substituted_negate(int32_t arg0) {
    extern unsigned int isub147_add(unsigned int, unsigned int);
    unsigned int ret;
    // x86-64 prologue: save rbp, frame 8 bytes
    ret = isub147_add((unsigned long)((unsigned int)((~(unsigned long)((unsigned int)(arg0))))), 1);
    // x86-64 epilogue: restore rbp
    return ret;
}
substituted_sub pass 9 lines
// glaurung: substituted_sub @ 0x1205
uint32_t substituted_sub(uint32_t arg0, uint32_t arg1) {
    extern unsigned int isub147_sub(unsigned int, unsigned int);
    unsigned int ret;
    // x86-64 prologue: save rbp, frame 8 bytes
    ret = isub147_sub(arg0, arg1);
    // x86-64 epilogue: restore rbp
    return ret;
}

gcc -O2

6/6
substituted_add pass 4 lines
// glaurung: substituted_add @ 0x1100
uint32_t substituted_add(uint32_t arg0, uint32_t arg1) {
    return (unsigned int)(((unsigned long)((unsigned int)((arg0 ^ arg1))) + ((unsigned long)((unsigned int)(((unsigned long)(arg0) & arg1))) * 2)));
}
substituted_bitops pass 33 lines
// glaurung: substituted_bitops @ 0x1130
uint32_t substituted_bitops(uint32_t arg0, uint32_t arg1) {
    unsigned int b;
    unsigned int c;
    unsigned int a;
    int var12;
    int var18;
    int var28;
    long var3;
    long var30;
    int var35;
    int var45;
    long var5;
    int var52;
    long var60;
    long var7;
    long var9;
    var3 = (unsigned long)((unsigned int)((arg0 & arg1)));
    var5 = (unsigned long)((unsigned int)((arg0 | arg1)));
    var7 = (unsigned long)((unsigned int)((arg0 ^ arg1)));
    var9 = (unsigned long)((unsigned int)((var7 + (var3 * 2))));
    var12 = (~(unsigned long)((unsigned int)(var5)));
    var18 = ((unsigned int)(((unsigned long)((unsigned int)((var12 + var12))) & 2)) + (unsigned int)((var5 ^ -2)));
    b = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var18)) ^ var9))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var9)) & (unsigned long)((unsigned int)(var18))))) * 2))));
    var28 = (~(unsigned long)((unsigned int)(var3)));
    var30 = (unsigned long)((unsigned int)((var7 ^ b)));
    var35 = ((unsigned int)(((unsigned long)((unsigned int)((var28 + var28))) & 2)) + (unsigned int)((var3 ^ -2)));
    c = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var35)) ^ var9))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var35)) & var9))) * 2))));
    var45 = (~b);
    var52 = ((unsigned int)(((unsigned long)((unsigned int)((var45 + var45))) & 2)) + (unsigned int)((b ^ -2)));
    var60 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var52)) ^ c))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var52)) & c))) * 2))));
    return (unsigned int)(((unsigned long)((unsigned int)((var30 ^ var60))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var30)) & var60))) * 2)));
}
substituted_checksum pass 46 lines
// glaurung: substituted_checksum @ 0x11f0
uint32_t substituted_checksum(uint8_t * arg0, int32_t arg1) {
    unsigned int acc;
    unsigned int byte;
    int index;
    long var13;
    long var19;
    long var2;
    int var21;
    long var24;
    long var30;
    int var39;
    int var44;
    long var5;
    long var6;
    long var7;
    int var8;
    if ((arg0 == 0)) {
        return 0;
    }
    if (((unsigned long)(16) < (unsigned long)((unsigned long)((unsigned int)(arg1))))) {
        return 0;
    }
    if (((unsigned long)((unsigned int)(arg1)) == 0)) {
        var2 = 0x811c9dc5;
    } else {
        var5 = (long)((((long)arg0 + (unsigned long)((unsigned int)((arg1 - 1)))) + 1));
        var6 = (long)arg0;
        var7 = 0x811c9dc5;
        do {
            var8 = (unsigned int)((unsigned char)(*(char *)((var6))));
            var6 = (var6 + 1);
            acc = (unsigned long)((unsigned int)((var8 ^ var7)));
            var13 = (unsigned long)((unsigned int)((acc << 7)));
            var19 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var13 ^ acc))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var13)) & acc))) * 2))));
            var21 = (acc + acc);
            var24 = (unsigned long)((unsigned int)((acc << 4)));
            var30 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var24 ^ (unsigned long)((unsigned int)(var21))))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var24)) & (unsigned long)((unsigned int)(var21))))) * 2))));
            var2 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var30 ^ var19))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var30)) & var19))) * 2))));
            var7 = var2;
        } while ((var5 != var6));
    }
    var39 = (~(unsigned long)((unsigned int)(arg1)));
    var44 = ((unsigned int)((arg1 ^ -2)) + (unsigned int)(((unsigned long)((unsigned int)((var39 + var39))) & 2)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) ^ var2))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var44)) & var2))) * 2)));
}
substituted_multiply pass 15 lines
// glaurung: substituted_multiply @ 0x11a0
uint32_t substituted_multiply(uint32_t arg0) {
    unsigned int s1;
    unsigned int s2;
    unsigned int s4;
    long var10;
    long var16;
    long var5;
    s1 = (unsigned long)((unsigned int)((arg0 + arg0)));
    s2 = (unsigned long)((unsigned int)((arg0 * 4)));
    var5 = (unsigned long)((unsigned int)((arg0 << 4)));
    var10 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((arg0 ^ s1))) + ((unsigned long)((unsigned int)((arg0 & s1))) * 2))));
    var16 = (unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var5 ^ s2))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var5)) & s2))) * 2))));
    return (unsigned int)(((unsigned long)((unsigned int)((var16 ^ var10))) + ((unsigned long)((unsigned int)(((unsigned long)((unsigned int)(var16)) & var10))) * 2)));
}
substituted_negate pass 6 lines
// glaurung: substituted_negate @ 0x11d0
int32_t substituted_negate(int32_t arg0) {
    int var3;
    var3 = (~(unsigned long)((unsigned int)(arg0)));
    return (unsigned int)(((unsigned long)((unsigned int)(((unsigned long)((unsigned int)((var3 + var3))) & 2))) + (unsigned long)((unsigned int)((arg0 ^ -2)))));
}
substituted_sub pass 8 lines
// glaurung: substituted_sub @ 0x1110
uint32_t substituted_sub(uint32_t arg0, uint32_t arg1) {
    int var3;
    int var8;
    var3 = (~arg1);
    var8 = ((unsigned int)((arg1 ^ -2)) + (unsigned int)(((unsigned long)((unsigned int)((var3 + var3))) & 2)));
    return (unsigned int)(((unsigned long)((unsigned int)((arg0 ^ (unsigned long)((unsigned int)(var8))))) + ((unsigned long)((unsigned int)(((unsigned long)(arg0) & (unsigned long)((unsigned int)(var8))))) * 2)));
}

← 213 fixtures