rellic icon indicating copy to clipboard operation
rellic copied to clipboard

Signed bitcode values emitted as unsigned C

Open artemdinaburg opened this issue 4 years ago • 2 comments

Rellic will sometimes forget signedess and emit unsigned casts for signed integers. Simple example below:

signed.c:

#include <stdbool.h>

bool signed_less_than_1(signed short v) {
  return v < 1;
}

Compile:

clang-11 -O1 -std=c99 -emit-llvm -c -o signed.bc signed.c

Rellic:

rellic-decomp-11.0 --input signed.bc --output signed_decomp.c

Output:

unsigned char signed_less_than_1(unsigned short arg0);
unsigned char signed_less_than_1(unsigned short arg0) {
    return (arg0 < (unsigned short)1U);
}

The bitcode in question performs a signed compare, and rellic should emit a signed compare as well:

define dso_local zeroext i1 @signed_less_than_1(i16 signext %0) local_unnamed_addr #0 {
  %2 = icmp slt i16 %0, 1
  ret i1 %2
}

artemdinaburg avatar Apr 15 '21 13:04 artemdinaburg

Resolved by #121

Unfortunately I haven't found a good way of regression testing this one using our executable roundtrip tests, because we don't have type inference.

surovic avatar Jun 08 '21 16:06 surovic

I might just be out of the loop, but it seems that the issue still exists; after building 356ecb16bc7a1eb4e34989b5765e3a011fdcbc0e and reproducing the test case, the LLVM IR is identical to before:

define dso_local zeroext i1 @signed_less_than_1(i16 signext %0) local_unnamed_addr #0 {
  %2 = icmp slt i16 %0, 1
  ret i1 %2
}

while the produced roundtrip code is slightly different, but still with the wrong type signature:

unsigned char signed_less_than_1(unsigned short arg0);
unsigned char signed_less_than_1(unsigned short arg0) {
    return (short)arg0 < 1;
}

greenbagels avatar Sep 02 '21 22:09 greenbagels