Introduction

AddressSanitizer, LibFuzzer, In recent years there has been a significant increase in the interest into the LLVM project from security practitioners in both industry and academia. The reason for this is largely that the LLVM project offers a convenient way to develop novel program analysis tools and techniques allowing researchers to rapidly prototype new systems. This has resulted in a a significant amount of work being contributed to the project and attracted more and more engineers, resulting in a compound-like growth. There are many popular security-oriented projects that rely heavily on LLVM with some of the popular ones being KLEE S2E and PANDA . In addition to this, LLVM has a large body of analysis capabilities integrated into the compiler framework itself , which can perform a broad series of optimisations, security analyses and so on.

The analysis capabilities that comes with the LLVM framework has also attracted practitioners from the binary analysis domain. Although LLVM is a compiler framework and thus largley focused on forward-engineering, the project and its surrounding tools offer such a rich set of analysis capabilities that it is attractive to use them in a reverse engineering context. To this end, several tools are being developed that translate binary code into the LLVM intermediate representation (IR), sometimes called binary lifters or binary raisers. However, despite these tools offering the same overall goal, namely translation of binary executables to LLVM modules, they each have very different properties and maturity-levels. As such, it can be difficult to assess which tool is most likely the best solution to a given problem. In this blogpost we share some brief insights into the code produced by some of these lifters through an empirical comparison between the LLVM code created by three different translators when matched with the same binary code samples.

We have picked three popular binary-to-llvm translators, namely mcsema by Trail of Bits, mctoll (acronym for machine code to LLVM I believe) by Microsoft and retdec by Avast. The goal of this blogpost is to focus purely on the generated LLVM IR, rather than creating an overall assessment of each project on their strengths and weaknesses. Perhaps most importantly, we are not going to investigate their overall maturity and how each of them work against a large and diverse sample database as this deserves a study on its own.

The procedure we will use to assess the projects are simply to translate a given binary with each of the three projects, and then inspect the LLVM code produced by each of them. Specifically, the steps we deploy when assessing the code are the following: Create source code in C

Compile C code to: (1) binary; (2) non-optimised LLVM code and (3) optimised LLVM code

Translate binary to LLVM IR with each of McSema, mctoll, retdec

Perform a qualitative comparison between the LLVM IR obtained In total we have created six small C code samples that we will use for our study. We will go into details with two of these samples and then leave the results from the other samples as a reference point for those who are interested.

Setup All of the source that we have used in this study is open source. Specifically, we use the latest version of mctoll which can be retrieved from here. For Retdec we used the released binary for version 3.3 retrieved from here. The McSema version that we will be using is the one from Lukas Korencik's Master's thesis found here which relies on the DynInst framework for disassembling a given binary. As such, all of the software that we use is completely open source and, in particular, no proprietary disassembler is needed to repeat our experiments.

Result overview

LLVM IR size

opt -O3

The following two tables display the lines of code of the LLVM IR from compiling the source code directly and lifting the binary with mctoll, retdec and mcsema, respectively, as well as the size in bytes of the compiled bitcode file (the binary version of the LLVM IR). There are two tables, one for the the non-optimised LLVM code and one where we have applied LLVM optimisations on the given LLVM code using

Non-optimised LLVM

Test LoC LLVM LoC mctoll LoC retdec LoC mcsema .bc size LLVM .bc size mctoll .bc size retdec .bc size mcsema 1 41 35 206 1212 2264 1140 3424 39140 2 49 49 202 1199 2316 1204 3348 39108 3 52 49 216 1265 2388 1276 3480 39812 4 77 87 253 1320 3428 1544 4088 41260 5 116 149 291 1466 3344 1764 4276 41868 6 253 386 413 1778 4612 3144 5908 43924

Optimised LLVM

Test LoC LLVM LoC mctoll LoC retdec LoC mcsema .bc size LLVM .bc size mctoll .bc size retdec .bc size mcsema 1 27 19 137 1179 2116 1052 3444 40892 2 28 20 139 1160 2160 1100 3348 40808 3 31 22 142 1230 2256 1112 3480 41584 4 62 78 203 1280 3292 1600 4088 43172 5 115 94 220 1398 3864 1668 4488 43716 6 178 164 314 1728 4716 2364 6056 46428

Function count in produced LLVM

Test func count LLVM func count mctoll func count retdec func count mcsema 1 2 2 12 25 2 2 2 12 25 3 3 3 13 27 4 2 2 14 27 5 2 2 13 26 6 2 2 14 27

The following table lists the number of functions defined in the LLVM modules of the non-optimizes version:

Qualitative discussion

Test1

int add(int arg1, int arg2) { return arg1 + arg2; }

define dso_local i32 @add(i32 %arg1, i32 %arg2) #0 { entry: %arg1.addr = alloca i32, align 4 %arg2.addr = alloca i32, align 4 store i32 %arg1, i32* %arg1.addr, align 4 store i32 %arg2, i32* %arg2.addr, align 4 %0 = load i32, i32* %arg1.addr, align 4 %1 = load i32, i32* %arg2.addr, align 4 %add = add nsw i32 %0, %1 ret i32 %add }

define dso_local i32 @add(i32 %arg1, i32 %arg2) local_unnamed_addr #0 { entry: %add = add nsw i32 %arg2, %arg1 ret i32 %add }

(gdb) disass add Dump of assembler code for function add: 0x00000000000005fa : push rbp 0x00000000000005fb : mov rbp,rsp 0x00000000000005fe : mov DWORD PTR [rbp-0x4],edi 0x0000000000000601 : mov DWORD PTR [rbp-0x8],esi 0x0000000000000604 : mov edx,DWORD PTR [rbp-0x4] 0x0000000000000607 : mov eax,DWORD PTR [rbp-0x8] 0x000000000000060a : add eax,edx 0x000000000000060c : pop rbp 0x000000000000060d : ret End of assembler dump.

define dso_local i32 @add(i32 %arg1, i32 %arg2) { entry: %0 = alloca i64, align 8 %1 = alloca i32, align 4 %2 = alloca i32, align 4 %3 = ptrtoint i64* %0 to i64 store i32 %arg1, i32* %1, align 4 store i32 %arg2, i32* %2, align 4 %4 = load i32, i32* %1, align 4 %5 = load i32, i32* %2, align 4 %6 = add nsw i32 %5, %4 %7 = shl i32 1, 31 %8 = and i32 %7, %6 %SF = icmp eq i32 %8, %7 %ZF = icmp eq i32 %6, 0 ret i32 %6 }

define i64 @add(i64 %arg1, i64 %arg2) local_unnamed_addr { dec_label_pc_5fa: %rdi.global-to-local = alloca i64, align 8 %rsi.global-to-local = alloca i64, align 8 store i64 %arg2, i64* %rsi.global-to-local, align 8 store i64 %arg1, i64* %rdi.global-to-local, align 8 %v0_5fe = load i64, i64* %rdi.global-to-local, align 8 %v0_601 = load i64, i64* %rsi.global-to-local, align 8 %v4_60a = add i64 %v0_601, %v0_5fe %v20_60a = and i64 %v4_60a, 4294967295 ret i64 %v20_60a }

define %struct.Memory* @sub_5fa_add(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_5fa: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %7 = bitcast %union.anon* %6 to i32* %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %12 = load i64, i64* %11, align 8 %13 = load i64, i64* %10, align 8, !tbaa !1261 %14 = add i64 %13, -8 %15 = inttoptr i64 %14 to i64* store i64 %12, i64* %15 %16 = add i64 %13, -12 %17 = load i32, i32* %7, align 4 %18 = inttoptr i64 %16 to i32* store i32 %17, i32* %18 %19 = add i64 %13, -16 %20 = load i32, i32* %5, align 4 %21 = inttoptr i64 %19 to i32* store i32 %20, i32* %21 %22 = add i64 %13, -12 %23 = inttoptr i64 %22 to i32* %24 = load i32, i32* %23 %25 = zext i32 %24 to i64 store i64 %25, i64* %9, align 8, !tbaa !1261 %26 = add i64 %13, -16 %27 = inttoptr i64 %26 to i32* %28 = load i32, i32* %27 %29 = add i32 %24, %28 %30 = zext i32 %29 to i64 store i64 %30, i64* %8, align 8, !tbaa !1261 %31 = icmp ult i32 %29, %28 %32 = icmp ult i32 %29, %24 %33 = or i1 %31, %32 %34 = zext i1 %33 to i8 %35 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 store i8 %34, i8* %35, align 1, !tbaa !1265 %36 = and i32 %29, 255 %37 = tail call i32 @llvm.ctpop.i32(i32 %36) #5 %38 = trunc i32 %37 to i8 %39 = and i8 %38, 1 %40 = xor i8 %39, 1 %41 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 store i8 %40, i8* %41, align 1, !tbaa !1279 %42 = xor i32 %24, %28 %43 = xor i32 %42, %29 %44 = lshr i32 %43, 4 %45 = trunc i32 %44 to i8 %46 = and i8 %45, 1 %47 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 store i8 %46, i8* %47, align 1, !tbaa !1283 %48 = icmp eq i32 %29, 0 %49 = zext i1 %48 to i8 %50 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 store i8 %49, i8* %50, align 1, !tbaa !1280 %51 = lshr i32 %29, 31 %52 = trunc i32 %51 to i8 %53 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 store i8 %52, i8* %53, align 1, !tbaa !1281 %54 = lshr i32 %28, 31 %55 = lshr i32 %24, 31 %56 = xor i32 %51, %54 %57 = xor i32 %51, %55 %58 = add nuw nsw i32 %56, %57 %59 = icmp eq i32 %58, 2 %60 = zext i1 %59 to i8 %61 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i8 %60, i8* %61, align 1, !tbaa !1282 %62 = inttoptr i64 %14 to i64* %63 = load i64, i64* %62 store i64 %63, i64* %11, align 8, !tbaa !1261 %64 = inttoptr i64 %13 to i64* %65 = load i64, i64* %64 store i64 %65, i64* %3, align 8, !tbaa !1261 %66 = add i64 %13, 8 store i64 %66, i64* %10, align 8, !tbaa !1261 ret %struct.Memory* %2 }

define dso_local i32 @add(i32 %arg1, i32 %arg2) local_unnamed_addr #0 { entry: %0 = add nsw i32 %arg2, %arg1 ret i32 %0 }

define i64 @add(i64 %arg1, i64 %arg2) local_unnamed_addr #1 { dec_label_pc_5fa: %v4_60a = add i64 %arg2, %arg1 %v20_60a = and i64 %v4_60a, 4294967295 ret i64 %v20_60a }

define %struct.Memory* @sub_5fa_add(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias readnone returned) local_unnamed_addr #2 { block_5fa: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %7 = bitcast %union.anon* %6 to i32* %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %12 = load i64, i64* %11, align 8 %13 = load i64, i64* %10, align 8, !tbaa !1261 %14 = add i64 %13, -8 %15 = inttoptr i64 %14 to i64* store i64 %12, i64* %15, align 8 %16 = add i64 %13, -12 %17 = load i32, i32* %7, align 4 %18 = inttoptr i64 %16 to i32* store i32 %17, i32* %18, align 4 %19 = add i64 %13, -16 %20 = load i32, i32* %5, align 4 %21 = inttoptr i64 %19 to i32* store i32 %20, i32* %21, align 4 %22 = load i32, i32* %18, align 4 %23 = zext i32 %22 to i64 store i64 %23, i64* %9, align 8, !tbaa !1261 %24 = load i32, i32* %21, align 4 %25 = add i32 %24, %22 %26 = zext i32 %25 to i64 store i64 %26, i64* %8, align 8, !tbaa !1261 %27 = icmp ult i32 %25, %24 %28 = icmp ult i32 %25, %22 %29 = or i1 %27, %28 %30 = zext i1 %29 to i8 %31 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 store i8 %30, i8* %31, align 1, !tbaa !1265 %32 = and i32 %25, 255 %33 = tail call i32 @llvm.ctpop.i32(i32 %32) #8 %34 = trunc i32 %33 to i8 %35 = and i8 %34, 1 %36 = xor i8 %35, 1 %37 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 store i8 %36, i8* %37, align 1, !tbaa !1279 %38 = xor i32 %24, %22 %39 = xor i32 %38, %25 %40 = lshr i32 %39, 4 %41 = trunc i32 %40 to i8 %42 = and i8 %41, 1 %43 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 store i8 %42, i8* %43, align 1, !tbaa !1283 %44 = icmp eq i32 %25, 0 %45 = zext i1 %44 to i8 %46 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 store i8 %45, i8* %46, align 1, !tbaa !1280 %47 = lshr i32 %25, 31 %48 = trunc i32 %47 to i8 %49 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 store i8 %48, i8* %49, align 1, !tbaa !1281 %50 = lshr i32 %24, 31 %51 = lshr i32 %22, 31 %52 = xor i32 %47, %50 %53 = xor i32 %47, %51 %54 = add nuw nsw i32 %52, %53 %55 = icmp eq i32 %54, 2 %56 = zext i1 %55 to i8 %57 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i8 %56, i8* %57, align 1, !tbaa !1282 %58 = load i64, i64* %15, align 8 store i64 %58, i64* %11, align 8, !tbaa !1261 %59 = inttoptr i64 %13 to i64* %60 = load i64, i64* %59, align 8 store i64 %60, i64* %3, align 8, !tbaa !1261 %61 = add i64 %13, 8 store i64 %61, i64* %10, align 8, !tbaa !1261 ret %struct.Memory* %2 }

In order to give a better intuition behind the code we will discuss two test samples in more depth.First, we will go through test1 where the primary function we lift is the following function:This code is compiled into the following LLVM code by clang and no optimisations:and is compiled to the following code with clang and heavy optimisations (O3):The function when compiled with GCC looks as follows:As such, the non-optimised version of the LLVM is incredibly similar to the compiled code.The following boxes show the non-optimised code when lifted by the three lifters:andand the optimised versions:and

The code produced for the add function by mctoll and retdec is quite similar in both non-optimised and optimised versions. Furthermore, mctoll produces equivalent code to the compiled LLVM function when aggressive optimisations are applied. Both mctoll and retdec retain the original number of parameters but retdec changes the return value to be an i64 instead of the original i32 . Mcsema's code is quite different to the two other lifters and one of the key aspects that separate mcsema from the two others is its use of the %struct.State struct. This is a struct that contains the various artefacts of the architecture of the lifted binary, e.g. the registers (RSP, RBP, RAX, ... for amd64) and the computations perfomed by the instructions raised by mcsema are then based on this struct. In some sense, the lifted code can be considered a form of "virtual machine" since there is a level of indirection through the %struct.State struct. This is also why several getelementptr instructions occur at the beginning of the function since these grab pointers to various "registers" that will be used in the code. However, it makes the code quite difficult to read in comparison to the LLVM produced by the other two lifters and also significantly larger in terms of instructions. Finally, the function signature of the functions lifted by Mcsema are all the same which makes it hard to interpret the signature of a given function since it must be interpreted from the code itself.

Test3

int main(int argc, char **argv) { if (argc < 5) return return_9s(); return return_8s(); }

define dso_local i32 @main(i32 %argc, i8** %argv) #0 { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 8 store i32 0, i32* %retval, align 4 store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 8 %0 = load i32, i32* %argc.addr, align 4 %cmp = icmp slt i32 %0, 5 br i1 %cmp, label %if.then, label %if.end if.then: ; preds = %entry %call = call i32 @return_9s() store i32 %call, i32* %retval, align 4 br label %return if.end: ; preds = %entry %call1 = call i32 @return_8s() store i32 %call1, i32* %retval, align 4 br label %return return: ; preds = %if.end, %if.then %1 = load i32, i32* %retval, align 4 ret i32 %1 }

define dso_local void @main(i32 %arg1, i64 %arg2) { entry: %0 = alloca i64, align 8 %StackAdj = alloca i64, align 8 %1 = alloca i32, align 4 %2 = ptrtoint i64* %0 to i64 store i32 %arg1, i32* %1, align 4 store i64 %arg2, i64* %StackAdj, align 8 %3 = load i32, i32* %1, align 4 %4 = zext i32 %3 to i64 %5 = zext i32 4 to i64 %6 = sub i64 %4, %5 %ZF = icmp eq i64 %6, 0 %7 = shl i64 1, 63 %8 = and i64 %7, %6 %SF = icmp eq i64 %8, %7 %ZFCmp_JG = icmp eq i1 %ZF, false %SFOFCmp_JG = icmp eq i1 %SF, false %ZFAndSFOF_JG = and i1 %ZFCmp_JG, %SFOFCmp_JG br i1 %ZFAndSFOF_JG, label %bb.2, label %bb.1 bb.1: ; preds = %entry %9 = call i32 @return_9s() br label %bb.3 bb.2: ; preds = %entry %10 = call i32 @return_8s() br label %bb.3 bb.3: ; preds = %bb.2, %bb.1 ret void }

define i64 @main(i64 %argc, i8** %argv) local_unnamed_addr { dec_label_pc_610: %rdi.global-to-local = alloca i64, align 8 store i64 %argc, i64* %rdi.global-to-local, align 8 %v0_618 = load i64, i64* %rdi.global-to-local, align 8 %v4_61f = trunc i64 %v0_618 to i32 %v9_623 = icmp sgt i32 %v4_61f, 4 br i1 %v9_623, label %dec_label_pc_631, label %dec_label_pc_625 dec_label_pc_625: ; preds = %dec_label_pc_610 %v0_62a = call i64 @return_9s() br label %dec_label_pc_63b dec_label_pc_631: ; preds = %dec_label_pc_610 %v0_636 = call i64 @return_8s() br label %dec_label_pc_63b dec_label_pc_63b: ; preds = %dec_label_pc_631, %dec_label_pc_625 %storemerge = phi i64 [ %v0_636, %dec_label_pc_631 ], [ %v0_62a, %dec_label_pc_625 ] ret i64 %storemerge }

define %struct.Memory* @sub_610_main(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_610: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %9 = load i64, i64* %8, align 8 %10 = load i64, i64* %7, align 8, !tbaa !1261 %11 = add i64 %10, -8 %12 = inttoptr i64 %11 to i64* store i64 %9, i64* %12 store i64 %11, i64* %8, align 8, !tbaa !1261 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %15 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %18 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 %19 = add i64 %10, -12 %20 = load i32, i32* %5, align 4 %21 = inttoptr i64 %19 to i32* store i32 %20, i32* %21 %22 = add i64 %10, -24 %23 = load i64, i64* %6, align 8 %24 = inttoptr i64 %22 to i64* store i64 %23, i64* %24 %25 = inttoptr i64 %19 to i32* %26 = load i32, i32* %25 %27 = add i32 %26, -4 %28 = icmp ult i32 %26, 4 %29 = zext i1 %28 to i8 store i8 %29, i8* %13, align 1, !tbaa !1265 %30 = and i32 %27, 255 %31 = tail call i32 @llvm.ctpop.i32(i32 %30) #5 %32 = trunc i32 %31 to i8 %33 = and i8 %32, 1 %34 = xor i8 %33, 1 store i8 %34, i8* %14, align 1, !tbaa !1279 %35 = xor i32 %27, %26 %36 = lshr i32 %35, 4 %37 = trunc i32 %36 to i8 %38 = and i8 %37, 1 store i8 %38, i8* %15, align 1, !tbaa !1280 %39 = icmp eq i32 %27, 0 %40 = zext i1 %39 to i8 store i8 %40, i8* %16, align 1, !tbaa !1281 %41 = lshr i32 %27, 31 %42 = trunc i32 %41 to i8 store i8 %42, i8* %17, align 1, !tbaa !1282 %43 = lshr i32 %26, 31 %44 = xor i32 %41, %43 %45 = add nuw nsw i32 %44, %43 %46 = icmp eq i32 %45, 2 %47 = zext i1 %46 to i8 store i8 %47, i8* %18, align 1, !tbaa !1283 %48 = icmp ne i8 %42, 0 %49 = xor i1 %48, %46 %50 = or i1 %39, %49 %51 = select i1 %50, i64 21, i64 33 %52 = add i64 %51, %1 br i1 %50, label %block_625, label %block_631 block_63b: ; preds = %block_625, %block_631 %53 = phi %struct.Memory* [ %65, %block_631 ], [ %70, %block_625 ] %54 = load i64, i64* %8, align 8, !tbaa !1261 %55 = inttoptr i64 %54 to i64* %56 = load i64, i64* %55 store i64 %56, i64* %8, align 8, !tbaa !1261 %57 = add i64 %54, 8 %58 = inttoptr i64 %57 to i64* %59 = load i64, i64* %58 store i64 %59, i64* %3, align 8, !tbaa !1261 %60 = add i64 %54, 16 store i64 %60, i64* %7, align 8, !tbaa !1261 ret %struct.Memory* %53 block_631: ; preds = %block_610 %61 = add i64 %52, -44 %62 = add i64 %52, 10 %63 = add i64 %10, -32 %64 = inttoptr i64 %63 to i64* store i64 %62, i64* %64 store i64 %63, i64* %7, align 8, !tbaa !1261 %65 = tail call %struct.Memory* @sub_605_return_8s(%struct.State* nonnull %0, i64 %61, %struct.Memory* %2) br label %block_63b block_625: ; preds = %block_610 %66 = add i64 %52, -43 %67 = add i64 %52, 10 %68 = add i64 %10, -32 %69 = inttoptr i64 %68 to i64* store i64 %67, i64* %69 store i64 %68, i64* %7, align 8, !tbaa !1261 %70 = tail call %struct.Memory* @sub_5fa_return_9s(%struct.State* nonnull %0, i64 %66, %struct.Memory* %2) br label %block_63b }

Second, we will go through a few details from test3. One of the reasons we select this test case is because it shows the difficulty of raising to LLVM since we find a minor issue in one of the lifters (mctoll).The C code for the main function in test3 is the following:which compiles to the following non-optimised LLVM:The non-optimised LLVM code produced by the lifters look as follows:and

All three lifters produce the same basic block composition and, again, the code by mctoll and retdec look more similar to each other compared to mcsema. The code produced by retdec is more condensed and is quite nice to read in terms of understanding the code.

The code generated by mctoll contains the following sequence at the end of the main function: bb.1: ; preds = %entry %9 = call i32 @return_9s() br label %bb.3 bb.2: ; preds = %entry %10 = call i32 @return_8s() br label %bb.3 bb.3: ; preds = %bb.2, %bb.1 ret void } Specifically, the main function returns void and the return values from each of the functions are not used. As such, when we apply optimisations to the code we get the following: define dso_local void @main(i32 %arg1, i64 %arg2) local_unnamed_addr #0 { entry: ret void } which is naturally wrong.

The section All results below lists all of the results from the samples that we used in our study. We will not go into the details of all these samples but rather leave the code for inspection to those who are interested. In the section below we will give a few remarks on our overall impression of the generated LLVM IR.

Some conclusive remarks Translating binary code to LLVM will surely become more attractive as LLVM continues to grow and the analysis capabilities become more powerful. We have given a brief look into the LLVM code produced by three different binary-to-llvm translators in order to give a better intuition for the expected output. The output of mctoll seems to be closer to the LLVM produced from forward compilation, in particular based on the number of functions in each LLVM module. Both retdec and mcsema seem closer to specific reverse engineering tools in that each of them tries to lift everything from the binary, e.g. compiler-generated functions too. This is the reason each of these lifters produce many more functions in the lifted output in comparison to mctoll. However, despite the similarity in terms of goal between retdec and mcsema, the specific code created by mctoll and retdec seems more comparable, whereas the code produced by mcsema performs a kind of indirect execution by way of a struct that holds the architecture-specific data of the given binary, e.g. the general purpose registers.

In this blogpost our focus was purely on the LLVM IR produced by the lifters and this on rather small samples of code. There are naturally many more aspects to each the lifters where they will differ, e.g. how well they work with real-world applications, accuracy and correctness of the lifted code, support for various targets, ability to recompile the lifted code and so on. These are interesting questions and we leave this for future work.

All results In the following section we list each of the six test samples we exercised with and the code produced by each of the three lifters. The only thing we have removed is some metadata produced by mcsema from each of the files, but other than that files remain exact.

Test1

Source code:

#include #include int add(int arg1, int arg2) { return arg1 + arg2; } int main(int argc, char **argv) { return add(argc, argc+2); }

Compiled LLVM:

Non-optimised:

; ModuleID = 'test.bc' source_filename = "test.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @add(i32 %arg1, i32 %arg2) #0 { entry: %arg1.addr = alloca i32, align 4 %arg2.addr = alloca i32, align 4 store i32 %arg1, i32* %arg1.addr, align 4 store i32 %arg2, i32* %arg2.addr, align 4 %0 = load i32, i32* %arg1.addr, align 4 %1 = load i32, i32* %arg2.addr, align 4 %add = add nsw i32 %0, %1 ret i32 %add } ; Function Attrs: noinline nounwind optnone uwtable define dso_local i32 @main(i32 %argc, i8** %argv) #0 { entry: %retval = alloca i32, align 4 %argc.addr = alloca i32, align 4 %argv.addr = alloca i8**, align 8 store i32 0, i32* %retval, align 4 store i32 %argc, i32* %argc.addr, align 4 store i8** %argv, i8*** %argv.addr, align 8 %0 = load i32, i32* %argc.addr, align 4 %1 = load i32, i32* %argc.addr, align 4 %add = add nsw i32 %1, 2 %call = call i32 @add(i32 %0, i32 %add) ret i32 %call } attributes #0 = { noinline nounwind optnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="true" "no-frame-pointer-elim-non-leaf" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"}

Optimised:

; ModuleID = 'opt_test.bc' source_filename = "test.c" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-unknown-linux-gnu" ; Function Attrs: norecurse nounwind readnone uwtable define dso_local i32 @add(i32 %arg1, i32 %arg2) local_unnamed_addr #0 { entry: %add = add nsw i32 %arg2, %arg1 ret i32 %add } ; Function Attrs: norecurse nounwind readnone uwtable define dso_local i32 @main(i32 %argc, i8** nocapture readnone %argv) local_unnamed_addr #0 { entry: %factor = shl i32 %argc, 1 %add.i = add i32 %factor, 2 ret i32 %add.i } attributes #0 = { norecurse nounwind readnone uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" } !llvm.module.flags = !{!0} !llvm.ident = !{!1} !0 = !{i32 1, !"wchar_size", i32 4} !1 = !{!"clang version 8.0.0 (tags/RELEASE_800/final)"}

Raised by mctoll

Non-optimised:

; ModuleID = '../a.out' source_filename = "../a.out" define dso_local i32 @add(i32 %arg1, i32 %arg2) { entry: %0 = alloca i64, align 8 %1 = alloca i32, align 4 %2 = alloca i32, align 4 %3 = ptrtoint i64* %0 to i64 store i32 %arg1, i32* %1, align 4 store i32 %arg2, i32* %2, align 4 %4 = load i32, i32* %1, align 4 %5 = load i32, i32* %2, align 4 %6 = add nsw i32 %5, %4 %7 = shl i32 1, 31 %8 = and i32 %7, %6 %SF = icmp eq i32 %8, %7 %ZF = icmp eq i32 %6, 0 ret i32 %6 } define dso_local i32 @main(i32 %arg1, i64 %arg2) { entry: %0 = alloca i64, align 8 %StackAdj = alloca i64, align 8 %1 = alloca i32, align 4 %2 = ptrtoint i64* %0 to i64 store i32 %arg1, i32* %1, align 4 store i64 %arg2, i64* %StackAdj, align 8 %3 = load i32, i32* %1, align 4 %4 = add i32 %3, 2 %5 = load i32, i32* %1, align 4 %6 = call i32 @add(i32 %5, i32 %4) ret i32 %6 }

Optimised:

; ModuleID = 'opt_lifted.bc' source_filename = "../a.out" ; Function Attrs: norecurse nounwind readnone define dso_local i32 @add(i32 %arg1, i32 %arg2) local_unnamed_addr #0 { entry: %0 = add nsw i32 %arg2, %arg1 ret i32 %0 } ; Function Attrs: norecurse nounwind readnone define dso_local i32 @main(i32 %arg1, i64 %arg2) local_unnamed_addr #0 { entry: %factor = shl i32 %arg1, 1 %0 = add i32 %factor, 2 ret i32 %0 } attributes #0 = { norecurse nounwind readnone }

Raised by retdec

Non-optimised:

source_filename = "test" target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128" @global_var_201010.1 = global i64 0 @global_var_200df0.2 = global i64 1520 @global_var_200df8.3 = global i64 1456 @0 = external global i32 define i64 @_init() local_unnamed_addr { dec_label_pc_4b8: %v0_4bc = load i64, i64* inttoptr (i64 2101224 to i64*), align 8 %v1_4c3 = icmp eq i64 %v0_4bc, 0 br i1 %v1_4c3, label %dec_label_pc_4ca, label %dec_label_pc_4c8 dec_label_pc_4c8: ; preds = %dec_label_pc_4b8 call void @__gmon_start__() br label %dec_label_pc_4ca dec_label_pc_4ca: ; preds = %dec_label_pc_4c8, %dec_label_pc_4b8 %v0_4ce = phi i64 [ ptrtoint (i32* @0 to i64), %dec_label_pc_4c8 ], [ 0, %dec_label_pc_4b8 ] ret i64 %v0_4ce } define void @function_4e0(i64* %d) local_unnamed_addr { dec_label_pc_4e0: call void @__cxa_finalize(i64* %d) ret void } define i64 @_start(i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4) local_unnamed_addr { dec_label_pc_4f0: %rdx.global-to-local = alloca i64, align 8 store i64 %arg3, i64* %rdx.global-to-local, align 8 %stack_var_8 = alloca i64, align 8 %v0_4f2 = load i64, i64* %rdx.global-to-local, align 8 %v4_4f5 = ptrtoint i64* %stack_var_8 to i64 %tmp248 = bitcast i64* %stack_var_8 to i8** store i64 %v4_4f5, i64* %rdx.global-to-local, align 8 %v2_514 = trunc i64 %arg4 to i32 %v13_514 = inttoptr i64 %v0_4f2 to void ()* %v14_514 = call i32 @__libc_start_main(i64 1550, i32 %v2_514, i8** %tmp248, void ()* inttoptr (i64 1600 to void ()*), void ()* inttoptr (i64 1712 to void ()*), void ()* %v13_514) %v0_51a = call i64 @__asm_hlt() unreachable } define i64 @deregister_tm_clones() local_unnamed_addr { dec_label_pc_520: ret i64 ptrtoint (i64* @global_var_201010.1 to i64) } define i64 @register_tm_clones() local_unnamed_addr { dec_label_pc_560: ret i64 0 } define i64 @__do_global_dtors_aux() local_unnamed_addr { dec_label_pc_5b0: %rax.global-to-local = alloca i64, align 8 %rbp.global-to-local = alloca i64, align 8 %stack_var_-8 = alloca i64, align 8 %v0_5b0 = load i8, i8* bitcast (i64* @global_var_201010.1 to i8*), align 8 %v7_5b0 = icmp eq i8 %v0_5b0, 0 %v1_5b7 = icmp eq i1 %v7_5b0, false br i1 %v1_5b7, label %dec_label_pc_5e8, label %dec_label_pc_5b9 dec_label_pc_5b9: ; preds = %dec_label_pc_5b0 %v0_5b9 = load i64, i64* inttoptr (i64 2101240 to i64*), align 8 %v7_5b9 = icmp eq i64 %v0_5b9, 0 %v0_5c1 = load i64, i64* %rbp.global-to-local, align 8 store i64 %v0_5c1, i64* %stack_var_-8, align 8 %v4_5c1 = ptrtoint i64* %stack_var_-8 to i64 store i64 %v4_5c1, i64* %rbp.global-to-local, align 8 br i1 %v7_5b9, label %dec_label_pc_5d3, label %dec_label_pc_5c7 dec_label_pc_5c7: ; preds = %dec_label_pc_5b9 %v0_5c7 = load i64, i64* inttoptr (i64 2101256 to i64*), align 8 %v1_5ce = inttoptr i64 %v0_5c7 to i64* call void @__cxa_finalize(i64* %v1_5ce) store i64 ptrtoint (i32* @0 to i64), i64* %rax.global-to-local, align 8 br label %dec_label_pc_5d3 dec_label_pc_5d3: ; preds = %dec_label_pc_5c7, %dec_label_pc_5b9 %v0_5d3 = call i64 @deregister_tm_clones() store i64 %v0_5d3, i64* %rax.global-to-local, align 8 store i8 1, i8* bitcast (i64* @global_var_201010.1 to i8*), align 8 %v2_5df = load i64, i64* %stack_var_-8, align 8 store i64 %v2_5df, i64* %rbp.global-to-local, align 8 ret i64 %v0_5d3 dec_label_pc_5e8: ; preds = %dec_label_pc_5b0 %v0_5e8 = load i64, i64* %rax.global-to-local, align 8 ret i64 %v0_5e8 } define i64 @frame_dummy() local_unnamed_addr { dec_label_pc_5f0: %v0_5f5 = call i64 @register_tm_clones() ret i64 %v0_5f5 } define i64 @add(i64 %arg1, i64 %arg2) local_unnamed_addr { dec_label_pc_5fa: %rdi.global-to-local = alloca i64, align 8 %rsi.global-to-local = alloca i64, align 8 store i64 %arg2, i64* %rsi.global-to-local, align 8 store i64 %arg1, i64* %rdi.global-to-local, align 8 %v0_5fe = load i64, i64* %rdi.global-to-local, align 8 %v0_601 = load i64, i64* %rsi.global-to-local, align 8 %v4_60a = add i64 %v0_601, %v0_5fe %v20_60a = and i64 %v4_60a, 4294967295 ret i64 %v20_60a } define i64 @main(i64 %argc, i8** %argv) local_unnamed_addr { dec_label_pc_60e: %rdi.global-to-local = alloca i64, align 8 store i64 %argc, i64* %rdi.global-to-local, align 8 %v0_616 = load i64, i64* %rdi.global-to-local, align 8 %v1_620 = add i64 %v0_616, 2 %v2_62a = call i64 @add(i64 %v0_616, i64 %v1_620) ret i64 %v2_62a } define i64 @__libc_csu_init(i64 %arg1, i64 %arg2, i64 %arg3) local_unnamed_addr { dec_label_pc_640: %r12.global-to-local = alloca i64, align 8 %r13.global-to-local = alloca i64, align 8 %r14.global-to-local = alloca i64, align 8 %r15.global-to-local = alloca i64, align 8 %rbp.global-to-local = alloca i64, align 8 %rbx.global-to-local = alloca i64, align 8 %rdi.global-to-local = alloca i64, align 8 %rdx.global-to-local = alloca i64, align 8 %rsi.global-to-local = alloca i64, align 8 store i64 %arg3, i64* %rdx.global-to-local, align 8 store i64 %arg2, i64* %rsi.global-to-local, align 8 store i64 %arg1, i64* %rdi.global-to-local, align 8 %v0_640 = load i64, i64* %r15.global-to-local, align 8 %v0_642 = load i64, i64* %r14.global-to-local, align 8 %v0_644 = load i64, i64* %rdx.global-to-local, align 8 store i64 %v0_644, i64* %r15.global-to-local, align 8 %v0_647 = load i64, i64* %r13.global-to-local, align 8 %v0_649 = load i64, i64* %r12.global-to-local, align 8 store i64 ptrtoint (i64* @global_var_200df0.2 to i64), i64* %r12.global-to-local, align 8 %v0_652 = load i64, i64* %rbp.global-to-local, align 8 %v0_65a = load i64, i64* %rbx.global-to-local, align 8 %v0_65b = load i64, i64* %rdi.global-to-local, align 8 store i64 %v0_65b, i64* %r13.global-to-local, align 8 %v0_65e = load i64, i64* %rsi.global-to-local, align 8 store i64 %v0_65e, i64* %r14.global-to-local, align 8 store i64 ashr (i64 sub (i64 ptrtoint (i64* @global_var_200df8.3 to i64), i64 ptrtoint (i64* @global_var_200df0.2 to i64)), i64 3), i64* %rbp.global-to-local, align 8 %v0_66c = call i64 @_init() br i1 icmp eq (i64 ashr (i64 sub (i64 ptrtoint (i64* @global_var_200df8.3 to i64), i64 ptrtoint (i64* @global_var_200df0.2 to i64)), i64 3), i64 0), label %dec_label_pc_696, label %dec_label_pc_676 dec_label_pc_676: ; preds = %dec_label_pc_640 store i64 0, i64* %rbx.global-to-local, align 8 %v0_680 = load i64, i64* %r15.global-to-local, align 8 %v0_683 = load i64, i64* %r14.global-to-local, align 8 %v0_686 = load i64, i64* %r13.global-to-local, align 8 br label %dec_label_pc_680 dec_label_pc_680: ; preds = %dec_label_pc_680, %dec_label_pc_676 %v1_68d2 = phi i64 [ %v1_68d, %dec_label_pc_680 ], [ 0, %dec_label_pc_676 ] %v1_68d = add i64 %v1_68d2, 1 %v12_691 = icmp eq i64 %v1_68d2, sub (i64 ashr (i64 sub (i64 ptrtoint (i64* @global_var_200df8.3 to i64), i64 ptrtoint (i64* @global_var_200df0.2 to i64)), i64 3), i64 1) %v1_694 = icmp eq i1 %v12_691, false br i1 %v1_694, label %dec_label_pc_680, label %dec_label_pc_696.loopexit dec_label_pc_696.loopexit: ; preds = %dec_label_pc_680 store i64 %v0_680, i64* %rdx.global-to-local, align 8 store i64 %v0_683, i64* %rsi.global-to-local, align 8 store i64 %v0_686, i64* %rdi.global-to-local, align 8 store i64 %v1_68d, i64* %rbx.global-to-local, align 8 br label %dec_label_pc_696 dec_label_pc_696: ; preds = %dec_label_pc_696.loopexit, %dec_label_pc_640 store i64 %v0_65a, i64* %rbx.global-to-local, align 8 store i64 %v0_652, i64* %rbp.global-to-local, align 8 store i64 %v0_649, i64* %r12.global-to-local, align 8 store i64 %v0_647, i64* %r13.global-to-local, align 8 store i64 %v0_642, i64* %r14.global-to-local, align 8 store i64 %v0_640, i64* %r15.global-to-local, align 8 ret i64 %v0_66c } define i64 @__libc_csu_fini() local_unnamed_addr { dec_label_pc_6b0: %rax.global-to-local = alloca i64, align 8 %v0_6b0 = load i64, i64* %rax.global-to-local, align 8 ret i64 %v0_6b0 } define i64 @_fini() local_unnamed_addr { dec_label_pc_6b4: %rax.global-to-local = alloca i64, align 8 %v0_6bc = load i64, i64* %rax.global-to-local, align 8 ret i64 %v0_6bc } declare i32 @__libc_start_main(i64, i32, i8**, void ()*, void ()*, void ()*) local_unnamed_addr declare void @__gmon_start__() local_unnamed_addr declare void @__cxa_finalize(i64*) local_unnamed_addr declare i64 @__asm_hlt() local_unnamed_addr

Optimised:

; ModuleID = 'opt_lifted.bc' source_filename = "test" target datalayout = "e-m:e-p:64:64-i64:64-f80:128-n8:16:32:64-S128" @global_var_201010.1 = global i64 0 @global_var_200df0.2 = local_unnamed_addr global i64 1520 @global_var_200df8.3 = local_unnamed_addr global i64 1456 @0 = external global i32 define i64 @_init() local_unnamed_addr { dec_label_pc_4b8: %v0_4bc = load i64, i64* inttoptr (i64 2101224 to i64*), align 8 %v1_4c3 = icmp eq i64 %v0_4bc, 0 br i1 %v1_4c3, label %dec_label_pc_4ca, label %dec_label_pc_4c8 dec_label_pc_4c8: ; preds = %dec_label_pc_4b8 tail call void @__gmon_start__() br label %dec_label_pc_4ca dec_label_pc_4ca: ; preds = %dec_label_pc_4c8, %dec_label_pc_4b8 %v0_4ce = phi i64 [ ptrtoint (i32* @0 to i64), %dec_label_pc_4c8 ], [ 0, %dec_label_pc_4b8 ] ret i64 %v0_4ce } define void @function_4e0(i64* %d) local_unnamed_addr { dec_label_pc_4e0: tail call void @__cxa_finalize(i64* %d) ret void } ; Function Attrs: noreturn define i64 @_start(i64 %arg1, i64 %arg2, i64 %arg3, i64 %arg4) local_unnamed_addr #0 { dec_label_pc_4f0: %stack_var_8 = alloca i8*, align 8 %v2_514 = trunc i64 %arg4 to i32 %v13_514 = inttoptr i64 %arg3 to void ()* %v14_514 = call i32 @__libc_start_main(i64 1550, i32 %v2_514, i8** nonnull %stack_var_8, void ()* inttoptr (i64 1600 to void ()*), void ()* inttoptr (i64 1712 to void ()*), void ()* %v13_514) %v0_51a = call i64 @__asm_hlt() unreachable } ; Function Attrs: norecurse nounwind readnone define i64 @deregister_tm_clones() local_unnamed_addr #1 { dec_label_pc_520: ret i64 ptrtoint (i64* @global_var_201010.1 to i64) } ; Function Attrs: norecurse nounwind readnone define i64 @register_tm_clones() local_unnamed_addr #1 { dec_label_pc_560: ret i64 0 } define i64 @__do_global_dtors_aux() local_unnamed_addr { dec_label_pc_5b0: %v0_5b0 = load i8, i8* bitcast (i64* @global_var_201010.1 to i8*), align 8 %v7_5b0 = icmp eq i8 %v0_5b0, 0 br i1 %v7_5b0, label %dec_label_pc_5b9, label %dec_label_pc_5e8 dec_label_pc_5b9: ; preds = %dec_label_pc_5b0 %v0_5b9 = load i64, i64* inttoptr (i64 2101240 to i64*), align 8 %v7_5b9 = icmp eq i64 %v0_5b9, 0 br i1 %v7_5b9, label %dec_label_pc_5d3, label %dec_label_pc_5c7 dec_label_pc_5c7: ; preds = %dec_label_pc_5b9 %v0_5c71 = load i64*, i64** inttoptr (i64 2101256 to i64**), align 8 tail call void @__cxa_finalize(i64* %v0_5c71) br label %dec_label_pc_5d3 dec_label_pc_5d3: ; preds = %dec_label_pc_5c7, %dec_label_pc_5b9 store i8 1, i8* bitcast (i64* @global_var_201010.1 to i8*), align 8 ret i64 ptrtoint (i64* @global_var_201010.1 to i64) dec_label_pc_5e8: ; preds = %dec_label_pc_5b0 ret i64 undef } ; Function Attrs: norecurse nounwind readnone define i64 @frame_dummy() local_unnamed_addr #1 { dec_label_pc_5f0: ret i64 0 } ; Function Attrs: norecurse nounwind readnone define i64 @add(i64 %arg1, i64 %arg2) local_unnamed_addr #1 { dec_label_pc_5fa: %v4_60a = add i64 %arg2, %arg1 %v20_60a = and i64 %v4_60a, 4294967295 ret i64 %v20_60a } ; Function Attrs: norecurse nounwind readnone define i64 @main(i64 %argc, i8** nocapture readnone %argv) local_unnamed_addr #1 { dec_label_pc_60e: %factor = shl i64 %argc, 1 %v4_60a.i = add i64 %factor, 2 %v20_60a.i = and i64 %v4_60a.i, 4294967294 ret i64 %v20_60a.i } define i64 @__libc_csu_init(i64 %arg1, i64 %arg2, i64 %arg3) local_unnamed_addr { dec_label_pc_640: %v0_4bc.i = load i64, i64* inttoptr (i64 2101224 to i64*), align 8 %v1_4c3.i = icmp eq i64 %v0_4bc.i, 0 br i1 %v1_4c3.i, label %dec_label_pc_696, label %dec_label_pc_4c8.i dec_label_pc_4c8.i: ; preds = %dec_label_pc_640 tail call void @__gmon_start__() br label %dec_label_pc_696 dec_label_pc_696: ; preds = %dec_label_pc_4c8.i, %dec_label_pc_640 %v0_4ce.i = phi i64 [ ptrtoint (i32* @0 to i64), %dec_label_pc_4c8.i ], [ 0, %dec_label_pc_640 ] ret i64 %v0_4ce.i } ; Function Attrs: norecurse nounwind readnone define i64 @__libc_csu_fini() local_unnamed_addr #1 { dec_label_pc_6b0: ret i64 undef } ; Function Attrs: norecurse nounwind readnone define i64 @_fini() local_unnamed_addr #1 { dec_label_pc_6b4: ret i64 undef } declare i32 @__libc_start_main(i64, i32, i8**, void ()*, void ()*, void ()*) local_unnamed_addr declare void @__gmon_start__() local_unnamed_addr declare void @__cxa_finalize(i64*) local_unnamed_addr declare i64 @__asm_hlt() local_unnamed_addr attributes #0 = { noreturn } attributes #1 = { norecurse nounwind readnone }

Raised by mcsema

Non-optimised:

; ModuleID = 'lifted.bc' source_filename = "llvm-link" target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" target triple = "x86_64-pc-linux-gnu-elf" %union.anon = type { i64 } %seg_200df0__init_array_type = type %seg_200fc0__got_type = type %seg_201000__data_type = type %seg_201010__bss_type = type %struct.State = type { %struct.ArchState, [32 x %union.VectorReg], %struct.ArithFlags, %union.anon, %struct.Segments, %struct.AddressSpace, %struct.GPR, %struct.X87Stack, %struct.MMX, %struct.FPUStatusFlags, %union.anon, %union.FPU, %struct.SegmentCaches } %struct.ArchState = type { i32, i32, %union.anon } %union.VectorReg = type { %union.vec512_t } %union.vec512_t = type { %struct.uint64v8_t } %struct.uint64v8_t = type { [8 x i64] } %struct.ArithFlags = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8 } %struct.Segments = type { i16, %union.SegmentSelector, i16, %union.SegmentSelector, i16, %union.SegmentSelector, i16, %union.SegmentSelector, i16, %union.SegmentSelector, i16, %union.SegmentSelector } %union.SegmentSelector = type { i16 } %struct.AddressSpace = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } %struct.Reg = type { %union.anon } %struct.GPR = type { i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg, i64, %struct.Reg } %struct.X87Stack = type { [8 x %struct.anon.3] } %struct.anon.3 = type { i64, double } %struct.MMX = type { [8 x %struct.anon.4] } %struct.anon.4 = type { i64, %union.vec64_t } %union.vec64_t = type { %struct.uint64v1_t } %struct.uint64v1_t = type { [1 x i64] } %struct.FPUStatusFlags = type { i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, i8, [4 x i8] } %union.FPU = type { %struct.anon.13 } %struct.anon.13 = type { %struct.FpuFXSAVE, [96 x i8] } %struct.FpuFXSAVE = type { %union.SegmentSelector, %union.SegmentSelector, %union.FPUAbridgedTagWord, i8, i16, i32, %union.SegmentSelector, i16, i32, %union.SegmentSelector, i16, %union.FPUControlStatus, %union.FPUControlStatus, [8 x %struct.FPUStackElem], [16 x %union.vec128_t] } %union.FPUAbridgedTagWord = type { i8 } %union.FPUControlStatus = type { i32 } %struct.FPUStackElem = type { %union.anon.11, [6 x i8] } %union.anon.11 = type { %struct.float80_t } %struct.float80_t = type { [10 x i8] } %union.vec128_t = type { %struct.uint128v1_t } %struct.uint128v1_t = type { [1 x i128] } %struct.SegmentCaches = type { %struct.SegmentShadow, %struct.SegmentShadow, %struct.SegmentShadow, %struct.SegmentShadow, %struct.SegmentShadow, %struct.SegmentShadow } %struct.SegmentShadow = type { %union.anon, i32, i32 } %struct.Memory = type opaque @DR0 = external global i64, align 8 @DR1 = external global i64, align 8 @DR2 = external global i64, align 8 @DR3 = external global i64, align 8 @DR4 = external global i64, align 8 @DR5 = external global i64, align 8 @DR6 = external global i64, align 8 @DR7 = external global i64, align 8 @gCR0 = external global %union.anon, align 1 @gCR1 = external global %union.anon, align 1 @gCR2 = external global %union.anon, align 1 @gCR3 = external global %union.anon, align 1 @gCR4 = external global %union.anon, align 1 @gCR8 = external global %union.anon, align 1 @seg_200df0__init_array = internal global %seg_200df0__init_array_type @seg_200fc0__got = internal global %seg_200fc0__got_type @seg_201000__data = internal global %seg_201000__data_type @seg_201010__bss = internal global %seg_201010__bss_type zeroinitializer @__mcsema_reg_state = internal thread_local global %struct.State zeroinitializer @__mcsema_stack = internal thread_local global [131072 x i64] zeroinitializer @__mcsema_tls = internal thread_local global [512 x i64] zeroinitializer @0 = internal global i1 false @llvm.global_dtors = appending constant [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 101, void ()* @__mcsema_destructor, i8* null }] @llvm.global_ctors = appending constant [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 101, void ()* @__mcsema_constructor, i8* null }] ; Function Attrs: nounwind readnone declare i32 @llvm.ctpop.i32(i32) #0 ; Function Attrs: noduplicate noinline nounwind optnone define %struct.Memory* @__remill_error(%struct.State* dereferenceable(3376), i64, %struct.Memory*) local_unnamed_addr #1 { call void @llvm.trap() unreachable } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_4b8__init(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_4b8: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %6 = load i64, i64* %5, align 8 %7 = add i64 %6, -8 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %12 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 %14 = load i64, i64* inttoptr (i64 add (i64 ptrtoint (%seg_200fc0__got_type* @seg_200fc0__got to i64), i64 40) to i64*) store i64 %14, i64* %4, align 8, !tbaa !1261 store i8 0, i8* %8, align 1, !tbaa !1265 %15 = trunc i64 %14 to i32 %16 = and i32 %15, 255 %17 = tail call i32 @llvm.ctpop.i32(i32 %16) #5 %18 = trunc i32 %17 to i8 %19 = and i8 %18, 1 %20 = xor i8 %19, 1 store i8 %20, i8* %9, align 1, !tbaa !1279 %21 = icmp eq i64 %14, 0 %22 = zext i1 %21 to i8 store i8 %22, i8* %11, align 1, !tbaa !1280 %23 = lshr i64 %14, 63 %24 = trunc i64 %23 to i8 store i8 %24, i8* %12, align 1, !tbaa !1281 store i8 0, i8* %13, align 1, !tbaa !1282 store i8 0, i8* %10, align 1, !tbaa !1283 %25 = select i1 %21, i64 18, i64 16 %26 = add i64 %25, %1 br i1 %21, label %block_4ca, label %block_4c8 block_4ca: ; preds = %block_4c8, %block_4b8 %27 = phi i64 [ %7, %block_4b8 ], [ %58, %block_4c8 ] %28 = phi %struct.Memory* [ %2, %block_4b8 ], [ %57, %block_4c8 ] %29 = add i64 %27, 8 %30 = icmp ugt i64 %27, -9 %31 = zext i1 %30 to i8 store i8 %31, i8* %8, align 1, !tbaa !1265 %32 = trunc i64 %29 to i32 %33 = and i32 %32, 255 %34 = tail call i32 @llvm.ctpop.i32(i32 %33) #5 %35 = trunc i32 %34 to i8 %36 = and i8 %35, 1 %37 = xor i8 %36, 1 store i8 %37, i8* %9, align 1, !tbaa !1279 %38 = xor i64 %29, %27 %39 = lshr i64 %38, 4 %40 = trunc i64 %39 to i8 %41 = and i8 %40, 1 store i8 %41, i8* %10, align 1, !tbaa !1283 %42 = icmp eq i64 %29, 0 %43 = zext i1 %42 to i8 store i8 %43, i8* %11, align 1, !tbaa !1280 %44 = lshr i64 %29, 63 %45 = trunc i64 %44 to i8 store i8 %45, i8* %12, align 1, !tbaa !1281 %46 = lshr i64 %27, 63 %47 = xor i64 %44, %46 %48 = add nuw nsw i64 %47, %44 %49 = icmp eq i64 %48, 2 %50 = zext i1 %49 to i8 store i8 %50, i8* %13, align 1, !tbaa !1282 %51 = inttoptr i64 %29 to i64* %52 = load i64, i64* %51 store i64 %52, i64* %3, align 8, !tbaa !1261 %53 = add i64 %27, 16 store i64 %53, i64* %5, align 8, !tbaa !1261 ret %struct.Memory* %28 block_4c8: ; preds = %block_4b8 %54 = add i64 %26, 2 %55 = add i64 %6, -16 %56 = inttoptr i64 %55 to i64* store i64 %54, i64* %56 store i64 %55, i64* %5, align 8, !tbaa !1261 store i64 %14, i64* %3, align 8, !tbaa !1261 %57 = tail call %struct.Memory* @__mcsema_detach_call_value(%struct.State* nonnull %0, i64 %14, %struct.Memory* %2) %58 = load i64, i64* %5, align 8 br label %block_4ca } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_5f0_frame_dummy(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_5f0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %5 = load i64, i64* %4, align 8 %6 = load i64, i64* %3, align 8, !tbaa !1261 %7 = add i64 %6, -8 %8 = inttoptr i64 %7 to i64* store i64 %5, i64* %8 %9 = inttoptr i64 %7 to i64* %10 = load i64, i64* %9 store i64 %10, i64* %4, align 8, !tbaa !1261 store i64 %6, i64* %3, align 8, !tbaa !1261 %11 = add i64 %1, -144 %12 = tail call %struct.Memory* @sub_560_register_tm_clones(%struct.State* nonnull %0, i64 %11, %struct.Memory* %2) ret %struct.Memory* %12 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_4e0_targ4e0(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_4e0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = load i64, i64* inttoptr (i64 add (i64 ptrtoint (%seg_200fc0__got_type* @seg_200fc0__got to i64), i64 56) to i64*) store i64 %4, i64* %3, align 8, !tbaa !1261 %5 = icmp eq i64 %4, 1254 br i1 %5, label %block_4e6, label %7 block_4e6: ; preds = %block_4e0 %6 = tail call %struct.Memory* @__remill_error(%struct.State* nonnull %0, i64 1254, %struct.Memory* %2) ret %struct.Memory* %6 ; :7: ; preds = %block_4e0 %8 = tail call %struct.Memory* @__mcsema_detach_call_value(%struct.State* nonnull %0, i64 %4, %struct.Memory* %2) ret %struct.Memory* %8 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_5b0___do_global_dtors_aux(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_5b0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %6 = load i8, i8* getelementptr inbounds (%seg_201010__bss_type, %seg_201010__bss_type* @seg_201010__bss, i32 0, i32 0, i32 0) %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 store i8 0, i8* %7, align 1, !tbaa !1265 %8 = zext i8 %6 to i32 %9 = tail call i32 @llvm.ctpop.i32(i32 %8) #5 %10 = trunc i32 %9 to i8 %11 = and i8 %10, 1 %12 = xor i8 %11, 1 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 store i8 %12, i8* %13, align 1, !tbaa !1279 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 store i8 0, i8* %14, align 1, !tbaa !1283 %15 = icmp eq i8 %6, 0 %16 = zext i1 %15 to i8 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 store i8 %16, i8* %17, align 1, !tbaa !1280 %18 = lshr i8 %6, 7 %19 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 store i8 %18, i8* %19, align 1, !tbaa !1281 %20 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i8 0, i8* %20, align 1, !tbaa !1282 %21 = select i1 %15, i64 9, i64 56 %22 = add i64 %21, %1 %23 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 br i1 %15, label %block_5b9, label %block_5e8 block_5c7: ; preds = %block_5b9 %24 = load i64, i64* inttoptr (i64 add (i64 ptrtoint (%seg_201000__data_type* @seg_201000__data to i64), i64 8) to i64*) store i64 %24, i64* %4, align 8, !tbaa !1261 %25 = add i64 %48, -231 %26 = add i64 %48, 12 %27 = add i64 %44, -16 %28 = inttoptr i64 %27 to i64* store i64 %26, i64* %28 store i64 %27, i64* %23, align 8, !tbaa !1261 %29 = tail call %struct.Memory* @sub_4e0_targ4e0(%struct.State* nonnull %0, i64 %25, %struct.Memory* %2) %30 = load i64, i64* %3, align 8 %31 = load i64, i64* %23, align 8, !tbaa !1261 br label %block_5d3 block_5b9: ; preds = %block_5b0 %32 = load i64, i64* inttoptr (i64 add (i64 ptrtoint (%seg_200fc0__got_type* @seg_200fc0__got to i64), i64 56) to i64*) store i8 0, i8* %7, align 1, !tbaa !1265 %33 = trunc i64 %32 to i32 %34 = and i32 %33, 255 %35 = tail call i32 @llvm.ctpop.i32(i32 %34) #5 %36 = trunc i32 %35 to i8 %37 = and i8 %36, 1 %38 = xor i8 %37, 1 store i8 %38, i8* %13, align 1, !tbaa !1279 store i8 0, i8* %14, align 1, !tbaa !1283 %39 = icmp eq i64 %32, 0 %40 = zext i1 %39 to i8 store i8 %40, i8* %17, align 1, !tbaa !1280 %41 = lshr i64 %32, 63 %42 = trunc i64 %41 to i8 store i8 %42, i8* %19, align 1, !tbaa !1281 store i8 0, i8* %20, align 1, !tbaa !1282 %43 = load i64, i64* %5, align 8 %44 = load i64, i64* %23, align 8, !tbaa !1261 %45 = add i64 %44, -8 %46 = inttoptr i64 %45 to i64* store i64 %43, i64* %46 store i64 %45, i64* %5, align 8, !tbaa !1261 %47 = select i1 %39, i64 26, i64 14 %48 = add i64 %22, %47 br i1 %39, label %block_5d3, label %block_5c7 block_5e8: ; preds = %block_5b0 %49 = load i64, i64* %23, align 8, !tbaa !1261 %50 = inttoptr i64 %49 to i64* %51 = load i64, i64* %50 store i64 %51, i64* %3, align 8, !tbaa !1261 %52 = add i64 %49, 8 store i64 %52, i64* %23, align 8, !tbaa !1261 ret %struct.Memory* %2 block_5d3: ; preds = %block_5b9, %block_5c7 %53 = phi i64 [ %45, %block_5b9 ], [ %31, %block_5c7 ] %54 = phi i64 [ %48, %block_5b9 ], [ %30, %block_5c7 ] %55 = phi %struct.Memory* [ %2, %block_5b9 ], [ %29, %block_5c7 ] %56 = add i64 %54, -179 %57 = add i64 %54, 5 %58 = add i64 %53, -8 %59 = inttoptr i64 %58 to i64* store i64 %57, i64* %59 store i64 %58, i64* %23, align 8, !tbaa !1261 %60 = tail call %struct.Memory* @sub_520_deregister_tm_clones(%struct.State* nonnull %0, i64 %56, %struct.Memory* %55) store i8 1, i8* getelementptr inbounds (%seg_201010__bss_type, %seg_201010__bss_type* @seg_201010__bss, i32 0, i32 0, i32 0) %61 = load i64, i64* %23, align 8, !tbaa !1261 %62 = add i64 %61, 8 %63 = inttoptr i64 %61 to i64* %64 = load i64, i64* %63 store i64 %64, i64* %5, align 8, !tbaa !1261 %65 = inttoptr i64 %62 to i64* %66 = load i64, i64* %65 store i64 %66, i64* %3, align 8, !tbaa !1261 %67 = add i64 %61, 16 store i64 %67, i64* %23, align 8, !tbaa !1261 ret %struct.Memory* %60 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_4f0__start(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_4f0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 5, i32 0, i32 0 %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 17, i32 0, i32 0 %12 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 19, i32 0, i32 0 store i64 0, i64* %10, align 8, !tbaa !1261 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %15 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 %18 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %19 = load i64, i64* %6, align 8 store i64 %19, i64* %12, align 8, !tbaa !1261 %20 = load i64, i64* %9, align 8, !tbaa !1261 %21 = add i64 %20, 8 %22 = inttoptr i64 %20 to i64* %23 = load i64, i64* %22 store i64 %23, i64* %7, align 8, !tbaa !1261 store i64 %21, i64* %6, align 8, !tbaa !1261 %24 = and i64 %21, -16 store i8 0, i8* %13, align 1, !tbaa !1265 %25 = trunc i64 %21 to i32 %26 = and i32 %25, 240 %27 = tail call i32 @llvm.ctpop.i32(i32 %26) #5 %28 = trunc i32 %27 to i8 %29 = and i8 %28, 1 %30 = xor i8 %29, 1 store i8 %30, i8* %14, align 1, !tbaa !1279 %31 = icmp eq i64 %24, 0 %32 = zext i1 %31 to i8 store i8 %32, i8* %15, align 1, !tbaa !1280 %33 = lshr i64 %21, 63 %34 = trunc i64 %33 to i8 store i8 %34, i8* %16, align 1, !tbaa !1281 store i8 0, i8* %17, align 1, !tbaa !1282 store i8 0, i8* %18, align 1, !tbaa !1283 %35 = load i64, i64* %4, align 8 %36 = add i64 %24, -8 %37 = inttoptr i64 %36 to i64* store i64 %35, i64* %37 %38 = add i64 %24, -16 %39 = inttoptr i64 %38 to i64* store i64 %36, i64* %39 store i64 ptrtoint (i64 ()* @callback_sub_6b0___libc_csu_fini to i64), i64* %11, align 8, !tbaa !1261 store i64 ptrtoint (i64 ()* @callback_sub_640___libc_csu_init to i64), i64* %5, align 8, !tbaa !1261 store i64 ptrtoint (i64 (i64, i64, i64)* @main to i64), i64* %8, align 8, !tbaa !1261 %40 = add i64 %1, 42 %41 = add i64 %24, -24 %42 = inttoptr i64 %41 to i64* store i64 %40, i64* %42 store i64 %41, i64* %9, align 8, !tbaa !1261 %43 = load i64, i64* inttoptr (i64 add (i64 ptrtoint (%seg_200fc0__got_type* @seg_200fc0__got to i64), i64 32) to i64*) store i64 %43, i64* %3, align 8, !tbaa !1261 %44 = tail call %struct.Memory* @__mcsema_detach_call_value(%struct.State* nonnull %0, i64 %43, %struct.Memory* %2) %45 = load i64, i64* %3, align 8 %46 = add i64 %45, 1 store i64 %46, i64* %3, align 8 %47 = tail call %struct.Memory* @__remill_error(%struct.State* nonnull %0, i64 %46, %struct.Memory* %44) ret %struct.Memory* %47 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_520_deregister_tm_clones(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_550: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0, i32 0 %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 store i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64* %5, align 8, !tbaa !1261 %8 = load i64, i64* %7, align 8 %9 = load i64, i64* %6, align 8, !tbaa !1261 %10 = add i64 %9, -8 %11 = inttoptr i64 %10 to i64* store i64 %8, i64* %11 store i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64* %4, align 8, !tbaa !1261 %12 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 store i8 0, i8* %12, align 1, !tbaa !1265 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 store i8 1, i8* %13, align 1, !tbaa !1279 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 store i8 and (i8 trunc (i64 lshr (i64 xor (i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64)), i64 4) to i8), i8 1), i8* %14, align 1, !tbaa !1283 %15 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 store i8 1, i8* %15, align 1, !tbaa !1280 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 store i8 0, i8* %16, align 1, !tbaa !1281 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i8 zext (i1 icmp eq (i64 add (i64 lshr (i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64 63), i64 xor (i64 lshr (i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64 63), i64 lshr (i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64 63))), i64 2) to i8), i8* %17, align 1, !tbaa !1282 %18 = inttoptr i64 %10 to i64* %19 = load i64, i64* %18 store i64 %19, i64* %7, align 8, !tbaa !1261 %20 = inttoptr i64 %9 to i64* %21 = load i64, i64* %20 store i64 %21, i64* %3, align 8, !tbaa !1261 %22 = add i64 %9, 8 store i64 %22, i64* %6, align 8, !tbaa !1261 ret %struct.Memory* %2 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_60e_main(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_60e: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %7 = getelementptr inbounds %union.anon, %union.anon* %4, i64 0, i32 0 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %10 = load i64, i64* %9, align 8 %11 = load i64, i64* %8, align 8, !tbaa !1261 %12 = add i64 %11, -8 %13 = inttoptr i64 %12 to i64* store i64 %10, i64* %13 store i64 %12, i64* %9, align 8, !tbaa !1261 %14 = add i64 %11, -12 %15 = load i32, i32* %5, align 4 %16 = inttoptr i64 %14 to i32* store i32 %15, i32* %16 %17 = add i64 %11, -24 %18 = load i64, i64* %6, align 8 %19 = inttoptr i64 %17 to i64* store i64 %18, i64* %19 %20 = inttoptr i64 %14 to i32* %21 = load i32, i32* %20 %22 = zext i32 %21 to i64 %23 = add nuw nsw i64 %22, 2 %24 = and i64 %23, 4294967295 store i64 %24, i64* %6, align 8, !tbaa !1261 store i64 %22, i64* %7, align 8, !tbaa !1261 %25 = add i64 %1, -20 %26 = add i64 %1, 33 %27 = add i64 %11, -32 %28 = inttoptr i64 %27 to i64* store i64 %26, i64* %28 store i64 %27, i64* %8, align 8, !tbaa !1261 %29 = tail call %struct.Memory* @sub_5fa_add(%struct.State* nonnull %0, i64 %25, %struct.Memory* %2) %30 = load i64, i64* %9, align 8, !tbaa !1261 %31 = inttoptr i64 %30 to i64* %32 = load i64, i64* %31 store i64 %32, i64* %9, align 8, !tbaa !1261 %33 = add i64 %30, 8 %34 = inttoptr i64 %33 to i64* %35 = load i64, i64* %34 store i64 %35, i64* %3, align 8, !tbaa !1261 %36 = add i64 %30, 16 store i64 %36, i64* %8, align 8, !tbaa !1261 ret %struct.Memory* %29 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_6b4__fini(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias returned) local_unnamed_addr #2 { block_6b4: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %5 = load i64, i64* %4, align 8 %6 = add i64 %5, -8 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %9 = xor i64 %6, %5 %10 = lshr i64 %9, 4 %11 = trunc i64 %10 to i8 %12 = and i8 %11, 1 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %15 = lshr i64 %6, 63 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %17 = lshr i64 %5, 63 %18 = xor i64 %15, %17 %19 = add nuw nsw i64 %18, %17 %20 = icmp eq i64 %19, 2 %21 = zext i1 %20 to i8 %22 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 %23 = icmp ult i64 %5, 8 %24 = zext i1 %23 to i8 store i8 %24, i8* %7, align 1, !tbaa !1265 %25 = trunc i64 %5 to i32 %26 = and i32 %25, 255 %27 = tail call i32 @llvm.ctpop.i32(i32 %26) #5 %28 = trunc i32 %27 to i8 %29 = and i8 %28, 1 %30 = xor i8 %29, 1 store i8 %30, i8* %8, align 1, !tbaa !1279 store i8 %12, i8* %13, align 1, !tbaa !1283 %31 = icmp eq i64 %5, 0 %32 = zext i1 %31 to i8 store i8 %32, i8* %14, align 1, !tbaa !1280 %33 = trunc i64 %17 to i8 store i8 %33, i8* %16, align 1, !tbaa !1281 store i8 %21, i8* %22, align 1, !tbaa !1282 %34 = inttoptr i64 %5 to i64* %35 = load i64, i64* %34 store i64 %35, i64* %3, align 8, !tbaa !1261 %36 = add i64 %5, 8 store i64 %36, i64* %4, align 8, !tbaa !1261 ret %struct.Memory* %2 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_560_register_tm_clones(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_5a0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0, i32 0 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 store i64 ptrtoint (%seg_201010__bss_type* @seg_201010__bss to i64), i64* %6, align 8, !tbaa !1261 %9 = load i64, i64* %8, align 8 %10 = load i64, i64* %7, align 8, !tbaa !1261 %11 = add i64 %10, -8 %12 = inttoptr i64 %11 to i64* store i64 %9, i64* %12 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %15 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %18 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i64 0, i64* %4, align 8, !tbaa !1261 store i64 0, i64* %5, align 8, !tbaa !1261 store i8 0, i8* %13, align 1, !tbaa !1284 store i8 1, i8* %14, align 1, !tbaa !1284 store i8 0, i8* %15, align 1, !tbaa !1284 store i8 1, i8* %16, align 1, !tbaa !1284 store i8 0, i8* %17, align 1, !tbaa !1284 store i8 0, i8* %18, align 1, !tbaa !1284 %19 = inttoptr i64 %11 to i64* %20 = load i64, i64* %19 store i64 %20, i64* %8, align 8, !tbaa !1261 %21 = inttoptr i64 %10 to i64* %22 = load i64, i64* %21 store i64 %22, i64* %3, align 8, !tbaa !1261 %23 = add i64 %10, 8 store i64 %23, i64* %7, align 8, !tbaa !1261 ret %struct.Memory* %2 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_5fa_add(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_5fa: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %7 = bitcast %union.anon* %6 to i32* %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %12 = load i64, i64* %11, align 8 %13 = load i64, i64* %10, align 8, !tbaa !1261 %14 = add i64 %13, -8 %15 = inttoptr i64 %14 to i64* store i64 %12, i64* %15 %16 = add i64 %13, -12 %17 = load i32, i32* %7, align 4 %18 = inttoptr i64 %16 to i32* store i32 %17, i32* %18 %19 = add i64 %13, -16 %20 = load i32, i32* %5, align 4 %21 = inttoptr i64 %19 to i32* store i32 %20, i32* %21 %22 = add i64 %13, -12 %23 = inttoptr i64 %22 to i32* %24 = load i32, i32* %23 %25 = zext i32 %24 to i64 store i64 %25, i64* %9, align 8, !tbaa !1261 %26 = add i64 %13, -16 %27 = inttoptr i64 %26 to i32* %28 = load i32, i32* %27 %29 = add i32 %24, %28 %30 = zext i32 %29 to i64 store i64 %30, i64* %8, align 8, !tbaa !1261 %31 = icmp ult i32 %29, %28 %32 = icmp ult i32 %29, %24 %33 = or i1 %31, %32 %34 = zext i1 %33 to i8 %35 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 store i8 %34, i8* %35, align 1, !tbaa !1265 %36 = and i32 %29, 255 %37 = tail call i32 @llvm.ctpop.i32(i32 %36) #5 %38 = trunc i32 %37 to i8 %39 = and i8 %38, 1 %40 = xor i8 %39, 1 %41 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 store i8 %40, i8* %41, align 1, !tbaa !1279 %42 = xor i32 %24, %28 %43 = xor i32 %42, %29 %44 = lshr i32 %43, 4 %45 = trunc i32 %44 to i8 %46 = and i8 %45, 1 %47 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 store i8 %46, i8* %47, align 1, !tbaa !1283 %48 = icmp eq i32 %29, 0 %49 = zext i1 %48 to i8 %50 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 store i8 %49, i8* %50, align 1, !tbaa !1280 %51 = lshr i32 %29, 31 %52 = trunc i32 %51 to i8 %53 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 store i8 %52, i8* %53, align 1, !tbaa !1281 %54 = lshr i32 %28, 31 %55 = lshr i32 %24, 31 %56 = xor i32 %51, %54 %57 = xor i32 %51, %55 %58 = add nuw nsw i32 %56, %57 %59 = icmp eq i32 %58, 2 %60 = zext i1 %59 to i8 %61 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i8 %60, i8* %61, align 1, !tbaa !1282 %62 = inttoptr i64 %14 to i64* %63 = load i64, i64* %62 store i64 %63, i64* %11, align 8, !tbaa !1261 %64 = inttoptr i64 %13 to i64* %65 = load i64, i64* %64 store i64 %65, i64* %3, align 8, !tbaa !1261 %66 = add i64 %13, 8 store i64 %66, i64* %10, align 8, !tbaa !1261 ret %struct.Memory* %2 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_6b0___libc_csu_fini(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias returned) local_unnamed_addr #2 { block_6b0: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %5 = load i64, i64* %4, align 8, !tbaa !1261 %6 = inttoptr i64 %5 to i64* %7 = load i64, i64* %6 store i64 %7, i64* %3, align 8, !tbaa !1261 %8 = add i64 %5, 8 store i64 %8, i64* %4, align 8, !tbaa !1261 ret %struct.Memory* %2 } ; Function Attrs: noinline nounwind define %struct.Memory* @sub_640___libc_csu_init(%struct.State* noalias dereferenceable(3376), i64, %struct.Memory* noalias) local_unnamed_addr #2 { block_640: %3 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0 %5 = bitcast %union.anon* %4 to i32* %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 27, i32 0 %7 = bitcast %union.anon* %6 to i32* %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 3, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %11 = getelementptr inbounds %union.anon, %union.anon* %4, i64 0, i32 0 %12 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %13 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 15, i32 0, i32 0 %14 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 25, i32 0, i32 0 %15 = getelementptr inbounds %union.anon, %union.anon* %6, i64 0, i32 0 %16 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 29, i32 0, i32 0 %17 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 31, i32 0, i32 0 %18 = load i64, i64* %17, align 8 %19 = load i64, i64* %12, align 8, !tbaa !1261 %20 = add i64 %19, -8 %21 = inttoptr i64 %20 to i64* store i64 %18, i64* %21 %22 = load i64, i64* %16, align 8 %23 = add i64 %19, -16 %24 = inttoptr i64 %23 to i64* store i64 %22, i64* %24 %25 = load i64, i64* %9, align 8 store i64 %25, i64* %17, align 8, !tbaa !1261 %26 = load i64, i64* %15, align 8 %27 = add i64 %19, -24 %28 = inttoptr i64 %27 to i64* store i64 %26, i64* %28 %29 = load i64, i64* %14, align 8 %30 = add i64 %19, -32 %31 = inttoptr i64 %30 to i64* store i64 %29, i64* %31 store i64 ptrtoint (%seg_200df0__init_array_type* @seg_200df0__init_array to i64), i64* %14, align 8, !tbaa !1261 %32 = load i64, i64* %13, align 8 %33 = add i64 %19, -40 %34 = inttoptr i64 %33 to i64* store i64 %32, i64* %34 %35 = load i64, i64* %8, align 8 %36 = add i64 %19, -48 %37 = inttoptr i64 %36 to i64* store i64 %35, i64* %37 %38 = load i32, i32* %5, align 4 %39 = zext i32 %38 to i64 store i64 %39, i64* %15, align 8, !tbaa !1261 %40 = load i64, i64* %10, align 8 store i64 %40, i64* %16, align 8, !tbaa !1261 %41 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 1 %42 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 3 %43 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 5 %44 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 7 %45 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 9 %46 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 2, i32 13 store i64 ashr (i64 sub (i64 add (i64 ptrtoint (%seg_200df0__init_array_type* @seg_200df0__init_array to i64), i64 8), i64 ptrtoint (%seg_200df0__init_array_type* @seg_200df0__init_array to i64)), i64 3), i64* %13, align 8, !tbaa !1261 %47 = add i64 %1, -392 %48 = add i64 %1, 49 %49 = add i64 %19, -64 %50 = inttoptr i64 %49 to i64* store i64 %48, i64* %50 store i64 %49, i64* %12, align 8, !tbaa !1261 %51 = tail call %struct.Memory* @sub_4b8__init(%struct.State* nonnull %0, i64 %47, %struct.Memory* %2) %52 = load i64, i64* %13, align 8 %53 = load i64, i64* %3, align 8 %54 = icmp eq i64 %52, 0 %55 = select i1 %54, i64 37, i64 5 %56 = add i64 %53, %55 br i1 %54, label %block_696, label %block_676 block_696.loopexit: ; preds = %block_680 br label %block_696 block_696: ; preds = %block_696.loopexit, %block_640 %57 = phi %struct.Memory* [ %51, %block_640 ], [ %118, %block_696.loopexit ] %58 = load i64, i64* %12, align 8 %59 = add i64 %58, 8 %60 = icmp ugt i64 %58, -9 %61 = zext i1 %60 to i8 store i8 %61, i8* %41, align 1, !tbaa !1265 %62 = trunc i64 %59 to i32 %63 = and i32 %62, 255 %64 = tail call i32 @llvm.ctpop.i32(i32 %63) #5 %65 = trunc i32 %64 to i8 %66 = and i8 %65, 1 %67 = xor i8 %66, 1 store i8 %67, i8* %42, align 1, !tbaa !1279 %68 = xor i64 %59, %58 %69 = lshr i64 %68, 4 %70 = trunc i64 %69 to i8 %71 = and i8 %70, 1 store i8 %71, i8* %43, align 1, !tbaa !1283 %72 = icmp eq i64 %59, 0 %73 = zext i1 %72 to i8 store i8 %73, i8* %44, align 1, !tbaa !1280 %74 = lshr i64 %59, 63 %75 = trunc i64 %74 to i8 store i8 %75, i8* %45, align 1, !tbaa !1281 %76 = lshr i64 %58, 63 %77 = xor i64 %74, %76 %78 = add nuw nsw i64 %77, %74 %79 = icmp eq i64 %78, 2 %80 = zext i1 %79 to i8 store i8 %80, i8* %46, align 1, !tbaa !1282 %81 = add i64 %58, 16 %82 = inttoptr i64 %59 to i64* %83 = load i64, i64* %82 store i64 %83, i64* %8, align 8, !tbaa !1261 %84 = add i64 %58, 24 %85 = inttoptr i64 %81 to i64* %86 = load i64, i64* %85 store i64 %86, i64* %13, align 8, !tbaa !1261 %87 = add i64 %58, 32 %88 = inttoptr i64 %84 to i64* %89 = load i64, i64* %88 store i64 %89, i64* %14, align 8, !tbaa !1261 %90 = add i64 %58, 40 %91 = inttoptr i64 %87 to i64* %92 = load i64, i64* %91 store i64 %92, i64* %15, align 8, !tbaa !1261 %93 = add i64 %58, 48 %94 = inttoptr i64 %90 to i64* %95 = load i64, i64* %94 store i64 %95, i64* %16, align 8, !tbaa !1261 %96 = add i64 %58, 56 %97 = inttoptr i64 %93 to i64* %98 = load i64, i64* %97 store i64 %98, i64* %17, align 8, !tbaa !1261 %99 = inttoptr i64 %96 to i64* %100 = load i64, i64* %99 store i64 %100, i64* %3, align 8, !tbaa !1261 %101 = add i64 %58, 64 store i64 %101, i64* %12, align 8, !tbaa !1261 ret %struct.Memory* %57 block_680: ; preds = %block_676, %block_680 %102 = phi i64 [ 0, %block_676 ], [ %121, %block_680 ] %103 = phi i64 [ %150, %block_676 ], [ %149, %block_680 ] %104 = phi %struct.Memory* [ %51, %block_676 ], [ %118, %block_680 ] %105 = load i64, i64* %17, align 8 store i64 %105, i64* %9, align 8, !tbaa !1261 %106 = load i64, i64* %16, align 8 store i64 %106, i64* %10, align 8, !tbaa !1261 %107 = load i32, i32* %7, align 4 %108 = zext i32 %107 to i64 store i64 %108, i64* %11, align 8, !tbaa !1261 %109 = load i64, i64* %14, align 8 %110 = shl i64 %102, 3 %111 = add i64 %110, %109 %112 = add i64 %103, 13 %113 = load i64, i64* %12, align 8, !tbaa !1261 %114 = add i64 %113, -8 %115 = inttoptr i64 %114 to i64* store i64 %112, i64* %115 store i64 %114, i64* %12, align 8, !tbaa !1261 %116 = inttoptr i64 %111 to i64* %117 = load i64, i64* %116 store i64 %117, i64* %3, align 8, !tbaa !1261 %118 = tail call %struct.Memory* @__mcsema_detach_call_value(%struct.State* nonnull %0, i64 %117, %struct.Memory* %104) %119 = load i64, i64* %8, align 8 %120 = load i64, i64* %3, align 8 %121 = add i64 %119, 1 store i64 %121, i64* %8, align 8, !tbaa !1261 %122 = lshr i64 %121, 63 %123 = load i64, i64* %13, align 8 %124 = sub i64 %123, %121 %125 = icmp ult i64 %123, %121 %126 = zext i1 %125 to i8 store i8 %126, i8* %41, align 1, !tbaa !1265 %127 = trunc i64 %124 to i32 %128 = and i32 %127, 255 %129 = tail call i32 @llvm.ctpop.i32(i32 %128) #5 %130 = trunc i32 %129 to i8 %131 = and i8 %130, 1 %132 = xor i8 %131, 1 store i8 %132, i8* %42, align 1, !tbaa !1279 %133 = xor i64 %121, %123 %134 = xor i64 %133, %124 %135 = lshr i64 %134, 4 %136 = trunc i64 %135 to i8 %137 = and i8 %136, 1 store i8 %137, i8* %43, align 1, !tbaa !1283 %138 = icmp eq i64 %124, 0 %139 = zext i1 %138 to i8 store i8 %139, i8* %44, align 1, !tbaa !1280 %140 = lshr i64 %124, 63 %141 = trunc i64 %140 to i8 store i8 %141, i8* %45, align 1, !tbaa !1281 %142 = lshr i64 %123, 63 %143 = xor i64 %122, %142 %144 = xor i64 %140, %142 %145 = add nuw nsw i64 %144, %143 %146 = icmp eq i64 %145, 2 %147 = zext i1 %146 to i8 store i8 %147, i8* %46, align 1, !tbaa !1282 %148 = select i1 %138, i64 9, i64 -13 %149 = add i64 %120, %148 br i1 %138, label %block_696.loopexit, label %block_680 block_676: ; preds = %block_640 store i64 0, i64* %8, align 8, !tbaa !1261 store i8 0, i8* %41, align 1, !tbaa !1265 store i8 1, i8* %42, align 1, !tbaa !1279 store i8 1, i8* %44, align 1, !tbaa !1280 store i8 0, i8* %45, align 1, !tbaa !1281 store i8 0, i8* %46, align 1, !tbaa !1282 store i8 0, i8* %43, align 1, !tbaa !1283 %150 = add i64 %56, 10 br label %block_680 } ; Function Attrs: nobuiltin noinline nounwind define i64 @callback_sub_5f0_frame_dummy(i64, i64, i64, i64, i64, i64, i64, i64) #3 { %9 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %10 = icmp eq i64 %9, 0 br i1 %10, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %8 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %8 %11 = phi i64 [ %9, %8 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1520, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %12 = load volatile i1, i1* @0, align 1 br i1 %12, label %__mcsema_early_init.exit, label %13 ; :13: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %13, %__mcsema_verify_reg_state.exit store i64 %0, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 11, i32 0, i32 0), align 8 store i64 %1, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 9, i32 0, i32 0), align 8 store i64 %2, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 7, i32 0, i32 0), align 8 store i64 %3, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 5, i32 0, i32 0), align 8 store i64 %4, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 17, i32 0, i32 0), align 8 store i64 %5, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 19, i32 0, i32 0), align 8 %14 = inttoptr i64 %11 to i64* store i64 %7, i64* %14 %15 = add i64 %11, -8 %16 = inttoptr i64 %15 to i64* store i64 %6, i64* %16 %17 = add i64 %11, -24 store i64 %17, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %18 = tail call %struct.Memory* @sub_5f0_frame_dummy(%struct.State* nonnull @__mcsema_reg_state, i64 1520, %struct.Memory* null) store i64 %11, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %19 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %19 } ; Function Attrs: norecurse nounwind define void @__mcsema_verify_reg_state() local_unnamed_addr #4 { entry: %0 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %1 = icmp eq i64 %0, 0 br i1 %1, label %is_null, label %end is_null: ; preds = %entry store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %end end: ; preds = %is_null, %entry ret void } ; Function Attrs: nobuiltin noinline nounwind define i64 @callback_sub_5b0___do_global_dtors_aux(i64, i64, i64, i64, i64, i64, i64, i64) #3 { %9 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %10 = icmp eq i64 %9, 0 br i1 %10, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %8 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %8 %11 = phi i64 [ %9, %8 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1456, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %12 = load volatile i1, i1* @0, align 1 br i1 %12, label %__mcsema_early_init.exit, label %13 ; :13: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %13, %__mcsema_verify_reg_state.exit store i64 %0, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 11, i32 0, i32 0), align 8 store i64 %1, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 9, i32 0, i32 0), align 8 store i64 %2, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 7, i32 0, i32 0), align 8 store i64 %3, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 5, i32 0, i32 0), align 8 store i64 %4, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 17, i32 0, i32 0), align 8 store i64 %5, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 19, i32 0, i32 0), align 8 %14 = inttoptr i64 %11 to i64* store i64 %7, i64* %14 %15 = add i64 %11, -8 %16 = inttoptr i64 %15 to i64* store i64 %6, i64* %16 %17 = add i64 %11, -24 store i64 %17, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %18 = tail call %struct.Memory* @sub_5b0___do_global_dtors_aux(%struct.State* nonnull @__mcsema_reg_state, i64 1456, %struct.Memory* null) store i64 %11, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %19 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %19 } ; Function Attrs: noinline nounwind define %struct.Memory* @__mcsema_detach_call_value(%struct.State* noalias nocapture dereferenceable(3376), i64, %struct.Memory* noalias returned) local_unnamed_addr #2 { %4 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 33, i32 0, i32 0 %5 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 1, i32 0, i32 0 %6 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 5, i32 0, i32 0 %7 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 7, i32 0, i32 0 %8 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 9, i32 0, i32 0 %9 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 11, i32 0, i32 0 %10 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 13, i32 0, i32 0 %11 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 17, i32 0, i32 0 %12 = getelementptr inbounds %struct.State, %struct.State* %0, i64 0, i32 6, i32 19, i32 0, i32 0 %13 = load i64, i64* %9, align 8 %14 = load i64, i64* %8, align 8 %15 = load i64, i64* %7, align 8 %16 = load i64, i64* %6, align 8 %17 = load i64, i64* %11, align 8 %18 = load i64, i64* %12, align 8 %19 = load i64, i64* %10, align 8 %20 = add i64 %19, 8 %21 = inttoptr i64 %20 to i64* %22 = load i64, i64* %21 %23 = add i64 %19, 16 %24 = inttoptr i64 %23 to i64* %25 = load i64, i64* %24 %26 = inttoptr i64 %1 to i64 (i64, i64, i64, i64, i64, i64, i64, i64)* %27 = tail call i64 %26(i64 %13, i64 %14, i64 %15, i64 %16, i64 %17, i64 %18, i64 %22, i64 %25) #5 store i64 %27, i64* %5, align 8 %28 = inttoptr i64 %19 to i64* %29 = load i64, i64* %28 store i64 %29, i64* %4, align 8 store i64 %20, i64* %10, align 8 ret %struct.Memory* %2 } ; Function Attrs: nobuiltin noinline nounwind define i64 @callback_sub_6b0___libc_csu_fini() #3 { %1 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %2 = icmp eq i64 %1, 0 br i1 %2, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %0 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %0 %3 = phi i64 [ %1, %0 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1712, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %4 = load volatile i1, i1* @0, align 1 br i1 %4, label %__mcsema_early_init.exit, label %5 ; :5: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %5, %__mcsema_verify_reg_state.exit %6 = add i64 %3, -8 store i64 %6, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %7 = tail call %struct.Memory* @sub_6b0___libc_csu_fini(%struct.State* nonnull @__mcsema_reg_state, i64 1712, %struct.Memory* null) store i64 %3, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %8 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %8 } ; Function Attrs: nobuiltin noinline nounwind define i64 @callback_sub_640___libc_csu_init() #3 { %1 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %2 = icmp eq i64 %1, 0 br i1 %2, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %0 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %0 %3 = phi i64 [ %1, %0 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1600, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %4 = load volatile i1, i1* @0, align 1 br i1 %4, label %__mcsema_early_init.exit, label %5 ; :5: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %5, %__mcsema_verify_reg_state.exit %6 = add i64 %3, -8 store i64 %6, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %7 = tail call %struct.Memory* @sub_640___libc_csu_init(%struct.State* nonnull @__mcsema_reg_state, i64 1600, %struct.Memory* null) store i64 %3, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %8 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %8 } ; Function Attrs: nobuiltin noinline nounwind define i64 @main(i64, i64, i64) #3 { %4 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %5 = icmp eq i64 %4, 0 br i1 %5, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %3 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %3 %6 = phi i64 [ %4, %3 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1550, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %7 = load volatile i1, i1* @0, align 1 br i1 %7, label %__mcsema_early_init.exit, label %8 ; :8: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %8, %__mcsema_verify_reg_state.exit store i64 %0, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 11, i32 0, i32 0), align 8 store i64 %1, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 9, i32 0, i32 0), align 8 store i64 %2, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 7, i32 0, i32 0), align 8 %9 = add i64 %6, -8 store i64 %9, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %10 = tail call %struct.Memory* @sub_60e_main(%struct.State* nonnull @__mcsema_reg_state, i64 1550, %struct.Memory* null) store i64 %6, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %11 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %11 } ; Function Attrs: nobuiltin noinline nounwind define i64 @targ4e0(i64, i64, i64, i64, i64, i64, i64, i64) local_unnamed_addr #3 { %9 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %10 = icmp eq i64 %9, 0 br i1 %10, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %8 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 br label %__mcsema_verify_reg_state.exit __mcsema_verify_reg_state.exit: ; preds = %is_null.i, %8 %11 = phi i64 [ %9, %8 ], [ ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) to i64), %is_null.i ] store i64 1248, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 33, i32 0, i32 0), align 8 store i64 ptrtoint ([512 x i64]* @__mcsema_tls to i64), i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 5, i32 7, i32 0, i32 0), align 8 %12 = load volatile i1, i1* @0, align 1 br i1 %12, label %__mcsema_early_init.exit, label %13 ; :13: ; preds = %__mcsema_verify_reg_state.exit store volatile i1 true, i1* @0, align 1 br label %__mcsema_early_init.exit __mcsema_early_init.exit: ; preds = %13, %__mcsema_verify_reg_state.exit store i64 %0, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 11, i32 0, i32 0), align 8 store i64 %1, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 9, i32 0, i32 0), align 8 store i64 %2, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 7, i32 0, i32 0), align 8 store i64 %3, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 5, i32 0, i32 0), align 8 store i64 %4, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 17, i32 0, i32 0), align 8 store i64 %5, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 19, i32 0, i32 0), align 8 %14 = inttoptr i64 %11 to i64* store i64 %7, i64* %14 %15 = add i64 %11, -8 %16 = inttoptr i64 %15 to i64* store i64 %6, i64* %16 %17 = add i64 %11, -24 store i64 %17, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %18 = tail call %struct.Memory* @sub_4e0_targ4e0(%struct.State* nonnull @__mcsema_reg_state, i64 1248, %struct.Memory* null) store i64 %11, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %19 = load i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 1, i32 0, i32 0), align 8 ret i64 %19 } ; Function Attrs: nobuiltin noinline nounwind define i64 @add(i64, i64, i64, i64, i64, i64, i64, i64) local_unnamed_addr #3 { %9 = load volatile i64, i64* getelementptr inbounds (%struct.State, %struct.State* @__mcsema_reg_state, i64 0, i32 6, i32 13, i32 0, i32 0), align 8 %10 = icmp eq i64 %9, 0 br i1 %10, label %is_null.i, label %__mcsema_verify_reg_state.exit is_null.i: ; preds = %8 store i64 ptrtoint (i64* getelementptr inbounds ([131072 x i64], [131072 x i64]* @__mcsema_stack, i64 0, i64 131064) 