diff --git a/.clang-format b/.clang-format new file mode 100644 index 000000000..5d75fab20 --- /dev/null +++ b/.clang-format @@ -0,0 +1,69 @@ +--- +BasedOnStyle: Google +AccessModifierOffset: '-1' +AlignAfterOpenBracket: Align +AlignConsecutiveMacros: 'false' +AlignConsecutiveAssignments: 'false' +AlignConsecutiveDeclarations: 'false' +AlignEscapedNewlines: DontAlign +AlignOperands: 'true' +AlignTrailingComments: 'false' +AllowAllArgumentsOnNextLine: 'true' +AllowAllConstructorInitializersOnNextLine: 'false' +AllowAllParametersOfDeclarationOnNextLine: 'true' +AllowShortBlocksOnASingleLine: 'false' +AllowShortCaseLabelsOnASingleLine: 'true' +AllowShortFunctionsOnASingleLine: Empty +AllowShortIfStatementsOnASingleLine: Never +AllowShortLambdasOnASingleLine: All +AllowShortLoopsOnASingleLine: 'false' +AlwaysBreakAfterReturnType: None +AlwaysBreakTemplateDeclarations: 'Yes' +BinPackParameters: 'true' +BreakBeforeBinaryOperators: None +BreakBeforeBraces: Custom +BreakConstructorInitializers: BeforeColon +BreakInheritanceList: BeforeColon +BreakStringLiterals: 'false' +ColumnLimit: '80' +CompactNamespaces: 'false' +ConstructorInitializerAllOnOneLineOrOnePerLine: 'true' +ConstructorInitializerIndentWidth: '4' +ContinuationIndentWidth: '4' +Cpp11BracedListStyle: 'true' +DerivePointerAlignment: 'false' +FixNamespaceComments: 'true' +IncludeBlocks: Regroup +IndentCaseLabels: 'true' +IndentPPDirectives: AfterHash +IndentWidth: '2' +IndentWrappedFunctionNames: 'false' +KeepEmptyLinesAtTheStartOfBlocks: 'true' +Language: Cpp +MaxEmptyLinesToKeep: '2' +NamespaceIndentation: None +PointerAlignment: Right +ReflowComments: 'false' +SortIncludes: 'true' +SortUsingDeclarations: 'true' +SpaceAfterCStyleCast: 'true' +SpaceAfterLogicalNot: 'false' +SpaceAfterTemplateKeyword: 'true' +SpaceBeforeAssignmentOperators: 'true' +SpaceBeforeCtorInitializerColon: 'true' +SpaceBeforeInheritanceColon: 'true' +SpaceBeforeParens: ControlStatements +SpaceBeforeRangeBasedForLoopColon: 'true' +SpaceInEmptyParentheses: 'false' +SpacesBeforeTrailingComments: '2' +SpacesInAngles: 'false' +SpacesInCStyleCastParentheses: 'false' +SpacesInContainerLiterals: 'false' +SpacesInParentheses: 'false' +SpacesInSquareBrackets: 'false' +Standard: Cpp11 +TabWidth: '2' +UseTab: Never +PenaltyReturnTypeOnItsOwnLine: '40' + +... diff --git a/.remill_commit_id b/.remill_commit_id index 7676fe105..50ad550a3 100644 --- a/.remill_commit_id +++ b/.remill_commit_id @@ -1 +1 @@ -e26fea16bb5a04f700cee590af8d810b916461a7 +99df2e19d4c4af677948a851461e9ffb3c164331 \ No newline at end of file diff --git a/mcsema/Arch/Arch.cpp b/mcsema/Arch/Arch.cpp index 4b47806a4..0c4430cc4 100644 --- a/mcsema/Arch/Arch.cpp +++ b/mcsema/Arch/Arch.cpp @@ -18,11 +18,7 @@ #include "mcsema/Arch/Arch.h" #include - -#include - #include - #include #include #include @@ -30,13 +26,13 @@ #include #include #include - -#include #include #include - +#include #include +#include + #include "mcsema/BC/Util.h" namespace mcsema { @@ -46,12 +42,11 @@ extern std::shared_ptr gContext; std::unique_ptr gArch(nullptr); bool InitArch(const std::string &os, const std::string &arch) { - LOG(INFO) - << "Initializing for " << arch << " code on " << os; + LOG(INFO) << "Initializing for " << arch << " code on " << os; remill::Arch::GetTargetArch(*gContext).swap(gArch); - gWordType = llvm::Type::getIntNTy( - *gContext, static_cast(gArch->address_size)); + gWordType = llvm::Type::getIntNTy(*gContext, + static_cast(gArch->address_size)); gWordMask = 0; if (32 == gArch->address_size) { diff --git a/mcsema/Arch/X86/Runtime/Runtime.cpp b/mcsema/Arch/X86/Runtime/Runtime.cpp index 2dd058160..4d3de93c1 100644 --- a/mcsema/Arch/X86/Runtime/Runtime.cpp +++ b/mcsema/Arch/X86/Runtime/Runtime.cpp @@ -15,34 +15,35 @@ * along with this program. If not, see . */ -#include -#include -#include #include #include +#include +#include +#include + #define HAS_FEATURE_AVX 1 #define HAS_FEATURE_AVX512 0 #ifndef ADDRESS_SIZE_BITS -# define ADDRESS_SIZE_BITS 64 +# define ADDRESS_SIZE_BITS 64 #endif -#include "remill/Arch/X86/Runtime/State.h" #include "mcsema/Arch/X86/Runtime/Registers.h" +#include "remill/Arch/X86/Runtime/State.h" #ifndef PRIx64 -# define PRIx64 "llx" +# define PRIx64 "llx" #endif #ifndef PRIx32 -# define PRIx32 "x" +# define PRIx32 "x" #endif #if ADDRESS_SIZE_BITS == 64 -# define PRIxADDR PRIx64 +# define PRIxADDR PRIx64 #else -# define PRIxADDR PRIx32 +# define PRIxADDR PRIx32 #endif extern "C" { @@ -84,8 +85,8 @@ CR8Reg gCR8; // return &(__mcsema_stack.bytes[kStackSize - 16UL]); // } -Memory *__remill_sync_hyper_call( - State &state, Memory *mem, SyncHyperCall::Name call) { +Memory *__remill_sync_hyper_call(State &state, Memory *mem, + SyncHyperCall::Name call) { auto eax = state.gpr.rax.dword; auto ebx = state.gpr.rbx.dword; auto ecx = state.gpr.rcx.dword; @@ -98,43 +99,29 @@ Memory *__remill_sync_hyper_call( state.gpr.rcx.aword = 0; state.gpr.rdx.aword = 0; - asm volatile( - "cpuid" - : "=a"(state.gpr.rax.dword), - "=b"(state.gpr.rbx.dword), - "=c"(state.gpr.rcx.dword), - "=d"(state.gpr.rdx.dword) - : "a"(eax), - "b"(ebx), - "c"(ecx), - "d"(edx) - ); + asm volatile("cpuid" + : "=a"(state.gpr.rax.dword), "=b"(state.gpr.rbx.dword), + "=c"(state.gpr.rcx.dword), "=d"(state.gpr.rdx.dword) + : "a"(eax), "b"(ebx), "c"(ecx), "d"(edx)); break; case SyncHyperCall::kX86ReadTSC: state.gpr.rax.aword = 0; state.gpr.rdx.aword = 0; - asm volatile( - "rdtsc" - : "=a"(state.gpr.rax.dword), - "=d"(state.gpr.rdx.dword) - ); + asm volatile("rdtsc" + : "=a"(state.gpr.rax.dword), "=d"(state.gpr.rdx.dword)); break; case SyncHyperCall::kX86ReadTSCP: state.gpr.rax.aword = 0; state.gpr.rcx.aword = 0; state.gpr.rdx.aword = 0; - asm volatile( - "rdtscp" - : "=a"(state.gpr.rax.dword), - "=c"(state.gpr.rcx.dword), - "=d"(state.gpr.rdx.dword) - ); + asm volatile("rdtscp" + : "=a"(state.gpr.rax.dword), "=c"(state.gpr.rcx.dword), + "=d"(state.gpr.rdx.dword)); break; - default: - __builtin_unreachable(); + default: __builtin_unreachable(); } return mem; @@ -142,26 +129,24 @@ Memory *__remill_sync_hyper_call( Memory *__mcsema_reg_tracer(State &state, addr_t, Memory *memory) { if (sizeof(void *) == 8) { - fprintf( - stderr, - "RIP=%" PRIxADDR ",RAX=%" PRIxADDR ",RBX=%" PRIxADDR - ",RCX=%" PRIxADDR ",RDX=%" PRIxADDR ",RSI=%" PRIxADDR - ",RDI=%" PRIxADDR ",RBP=%" PRIxADDR ",RSP=%" PRIxADDR - ",R8=%" PRIxADDR ",R9=%" PRIxADDR ",R10=%" PRIxADDR - ",R11=%" PRIxADDR ",R12=%" PRIxADDR ",R13=%" PRIxADDR - ",R14=%" PRIxADDR ",R15=%" PRIxADDR "\n", - - state.RIP, state.RAX, state.RBX, state.RCX, state.RDX, state.RSI, - state.RDI, state.RBP, state.RSP, state.R8, state.R9, state.R10, - state.R11, state.R12, state.R13, state.R14, state.R15); + fprintf(stderr, + "RIP=%" PRIxADDR ",RAX=%" PRIxADDR ",RBX=%" PRIxADDR + ",RCX=%" PRIxADDR ",RDX=%" PRIxADDR ",RSI=%" PRIxADDR + ",RDI=%" PRIxADDR ",RBP=%" PRIxADDR ",RSP=%" PRIxADDR + ",R8=%" PRIxADDR ",R9=%" PRIxADDR ",R10=%" PRIxADDR + ",R11=%" PRIxADDR ",R12=%" PRIxADDR ",R13=%" PRIxADDR + ",R14=%" PRIxADDR ",R15=%" PRIxADDR "\n", + + state.RIP, state.RAX, state.RBX, state.RCX, state.RDX, state.RSI, + state.RDI, state.RBP, state.RSP, state.R8, state.R9, state.R10, + state.R11, state.R12, state.R13, state.R14, state.R15); } else { - fprintf( - stderr, - "EIP=%" PRIx32 ",EAX=%" PRIx32 ",EBX=%" PRIx32 - ",ECX=%" PRIx32 ",EDX=%" PRIx32 ",ESI=%" PRIx32 - ",EDI=%" PRIx32 ",ESP=%" PRIx32 ",EBP=%" PRIx32 "\n", - state.EIP, state.EAX, state.EBX, state.ECX, state.EDX, state.ESI, - state.EDI, state.EBP, state.ESP); + fprintf(stderr, + "EIP=%" PRIx32 ",EAX=%" PRIx32 ",EBX=%" PRIx32 ",ECX=%" PRIx32 + ",EDX=%" PRIx32 ",ESI=%" PRIx32 ",EDI=%" PRIx32 ",ESP=%" PRIx32 + ",EBP=%" PRIx32 "\n", + state.EIP, state.EAX, state.EBX, state.ECX, state.EDX, state.ESI, + state.EDI, state.EBP, state.ESP); } return memory; } @@ -209,243 +194,229 @@ uint64_t __remill_read_memory_64(Memory *, addr_t addr) { } // Memory write intrinsics. -Memory *__remill_write_memory_8( - Memory * memory, addr_t addr, uint8_t val) { +Memory *__remill_write_memory_8(Memory *memory, addr_t addr, uint8_t val) { *reinterpret_cast(addr) = val; return memory; } -Memory *__remill_write_memory_16( - Memory * memory, addr_t addr, uint16_t val) { +Memory *__remill_write_memory_16(Memory *memory, addr_t addr, uint16_t val) { *reinterpret_cast(addr) = val; return memory; } -Memory *__remill_write_memory_32( - Memory * memory, addr_t addr, uint32_t val) { +Memory *__remill_write_memory_32(Memory *memory, addr_t addr, uint32_t val) { *reinterpret_cast(addr) = val; return memory; } -Memory *__remill_write_memory_64( - Memory * memory, addr_t addr, uint64_t val) { +Memory *__remill_write_memory_64(Memory *memory, addr_t addr, uint64_t val) { *reinterpret_cast(addr) = val; return memory; } -float32_t __remill_read_memory_f32( - Memory *, addr_t addr, float32_t val) { +float32_t __remill_read_memory_f32(Memory *, addr_t addr, float32_t val) { return *reinterpret_cast(addr); } -float64_t __remill_read_memory_f64( - Memory *, addr_t addr, float64_t val) { +float64_t __remill_read_memory_f64(Memory *, addr_t addr, float64_t val) { return *reinterpret_cast(addr); - } float64_t __remill_read_memory_f80(Memory *, addr_t addr) { return static_cast(*reinterpret_cast(addr)); } -Memory *__remill_write_memory_f32( - Memory * memory, addr_t addr, float32_t val) { +Memory *__remill_write_memory_f32(Memory *memory, addr_t addr, float32_t val) { *reinterpret_cast(addr) = val; return memory; } -Memory *__remill_write_memory_f64( - Memory * memory, addr_t addr, float64_t val) { +Memory *__remill_write_memory_f64(Memory *memory, addr_t addr, float64_t val) { *reinterpret_cast(addr) = val; return memory; } -Memory *__remill_write_memory_f80( - Memory * memory, addr_t addr, float64_t val) { +Memory *__remill_write_memory_f80(Memory *memory, addr_t addr, float64_t val) { *reinterpret_cast(addr) = static_cast(val); return memory; } // Memory barriers types, see: http://g.oswego.edu/dl/jmm/cookbook.html -Memory *__remill_barrier_load_load(Memory * memory) { +Memory *__remill_barrier_load_load(Memory *memory) { return memory; } -Memory *__remill_barrier_load_store(Memory * memory) { +Memory *__remill_barrier_load_store(Memory *memory) { return memory; } -Memory *__remill_barrier_store_load(Memory * memory) { +Memory *__remill_barrier_store_load(Memory *memory) { return memory; } -Memory *__remill_barrier_store_store(Memory * memory) { +Memory *__remill_barrier_store_store(Memory *memory) { return memory; } // Atomic operations. The address/size are hints, but the granularity of the // access can be bigger. These have implicit StoreLoad semantics. -Memory *__remill_atomic_begin(Memory * memory) { +Memory *__remill_atomic_begin(Memory *memory) { return memory; } -Memory *__remill_atomic_end(Memory * memory) { +Memory *__remill_atomic_end(Memory *memory) { return memory; } -Memory *__remill_compare_exchange_memory_8( - Memory *memory, addr_t addr, uint8_t &expected, uint8_t desired) { - expected = __sync_val_compare_and_swap( - reinterpret_cast(addr), expected, desired); +Memory *__remill_compare_exchange_memory_8(Memory *memory, addr_t addr, + uint8_t &expected, uint8_t desired) { + expected = __sync_val_compare_and_swap(reinterpret_cast(addr), + expected, desired); return memory; } -Memory *__remill_compare_exchange_memory_16( - Memory *memory, addr_t addr, uint16_t &expected, uint16_t desired) { - expected = __sync_val_compare_and_swap( - reinterpret_cast(addr), expected, desired); +Memory *__remill_compare_exchange_memory_16(Memory *memory, addr_t addr, + uint16_t &expected, + uint16_t desired) { + expected = __sync_val_compare_and_swap(reinterpret_cast(addr), + expected, desired); return memory; } -Memory *__remill_compare_exchange_memory_32( - Memory *memory, addr_t addr, uint32_t &expected, uint32_t desired) { - expected = __sync_val_compare_and_swap( - reinterpret_cast(addr), expected, desired); +Memory *__remill_compare_exchange_memory_32(Memory *memory, addr_t addr, + uint32_t &expected, + uint32_t desired) { + expected = __sync_val_compare_and_swap(reinterpret_cast(addr), + expected, desired); return memory; } -Memory *__remill_compare_exchange_memory_64( - Memory *memory, addr_t addr, uint64_t &expected, uint64_t desired) { - expected = __sync_val_compare_and_swap( - reinterpret_cast(addr), expected, desired); +Memory *__remill_compare_exchange_memory_64(Memory *memory, addr_t addr, + uint64_t &expected, + uint64_t desired) { + expected = __sync_val_compare_and_swap(reinterpret_cast(addr), + expected, desired); return memory; } #ifdef _GXX_EXPERIMENTAL_CXX0X__ -Memory *__remill_compare_exchange_memory_128( - Memory *memory, addr_t addr, uint128_t &expected, uint128_t &desired) { - expected = __sync_val_compare_and_swap( - reinterpret_cast(addr), expected, desired); +Memory *__remill_compare_exchange_memory_128(Memory *memory, addr_t addr, + uint128_t &expected, + uint128_t &desired) { + expected = __sync_val_compare_and_swap(reinterpret_cast(addr), + expected, desired); return memory; } #endif -Memory *__remill_fetch_and_add_8( - Memory *memory, addr_t addr, uint8_t &value) { - value = __sync_fetch_and_add(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_add_8(Memory *memory, addr_t addr, uint8_t &value) { + value = __sync_fetch_and_add(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_add_16( - Memory *memory, addr_t addr, uint16_t &value) { - value = __sync_fetch_and_add(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_add_16(Memory *memory, addr_t addr, + uint16_t &value) { + value = __sync_fetch_and_add(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_add_32( - Memory *memory, addr_t addr, uint32_t &value) { +Memory *__remill_fetch_and_add_32(Memory *memory, addr_t addr, + uint32_t &value) { value = __sync_fetch_and_add(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_add_64( - Memory *memory, addr_t addr, uint64_t &value) { +Memory *__remill_fetch_and_add_64(Memory *memory, addr_t addr, + uint64_t &value) { value = __sync_fetch_and_add(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_sub_8( - Memory *memory, addr_t addr, uint8_t &value) { +Memory *__remill_fetch_and_sub_8(Memory *memory, addr_t addr, uint8_t &value) { value = __sync_fetch_and_sub(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_sub_16( - Memory *memory, addr_t addr, uint16_t &value) { - value = __sync_fetch_and_sub(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_sub_16(Memory *memory, addr_t addr, + uint16_t &value) { + value = __sync_fetch_and_sub(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_sub_32( - Memory *memory, addr_t addr, uint32_t &value) { +Memory *__remill_fetch_and_sub_32(Memory *memory, addr_t addr, + uint32_t &value) { value = __sync_fetch_and_sub(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_sub_64( - Memory *memory, addr_t addr, uint64_t &value) { +Memory *__remill_fetch_and_sub_64(Memory *memory, addr_t addr, + uint64_t &value) { value = __sync_fetch_and_sub(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_or_8( - Memory *memory, addr_t addr, uint8_t &value) { +Memory *__remill_fetch_and_or_8(Memory *memory, addr_t addr, uint8_t &value) { value = __sync_fetch_and_or(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_or_16( - Memory *memory, addr_t addr, uint16_t &value) { - value = __sync_fetch_and_or(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_or_16(Memory *memory, addr_t addr, uint16_t &value) { + value = __sync_fetch_and_or(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_or_32( - Memory *memory, addr_t addr, uint32_t &value) { +Memory *__remill_fetch_and_or_32(Memory *memory, addr_t addr, uint32_t &value) { value = __sync_fetch_and_or(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_or_64( - Memory *memory, addr_t addr, uint64_t &value) { +Memory *__remill_fetch_and_or_64(Memory *memory, addr_t addr, uint64_t &value) { value = __sync_fetch_and_or(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_and_8( - Memory *memory, addr_t addr, uint8_t &value) { +Memory *__remill_fetch_and_and_8(Memory *memory, addr_t addr, uint8_t &value) { value = __sync_fetch_and_and(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_and_16( - Memory *memory, addr_t addr, uint16_t &value) { - value = __sync_fetch_and_and(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_and_16(Memory *memory, addr_t addr, + uint16_t &value) { + value = __sync_fetch_and_and(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_and_32( - Memory *memory, addr_t addr, uint32_t &value) { +Memory *__remill_fetch_and_and_32(Memory *memory, addr_t addr, + uint32_t &value) { value = __sync_fetch_and_and(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_and_64( - Memory *memory, addr_t addr, uint64_t &value) { +Memory *__remill_fetch_and_and_64(Memory *memory, addr_t addr, + uint64_t &value) { value = __sync_fetch_and_and(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_xor_8( - Memory *memory, addr_t addr, uint8_t &value) { +Memory *__remill_fetch_and_xor_8(Memory *memory, addr_t addr, uint8_t &value) { value = __sync_fetch_and_xor(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_xor_16( - Memory *memory, addr_t addr, uint16_t &value) { - value = __sync_fetch_and_xor(reinterpret_cast(addr), value); +Memory *__remill_fetch_and_xor_16(Memory *memory, addr_t addr, + uint16_t &value) { + value = __sync_fetch_and_xor(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_xor_32( - Memory *memory, addr_t addr, uint32_t &value) { +Memory *__remill_fetch_and_xor_32(Memory *memory, addr_t addr, + uint32_t &value) { value = __sync_fetch_and_xor(reinterpret_cast(addr), value); return memory; } -Memory *__remill_fetch_and_xor_64( - Memory *memory, addr_t addr, uint64_t &value) { +Memory *__remill_fetch_and_xor_64(Memory *memory, addr_t addr, + uint64_t &value) { value = __sync_fetch_and_xor(reinterpret_cast(addr), value); return memory; } diff --git a/mcsema/Arch/X86/Runtime/print_ELF_32_linux.cpp b/mcsema/Arch/X86/Runtime/print_ELF_32_linux.cpp index 9643425d3..b65d567b7 100644 --- a/mcsema/Arch/X86/Runtime/print_ELF_32_linux.cpp +++ b/mcsema/Arch/X86/Runtime/print_ELF_32_linux.cpp @@ -15,24 +15,26 @@ * along with this program. If not, see . */ -#include #include +#include #define HAS_FEATURE_AVX 1 #define HAS_FEATURE_AVX512 0 #define ADDRESS_SIZE_BITS 32 -#include #include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat" static const size_t kStackSize = 1UL << 20UL; -static void PrintStoreFlags(FILE * out) { +static void PrintStoreFlags(FILE *out) { + // FPU control. - fprintf(out, " fnstcw WORD PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, x87.fxsave.cwd)); + fprintf(out, " fnstcw WORD PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, x87.fxsave.cwd)); fprintf(out, " pushfd\n"); fprintf(out, " mov edx, 0xcd5\n"); @@ -40,81 +42,102 @@ static void PrintStoreFlags(FILE * out) { fprintf(out, " and DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, CF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, CF)); fprintf(out, " shl edx, 0\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, PF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, PF)); fprintf(out, " shl edx, 2\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, AF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, AF)); fprintf(out, " shl edx, 4\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ZF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ZF)); fprintf(out, " shl edx, 6\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, SF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, SF)); fprintf(out, " shl edx, 7\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, DF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, DF)); fprintf(out, " shl edx, 10\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, OF)); + fprintf(out, " and dl, BYTE PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, OF)); fprintf(out, " shl edx, 11\n"); fprintf(out, " or DWORD PTR [esp], edx\n"); fprintf(out, " popfd\n"); } -static void PrintLoadFlags(FILE * out) { +static void PrintLoadFlags(FILE *out) { + // FPU control. fprintf(out, " push dx\n"); fprintf(out, " fldcw WORD PTR [esp]\n"); - fprintf(out, " pop WORD PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, x87.fxsave.cwd)); + fprintf(out, " pop WORD PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, x87.fxsave.cwd)); // Clear our the `ArithFlags` struct, which is 16 bytes. - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag)); - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag) + 4); - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag) + 8); - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag) + 12); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag)); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag) + 4); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag) + 8); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag) + 12); // Get the EFlags. fprintf(out, " pushfd\n"); fprintf(out, " pop edx\n"); - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], edx\n", __builtin_offsetof(State, rflag)); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], edx\n", + __builtin_offsetof(State, rflag)); // Marshal the EFlags into the ArithFlags struct. fprintf(out, " bt edx, 0\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, CF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, CF)); fprintf(out, " bt edx, 2\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, PF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, PF)); fprintf(out, " bt edx, 4\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, AF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, AF)); fprintf(out, " bt edx, 6\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, ZF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, ZF)); fprintf(out, " bt edx, 7\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, SF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, SF)); fprintf(out, " bt edx, 10\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, DF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, DF)); fprintf(out, " bt edx, 11\n"); - fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, OF)); + fprintf(out, " adc BYTE PTR [edi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, OF)); } int main(void) { @@ -159,8 +182,10 @@ int main(void) { fprintf(out, " .cfi_startproc\n"); // General-purpose registers. - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, EDI)); // Set up the `GS` segment register so that TLS works :-) fprintf(out, " mov esi, DWORD PTR gs:[0]\n"); @@ -173,32 +198,47 @@ int main(void) { // `EDI` points to the State structure // Rest of the GPRs. - fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov [edi + %" PRIuMAX "], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ebp\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov [edi + %" PRIuMAX "], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ebp\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); PrintLoadFlags(out); // Note: Clobbers EDX. // If `ESP` is null then we need to initialize it to our new stack. // // Note: `ESI` is the TLS base. - fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESP)); fprintf(out, " cmp edx, 0\n"); fprintf(out, " jnz .Lhave_stack\n"); fprintf(out, " lea eax, DWORD PTR [__mcsema_stack@TPOFF]\n"); - fprintf(out, " lea edx, DWORD PTR [esi + eax + %" PRIuMAX "]\n", (kStackSize - 16)); + fprintf(out, " lea edx, DWORD PTR [esi + eax + %" PRIuMAX "]\n", + (kStackSize - 16)); fprintf(out, ".Lhave_stack:\n"); // `ESI` is the TLS base @@ -212,7 +252,8 @@ int main(void) { // Get the program counter off of the stack. fprintf(out, " pop esi\n"); - fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], esi\n", __builtin_offsetof(State, EIP)); + fprintf(out, " mov DWORD PTR [edi + %" PRIuMAX "], esi\n", + __builtin_offsetof(State, EIP)); // Set up the arguments on the McSema stack: state, pc, memory. fprintf(out, " lea edx, [edx - 20]\n"); @@ -229,14 +270,16 @@ int main(void) { fprintf(out, " pop DWORD PTR [edx]\n", __builtin_offsetof(State, EIP)); // Swap onto the lifted stack. The native `ESP` is now where it should be. - fprintf(out, " mov [edi + %" PRIuMAX "], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov [edi + %" PRIuMAX "], esp\n", + __builtin_offsetof(State, ESP)); fprintf(out, " mov esp, edx\n"); // Ret to the target. fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end1:\n"); - fprintf(out, " .size __mcsema_attach_call,.Lfunc_end1-__mcsema_attach_call\n"); + fprintf(out, + " .size __mcsema_attach_call,.Lfunc_end1-__mcsema_attach_call\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -260,30 +303,47 @@ int main(void) { // We "undo" that, then swap back to the native stack. When we swap, we // save into `State::RSP` where we are in the lifted stack, so that the // next attach can continue on where we left off. - fprintf(out, " sub DWORD PTR [edi + %" PRIuMAX "], 4\n", __builtin_offsetof(State, ESP)); - fprintf(out, " xchg [edi + %" PRIuMAX "], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, " sub DWORD PTR [edi + %" PRIuMAX "], 4\n", + __builtin_offsetof(State, ESP)); + fprintf(out, " xchg [edi + %" PRIuMAX "], esp\n", + __builtin_offsetof(State, ESP)); PrintStoreFlags(out); // Clobbers RDX. // General purpose registers. - fprintf(out, " mov eax, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov ebx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ecx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov ebp, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov eax, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov ebx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ecx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov ebp, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movntdqa xmm0, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdqa xmm1, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdqa xmm2, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdqa xmm3, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdqa xmm4, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdqa xmm5, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdqa xmm6, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdqa xmm7, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM7)); - - fprintf(out, " mov edi, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EDI)); + fprintf(out, " movntdqa xmm0, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdqa xmm1, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdqa xmm2, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdqa xmm3, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdqa xmm4, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdqa xmm5, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdqa xmm6, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdqa xmm7, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM7)); + + fprintf(out, " mov edi, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EDI)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end3:\n"); @@ -331,7 +391,8 @@ int main(void) { // Stash the return address stored on the native stack, the replace it // with the re-attach function. - fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESP)); fprintf(out, " push DWORD PTR [esi]\n"); fprintf(out, " push __mcsema_attach_ret\n"); fprintf(out, " pop DWORD PTR [esi]\n"); @@ -348,29 +409,45 @@ int main(void) { PrintStoreFlags(out); // Clobbers EDX. // Swap off-stack, stash the lifted stack pointer. - fprintf(out, " mov [edi + %" PRIuMAX "], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov [edi + %" PRIuMAX "], esp\n", + __builtin_offsetof(State, ESP)); fprintf(out, " mov esp, esi\n"); // (Most) General purpose registers. - fprintf(out, " mov eax, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov ebx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ecx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov ebp, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov eax, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov ebx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ecx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov edx, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov esi, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov ebp, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movntdqa xmm0, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdqa xmm1, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdqa xmm2, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdqa xmm3, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdqa xmm4, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdqa xmm5, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdqa xmm6, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdqa xmm7, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdqa xmm0, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdqa xmm1, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdqa xmm2, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdqa xmm3, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdqa xmm4, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdqa xmm5, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdqa xmm6, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdqa xmm7, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM7)); // Swap out EDI. - fprintf(out, " mov edi, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov edi, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EDI)); // Code above put the native target address (stored in RDI on entry to // `__remill_function_call`) on the stack, just below the return address, @@ -379,7 +456,9 @@ int main(void) { fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end5:\n"); - fprintf(out, " .size __remill_function_call,.Lfunc_end5-__remill_function_call\n"); + fprintf( + out, + " .size __remill_function_call,.Lfunc_end5-__remill_function_call\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -393,33 +472,50 @@ int main(void) { // Copy RSI, then store the address of the reg state struct into RSI for // easier indexing later on. Also set up the `FS` segment register so that // TLS works :-) - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, EDI)); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", __builtin_offsetof(State, ESI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, EDI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", + __builtin_offsetof(State, ESI)); fprintf(out, " mov edi, DWORD PTR gs:[0]\n"); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, FS_BASE)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, FS_BASE)); fprintf(out, " lea esi, [__mcsema_reg_state@TPOFF]\n"); fprintf(out, " lea edi, DWORD PTR [esi + edi]\n"); // General purpose registers. - fprintf(out, " mov [edi + %" PRIuMAX "], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ebp\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov [edi + %" PRIuMAX "], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ebp\n", + __builtin_offsetof(State, EBP)); // Swap into the mcsema stack. - fprintf(out, " xchg esp, [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " xchg esp, [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESP)); // XMM registers. - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); PrintLoadFlags(out); // Note: Clobbers EDX. @@ -431,7 +527,8 @@ int main(void) { // 16 stashed ebx // Restore emulated return address. - fprintf(out, " pop DWORD PTR [edi + %" PRIuMAX "]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " pop DWORD PTR [edi + %" PRIuMAX "]\n", + __builtin_offsetof(State, EIP)); // Callee-saved registers. @@ -459,44 +556,64 @@ int main(void) { fprintf(out, ".Lfunc_begin10:\n"); fprintf(out, ".cfi_startproc\n"); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, EDI)); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", __builtin_offsetof(State, ESI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, EDI)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", + __builtin_offsetof(State, ESI)); // Follow the cdecl ABI calling convention // Make `EDI` point to the stack pointer. fprintf(out, " mov edi, DWORD PTR [esp + 24]\n"); + // Make `ESI` point to the frame pointer. fprintf(out, " mov esi, DWORD PTR [esp + 28]\n"); + // Sets the native stack and base pointers - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, ESP)); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, ESP)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], esi\n", + __builtin_offsetof(State, EBP)); fprintf(out, " mov edi, DWORD PTR gs:[0]\n"); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", __builtin_offsetof(State, FS_BASE)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], edi\n", + __builtin_offsetof(State, FS_BASE)); fprintf(out, " lea esi, [__mcsema_reg_state@TPOFF]\n"); fprintf(out, " lea edi, DWORD PTR [esi + edi]\n"); // General purpose registers. //fprintf(out, " mov [edi + %" PRIuMAX "], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", __builtin_offsetof(State, EDX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [edi + %" PRIuMAX "], ecx\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov [edi + %" PRIuMAX "], edx\n", + __builtin_offsetof(State, EDX)); // XMM registers. - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [edi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); fprintf(out, " ret\n"); fprintf(out, " ud2\n"); fprintf(out, ".Lfunc_end10:\n"); - fprintf(out, " .size __mcsema_exception_ret,.Lfunc_end10-__mcsema_exception_ret\n"); + fprintf( + out, + " .size __mcsema_exception_ret,.Lfunc_end10-__mcsema_exception_ret\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -505,10 +622,13 @@ int main(void) { fprintf(out, " .type __mcsema_get_stack_pointer,@function\n"); fprintf(out, "__mcsema_get_stack_pointer:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov eax, gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov eax, gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, ESP)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end20:\n"); - fprintf(out, " .size __mcsema_get_stack_pointer,.Lfunc_end20-__mcsema_get_stack_pointer\n"); + fprintf( + out, + " .size __mcsema_get_stack_pointer,.Lfunc_end20-__mcsema_get_stack_pointer\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -517,10 +637,13 @@ int main(void) { fprintf(out, " .type __mcsema_get_frame_pointer,@function\n"); fprintf(out, "__mcsema_get_frame_pointer:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov eax, gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov eax, gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, EBP)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end21:\n"); - fprintf(out, " .size __mcsema_get_frame_pointer,.Lfunc_end21-__mcsema_get_frame_pointer\n"); + fprintf( + out, + " .size __mcsema_get_frame_pointer,.Lfunc_end21-__mcsema_get_frame_pointer\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -529,11 +652,14 @@ int main(void) { fprintf(out, " .type __mcsema_get_type_index,@function\n"); fprintf(out, "__mcsema_get_type_index:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], eax\n", __builtin_offsetof(State, EAX)); + fprintf(out, " mov gs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], eax\n", + __builtin_offsetof(State, EAX)); fprintf(out, " mov eax, edx\n"); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end22:\n"); - fprintf(out, " .size __mcsema_get_type_index,.Lfunc_end22-__mcsema_get_type_index\n"); + fprintf( + out, + " .size __mcsema_get_type_index,.Lfunc_end22-__mcsema_get_type_index\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -548,7 +674,9 @@ int main(void) { fprintf(out, " lea eax, [eax + edx]\n"); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end6:\n"); - fprintf(out, " .size __mcsema_debug_get_reg_state,.Lfunc_end6-__mcsema_debug_get_reg_state\n"); + fprintf( + out, + " .size __mcsema_debug_get_reg_state,.Lfunc_end6-__mcsema_debug_get_reg_state\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -579,4 +707,3 @@ int main(void) { // // Restore stack alignment // fprintf(out, " pop esp\n"); - diff --git a/mcsema/Arch/X86/Runtime/print_ELF_64_linux.cpp b/mcsema/Arch/X86/Runtime/print_ELF_64_linux.cpp index ac8af3228..2f5a53bc8 100644 --- a/mcsema/Arch/X86/Runtime/print_ELF_64_linux.cpp +++ b/mcsema/Arch/X86/Runtime/print_ELF_64_linux.cpp @@ -15,24 +15,26 @@ * along with this program. If not, see . */ -#include #include +#include #define HAS_FEATURE_AVX 1 #define HAS_FEATURE_AVX512 0 #define ADDRESS_SIZE_BITS 64 -#include #include +#include #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat" static const size_t kStackSize = 1UL << 20UL; -static void PrintStoreFlags(FILE * out) { +static void PrintStoreFlags(FILE *out) { + // FPU control. - fprintf(out, " fnstcw WORD PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, x87.fxsave.cwd)); + fprintf(out, " fnstcw WORD PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, x87.fxsave.cwd)); fprintf(out, " pushfq\n"); fprintf(out, " mov edx, 0xcd5\n"); @@ -40,79 +42,98 @@ static void PrintStoreFlags(FILE * out) { fprintf(out, " and QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, CF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, CF)); fprintf(out, " shl edx, 0\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, PF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, PF)); fprintf(out, " shl edx, 2\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, AF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, AF)); fprintf(out, " shl edx, 4\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, ZF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, ZF)); fprintf(out, " shl edx, 6\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, SF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, SF)); fprintf(out, " shl edx, 7\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, DF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, DF)); fprintf(out, " shl edx, 10\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " mov edx, 1\n"); - fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, OF)); + fprintf(out, " and dl, BYTE PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, OF)); fprintf(out, " shl edx, 11\n"); fprintf(out, " or QWORD PTR [rsp], rdx\n"); fprintf(out, " popfq\n"); } -static void PrintLoadFlags(FILE * out) { +static void PrintLoadFlags(FILE *out) { + // FPU control. fprintf(out, " push dx\n"); fprintf(out, " fldcw WORD PTR [rsp]\n"); - fprintf(out, " pop WORD PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, x87.fxsave.cwd)); + fprintf(out, " pop WORD PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, x87.fxsave.cwd)); // Get the RFlags. fprintf(out, " pushfq\n"); fprintf(out, " pop rdx\n"); - fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", __builtin_offsetof(State, rflag)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", + __builtin_offsetof(State, rflag)); // Clear our the `ArithFlags` struct, which is 16 bytes. - fprintf(out, " mov QWORD PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag)); - fprintf(out, " mov QWORD PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, aflag) + 8); + fprintf(out, " mov QWORD PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag)); + fprintf(out, " mov QWORD PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, aflag) + 8); // Marshal the RFlags into the ArithFlags struct. fprintf(out, " bt rdx, 0\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, CF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, CF)); fprintf(out, " bt rdx, 2\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, PF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, PF)); fprintf(out, " bt rdx, 4\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, AF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, AF)); fprintf(out, " bt rdx, 6\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, ZF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, ZF)); fprintf(out, " bt rdx, 7\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, SF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, SF)); fprintf(out, " bt rdx, 10\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, DF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, DF)); fprintf(out, " bt rdx, 11\n"); - fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", __builtin_offsetof(State, OF)); + fprintf(out, " adc BYTE PTR [rdi + %" PRIuMAX "], 0\n", + __builtin_offsetof(State, OF)); } int main(void) { @@ -157,9 +178,12 @@ int main(void) { fprintf(out, " .cfi_startproc\n"); // Save off the first three args of the ABI. - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", __builtin_offsetof(State, RSI)); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", __builtin_offsetof(State, RDI)); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdx\n", __builtin_offsetof(State, RDX)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", + __builtin_offsetof(State, RSI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", + __builtin_offsetof(State, RDI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdx\n", + __builtin_offsetof(State, RDX)); // On the stack: // 0 EA of the lifted function (from the CFG). @@ -168,56 +192,88 @@ int main(void) { // Set up the `FS` segment register so that TLS works :-) fprintf(out, " mov rsi, QWORD PTR fs:[0]\n"); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", __builtin_offsetof(State, FS_BASE)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", + __builtin_offsetof(State, FS_BASE)); // Get arg (rdi) to contain the State pointer. fprintf(out, " lea rdi, QWORD PTR [__mcsema_reg_state@TPOFF]\n"); fprintf(out, " lea rdi, QWORD PTR [rsi + rdi]\n"); // Get the program counter off of the stack. - fprintf(out, " pop QWORD PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RIP)); + fprintf(out, " pop QWORD PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RIP)); // Remaining general purpose registers. - fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RAX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", __builtin_offsetof(State, RBX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", __builtin_offsetof(State, RCX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rbp\n", __builtin_offsetof(State, RBP)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", __builtin_offsetof(State, R8)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", __builtin_offsetof(State, R9)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", __builtin_offsetof(State, R10)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", __builtin_offsetof(State, R11)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", __builtin_offsetof(State, R12)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", __builtin_offsetof(State, R13)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", __builtin_offsetof(State, R14)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", __builtin_offsetof(State, R15)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", + __builtin_offsetof(State, RAX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", + __builtin_offsetof(State, RBX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", + __builtin_offsetof(State, RCX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rbp\n", + __builtin_offsetof(State, RBP)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", + __builtin_offsetof(State, R8)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", + __builtin_offsetof(State, R9)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", + __builtin_offsetof(State, R10)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", + __builtin_offsetof(State, R11)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", + __builtin_offsetof(State, R12)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", + __builtin_offsetof(State, R13)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", + __builtin_offsetof(State, R14)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", + __builtin_offsetof(State, R15)); PrintLoadFlags(out); // Note: Clobbers RDX. // XMM registers. - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", __builtin_offsetof(State, XMM8)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", __builtin_offsetof(State, XMM9)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", __builtin_offsetof(State, XMM10)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", __builtin_offsetof(State, XMM11)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", __builtin_offsetof(State, XMM12)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", __builtin_offsetof(State, XMM13)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", __builtin_offsetof(State, XMM14)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", __builtin_offsetof(State, XMM15)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", + __builtin_offsetof(State, XMM8)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", + __builtin_offsetof(State, XMM9)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", + __builtin_offsetof(State, XMM10)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", + __builtin_offsetof(State, XMM11)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", + __builtin_offsetof(State, XMM12)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", + __builtin_offsetof(State, XMM13)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", + __builtin_offsetof(State, XMM14)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", + __builtin_offsetof(State, XMM15)); // If `RSP` is null then we need to initialize it to our new stack. - fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RSP)); + fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSP)); fprintf(out, " cmp rdx, 0\n"); fprintf(out, " jnz .Lhave_stack\n"); fprintf(out, " lea r8, QWORD PTR [__mcsema_stack@TPOFF]\n"); fprintf(out, " mov rsi, fs:[0];\n"); - fprintf(out, " lea rdx, QWORD PTR [rsi + r8 + %" PRIuMAX "]\n", (kStackSize - 16)); + fprintf(out, " lea rdx, QWORD PTR [rsi + r8 + %" PRIuMAX "]\n", + (kStackSize - 16)); fprintf(out, ".Lhave_stack:\n"); // Set up a return address so that when the lifted function returns, it will @@ -230,11 +286,13 @@ int main(void) { fprintf(out, " pop QWORD PTR [rdx - 16]\n"); // Swap onto the lifted stack. The native `RSP` is now where it should be. - fprintf(out, " mov [rdi + %" PRIuMAX "], rsp\n", __builtin_offsetof(State, RSP)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rsp\n", + __builtin_offsetof(State, RSP)); fprintf(out, " lea rsp, [rdx - 16]\n"); // Set up arg2 as the program counter. - fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RIP)); + fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RIP)); // Set up arg3 as the memory pointer, which is (for now?) a nullptr. fprintf(out, " xor rdx, rdx\n"); @@ -249,7 +307,8 @@ int main(void) { fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end1:\n"); - fprintf(out, " .size __mcsema_attach_call,.Lfunc_end1-__mcsema_attach_call\n"); + fprintf(out, + " .size __mcsema_attach_call,.Lfunc_end1-__mcsema_attach_call\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -270,46 +329,79 @@ int main(void) { // We "undo" that, then swap back to the native stack. When we swap, we // save into `State::RSP` where we are in the lifted stack, so that the // next attach can continue on where we left off. - fprintf(out, " sub QWORD PTR [rdi + %" PRIuMAX "], 8\n", __builtin_offsetof(State, RSP)); - fprintf(out, " xchg [rdi + %" PRIuMAX "], rsp\n", __builtin_offsetof(State, RSP)); + fprintf(out, " sub QWORD PTR [rdi + %" PRIuMAX "], 8\n", + __builtin_offsetof(State, RSP)); + fprintf(out, " xchg [rdi + %" PRIuMAX "], rsp\n", + __builtin_offsetof(State, RSP)); PrintStoreFlags(out); // Clobbers RDX. // General purpose registers. - fprintf(out, " mov rax, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RAX)); - fprintf(out, " mov rbx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RBX)); - fprintf(out, " mov rcx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RCX)); - fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RDX)); - fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RSI)); - fprintf(out, " mov rbp, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RBP)); - fprintf(out, " mov r8, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R8)); - fprintf(out, " mov r9, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R9)); - fprintf(out, " mov r10, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R10)); - fprintf(out, " mov r11, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R11)); - fprintf(out, " mov r12, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R12)); - fprintf(out, " mov r13, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R13)); - fprintf(out, " mov r14, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R14)); - fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R15)); + fprintf(out, " mov rax, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RAX)); + fprintf(out, " mov rbx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RBX)); + fprintf(out, " mov rcx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RCX)); + fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RDX)); + fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSI)); + fprintf(out, " mov rbp, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RBP)); + fprintf(out, " mov r8, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R8)); + fprintf(out, " mov r9, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R9)); + fprintf(out, " mov r10, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R10)); + fprintf(out, " mov r11, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R11)); + fprintf(out, " mov r12, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R12)); + fprintf(out, " mov r13, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R13)); + fprintf(out, " mov r14, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R14)); + fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R15)); // XMM registers. - fprintf(out, " movntdqa xmm0, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdqa xmm1, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdqa xmm2, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdqa xmm3, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdqa xmm4, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdqa xmm5, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdqa xmm6, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdqa xmm7, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM7)); - fprintf(out, " movntdqa xmm8, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM8)); - fprintf(out, " movntdqa xmm9, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM9)); - fprintf(out, " movntdqa xmm10, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM10)); - fprintf(out, " movntdqa xmm11, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM11)); - fprintf(out, " movntdqa xmm12, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM12)); - fprintf(out, " movntdqa xmm13, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM13)); - fprintf(out, " movntdqa xmm14, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM14)); - fprintf(out, " movntdqa xmm15, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM15)); - - fprintf(out, " mov rdi, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RDI)); + fprintf(out, " movntdqa xmm0, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdqa xmm1, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdqa xmm2, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdqa xmm3, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdqa xmm4, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdqa xmm5, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdqa xmm6, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdqa xmm7, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdqa xmm8, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM8)); + fprintf(out, " movntdqa xmm9, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM9)); + fprintf(out, " movntdqa xmm10, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM10)); + fprintf(out, " movntdqa xmm11, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM11)); + fprintf(out, " movntdqa xmm12, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM12)); + fprintf(out, " movntdqa xmm13, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM13)); + fprintf(out, " movntdqa xmm14, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM14)); + fprintf(out, " movntdqa xmm15, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM15)); + + fprintf(out, " mov rdi, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RDI)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end3:\n"); @@ -345,17 +437,18 @@ int main(void) { fprintf(out, " push r14\n"); fprintf(out, " push r15\n"); -// fprintf(out, " push rcx\n"); -// fprintf(out, " push rdx\n"); -// fprintf(out, " push r8\n"); -// fprintf(out, " push r9\n"); -// fprintf(out, " push r10\n"); -// fprintf(out, " push r11\n"); + // fprintf(out, " push rcx\n"); + // fprintf(out, " push rdx\n"); + // fprintf(out, " push r8\n"); + // fprintf(out, " push r9\n"); + // fprintf(out, " push r10\n"); + // fprintf(out, " push r11\n"); // Stash the return address stored on the native stack, the replace it // with the re-attach function. - fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RSP)); + fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSP)); fprintf(out, " push QWORD PTR [r15]\n"); fprintf(out, " lea r14, [rip + __mcsema_attach_ret]\n"); fprintf(out, " mov QWORD PTR [r15], r14\n"); @@ -369,47 +462,79 @@ int main(void) { fprintf(out, " mov QWORD PTR [r15], rsi\n"); // Swap off-stack, stash the lifted stack pointer. - fprintf(out, " mov [rdi + %" PRIuMAX "], rsp\n", __builtin_offsetof(State, RSP)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rsp\n", + __builtin_offsetof(State, RSP)); fprintf(out, " mov rsp, r15\n"); PrintStoreFlags(out); // Clobbers RDX. // (Most) General purpose registers. - fprintf(out, " mov rax, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RAX)); - fprintf(out, " mov rbx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RBX)); - fprintf(out, " mov rcx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RCX)); - fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RDX)); - fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RSI)); - fprintf(out, " mov rbp, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RBP)); - fprintf(out, " mov r8, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R8)); - fprintf(out, " mov r9, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R9)); - fprintf(out, " mov r10, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R10)); - fprintf(out, " mov r11, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R11)); - fprintf(out, " mov r12, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R12)); - fprintf(out, " mov r13, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R13)); - fprintf(out, " mov r14, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R14)); - fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, R15)); + fprintf(out, " mov rax, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RAX)); + fprintf(out, " mov rbx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RBX)); + fprintf(out, " mov rcx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RCX)); + fprintf(out, " mov rdx, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RDX)); + fprintf(out, " mov rsi, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSI)); + fprintf(out, " mov rbp, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RBP)); + fprintf(out, " mov r8, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R8)); + fprintf(out, " mov r9, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R9)); + fprintf(out, " mov r10, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R10)); + fprintf(out, " mov r11, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R11)); + fprintf(out, " mov r12, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R12)); + fprintf(out, " mov r13, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R13)); + fprintf(out, " mov r14, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R14)); + fprintf(out, " mov r15, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, R15)); // XMM registers. - fprintf(out, " movntdqa xmm0, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdqa xmm1, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdqa xmm2, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdqa xmm3, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdqa xmm4, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdqa xmm5, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdqa xmm6, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdqa xmm7, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM7)); - fprintf(out, " movntdqa xmm8, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM8)); - fprintf(out, " movntdqa xmm9, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM9)); - fprintf(out, " movntdqa xmm10, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM10)); - fprintf(out, " movntdqa xmm11, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM11)); - fprintf(out, " movntdqa xmm12, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM12)); - fprintf(out, " movntdqa xmm13, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM13)); - fprintf(out, " movntdqa xmm14, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM14)); - fprintf(out, " movntdqa xmm15, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, XMM15)); + fprintf(out, " movntdqa xmm0, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdqa xmm1, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdqa xmm2, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdqa xmm3, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdqa xmm4, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdqa xmm5, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdqa xmm6, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdqa xmm7, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdqa xmm8, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM8)); + fprintf(out, " movntdqa xmm9, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM9)); + fprintf(out, " movntdqa xmm10, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM10)); + fprintf(out, " movntdqa xmm11, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM11)); + fprintf(out, " movntdqa xmm12, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM12)); + fprintf(out, " movntdqa xmm13, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM13)); + fprintf(out, " movntdqa xmm14, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM14)); + fprintf(out, " movntdqa xmm15, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, XMM15)); // Swap out RDI. - fprintf(out, " mov rdi, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RDI)); + fprintf(out, " mov rdi, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RDI)); // Code above put the native target address (stored in RDI on entry to // `__remill_function_call`) on the stack, just below the return address, @@ -419,7 +544,9 @@ int main(void) { fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end5:\n"); - fprintf(out, " .size __remill_function_call,.Lfunc_end5-__remill_function_call\n"); + fprintf( + out, + " .size __remill_function_call,.Lfunc_end5-__remill_function_call\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -433,49 +560,82 @@ int main(void) { // Copy RSI, then store the address of the reg state struct into RSI for // easier indexing later on. Also set up the `FS` segment register so that // TLS works :-) - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", __builtin_offsetof(State, RDI)); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", __builtin_offsetof(State, RSI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", + __builtin_offsetof(State, RDI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", + __builtin_offsetof(State, RSI)); fprintf(out, " mov rdi, QWORD PTR fs:[0]\n"); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", __builtin_offsetof(State, FS_BASE)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", + __builtin_offsetof(State, FS_BASE)); fprintf(out, " lea rsi, [__mcsema_reg_state@TPOFF]\n"); fprintf(out, " lea rdi, QWORD PTR [rsi + rdi]\n"); // General purpose registers. - fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RAX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", __builtin_offsetof(State, RBX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", __builtin_offsetof(State, RCX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", __builtin_offsetof(State, RDX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rbp\n", __builtin_offsetof(State, RBP)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", __builtin_offsetof(State, R8)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", __builtin_offsetof(State, R9)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", __builtin_offsetof(State, R10)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", __builtin_offsetof(State, R11)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", __builtin_offsetof(State, R12)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", __builtin_offsetof(State, R13)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", __builtin_offsetof(State, R14)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", __builtin_offsetof(State, R15)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", + __builtin_offsetof(State, RAX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", + __builtin_offsetof(State, RBX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", + __builtin_offsetof(State, RCX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", + __builtin_offsetof(State, RDX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rbp\n", + __builtin_offsetof(State, RBP)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", + __builtin_offsetof(State, R8)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", + __builtin_offsetof(State, R9)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", + __builtin_offsetof(State, R10)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", + __builtin_offsetof(State, R11)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", + __builtin_offsetof(State, R12)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", + __builtin_offsetof(State, R13)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", + __builtin_offsetof(State, R14)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", + __builtin_offsetof(State, R15)); // Swap into the mcsema stack. - fprintf(out, " xchg rsp, [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RSP)); + fprintf(out, " xchg rsp, [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSP)); // XMM registers. - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", __builtin_offsetof(State, XMM8)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", __builtin_offsetof(State, XMM9)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", __builtin_offsetof(State, XMM10)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", __builtin_offsetof(State, XMM11)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", __builtin_offsetof(State, XMM12)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", __builtin_offsetof(State, XMM13)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", __builtin_offsetof(State, XMM14)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", __builtin_offsetof(State, XMM15)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", + __builtin_offsetof(State, XMM8)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", + __builtin_offsetof(State, XMM9)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", + __builtin_offsetof(State, XMM10)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", + __builtin_offsetof(State, XMM11)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", + __builtin_offsetof(State, XMM12)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", + __builtin_offsetof(State, XMM13)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", + __builtin_offsetof(State, XMM14)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", + __builtin_offsetof(State, XMM15)); PrintLoadFlags(out); // Note: Clobbers RDX. @@ -489,15 +649,16 @@ int main(void) { // 48 stashed rbx // Restore emulated return address. - fprintf(out, " pop QWORD PTR [rdi + %" PRIuMAX "]\n", __builtin_offsetof(State, RIP)); + fprintf(out, " pop QWORD PTR [rdi + %" PRIuMAX "]\n", + __builtin_offsetof(State, RIP)); -// -// fprintf(out, " pop r11\n"); -// fprintf(out, " pop r10\n"); -// fprintf(out, " pop r9\n"); -// fprintf(out, " pop r8\n"); -// fprintf(out, " pop rdx\n"); -// fprintf(out, " pop rcx\n"); + // + // fprintf(out, " pop r11\n"); + // fprintf(out, " pop r10\n"); + // fprintf(out, " pop r9\n"); + // fprintf(out, " pop r8\n"); + // fprintf(out, " pop rdx\n"); + // fprintf(out, " pop rcx\n"); // Callee-saved registers. @@ -530,59 +691,96 @@ int main(void) { fprintf(out, ".Lfunc_begin10:\n"); fprintf(out, ".cfi_startproc\n"); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", __builtin_offsetof(State, RDI)); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", __builtin_offsetof(State, RSI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", + __builtin_offsetof(State, RDI)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rsi\n", + __builtin_offsetof(State, RSI)); fprintf(out, " mov rdi, QWORD PTR fs:[0]\n"); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", __builtin_offsetof(State, FS_BASE)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rdi\n", + __builtin_offsetof(State, FS_BASE)); fprintf(out, " lea rsi, [__mcsema_reg_state@TPOFF]\n"); fprintf(out, " lea rdi, QWORD PTR [rsi + rdi]\n"); // General purpose registers. //fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RAX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", __builtin_offsetof(State, RBX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", __builtin_offsetof(State, RCX)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", __builtin_offsetof(State, RDX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rbx\n", + __builtin_offsetof(State, RBX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rcx\n", + __builtin_offsetof(State, RCX)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rdx\n", + __builtin_offsetof(State, RDX)); // Sets the native stack and base pointers - fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, RDI)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RSP)); - fprintf(out, " add QWORD PTR [rdi + %" PRIuMAX "], 8\n", __builtin_offsetof(State, RSP)); - fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, RSI)); - fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RBP)); - - - fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", __builtin_offsetof(State, R8)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", __builtin_offsetof(State, R9)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", __builtin_offsetof(State, R10)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", __builtin_offsetof(State, R11)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", __builtin_offsetof(State, R12)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", __builtin_offsetof(State, R13)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", __builtin_offsetof(State, R14)); - fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", __builtin_offsetof(State, R15)); + fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, RDI)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", + __builtin_offsetof(State, RSP)); + fprintf(out, " add QWORD PTR [rdi + %" PRIuMAX "], 8\n", + __builtin_offsetof(State, RSP)); + fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSI)); + fprintf(out, " mov [rdi + %" PRIuMAX "], rax\n", + __builtin_offsetof(State, RBP)); + + + fprintf(out, " mov [rdi + %" PRIuMAX "], r8\n", + __builtin_offsetof(State, R8)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r9\n", + __builtin_offsetof(State, R9)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r10\n", + __builtin_offsetof(State, R10)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r11\n", + __builtin_offsetof(State, R11)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r12\n", + __builtin_offsetof(State, R12)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r13\n", + __builtin_offsetof(State, R13)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r14\n", + __builtin_offsetof(State, R14)); + fprintf(out, " mov [rdi + %" PRIuMAX "], r15\n", + __builtin_offsetof(State, R15)); // XMM registers. - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", __builtin_offsetof(State, XMM7)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", __builtin_offsetof(State, XMM8)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", __builtin_offsetof(State, XMM9)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", __builtin_offsetof(State, XMM10)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", __builtin_offsetof(State, XMM11)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", __builtin_offsetof(State, XMM12)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", __builtin_offsetof(State, XMM13)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", __builtin_offsetof(State, XMM14)); - fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", __builtin_offsetof(State, XMM15)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm7\n", + __builtin_offsetof(State, XMM7)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm8\n", + __builtin_offsetof(State, XMM8)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm9\n", + __builtin_offsetof(State, XMM9)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm10\n", + __builtin_offsetof(State, XMM10)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm11\n", + __builtin_offsetof(State, XMM11)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm12\n", + __builtin_offsetof(State, XMM12)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm13\n", + __builtin_offsetof(State, XMM13)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm14\n", + __builtin_offsetof(State, XMM14)); + fprintf(out, " movntdq [rdi + %" PRIuMAX "], xmm15\n", + __builtin_offsetof(State, XMM15)); fprintf(out, " ret\n"); fprintf(out, " ud2\n"); fprintf(out, ".Lfunc_end10:\n"); - fprintf(out, " .size __mcsema_exception_ret,.Lfunc_end10-__mcsema_exception_ret\n"); + fprintf( + out, + " .size __mcsema_exception_ret,.Lfunc_end10-__mcsema_exception_ret\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -591,10 +789,13 @@ int main(void) { fprintf(out, " .type __mcsema_get_stack_pointer,@function\n"); fprintf(out, "__mcsema_get_stack_pointer:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, RSP)); + fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, RSP)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end20:\n"); - fprintf(out, " .size __mcsema_get_stack_pointer,.Lfunc_end20-__mcsema_get_stack_pointer\n"); + fprintf( + out, + " .size __mcsema_get_stack_pointer,.Lfunc_end20-__mcsema_get_stack_pointer\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -603,10 +804,13 @@ int main(void) { fprintf(out, " .type __mcsema_get_frame_pointer,@function\n"); fprintf(out, "__mcsema_get_frame_pointer:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", __builtin_offsetof(State, RBP)); + fprintf(out, " mov rax, fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "]\n", + __builtin_offsetof(State, RBP)); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end21:\n"); - fprintf(out, " .size __mcsema_get_frame_pointer,.Lfunc_end21-__mcsema_get_frame_pointer\n"); + fprintf( + out, + " .size __mcsema_get_frame_pointer,.Lfunc_end21-__mcsema_get_frame_pointer\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -615,11 +819,14 @@ int main(void) { fprintf(out, " .type __mcsema_get_type_index,@function\n"); fprintf(out, "__mcsema_get_type_index:\n"); fprintf(out, " .cfi_startproc\n"); - fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rax\n", __builtin_offsetof(State, RAX)); + fprintf(out, " mov fs:[__mcsema_reg_state@TPOFF + %" PRIuMAX "], rax\n", + __builtin_offsetof(State, RAX)); fprintf(out, " mov rax, rdx\n"); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end22:\n"); - fprintf(out, " .size __mcsema_get_type_index,.Lfunc_end22-__mcsema_get_type_index\n"); + fprintf( + out, + " .size __mcsema_get_type_index,.Lfunc_end22-__mcsema_get_type_index\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -634,7 +841,9 @@ int main(void) { fprintf(out, " lea rax, [rax + rdx]\n"); fprintf(out, " ret\n"); fprintf(out, ".Lfunc_end6:\n"); - fprintf(out, " .size __mcsema_debug_get_reg_state,.Lfunc_end6-__mcsema_debug_get_reg_state\n"); + fprintf( + out, + " .size __mcsema_debug_get_reg_state,.Lfunc_end6-__mcsema_debug_get_reg_state\n"); fprintf(out, " .cfi_endproc\n"); fprintf(out, "\n"); @@ -665,5 +874,3 @@ int main(void) { // // Restore stack alignment // fprintf(out, " pop rsp\n"); - - diff --git a/mcsema/Arch/X86/Runtime/print_PE_32_windows.cpp b/mcsema/Arch/X86/Runtime/print_PE_32_windows.cpp index c40fc262e..a877953f8 100644 --- a/mcsema/Arch/X86/Runtime/print_PE_32_windows.cpp +++ b/mcsema/Arch/X86/Runtime/print_PE_32_windows.cpp @@ -21,8 +21,8 @@ #define HAS_FEATURE_AVX512 0 #define ADDRESS_SIZE_BITS 32 -#include "remill/Arch/X86/Runtime/State.h" #include "mcsema/Arch/X86/Runtime/Registers.h" +#include "remill/Arch/X86/Runtime/State.h" static const unsigned kStackSize = 1UL << 20U; static const unsigned kStackArgSize = 256U; @@ -56,7 +56,7 @@ int main(void) { fprintf(out, " .globl __mcsema_stack\n"); fprintf(out, "__mcsema_stack:\n"); fprintf(out, " .align 16\n"); - fprintf(out, " .zero %u\n", kStackSize); // MiB + fprintf(out, " .zero %u\n", kStackSize); // MiB fprintf(out, "\n"); // Thread-local stack structure, named by `__mcsema_stack_args` @@ -98,43 +98,64 @@ int main(void) { //*** assume we can clobber eax // save reg for use with TLS offsets - fprintf(out, " push dword ptr [esp]\n"); // dupliate last stack element (the jump-to EIP), so we can pop it - fprintf(out, " mov dword ptr [esp+4], ebp\n"); // save ebp, we will clobber it + fprintf( + out, + " push dword ptr [esp]\n"); // dupliate last stack element (the jump-to EIP), so we can pop it + fprintf(out, + " mov dword ptr [esp+4], ebp\n"); // save ebp, we will clobber it getTlsIndex(out, "ebp"); // Pop the target function into the `State` structure. This resets `ESP` // to what it should be on entry to `__mcsema_attach_call`. - fprintf(out, " pop DWORD PTR [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " pop DWORD PTR [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); // General purpose registers. - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ecx\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], esi\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edi\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ecx\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], esi\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edi\n", + __builtin_offsetof(State, EDI)); fprintf(out, " pop ebp\n"); getTlsIndex(out, "eax"); - fprintf(out, " mov [eax + __mcsema_reg_state@SECREL32 + %u], ebp\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov [eax + __mcsema_reg_state@SECREL32 + %u], ebp\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm7\n", __builtin_offsetof(State, XMM7)); - - fprintf(out, " xchg esp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm7\n", + __builtin_offsetof(State, XMM7)); + + fprintf(out, " xchg esp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); // If `ESP` is null then we need to initialize it to our new stack. fprintf(out, " cmp esp, 0\n"); fprintf(out, " jnz .Lhave_stack\n"); - // end inline getTlsIndex + + // end inline getTlsIndex fprintf(out, " lea esp, [eax + __mcsema_stack@SECREL32 + %u]\n", kStackSize); fprintf(out, ".Lhave_stack:\n"); @@ -159,7 +180,10 @@ int main(void) { fprintf(out, " xchg eax, [esp]\n"); // get EIP we need to jump to, in the process, clobber TLS index - fprintf(out, " mov eax, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, + " mov eax, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); + // and away we go! fprintf(out, " jmp eax\n"); @@ -186,30 +210,47 @@ int main(void) { // up as expected // // add an extra 4 bytes to compensate for the fake return address - fprintf(out, " add esp, %u\n", kStackArgSize+4); + fprintf(out, " add esp, %u\n", kStackArgSize + 4); + // Swap into the mcsema stack. fprintf(out, "push eax\n"); getTlsIndex(out, "eax"); - fprintf(out, " xchg esp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " xchg esp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); + // simulate a pop eax from old stack - fprintf(out, " add dword ptr [eax + __mcsema_reg_state@SECREL32 + %u], 4\n", __builtin_offsetof(State, ESP)); - fprintf(out, " mov eax, dword ptr [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); - fprintf(out, " mov eax, dword ptr [eax-4]\n"); // use -4 here since we just added 4 to the old esp to simulate a pop + fprintf(out, " add dword ptr [eax + __mcsema_reg_state@SECREL32 + %u], 4\n", + __builtin_offsetof(State, ESP)); + fprintf(out, + " mov eax, dword ptr [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); + fprintf( + out, + " mov eax, dword ptr [eax-4]\n"); // use -4 here since we just added 4 to the old esp to simulate a pop fprintf(out, " push ecx\n"); getTlsIndex(out, "ecx"); + // Return registers. - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " movdqu [ecx + __mcsema_reg_state@SECREL32 + %u], xmm0\n", __builtin_offsetof(State, XMM0)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " movdqu [ecx + __mcsema_reg_state@SECREL32 + %u], xmm0\n", + __builtin_offsetof(State, XMM0)); // Callee-saved registers. - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebp\n", __builtin_offsetof(State, EBP)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], esi\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edi\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebp\n", + __builtin_offsetof(State, EBP)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], esi\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edi\n", + __builtin_offsetof(State, EDI)); fprintf(out, " pop ecx\n"); + // Unstash the callee-saved registers. fprintf(out, " pop ebp\n"); fprintf(out, " pop ebx\n"); @@ -238,28 +279,43 @@ int main(void) { getTlsIndex(out, "ebp"); // General purpose registers. - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ecx\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], esi\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edi\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], ecx\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], esi\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov [ebp + __mcsema_reg_state@SECREL32 + %u], edi\n", + __builtin_offsetof(State, EDI)); fprintf(out, " pop ebp\n"); // TODO(artem): check if we need to save eax getTlsIndex(out, "eax"); - fprintf(out, " mov [eax + __mcsema_reg_state@SECREL32 + %u], ebp\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov [eax + __mcsema_reg_state@SECREL32 + %u], ebp\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm0\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm1\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm2\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm3\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm4\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm5\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm6\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm7\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm0\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm1\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm2\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm3\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm4\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm5\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm6\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movdqu [eax + __mcsema_reg_state@SECREL32 + %u], xmm7\n", + __builtin_offsetof(State, XMM7)); // if this function had no args, this will be zero, otherwise @@ -268,12 +324,15 @@ int main(void) { fprintf(out, " mov ecx, DWORD PTR [eax + __mcsema_stack_mark@SECREL32]\n"); // adjust for our copied stack args + fake return - fprintf(out, " add esp, %u\n", kStackArgSize+4); + fprintf(out, " add esp, %u\n", kStackArgSize + 4); fprintf(out, " add esp, ecx\n"); - fprintf(out, " xchg esp, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, + " xchg esp, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); fprintf(out, " pop DWORD PTR [eax + __mcsema_stack_mark@SECREL32]\n"); + // Unstash the callee-saved registers. fprintf(out, " pop ebp\n"); fprintf(out, " pop ebx\n"); @@ -300,39 +359,62 @@ int main(void) { fprintf(out, " .cfi_startproc\n"); // the stack has the State structure argument on it. - // we need to pop it off anyway due to caller cleanup, so + // we need to pop it off anyway due to caller cleanup, so // just re-use it as a place to stash `ebp`, which we pop later fprintf(out, " mov [esp], ebp\n"); getTlsIndex(out, "ebp"); // General purpose registers. - fprintf(out, " mov eax, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov ebx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ecx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov edx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov esi, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov edi, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov eax, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov ebx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ecx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov edx, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov esi, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov edi, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDI)); // XMM registers. - fprintf(out, " movdqu xmm0, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movdqu xmm1, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movdqu xmm2, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movdqu xmm3, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movdqu xmm4, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movdqu xmm5, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movdqu xmm6, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movdqu xmm7, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM7)); + fprintf(out, " movdqu xmm0, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movdqu xmm1, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movdqu xmm2, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movdqu xmm3, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movdqu xmm4, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movdqu xmm5, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movdqu xmm6, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movdqu xmm7, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM7)); fprintf(out, " pop ebp\n"); fprintf(out, " push eax\n"); getTlsIndex(out, "eax"); - fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBP)); - fprintf(out, " xchg esp, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBP)); + fprintf(out, + " xchg esp, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); + // simulate a pop eax from old stack - fprintf(out, " add dword ptr [eax + __mcsema_reg_state@SECREL32 + %u], 4\n", __builtin_offsetof(State, ESP)); - fprintf(out, " mov eax, dword ptr [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); - fprintf(out, " mov eax, dword ptr [eax-4]\n"); // use -4 here since we just added 4 to the old esp to simulate a pop + fprintf(out, " add dword ptr [eax + __mcsema_reg_state@SECREL32 + %u], 4\n", + __builtin_offsetof(State, ESP)); + fprintf(out, + " mov eax, dword ptr [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); + fprintf( + out, + " mov eax, dword ptr [eax-4]\n"); // use -4 here since we just added 4 to the old esp to simulate a pop // We assume the lifted code was generated by a sane complier and ended in a RET // which will write a return address into State::XIP and then pop off the stack, @@ -340,10 +422,12 @@ int main(void) { // We will jump to State::XIP since it should be the 'real' return address we have to get to fprintf(out, " push eax\n"); getTlsIndex(out, "eax"); - fprintf(out, " mov eax, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " mov eax, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); + // conveniently restores EAX to its saved value, and // uses the stack slot to set up an address we can return to - + fprintf(out, " xchg eax, [esp]\n"); // use the ret instruction to call [esp] and pop @@ -366,12 +450,15 @@ int main(void) { fprintf(out, " .cfi_startproc\n"); // *** This function assumes we can clobber eax and ecx - + // clobber eax to use as TLS index getTlsIndex(out, "eax"); + // Pop the target function into the `State` structure. This resets `EIP` // to what it should be on entry to `__mcsema_detach_call_cdecl`. - fprintf(out, " pop DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " pop DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); + // Marshal the callee-saved registers (of the emulated code) into the native // state. We don't touch the argument registers. @@ -383,33 +470,46 @@ int main(void) { // copy posible stack args into temporary holding area fprintf(out, " lea edi, [eax + __mcsema_stack_args@SECREL32]\n"); + // stack args start after ebp+ebx+esi+edi + return address - fprintf(out, " lea esi, [esp + %u]\n", 4 + 4+4+4+4); + fprintf(out, " lea esi, [esp + %u]\n", 4 + 4 + 4 + 4 + 4); + // ecx is how much to copy fprintf(out, " mov ecx, %u\n", kStackArgSize); + // do the copy fprintf(out, " rep movsb\n"); - fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDI)); - fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDI)); + fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBP)); // Swap onto the native stack. - fprintf(out, " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, + " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", + __builtin_offsetof(State, ESP)); // copy posible stack args from holding area to native stack // allocate space for our arguments on stack fprintf(out, " sub esp, %u\n", kStackArgSize); - // we need to save these + + // we need to save these fprintf(out, " push esi\n"); fprintf(out, " push edi\n"); fprintf(out, " push ecx\n"); + // get the stack arg location, adjust for the just-pushed values - fprintf(out, " lea edi, [esp + %u]\n", 4+4+4); + fprintf(out, " lea edi, [esp + %u]\n", 4 + 4 + 4); + // source is temp area fprintf(out, " lea esi, [eax + __mcsema_stack_args@SECREL32]\n"); fprintf(out, " mov ecx, %u\n", kStackArgSize); + // copy stack args from temp area to new stack fprintf(out, " rep movsb\n"); @@ -424,12 +524,14 @@ int main(void) { // as a 16-bit push fprintf(out, " push eax\n"); fprintf(out, " lea eax, __mcsema_attach_ret_cdecl\n"); + // switched saved eax (TLS index) with current eax (pointer to function) // the pointer to function will be the first argument to the mcsema-xlated // code we are about to jump to fprintf(out, " xchg eax, [esp]\n"); - fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); fprintf(out, ".Lfunc_end4:\n"); fprintf(out, " .cfi_endproc\n"); @@ -464,57 +566,83 @@ int main(void) { fprintf(out, " push ebp\n"); getTlsIndex(out, "eax"); + // save current stack mark fprintf(out, " push DWORD PTR [eax + __mcsema_stack_mark@SECREL32]\n"); // copy posible stack args into temporary holding area fprintf(out, " lea edi, [eax + __mcsema_stack_args@SECREL32]\n"); - // this is not ESP since for do_call_value there is no spilling via an + + // this is not ESP since for do_call_value there is no spilling via an // intermediate function - fprintf(out, " mov esi, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, + " mov esi, DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); fprintf(out, " mov ecx, %u\n", kStackArgSize); fprintf(out, " rep movsb\n"); // we wil use ebp to index once we clobber eax fprintf(out, " mov ebp, eax\n"); + // General purpose registers. // we still read out eax on principle, in case we need to do debugging // but we clobber it later anyway, so... ignore it - fprintf(out, " mov eax, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EAX)); + fprintf(out, " mov eax, [ebp + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EAX)); fprintf(out, " mov eax, ebp\n"); - fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ecx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ECX)); - fprintf(out, " mov edx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDX)); - fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDI)); - fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ecx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ECX)); + fprintf(out, " mov edx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDI)); + fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBP)); // XMM registers. - fprintf(out, " movdqu xmm0, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM0)); - fprintf(out, " movdqu xmm1, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM1)); - fprintf(out, " movdqu xmm2, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM2)); - fprintf(out, " movdqu xmm3, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM3)); - fprintf(out, " movdqu xmm4, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM4)); - fprintf(out, " movdqu xmm5, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM5)); - fprintf(out, " movdqu xmm6, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM6)); - fprintf(out, " movdqu xmm7, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, XMM7)); - - fprintf(out, " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, " movdqu xmm0, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM0)); + fprintf(out, " movdqu xmm1, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM1)); + fprintf(out, " movdqu xmm2, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM2)); + fprintf(out, " movdqu xmm3, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM3)); + fprintf(out, " movdqu xmm4, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM4)); + fprintf(out, " movdqu xmm5, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM5)); + fprintf(out, " movdqu xmm6, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM6)); + fprintf(out, " movdqu xmm7, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, XMM7)); + + fprintf(out, + " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", + __builtin_offsetof(State, ESP)); // copy posible stack args from holding area to native stack // allocate space for our arguments on stack fprintf(out, " sub esp, %u\n", kStackArgSize); - // we need to save these + + // we need to save these fprintf(out, " push esi\n"); fprintf(out, " push edi\n"); fprintf(out, " push ecx\n"); + // get the stack arg location // compensate for esi+edi+ecx - fprintf(out, " lea edi, [esp + %u]\n", 4+4+4); + fprintf(out, " lea edi, [esp + %u]\n", 4 + 4 + 4); + // source is temp area fprintf(out, " lea esi, [eax + __mcsema_stack_args@SECREL32]\n"); fprintf(out, " mov ecx, %u\n", kStackArgSize); + // copy fprintf(out, " rep movsb\n"); @@ -535,7 +663,8 @@ int main(void) { fprintf(out, " xchg eax, [esp]\n"); // Go native. - fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); fprintf(out, ".Lfunc_end5:\n"); fprintf(out, " .cfi_endproc\n"); @@ -570,7 +699,9 @@ int main(void) { // Pop the target function into the `State` structure. This resets `EIP` // to what it should be on entry to `__mcsema_detach_call_stdcall`. getTlsIndex(out, "eax"); - fprintf(out, " pop DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " pop DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); + // Marshal the callee-saved registers (of the emulated code) into the native // state. We don't touch the argument registers. @@ -590,8 +721,9 @@ int main(void) { // copy posible stack args into temporary holding area fprintf(out, " lea edi, [eax + __mcsema_stack_args@SECREL32]\n"); + // ra + stack_mark + (ecx + edx) + (edi+esi+ebx+ebp) - fprintf(out, " lea esi, [esp + %u]\n", 4 + 4 + 4+4 + 4+4+4+4); + fprintf(out, " lea esi, [esp + %u]\n", 4 + 4 + 4 + 4 + 4 + 4 + 4 + 4); fprintf(out, " mov ecx, %u\n", kStackArgSize); fprintf(out, " rep movsb\n"); @@ -599,26 +731,36 @@ int main(void) { fprintf(out, " pop edx\n"); fprintf(out, " pop ecx\n"); - fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EDI)); - fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EBP)); + fprintf(out, " mov edi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EDI)); + fprintf(out, " mov esi, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov ebx, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov ebp, [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EBP)); // Swap onto the native stack. - fprintf(out, " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", __builtin_offsetof(State, ESP)); + fprintf(out, + " xchg DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u], esp\n", + __builtin_offsetof(State, ESP)); // copy posible stack args from holding area to native stack // allocate space for our arguments on stack fprintf(out, " sub esp, %u\n", kStackArgSize); - // we need to save these + + // we need to save these fprintf(out, " push esi\n"); fprintf(out, " push edi\n"); fprintf(out, " push ecx\n"); + // get the stack arg location - fprintf(out, " lea edi, [esp + %u]\n", 4+4+4); + fprintf(out, " lea edi, [esp + %u]\n", 4 + 4 + 4); + // source is temp area fprintf(out, " lea esi, [eax + __mcsema_stack_args@SECREL32]\n"); fprintf(out, " mov ecx, %u\n", kStackArgSize); + // copy fprintf(out, " rep movsb\n"); @@ -639,7 +781,8 @@ int main(void) { fprintf(out, " lea eax, __mcsema_attach_ret_stdcall\n"); fprintf(out, " xchg eax, [esp]\n"); - fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, EIP)); + fprintf(out, " jmp DWORD PTR [eax + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, EIP)); fprintf(out, ".Lfunc_endA:\n"); fprintf(out, " .cfi_endproc\n"); @@ -670,30 +813,43 @@ int main(void) { // assume we can clobber ecx getTlsIndex(out, "ecx"); - + // if this function had no args, this will be zero, otherwise // it will be -argcount*4 (esp is now > old esp, due to pops) fprintf(out, " sub DWORD PTR [ecx + __mcsema_stack_mark@SECREL32], esp\n"); + // adjust for our copied stack args + fake return - fprintf(out, " add esp, %u\n", kStackArgSize+4); + fprintf(out, " add esp, %u\n", kStackArgSize + 4); + //fprintf(out, " add esp, DWORD PTR [ecx + __mcsema_stack_mark@SECREL32]\n"); // Swap into the mcsema stack. - fprintf(out, " xchg esp, DWORD PTR [ecx + __mcsema_reg_state@SECREL32 + %u]\n", __builtin_offsetof(State, ESP)); + fprintf(out, + " xchg esp, DWORD PTR [ecx + __mcsema_reg_state@SECREL32 + %u]\n", + __builtin_offsetof(State, ESP)); // Return registers. - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], eax\n", __builtin_offsetof(State, EAX)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edx\n", __builtin_offsetof(State, EDX)); - fprintf(out, " movdqu [ecx + __mcsema_reg_state@SECREL32 + %u], xmm0\n", __builtin_offsetof(State, XMM0)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], eax\n", + __builtin_offsetof(State, EAX)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edx\n", + __builtin_offsetof(State, EDX)); + fprintf(out, " movdqu [ecx + __mcsema_reg_state@SECREL32 + %u], xmm0\n", + __builtin_offsetof(State, XMM0)); // Callee-saved registers. - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebp\n", __builtin_offsetof(State, EBP)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebx\n", __builtin_offsetof(State, EBX)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], esi\n", __builtin_offsetof(State, ESI)); - fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edi\n", __builtin_offsetof(State, EDI)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebp\n", + __builtin_offsetof(State, EBP)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], ebx\n", + __builtin_offsetof(State, EBX)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], esi\n", + __builtin_offsetof(State, ESI)); + fprintf(out, " mov [ecx + __mcsema_reg_state@SECREL32 + %u], edi\n", + __builtin_offsetof(State, EDI)); fprintf(out, " mov ebp, ecx\n"); + // ecx is old stack mark we need for this function, to adjust stack after retn fprintf(out, " mov ecx, DWORD PTR [ecx + __mcsema_stack_mark@SECREL32]\n"); + // restore old stack mark fprintf(out, " pop DWORD PTR [ebp + __mcsema_stack_mark@SECREL32]\n"); @@ -706,8 +862,8 @@ int main(void) { // adjust again for the poppped off arguments // this emulates a "retn XX", but that // only takes an immediate value - fprintf(out, " sub esp, ecx\n"); // this sub is an add since ecx is negative - fprintf(out, " add esp, 4\n"); // adjust for return address on stack + fprintf(out, " sub esp, ecx\n"); // this sub is an add since ecx is negative + fprintf(out, " add esp, 4\n"); // adjust for return address on stack // we still need to transfer control to the return addr on stack fprintf(out, " lea ecx, [esp+ecx]\n"); @@ -766,4 +922,3 @@ int main(void) { return 0; } - diff --git a/mcsema/Arch/X86/Runtime/print_PE_64_windows.cpp b/mcsema/Arch/X86/Runtime/print_PE_64_windows.cpp index c48835cbd..fe33486cf 100644 --- a/mcsema/Arch/X86/Runtime/print_PE_64_windows.cpp +++ b/mcsema/Arch/X86/Runtime/print_PE_64_windows.cpp @@ -21,32 +21,34 @@ #define HAS_FEATURE_AVX512 0 #define ADDRESS_SIZE_BITS 64 -#include "remill/Arch/X86/Runtime/State.h" #include "mcsema/Arch/X86/Runtime/Registers.h" +#include "remill/Arch/X86/Runtime/State.h" static const unsigned long long kStackSize = 1ULL << 20ULL; static const unsigned long long kStackArgSize = 264ULL; void getTlsIndex(FILE *out, const char dest_reg[]) { + // store TLS index into dest_reg - + fprintf(out, "push rdx\n"); - fprintf(out, "mov edx, DWORD ptr [rip + _tls_index]\n"); + fprintf(out, "mov edx, DWORD ptr [rip + _tls_index]\n"); + // do this awkward mov via rdx since we need to get a 32-bit - // value, and this helps us avoid figuring out the 32-bit + // value, and this helps us avoid figuring out the 32-bit // component of the destination register fprintf(out, "mov %s, rdx\n", dest_reg); - fprintf(out, "mov rdx, QWORD ptr gs:[88]\n"); - fprintf(out, "mov %s, QWORD ptr [rdx + 8*%s]\n", dest_reg, dest_reg); + fprintf(out, "mov rdx, QWORD ptr gs:[88]\n"); + fprintf(out, "mov %s, QWORD ptr [rdx + 8*%s]\n", dest_reg, dest_reg); fprintf(out, "pop rdx\n"); } void emitFunctionDef(FILE *out, const char func_name[]) { - fprintf(out, ".def %s;\n", func_name); - fprintf(out, ".scl 2;\n"); - fprintf(out, ".type 32;\n"); - fprintf(out, ".endef\n"); - fprintf(out, ".globl %s\n", func_name); + fprintf(out, ".def %s;\n", func_name); + fprintf(out, ".scl 2;\n"); + fprintf(out, ".type 32;\n"); + fprintf(out, ".endef\n"); + fprintf(out, ".globl %s\n", func_name); fprintf(out, ".align 16, 0x90\n"); fprintf(out, "%s:\n", func_name); } @@ -73,7 +75,7 @@ int main(void) { fprintf(out, " .globl __mcsema_stack\n"); fprintf(out, " .align 16\n"); fprintf(out, "__mcsema_stack:\n"); - fprintf(out, " .zero %llu\n", kStackSize); // MiB + fprintf(out, " .zero %llu\n", kStackSize); // MiB fprintf(out, "\n"); // Thread-local stack structure, named by `__mcsema_stack_args` @@ -94,7 +96,7 @@ int main(void) { fprintf(out, "\n"); fprintf(out, " .text\n"); - fprintf(out, " .align 16, 0x90\n"); + fprintf(out, " .align 16, 0x90\n"); fprintf(out, "\n"); /////////////////////////////////////////////////////////////////////////////////// @@ -110,56 +112,94 @@ int main(void) { // Pop the target function into the `RegState` structure. This resets `RSP` // to what it should be on entry to `__mcsema_attach_call`. // - fprintf(out, " push QWORD ptr [rsp]\n"); // dupliate last stack element (the jump-to RIP), so we can pop it - fprintf(out, " mov QWORD ptr [rsp+8], rbp\n"); // save rbp, we will clobber it + fprintf( + out, + " push QWORD ptr [rsp]\n"); // dupliate last stack element (the jump-to RIP), so we can pop it + fprintf(out, + " mov QWORD ptr [rsp+8], rbp\n"); // save rbp, we will clobber it getTlsIndex(out, "rbp"); - fprintf(out, " pop QWORD PTR [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RIP)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rax\n", __builtin_offsetof(RegState, RAX)); - fprintf(out, " pop rbp\n"); // restore rbp to previous value. - getTlsIndex(out, "rax"); // we can now clobber rax + fprintf(out, " pop QWORD PTR [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RIP)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rax\n", + __builtin_offsetof(RegState, RAX)); + fprintf(out, " pop rbp\n"); // restore rbp to previous value. + getTlsIndex(out, "rax"); // we can now clobber rax // General purpose registers. - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbx\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rcx\n", __builtin_offsetof(RegState, RCX)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rdx\n", __builtin_offsetof(RegState, RDX)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rsi\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rdi\n", __builtin_offsetof(RegState, RDI)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbp\n", __builtin_offsetof(RegState, RBP)); - - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r8\n", __builtin_offsetof(RegState, R8)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r9\n", __builtin_offsetof(RegState, R9)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r10\n", __builtin_offsetof(RegState, R10)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r11\n", __builtin_offsetof(RegState, R11)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r12\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r13\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r14\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r15\n", __builtin_offsetof(RegState, R15)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbx\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rcx\n", + __builtin_offsetof(RegState, RCX)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rdx\n", + __builtin_offsetof(RegState, RDX)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rsi\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rdi\n", + __builtin_offsetof(RegState, RDI)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbp\n", + __builtin_offsetof(RegState, RBP)); + + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r8\n", + __builtin_offsetof(RegState, R8)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r9\n", + __builtin_offsetof(RegState, R9)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r10\n", + __builtin_offsetof(RegState, R10)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r11\n", + __builtin_offsetof(RegState, R11)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r12\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r13\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r14\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], r15\n", + __builtin_offsetof(RegState, R15)); // XMM registers. - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", __builtin_offsetof(RegState, XMM0)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm1\n", __builtin_offsetof(RegState, XMM1)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm2\n", __builtin_offsetof(RegState, XMM2)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm3\n", __builtin_offsetof(RegState, XMM3)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm4\n", __builtin_offsetof(RegState, XMM4)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm5\n", __builtin_offsetof(RegState, XMM5)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", __builtin_offsetof(RegState, XMM6)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", __builtin_offsetof(RegState, XMM7)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", __builtin_offsetof(RegState, XMM8)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", __builtin_offsetof(RegState, XMM9)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", __builtin_offsetof(RegState, XMM10)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", __builtin_offsetof(RegState, XMM11)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", __builtin_offsetof(RegState, XMM12)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", __builtin_offsetof(RegState, XMM13)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", __builtin_offsetof(RegState, XMM14)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", __builtin_offsetof(RegState, XMM15)); - - fprintf(out, " xchg rsp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", + __builtin_offsetof(RegState, XMM0)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm1\n", + __builtin_offsetof(RegState, XMM1)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm2\n", + __builtin_offsetof(RegState, XMM2)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm3\n", + __builtin_offsetof(RegState, XMM3)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm4\n", + __builtin_offsetof(RegState, XMM4)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm5\n", + __builtin_offsetof(RegState, XMM5)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", + __builtin_offsetof(RegState, XMM6)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", + __builtin_offsetof(RegState, XMM7)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", + __builtin_offsetof(RegState, XMM8)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", + __builtin_offsetof(RegState, XMM9)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", + __builtin_offsetof(RegState, XMM10)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", + __builtin_offsetof(RegState, XMM11)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", + __builtin_offsetof(RegState, XMM12)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", + __builtin_offsetof(RegState, XMM13)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", + __builtin_offsetof(RegState, XMM14)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", + __builtin_offsetof(RegState, XMM15)); + + fprintf(out, " xchg rsp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); // If `RSP` is null then we need to initialize it to our new stack. fprintf(out, " cmp rsp, 0\n"); fprintf(out, " jnz .Lhave_stack\n"); + // end inline getTlsIndex -out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStackSize); + out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", + kStackSize); fprintf(out, ".Lhave_stack:\n"); // the state struture is the first and only arg to lifted functions @@ -171,7 +211,10 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, " push rdx\n"); // get RIP we need to jump to, in the process, clobber TLS index - fprintf(out, " mov rax, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RIP)); + fprintf(out, + " mov rax, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RIP)); + // and away we go! fprintf(out, " jmp rax\n"); fprintf(out, "\n"); @@ -193,56 +236,86 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac // up as expected // // add an extra 8 bytes to compensate for the fake return address - fprintf(out, " add rsp, %llu\n", kStackArgSize+8); + fprintf(out, " add rsp, %llu\n", kStackArgSize + 8); + // Swap into the mcsema stack. fprintf(out, "push rax\n"); getTlsIndex(out, "rax"); - fprintf(out, " xchg rsp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, " xchg rsp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); + // simulate a pop rax from old stack - fprintf(out, " add QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", __builtin_offsetof(RegState, RSP)); - fprintf(out, " mov rax, QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); - fprintf(out, " mov rax, QWORD ptr [rax-8]\n"); // use -8 here since we just added 8 to the old rsp to simulate a pop + fprintf(out, + " add QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", + __builtin_offsetof(RegState, RSP)); + fprintf(out, + " mov rax, QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); + fprintf( + out, + " mov rax, QWORD ptr [rax-8]\n"); // use -8 here since we just added 8 to the old rsp to simulate a pop fprintf(out, " push rcx\n"); getTlsIndex(out, "rcx"); + // Return registers. - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rax\n", __builtin_offsetof(RegState, RAX)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", __builtin_offsetof(RegState, XMM0)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rax\n", + __builtin_offsetof(RegState, RAX)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", + __builtin_offsetof(RegState, XMM0)); // Callee-saved registers. - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rbx\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rsi\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rdi\n", __builtin_offsetof(RegState, RDI)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rbp\n", __builtin_offsetof(RegState, RBP)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r12\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r13\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r14\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r15\n", __builtin_offsetof(RegState, R15)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", __builtin_offsetof(RegState, XMM6)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", __builtin_offsetof(RegState, XMM7)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", __builtin_offsetof(RegState, XMM8)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", __builtin_offsetof(RegState, XMM9)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", __builtin_offsetof(RegState, XMM10)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", __builtin_offsetof(RegState, XMM11)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", __builtin_offsetof(RegState, XMM12)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", __builtin_offsetof(RegState, XMM13)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", __builtin_offsetof(RegState, XMM14)); - fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", __builtin_offsetof(RegState, XMM15)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rbx\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rsi\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rdi\n", + __builtin_offsetof(RegState, RDI)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], rbp\n", + __builtin_offsetof(RegState, RBP)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r12\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r13\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r14\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov [rcx + __mcsema_reg_state@SECREL32 + %llu], r15\n", + __builtin_offsetof(RegState, R15)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", + __builtin_offsetof(RegState, XMM6)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", + __builtin_offsetof(RegState, XMM7)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", + __builtin_offsetof(RegState, XMM8)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", + __builtin_offsetof(RegState, XMM9)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", + __builtin_offsetof(RegState, XMM10)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", + __builtin_offsetof(RegState, XMM11)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", + __builtin_offsetof(RegState, XMM12)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", + __builtin_offsetof(RegState, XMM13)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", + __builtin_offsetof(RegState, XMM14)); + fprintf(out, " movdqu [rcx + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", + __builtin_offsetof(RegState, XMM15)); fprintf(out, " pop rcx\n"); // Unstash the callee-saved registers. - fprintf(out, " movdqu xmm6, [rsp+%llu]\n", 0*sizeof(RegState::XMM6)); - fprintf(out, " movdqu xmm7, [rsp+%llu]\n", 1*sizeof(RegState::XMM7)); - fprintf(out, " movdqu xmm8, [rsp+%llu]\n", 2*sizeof(RegState::XMM8)); - fprintf(out, " movdqu xmm9, [rsp+%llu]\n", 3*sizeof(RegState::XMM9)); - fprintf(out, " movdqu xmm10, [rsp+%llu]\n",4*sizeof(RegState::XMM10)); - fprintf(out, " movdqu xmm11, [rsp+%llu]\n",5*sizeof(RegState::XMM11)); - fprintf(out, " movdqu xmm12, [rsp+%llu]\n",6*sizeof(RegState::XMM12)); - fprintf(out, " movdqu xmm13, [rsp+%llu]\n",7*sizeof(RegState::XMM13)); - fprintf(out, " movdqu xmm14, [rsp+%llu]\n",8*sizeof(RegState::XMM14)); - fprintf(out, " movdqu xmm15, [rsp+%llu]\n",9*sizeof(RegState::XMM15)); - fprintf(out, " add rsp, %llu\n", sizeof(RegState::XMM0)*10); + fprintf(out, " movdqu xmm6, [rsp+%llu]\n", 0 * sizeof(RegState::XMM6)); + fprintf(out, " movdqu xmm7, [rsp+%llu]\n", 1 * sizeof(RegState::XMM7)); + fprintf(out, " movdqu xmm8, [rsp+%llu]\n", 2 * sizeof(RegState::XMM8)); + fprintf(out, " movdqu xmm9, [rsp+%llu]\n", 3 * sizeof(RegState::XMM9)); + fprintf(out, " movdqu xmm10, [rsp+%llu]\n", 4 * sizeof(RegState::XMM10)); + fprintf(out, " movdqu xmm11, [rsp+%llu]\n", 5 * sizeof(RegState::XMM11)); + fprintf(out, " movdqu xmm12, [rsp+%llu]\n", 6 * sizeof(RegState::XMM12)); + fprintf(out, " movdqu xmm13, [rsp+%llu]\n", 7 * sizeof(RegState::XMM13)); + fprintf(out, " movdqu xmm14, [rsp+%llu]\n", 8 * sizeof(RegState::XMM14)); + fprintf(out, " movdqu xmm15, [rsp+%llu]\n", 9 * sizeof(RegState::XMM15)); + fprintf(out, " add rsp, %llu\n", sizeof(RegState::XMM0) * 10); fprintf(out, " pop rbx\n"); fprintf(out, " pop rsi\n"); fprintf(out, " pop rdi\n"); @@ -255,7 +328,6 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, "\n"); - /////////////////////////////////////////////////////////////////////////////////// // // __mcsema_attach_ret_value @@ -269,49 +341,82 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac getTlsIndex(out, "rbp"); // General purpose registers. - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rax\n", __builtin_offsetof(RegState, RAX)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rbx\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rcx\n", __builtin_offsetof(RegState, RCX)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rdx\n", __builtin_offsetof(RegState, RDX)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rsi\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rdi\n", __builtin_offsetof(RegState, RDI)); - - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r8\n", __builtin_offsetof(RegState, R8)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r9\n", __builtin_offsetof(RegState, R9)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r10\n", __builtin_offsetof(RegState, R10)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r11\n", __builtin_offsetof(RegState, R11)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r12\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r13\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r14\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r15\n", __builtin_offsetof(RegState, R15)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rax\n", + __builtin_offsetof(RegState, RAX)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rbx\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rcx\n", + __builtin_offsetof(RegState, RCX)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rdx\n", + __builtin_offsetof(RegState, RDX)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rsi\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], rdi\n", + __builtin_offsetof(RegState, RDI)); + + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r8\n", + __builtin_offsetof(RegState, R8)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r9\n", + __builtin_offsetof(RegState, R9)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r10\n", + __builtin_offsetof(RegState, R10)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r11\n", + __builtin_offsetof(RegState, R11)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r12\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r13\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r14\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov [rbp + __mcsema_reg_state@SECREL32 + %llu], r15\n", + __builtin_offsetof(RegState, R15)); // restore rbp fprintf(out, " pop rbp\n"); // TODO(artem): check if we need to save rax getTlsIndex(out, "rax"); - fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbp\n", __builtin_offsetof(RegState, RBP)); + fprintf(out, " mov [rax + __mcsema_reg_state@SECREL32 + %llu], rbp\n", + __builtin_offsetof(RegState, RBP)); + // XMM registers. - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", __builtin_offsetof(RegState, XMM0)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm1\n", __builtin_offsetof(RegState, XMM1)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm2\n", __builtin_offsetof(RegState, XMM2)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm3\n", __builtin_offsetof(RegState, XMM3)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm4\n", __builtin_offsetof(RegState, XMM4)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm5\n", __builtin_offsetof(RegState, XMM5)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", __builtin_offsetof(RegState, XMM6)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", __builtin_offsetof(RegState, XMM7)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", __builtin_offsetof(RegState, XMM8)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", __builtin_offsetof(RegState, XMM9)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", __builtin_offsetof(RegState, XMM10)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", __builtin_offsetof(RegState, XMM11)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", __builtin_offsetof(RegState, XMM12)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", __builtin_offsetof(RegState, XMM13)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", __builtin_offsetof(RegState, XMM14)); - fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", __builtin_offsetof(RegState, XMM15)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm0\n", + __builtin_offsetof(RegState, XMM0)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm1\n", + __builtin_offsetof(RegState, XMM1)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm2\n", + __builtin_offsetof(RegState, XMM2)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm3\n", + __builtin_offsetof(RegState, XMM3)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm4\n", + __builtin_offsetof(RegState, XMM4)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm5\n", + __builtin_offsetof(RegState, XMM5)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm6\n", + __builtin_offsetof(RegState, XMM6)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm7\n", + __builtin_offsetof(RegState, XMM7)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm8\n", + __builtin_offsetof(RegState, XMM8)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm9\n", + __builtin_offsetof(RegState, XMM9)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm10\n", + __builtin_offsetof(RegState, XMM10)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm11\n", + __builtin_offsetof(RegState, XMM11)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm12\n", + __builtin_offsetof(RegState, XMM12)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm13\n", + __builtin_offsetof(RegState, XMM13)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm14\n", + __builtin_offsetof(RegState, XMM14)); + fprintf(out, " movdqu [rax + __mcsema_reg_state@SECREL32 + %llu], xmm15\n", + __builtin_offsetof(RegState, XMM15)); // if this function had no args, this will be zero, otherwise // it will be -argcount*8 (rsp is now > old rsp, due to pops) fprintf(out, " sub QWORD PTR [rax + __mcsema_stack_mark@SECREL32], rsp\n"); + // TODO(artem) check if we can clobber rcx fprintf(out, " mov rcx, QWORD PTR [rax + __mcsema_stack_mark@SECREL32]\n"); @@ -319,21 +424,24 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, " add rsp, %llu\n", kStackArgSize); fprintf(out, " add rsp, rcx\n"); - fprintf(out, " xchg rsp, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, + " xchg rsp, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); fprintf(out, " pop QWORD PTR [rax + __mcsema_stack_mark@SECREL32]\n"); + // Unstash the callee-saved registers. - fprintf(out, " movdqu xmm6, [rsp+%llu]\n", 0*sizeof(RegState::XMM6)); - fprintf(out, " movdqu xmm7, [rsp+%llu]\n", 1*sizeof(RegState::XMM7)); - fprintf(out, " movdqu xmm8, [rsp+%llu]\n", 2*sizeof(RegState::XMM8)); - fprintf(out, " movdqu xmm9, [rsp+%llu]\n", 3*sizeof(RegState::XMM9)); - fprintf(out, " movdqu xmm10, [rsp+%llu]\n",4*sizeof(RegState::XMM10)); - fprintf(out, " movdqu xmm11, [rsp+%llu]\n",5*sizeof(RegState::XMM11)); - fprintf(out, " movdqu xmm12, [rsp+%llu]\n",6*sizeof(RegState::XMM12)); - fprintf(out, " movdqu xmm13, [rsp+%llu]\n",7*sizeof(RegState::XMM13)); - fprintf(out, " movdqu xmm14, [rsp+%llu]\n",8*sizeof(RegState::XMM14)); - fprintf(out, " movdqu xmm15, [rsp+%llu]\n",9*sizeof(RegState::XMM15)); - fprintf(out, " add rsp, %llu\n", sizeof(RegState::XMM0)*10); + fprintf(out, " movdqu xmm6, [rsp+%llu]\n", 0 * sizeof(RegState::XMM6)); + fprintf(out, " movdqu xmm7, [rsp+%llu]\n", 1 * sizeof(RegState::XMM7)); + fprintf(out, " movdqu xmm8, [rsp+%llu]\n", 2 * sizeof(RegState::XMM8)); + fprintf(out, " movdqu xmm9, [rsp+%llu]\n", 3 * sizeof(RegState::XMM9)); + fprintf(out, " movdqu xmm10, [rsp+%llu]\n", 4 * sizeof(RegState::XMM10)); + fprintf(out, " movdqu xmm11, [rsp+%llu]\n", 5 * sizeof(RegState::XMM11)); + fprintf(out, " movdqu xmm12, [rsp+%llu]\n", 6 * sizeof(RegState::XMM12)); + fprintf(out, " movdqu xmm13, [rsp+%llu]\n", 7 * sizeof(RegState::XMM13)); + fprintf(out, " movdqu xmm14, [rsp+%llu]\n", 8 * sizeof(RegState::XMM14)); + fprintf(out, " movdqu xmm15, [rsp+%llu]\n", 9 * sizeof(RegState::XMM15)); + fprintf(out, " add rsp, %llu\n", sizeof(RegState::XMM0) * 10); fprintf(out, " pop rbx\n"); fprintf(out, " pop rsi\n"); fprintf(out, " pop rdi\n"); @@ -361,56 +469,99 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac // fprintf(out, " push rbp\n"); getTlsIndex(out, "rbp"); - fprintf(out, " mov rax, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RAX)); - fprintf(out, " mov rbx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov rcx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RCX)); - fprintf(out, " mov rdx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RDX)); - fprintf(out, " mov rsi, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov rdi, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RDI)); - - fprintf(out, " mov r8, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R8)); - fprintf(out, " mov r9, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R9)); - fprintf(out, " mov r10, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R10)); - fprintf(out, " mov r11, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R11)); - fprintf(out, " mov r12, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov r13, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov r14, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov r15, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R15)); + fprintf(out, " mov rax, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RAX)); + fprintf(out, " mov rbx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov rcx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RCX)); + fprintf(out, " mov rdx, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RDX)); + fprintf(out, " mov rsi, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov rdi, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RDI)); + + fprintf(out, " mov r8, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R8)); + fprintf(out, " mov r9, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R9)); + fprintf(out, " mov r10, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R10)); + fprintf(out, " mov r11, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R11)); + fprintf(out, " mov r12, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov r13, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov r14, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov r15, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R15)); + // XMM registers. - fprintf(out, " movdqu xmm0, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM0)); - fprintf(out, " movdqu xmm1, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM1)); - fprintf(out, " movdqu xmm2, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM2)); - fprintf(out, " movdqu xmm3, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM3)); - fprintf(out, " movdqu xmm4, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM4)); - fprintf(out, " movdqu xmm5, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM5)); - fprintf(out, " movdqu xmm6, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM6)); - fprintf(out, " movdqu xmm7, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM7)); - - fprintf(out, " movdqu xmm8, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM8)); - fprintf(out, " movdqu xmm9, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM9)); - fprintf(out, " movdqu xmm10, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM10)); - fprintf(out, " movdqu xmm11, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM11)); - fprintf(out, " movdqu xmm12, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM12)); - fprintf(out, " movdqu xmm13, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM13)); - fprintf(out, " movdqu xmm14, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM14)); - fprintf(out, " movdqu xmm15, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM15)); + fprintf(out, " movdqu xmm0, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM0)); + fprintf(out, " movdqu xmm1, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM1)); + fprintf(out, " movdqu xmm2, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM2)); + fprintf(out, " movdqu xmm3, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM3)); + fprintf(out, " movdqu xmm4, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM4)); + fprintf(out, " movdqu xmm5, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM5)); + fprintf(out, " movdqu xmm6, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM6)); + fprintf(out, " movdqu xmm7, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM7)); + + fprintf(out, " movdqu xmm8, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM8)); + fprintf(out, " movdqu xmm9, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM9)); + fprintf(out, " movdqu xmm10, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM10)); + fprintf(out, " movdqu xmm11, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM11)); + fprintf(out, " movdqu xmm12, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM12)); + fprintf(out, " movdqu xmm13, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM13)); + fprintf(out, " movdqu xmm14, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM14)); + fprintf(out, " movdqu xmm15, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM15)); fprintf(out, " pop rbp\n"); fprintf(out, " push rax\n"); getTlsIndex(out, "rax"); - fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBP)); + fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBP)); // The lifted code emulated a ret, which did incremented `rsp` by 8. // We "undo" that, then swap back to the native stack. When we swap, we // save into `RegState::RSP` where we are in the lifted stack, so that the // next attach can continue on where we left off. - fprintf(out, " sub QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", __builtin_offsetof(RegState, RSP)); - fprintf(out, " xchg rsp, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, + " sub QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", + __builtin_offsetof(RegState, RSP)); + fprintf(out, + " xchg rsp, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); + // simulate a pop rax from old stack - fprintf(out, " add QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", __builtin_offsetof(RegState, RSP)); - fprintf(out, " mov rax, qword ptr [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); - fprintf(out, " mov rax, qword ptr [rax-8]\n"); // use -8 here since we just added 8 to the old rsp to simulate a pop + fprintf(out, + " add QWORD ptr [rax + __mcsema_reg_state@SECREL32 + %llu], 8\n", + __builtin_offsetof(RegState, RSP)); + fprintf(out, + " mov rax, qword ptr [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); + fprintf( + out, + " mov rax, qword ptr [rax-8]\n"); // use -8 here since we just added 8 to the old rsp to simulate a pop fprintf(out, " ret\n"); @@ -426,12 +577,15 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac emitFunctionDef(out, "__mcsema_detach_call"); // *** This function assumes we can clobber rax - + // clobber rax to use as TLS index getTlsIndex(out, "rax"); + // Pop the target function into the `RegState` structure. This resets `RIP` // to what it should be on entry to `__mcsema_detach_call`. - fprintf(out, " pop QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RIP)); + fprintf(out, " pop QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RIP)); + // Marshal the callee-saved registers (of the emulated code) into the native // state. We don't touch the argument registers. @@ -444,54 +598,73 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, " push rdi\n"); fprintf(out, " push rsi\n"); fprintf(out, " push rbx\n"); - fprintf(out, " sub rsp, %llu\n", sizeof(RegState::XMM0)*10); - fprintf(out, " movdqu [rsp+%llu], xmm6 \n", 0*sizeof(RegState::XMM6)); - fprintf(out, " movdqu [rsp+%llu], xmm7 \n", 1*sizeof(RegState::XMM7)); - fprintf(out, " movdqu [rsp+%llu], xmm8 \n", 2*sizeof(RegState::XMM8)); - fprintf(out, " movdqu [rsp+%llu], xmm9 \n", 3*sizeof(RegState::XMM9)); - fprintf(out, " movdqu [rsp+%llu], xmm10\n", 4*sizeof(RegState::XMM10)); - fprintf(out, " movdqu [rsp+%llu], xmm11\n", 5*sizeof(RegState::XMM11)); - fprintf(out, " movdqu [rsp+%llu], xmm12\n", 6*sizeof(RegState::XMM12)); - fprintf(out, " movdqu [rsp+%llu], xmm13\n", 7*sizeof(RegState::XMM13)); - fprintf(out, " movdqu [rsp+%llu], xmm14\n", 8*sizeof(RegState::XMM14)); - fprintf(out, " movdqu [rsp+%llu], xmm15\n", 9*sizeof(RegState::XMM15)); + fprintf(out, " sub rsp, %llu\n", sizeof(RegState::XMM0) * 10); + fprintf(out, " movdqu [rsp+%llu], xmm6 \n", 0 * sizeof(RegState::XMM6)); + fprintf(out, " movdqu [rsp+%llu], xmm7 \n", 1 * sizeof(RegState::XMM7)); + fprintf(out, " movdqu [rsp+%llu], xmm8 \n", 2 * sizeof(RegState::XMM8)); + fprintf(out, " movdqu [rsp+%llu], xmm9 \n", 3 * sizeof(RegState::XMM9)); + fprintf(out, " movdqu [rsp+%llu], xmm10\n", 4 * sizeof(RegState::XMM10)); + fprintf(out, " movdqu [rsp+%llu], xmm11\n", 5 * sizeof(RegState::XMM11)); + fprintf(out, " movdqu [rsp+%llu], xmm12\n", 6 * sizeof(RegState::XMM12)); + fprintf(out, " movdqu [rsp+%llu], xmm13\n", 7 * sizeof(RegState::XMM13)); + fprintf(out, " movdqu [rsp+%llu], xmm14\n", 8 * sizeof(RegState::XMM14)); + fprintf(out, " movdqu [rsp+%llu], xmm15\n", 9 * sizeof(RegState::XMM15)); // copy posible stack args into temporary holding area fprintf(out, " lea rdi, [rax + __mcsema_stack_args@SECREL32]\n"); + // stack args start after return address + callee saved GPRs + callee saved XMM - fprintf(out, " lea rsi, [rsp + %llu]\n", 8 + 8*8 + sizeof(RegState::XMM0)*10); + fprintf(out, " lea rsi, [rsp + %llu]\n", + 8 + 8 * 8 + sizeof(RegState::XMM0) * 10); + // rcx is how much to copy fprintf(out, " mov rcx, %llu\n", kStackArgSize); + // do the copy fprintf(out, " rep movsb\n"); // restore arguments and callee-saved regs - fprintf(out, " mov rsi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov rdi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RDI)); - fprintf(out, " mov rbx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBP)); - fprintf(out, " mov rcx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RCX)); - fprintf(out, " mov r12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov r13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov r14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov r15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R15)); + fprintf(out, " mov rsi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov rdi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RDI)); + fprintf(out, " mov rbx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBP)); + fprintf(out, " mov rcx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RCX)); + fprintf(out, " mov r12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov r13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov r14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov r15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R15)); // Swap onto the native stack. - fprintf(out, " xchg QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], rsp\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, + " xchg QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], rsp\n", + __builtin_offsetof(RegState, RSP)); // copy posible stack args from holding area to native stack // allocate space for our arguments on stack fprintf(out, " sub rsp, %llu\n", kStackArgSize); - // we need to save these + + // we need to save these fprintf(out, " push rsi\n"); fprintf(out, " push rdi\n"); fprintf(out, " push rcx\n"); + // get the stack arg location, adjust for the just-pushed values - fprintf(out, " lea rdi, [rsp + %u]\n", 8+8+8); + fprintf(out, " lea rdi, [rsp + %u]\n", 8 + 8 + 8); + // source is temp area fprintf(out, " lea rsi, [rax + __mcsema_stack_args@SECREL32]\n"); fprintf(out, " mov rcx, %llu\n", kStackArgSize); + // copy stack args from temp area to new stack fprintf(out, " rep movsb\n"); @@ -506,12 +679,14 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac // as a 16-bit push fprintf(out, " push rax\n"); fprintf(out, " lea rax, [rip + __mcsema_attach_ret]\n"); + // switched saved rax (TLS index) with current rax (pointer to function) // the pointer to function will be the first argument to the mcsema-xlated // code we are about to jump to fprintf(out, " xchg rax, [rsp]\n"); - fprintf(out, " jmp QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RIP)); + fprintf(out, " jmp QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RIP)); fprintf(out, "\n"); @@ -537,88 +712,133 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, " push rdi\n"); fprintf(out, " push rsi\n"); fprintf(out, " push rbx\n"); - fprintf(out, " sub rsp, %llu\n", sizeof(RegState::XMM0)*10); - fprintf(out, " movdqu [rsp+%llu], xmm6 \n", 0*sizeof(RegState::XMM6)); - fprintf(out, " movdqu [rsp+%llu], xmm7 \n", 1*sizeof(RegState::XMM7)); - fprintf(out, " movdqu [rsp+%llu], xmm8 \n", 2*sizeof(RegState::XMM8)); - fprintf(out, " movdqu [rsp+%llu], xmm9 \n", 3*sizeof(RegState::XMM9)); - fprintf(out, " movdqu [rsp+%llu], xmm10\n", 4*sizeof(RegState::XMM10)); - fprintf(out, " movdqu [rsp+%llu], xmm11\n", 5*sizeof(RegState::XMM11)); - fprintf(out, " movdqu [rsp+%llu], xmm12\n", 6*sizeof(RegState::XMM12)); - fprintf(out, " movdqu [rsp+%llu], xmm13\n", 7*sizeof(RegState::XMM13)); - fprintf(out, " movdqu [rsp+%llu], xmm14\n", 8*sizeof(RegState::XMM14)); - fprintf(out, " movdqu [rsp+%llu], xmm15\n", 9*sizeof(RegState::XMM15)); + fprintf(out, " sub rsp, %llu\n", sizeof(RegState::XMM0) * 10); + fprintf(out, " movdqu [rsp+%llu], xmm6 \n", 0 * sizeof(RegState::XMM6)); + fprintf(out, " movdqu [rsp+%llu], xmm7 \n", 1 * sizeof(RegState::XMM7)); + fprintf(out, " movdqu [rsp+%llu], xmm8 \n", 2 * sizeof(RegState::XMM8)); + fprintf(out, " movdqu [rsp+%llu], xmm9 \n", 3 * sizeof(RegState::XMM9)); + fprintf(out, " movdqu [rsp+%llu], xmm10\n", 4 * sizeof(RegState::XMM10)); + fprintf(out, " movdqu [rsp+%llu], xmm11\n", 5 * sizeof(RegState::XMM11)); + fprintf(out, " movdqu [rsp+%llu], xmm12\n", 6 * sizeof(RegState::XMM12)); + fprintf(out, " movdqu [rsp+%llu], xmm13\n", 7 * sizeof(RegState::XMM13)); + fprintf(out, " movdqu [rsp+%llu], xmm14\n", 8 * sizeof(RegState::XMM14)); + fprintf(out, " movdqu [rsp+%llu], xmm15\n", 9 * sizeof(RegState::XMM15)); getTlsIndex(out, "rax"); + // save current stack mark fprintf(out, " push QWORD PTR [rax + __mcsema_stack_mark@SECREL32]\n"); // copy posible stack args into temporary holding area fprintf(out, " lea rdi, [rax + __mcsema_stack_args@SECREL32]\n"); - // this is not RSP since for do_call_value there is no spilling via an + + // this is not RSP since for do_call_value there is no spilling via an // intermediate function - fprintf(out, " mov rsi, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, + " mov rsi, QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSP)); + // use -8 since we have a ret addr on stack already and need alignment - fprintf(out, " mov rcx, %llu\n", kStackArgSize-8); + fprintf(out, " mov rcx, %llu\n", kStackArgSize - 8); fprintf(out, " rep movsb\n"); // we wil use rbp to index once we clobber rax fprintf(out, " mov rbp, rax\n"); + // we still read out rax on principle, in case we need to do debugging // but we clobber it later anyway, so... ignore it - fprintf(out, " mov rax, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RAX)); + fprintf(out, " mov rax, [rbp + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RAX)); fprintf(out, " mov rax, rbp\n"); - fprintf(out, " mov rbx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBX)); - fprintf(out, " mov rcx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RCX)); - fprintf(out, " mov rdx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RDX)); - fprintf(out, " mov rsi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RSI)); - fprintf(out, " mov rdi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RDI)); - fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RBP)); - - fprintf(out, " mov r8, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R8)); - fprintf(out, " mov r9, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R9)); - fprintf(out, " mov r10, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R10)); - fprintf(out, " mov r11, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R11)); - fprintf(out, " mov r12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R12)); - fprintf(out, " mov r13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R13)); - fprintf(out, " mov r14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R14)); - fprintf(out, " mov r15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, R15)); + fprintf(out, " mov rbx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBX)); + fprintf(out, " mov rcx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RCX)); + fprintf(out, " mov rdx, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RDX)); + fprintf(out, " mov rsi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RSI)); + fprintf(out, " mov rdi, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RDI)); + fprintf(out, " mov rbp, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RBP)); + + fprintf(out, " mov r8, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R8)); + fprintf(out, " mov r9, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R9)); + fprintf(out, " mov r10, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R10)); + fprintf(out, " mov r11, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R11)); + fprintf(out, " mov r12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R12)); + fprintf(out, " mov r13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R13)); + fprintf(out, " mov r14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R14)); + fprintf(out, " mov r15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, R15)); + // XMM registers. - fprintf(out, " movdqu xmm0, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM0)); - fprintf(out, " movdqu xmm1, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM1)); - fprintf(out, " movdqu xmm2, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM2)); - fprintf(out, " movdqu xmm3, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM3)); - fprintf(out, " movdqu xmm4, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM4)); - fprintf(out, " movdqu xmm5, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM5)); - fprintf(out, " movdqu xmm6, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM6)); - fprintf(out, " movdqu xmm7, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM7)); - - fprintf(out, " movdqu xmm8, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM8)); - fprintf(out, " movdqu xmm9, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM9)); - fprintf(out, " movdqu xmm10, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM10)); - fprintf(out, " movdqu xmm11, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM11)); - fprintf(out, " movdqu xmm12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM12)); - fprintf(out, " movdqu xmm13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM13)); - fprintf(out, " movdqu xmm14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM14)); - fprintf(out, " movdqu xmm15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, XMM15)); - - fprintf(out, " xchg QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], rsp\n", __builtin_offsetof(RegState, RSP)); + fprintf(out, " movdqu xmm0, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM0)); + fprintf(out, " movdqu xmm1, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM1)); + fprintf(out, " movdqu xmm2, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM2)); + fprintf(out, " movdqu xmm3, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM3)); + fprintf(out, " movdqu xmm4, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM4)); + fprintf(out, " movdqu xmm5, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM5)); + fprintf(out, " movdqu xmm6, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM6)); + fprintf(out, " movdqu xmm7, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM7)); + + fprintf(out, " movdqu xmm8, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM8)); + fprintf(out, " movdqu xmm9, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM9)); + fprintf(out, " movdqu xmm10, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM10)); + fprintf(out, " movdqu xmm11, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM11)); + fprintf(out, " movdqu xmm12, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM12)); + fprintf(out, " movdqu xmm13, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM13)); + fprintf(out, " movdqu xmm14, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM14)); + fprintf(out, " movdqu xmm15, [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, XMM15)); + + fprintf(out, + " xchg QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu], rsp\n", + __builtin_offsetof(RegState, RSP)); // copy posible stack args from holding area to native stack // allocate space for our arguments on stack // use -8 since we have a ret addr on stack already and need alignment - fprintf(out, " sub rsp, %llu\n", kStackArgSize-8); - // we need to save these + fprintf(out, " sub rsp, %llu\n", kStackArgSize - 8); + + // we need to save these fprintf(out, " push rsi\n"); fprintf(out, " push rdi\n"); fprintf(out, " push rcx\n"); + // get the stack arg location // compensate for rsi+rdi+rcx - fprintf(out, " lea rdi, [rsp + %u]\n", 8+8+8); + fprintf(out, " lea rdi, [rsp + %u]\n", 8 + 8 + 8); + // source is temp area fprintf(out, " lea rsi, [rax + __mcsema_stack_args@SECREL32]\n"); + // use -8 since we have a ret addr on stack already and need alignment - fprintf(out, " mov rcx, %llu\n", kStackArgSize-8); + fprintf(out, " mov rcx, %llu\n", kStackArgSize - 8); + // copy fprintf(out, " rep movsb\n"); @@ -639,7 +859,8 @@ out, fprintf(out, " lea rsp, [rax + __mcsema_stack@SECREL32 + %llu]\n", kStac fprintf(out, " xchg rax, [rsp]\n"); // Go native. - fprintf(out, " jmp QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", __builtin_offsetof(RegState, RIP)); + fprintf(out, " jmp QWORD PTR [rax + __mcsema_reg_state@SECREL32 + %llu]\n", + __builtin_offsetof(RegState, RIP)); fprintf(out, "\n"); /////////////////////////////////////////////////////////////////////////////////// diff --git a/mcsema/BC/Callback.cpp b/mcsema/BC/Callback.cpp index 6f5f5145c..1e6498b65 100644 --- a/mcsema/BC/Callback.cpp +++ b/mcsema/BC/Callback.cpp @@ -17,25 +17,18 @@ #include "mcsema/BC/Callback.h" -#include +#include +#include #include - -#include -#include -#include - +#include #include -#include -#include #include +#include +#include #include #include -#include #include - -#include -#include - +#include #include #include #include @@ -45,6 +38,10 @@ #include #include +#include +#include +#include + #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Legacy.h" #include "mcsema/BC/Segment.h" @@ -60,13 +57,14 @@ DEFINE_bool(explicit_args, false, "bitcode, especially where floating point argument and return " "values are concerned."); -DEFINE_uint32(explicit_args_count, 8, - "Number of explicit (integer) arguments to pass to an unknown " - "function, or to accept from an unknown function. This value is " - "used when calling external functions for which no type " - "information is known, or who take a variable number of arguments."); +DEFINE_uint32( + explicit_args_count, 8, + "Number of explicit (integer) arguments to pass to an unknown " + "function, or to accept from an unknown function. This value is " + "used when calling external functions for which no type " + "information is known, or who take a variable number of arguments."); -DEFINE_uint32(explicit_args_stack_size, 4096 * 256 /* 1 MiB */, +DEFINE_uint32(explicit_args_stack_size, 4096 * 256 /* 1 MiB */, "Size of the stack of the emulated program when the program " "is lifted using --explicit_args."); @@ -83,9 +81,9 @@ static llvm::Function *GetAttachCallFunc(void) { if (!handler) { auto void_type = llvm::Type::getVoidTy(*gContext); auto callback_type = llvm::FunctionType::get(void_type, false); - handler = llvm::Function::Create( - callback_type, llvm::GlobalValue::ExternalLinkage, - "__mcsema_attach_call", gModule.get()); + handler = llvm::Function::Create(callback_type, + llvm::GlobalValue::ExternalLinkage, + "__mcsema_attach_call", gModule.get()); handler->addFnAttr(llvm::Attribute::NoInline); remill::Annotate(handler); } @@ -101,13 +99,14 @@ static llvm::Function *DetachCallValueFunc(void) { } // Get a callback function for an internal function. -static llvm::Function *ImplementNativeToLiftedCallback( - const NativeObject *cfg_func, const std::string &callback_name) { +static llvm::Function * +ImplementNativeToLiftedCallback(const NativeObject *cfg_func, + const std::string &callback_name) { // If the native name of the function doesn't yet exist then add it in. auto func = gModule->getFunction(cfg_func->lifted_name); - CHECK(func != nullptr) - << "Cannot find lifted function " << cfg_func->lifted_name; + CHECK(func != nullptr) << "Cannot find lifted function " + << cfg_func->lifted_name; auto attach_func = GetAttachCallFunc(); @@ -119,9 +118,8 @@ static llvm::Function *ImplementNativeToLiftedCallback( std::stringstream asm_str; switch (gArch->arch_name) { case remill::kArchInvalid: - LOG(FATAL) - << "Cannot generate native-to-lifted entrypoint thunk for " - << "unknown architecture."; + LOG(FATAL) << "Cannot generate native-to-lifted entrypoint thunk for " + << "unknown architecture."; break; case remill::kArchAMD64: case remill::kArchAMD64_AVX: @@ -146,16 +144,14 @@ static llvm::Function *ImplementNativeToLiftedCallback( break; case remill::kArchAArch64LittleEndian: - LOG(ERROR) - << "TODO: Create a native-to-lifted callback for the " - << GetArchName(gArch->arch_name) << " instruction set."; + LOG(ERROR) << "TODO: Create a native-to-lifted callback for the " + << GetArchName(gArch->arch_name) << " instruction set."; asm_str << "nop;"; break; default: - LOG(FATAL) - << "Cannot create native-to-lifted callback for the " - << GetArchName(gArch->arch_name) << " instruction set."; + LOG(FATAL) << "Cannot create native-to-lifted callback for the " + << GetArchName(gArch->arch_name) << " instruction set."; break; } @@ -166,23 +162,24 @@ static llvm::Function *ImplementNativeToLiftedCallback( auto callback_func = gModule->getFunction(callback_name); if (!callback_func) { callback_func = llvm::Function::Create( - callback_type, llvm::GlobalValue::InternalLinkage, // Tentative linkage. + callback_type, + llvm::GlobalValue::InternalLinkage, // Tentative linkage. callback_name, gModule.get()); - } callback_func->setVisibility(llvm::GlobalValue::DefaultVisibility); callback_func->addFnAttr(llvm::Attribute::Naked); callback_func->addFnAttr(llvm::Attribute::NoInline); callback_func->addFnAttr(llvm::Attribute::NoBuiltin); + // Create the inline assembly. We use memory operands ( std::vector asm_arg_types; std::vector asm_args; asm_arg_types.push_back(llvm::PointerType::get(func->getType(), 0)); asm_arg_types.push_back(llvm::PointerType::get(attach_func->getType(), 0)); auto asm_func_type = llvm::FunctionType::get(void_type, asm_arg_types, false); - auto asm_func = llvm::InlineAsm::get( - asm_func_type, asm_str.str(), "*m,*m,~{dirflag},~{fpsr},~{flags}", - true /* hasSideEffects */); + auto asm_func = llvm::InlineAsm::get(asm_func_type, asm_str.str(), + "*m,*m,~{dirflag},~{fpsr},~{flags}", + true /* hasSideEffects */); // Make an initializer function that first calls `__mcsema_early_init`, // then calls the lifted bitcode function. When lifting C++ code, often @@ -200,7 +197,7 @@ static llvm::Function *ImplementNativeToLiftedCallback( func_wrapper_name << "_wrapper"; auto func_wrapper = llvm::Function::Create( func->getFunctionType(), llvm::GlobalValue::InternalLinkage, - func_wrapper_name.str(), gModule.get()); + func_wrapper_name.str(), gModule.get()); auto arg_it = func_wrapper->arg_begin(); llvm::IRBuilder<> ir(llvm::BasicBlock::Create(*gContext, "", func_wrapper)); @@ -256,8 +253,8 @@ static llvm::Function *ImplementNativeToLiftedCallback( // Create a stack and a variable that tracks the stack pointer. static llvm::Constant *InitialStackPointerValue(void) { unsigned min_frame_size = 512u; - const auto num_bytes = std::max(FLAGS_explicit_args_stack_size, - 4096u + min_frame_size); + const auto num_bytes = + std::max(FLAGS_explicit_args_stack_size, 4096u + min_frame_size); auto i8_type = llvm::Type::getInt8Ty(*gContext); auto stack_type = llvm::ArrayType::get(i8_type, num_bytes); @@ -265,8 +262,8 @@ static llvm::Constant *InitialStackPointerValue(void) { if (!stack) { auto stack_var = new llvm::GlobalVariable( *gModule, stack_type, false, llvm::GlobalValue::InternalLinkage, - llvm::ConstantAggregateZero::get(stack_type), "__mcsema_stack", - nullptr, llvm::GlobalValue::InitialExecTLSModel); + llvm::ConstantAggregateZero::get(stack_type), "__mcsema_stack", nullptr, + llvm::GlobalValue::InitialExecTLSModel); stack = stack_var; if (stack_var->getType()->getAddressSpace()) { @@ -283,60 +280,47 @@ static llvm::Constant *InitialStackPointerValue(void) { #if LLVM_VERSION_NUMBER <= LLVM_VERSION(3, 6) auto gep = llvm::ConstantExpr::getInBoundsGetElementPtr(stack, indexes); #else - auto gep = llvm::ConstantExpr::getInBoundsGetElementPtr( - nullptr, stack, indexes); + auto gep = + llvm::ConstantExpr::getInBoundsGetElementPtr(nullptr, stack, indexes); #endif return llvm::ConstantExpr::getPtrToInt(gep, gWordType); } static const char *ThreadPointerNameX86(void) { switch (gArch->os_name) { - case remill::kOSLinux: - return "GS_BASE"; - case remill::kOSWindows: - return "FS_BASE"; - default: - return nullptr; + case remill::kOSLinux: return "GS_BASE"; + case remill::kOSWindows: return "FS_BASE"; + default: return nullptr; } } static const char *ThreadPointerNameAMD64(void) { switch (gArch->os_name) { - case remill::kOSLinux: - return "FS_BASE"; - case remill::kOSWindows: - return "GS_BASE"; - default: - return nullptr; + case remill::kOSLinux: return "FS_BASE"; + case remill::kOSWindows: return "GS_BASE"; + default: return nullptr; } } static const char *ThreadPointerName(void) { const char *tp_name = nullptr; switch (gArch->arch_name) { - case remill::kArchAArch64LittleEndian: - return "TPIDR_EL0"; + case remill::kArchAArch64LittleEndian: return "TPIDR_EL0"; case remill::kArchX86: case remill::kArchX86_AVX: - case remill::kArchX86_AVX512: - tp_name = ThreadPointerNameX86(); - break; + case remill::kArchX86_AVX512: tp_name = ThreadPointerNameX86(); break; case remill::kArchAMD64: case remill::kArchAMD64_AVX: - case remill::kArchAMD64_AVX512: - tp_name = ThreadPointerNameAMD64(); - break; + case remill::kArchAMD64_AVX512: tp_name = ThreadPointerNameAMD64(); break; - default: - break; + default: break; } - LOG_IF(ERROR, !tp_name) - << "Can't get thread pointer name for architecture " - << remill::GetArchName(gArch->arch_name) << " and OS " - << remill::GetOSName(gArch->os_name); + LOG_IF(ERROR, !tp_name) << "Can't get thread pointer name for architecture " + << remill::GetArchName(gArch->arch_name) << " and OS " + << remill::GetOSName(gArch->os_name); return tp_name; } @@ -349,8 +333,8 @@ static llvm::Constant *InitialThreadLocalStorage(void) { auto tls_var = new llvm::GlobalVariable( *gModule, tls_type, false, llvm::GlobalValue::InternalLinkage, - llvm::Constant::getNullValue(tls_type), "__mcsema_tls", - nullptr, llvm::GlobalValue::InitialExecTLSModel); + llvm::Constant::getNullValue(tls_type), "__mcsema_tls", nullptr, + llvm::GlobalValue::InitialExecTLSModel); llvm::Constant *tls = tls_var; if (tls_var->getType()->getAddressSpace()) { @@ -366,8 +350,7 @@ static llvm::Constant *InitialThreadLocalStorage(void) { #if LLVM_VERSION_NUMBER <= LLVM_VERSION(3, 6) tls = llvm::ConstantExpr::getInBoundsGetElementPtr(tls, indexes); #else - tls = llvm::ConstantExpr::getInBoundsGetElementPtr( - nullptr, tls, indexes); + tls = llvm::ConstantExpr::getInBoundsGetElementPtr(nullptr, tls, indexes); #endif tls = llvm::ConstantExpr::getPtrToInt(tls, gWordType); @@ -378,11 +361,10 @@ static llvm::Constant *InitialThreadLocalStorage(void) { static llvm::Function *CreateVerifyRegState(void) { auto reg_state = GetStatePointer(); auto *func_type = llvm::FunctionType::get(reg_state->getType(), false); - auto new_func = gModule->getOrInsertFunction( - "__mcsema_init_reg_state", - func_type); - auto func = llvm::dyn_cast( - new_func IF_LLVM_GTE_900(.getCallee())); + auto new_func = + gModule->getOrInsertFunction("__mcsema_init_reg_state", func_type); + auto func = + llvm::dyn_cast(new_func IF_LLVM_GTE_900(.getCallee())); CHECK(func != nullptr) << "Could not get or create function '__mcsema_init_reg_state'"; @@ -397,20 +379,21 @@ static llvm::Function *CreateVerifyRegState(void) { // Need to find out where stack pointer is and known information is // byte offset in state structure -// auto byte_ty = llvm::Type::getInt8PtrTy(*gContext); + // auto byte_ty = llvm::Type::getInt8PtrTy(*gContext); unsigned ptr_size = static_cast(gArch->address_size); auto reg_ptr_ty = llvm::PointerType::getIntNPtrTy(*gContext, ptr_size); //TODO(lukas): remove after abi_libraries patch gets merged into master auto GetConstantInt = [&](unsigned size, uint64_t value) { - return llvm::ConstantInt::get( - llvm::Type::getIntNTy(*gContext, size), value); + return llvm::ConstantInt::get(llvm::Type::getIntNTy(*gContext, size), + value); }; -// auto casted_reg_state = ir.CreateBitCast(reg_state, byte_ty); + + // auto casted_reg_state = ir.CreateBitCast(reg_state, byte_ty); auto rsp = sp_reg->AddressOf(reg_state, entry_block); auto casted_rsp = ir.CreateBitCast(rsp, reg_ptr_ty); - auto rsp_val = ir.CreateLoad( - casted_rsp, llvm::Type::getIntNTy(*gContext, ptr_size)); + auto rsp_val = + ir.CreateLoad(casted_rsp, llvm::Type::getIntNTy(*gContext, ptr_size)); auto comparison = ir.CreateICmpEQ(rsp_val, GetConstantInt(ptr_size, 0)); ir.CreateCondBr(comparison, is_null_block, end_block); @@ -421,9 +404,8 @@ static llvm::Function *CreateVerifyRegState(void) { // Store the address of `__mcsema_tls` into the TLS register. if (auto tp_name = ThreadPointerName(); tp_name) { if (auto tp_reg = gArch->RegisterByName(tp_name); tp_reg) { - ir.CreateStore( - InitialThreadLocalStorage(), - tp_reg->AddressOf(reg_state, is_null_block)); + ir.CreateStore(InitialThreadLocalStorage(), + tp_reg->AddressOf(reg_state, is_null_block)); } } @@ -464,8 +446,9 @@ static llvm::Function *GetVerifyRegState(void) { // Implements a stub for an externally defined function in such a way that // the external is explicitly called, and arguments from the modeled CPU // state are passed into the external. -static llvm::Function *ImplementExplicitArgsEntryPoint( - const NativeFunction *cfg_func, const std::string &name) { +static llvm::Function * +ImplementExplicitArgsEntryPoint(const NativeFunction *cfg_func, + const std::string &name) { auto func = gModule->getFunction(name); if (!func) { @@ -478,15 +461,14 @@ static llvm::Function *ImplementExplicitArgsEntryPoint( ret_type = llvm::Type::getInt32Ty(*gContext); } - LOG(INFO) - << "Generating explicit argument entrypoint function for " - << name << ", calling into " << cfg_func->lifted_name; + LOG(INFO) << "Generating explicit argument entrypoint function for " << name + << ", calling into " << cfg_func->lifted_name; std::vector arg_types(num_args, gWordType); auto func_type = llvm::FunctionType::get(ret_type, arg_types, false); - func = llvm::Function::Create( - func_type, llvm::GlobalValue::InternalLinkage, name, gModule.get()); + func = llvm::Function::Create(func_type, llvm::GlobalValue::InternalLinkage, + name, gModule.get()); DCHECK_EQ(func->getName().str(), name); } @@ -496,8 +478,7 @@ static llvm::Function *ImplementExplicitArgsEntryPoint( auto maybe_decl = anvill::FunctionDecl::Create(*func, gArch); if (remill::IsError(maybe_decl)) { - LOG(FATAL) - << remill::GetErrorString(maybe_decl); + LOG(FATAL) << remill::GetErrorString(maybe_decl); } auto &decl = remill::GetReference(maybe_decl); @@ -526,9 +507,8 @@ static llvm::Function *ImplementExplicitArgsEntryPoint( auto arg_index = 0u; for (auto &arg : func->args()) { const auto ¶m_decl = decl.params[arg_index++]; - mem_ptr = anvill::StoreNativeValue( - &arg, param_decl, intrinsics, - block, state_ptr, mem_ptr); + mem_ptr = anvill::StoreNativeValue(&arg, param_decl, intrinsics, block, + state_ptr, mem_ptr); } llvm::Value *lifted_func_args[remill::kNumBlockArgs] = {}; @@ -540,22 +520,19 @@ static llvm::Function *ImplementExplicitArgsEntryPoint( llvm::Value *ret_val = nullptr; if (decl.returns.size() == 1) { - ret_val = anvill::LoadLiftedValue( - decl.returns.front(), intrinsics, block, - state_ptr, mem_ptr); + ret_val = anvill::LoadLiftedValue(decl.returns.front(), intrinsics, block, + state_ptr, mem_ptr); ir.SetInsertPoint(block); - } else if (1 < decl.returns.size()){ + } else if (1 < decl.returns.size()) { ret_val = llvm::UndefValue::get(func->getReturnType()); auto index = 0u; for (auto &ret_decl : decl.returns) { - auto partial_ret_val = anvill::LoadLiftedValue( - ret_decl, intrinsics, block, - state_ptr, mem_ptr); + auto partial_ret_val = anvill::LoadLiftedValue(ret_decl, intrinsics, + block, state_ptr, mem_ptr); ir.SetInsertPoint(block); unsigned indexes[] = {index}; - ret_val = ir.CreateInsertValue( - ret_val, partial_ret_val, indexes); + ret_val = ir.CreateInsertValue(ret_val, partial_ret_val, indexes); index += 1; } } @@ -578,11 +555,11 @@ static llvm::Function *GetOrCreateCallback(const NativeFunction *cfg_func, CHECK_NOTNULL(cfg_func->lifted_function); if (FLAGS_explicit_args) { - cfg_func->function = ImplementExplicitArgsEntryPoint( - cfg_func, callback_name); + cfg_func->function = + ImplementExplicitArgsEntryPoint(cfg_func, callback_name); } else { - cfg_func->function = ImplementNativeToLiftedCallback( - cfg_func, callback_name); + cfg_func->function = + ImplementNativeToLiftedCallback(cfg_func, callback_name); } return cfg_func->function; @@ -591,8 +568,8 @@ static llvm::Function *GetOrCreateCallback(const NativeFunction *cfg_func, // Adapt a variadic function type to have the same signature, but have additional // explicit "padding" arguments so that the function has at least `num_args` // parameters. -static llvm::FunctionType *AdaptFunctionType( - llvm::FunctionType *type, unsigned num_args) { +static llvm::FunctionType *AdaptFunctionType(llvm::FunctionType *type, + unsigned num_args) { std::vector param_types( std::max(num_args, type->getNumParams()), gWordType); @@ -601,8 +578,7 @@ static llvm::FunctionType *AdaptFunctionType( param_types[i++] = param_type; } - return llvm::FunctionType::get( - type->getReturnType(), param_types, false); + return llvm::FunctionType::get(type->getReturnType(), param_types, false); } // If `va_func` is not variadic, then this returns `va_func`, otherwise @@ -613,13 +589,12 @@ static llvm::Function *WrapVarArgsFunction(llvm::Function *va_func) { return va_func; } - auto func_type = AdaptFunctionType( - va_func->getFunctionType(), FLAGS_explicit_args_count); + auto func_type = + AdaptFunctionType(va_func->getFunctionType(), FLAGS_explicit_args_count); - auto wrapper_function = llvm::Function::Create( - func_type, - llvm::GlobalValue::InternalLinkage, - va_func->getName() + "_novarargs", gModule.get()); + auto wrapper_function = + llvm::Function::Create(func_type, llvm::GlobalValue::InternalLinkage, + va_func->getName() + "_novarargs", gModule.get()); std::vector params; for (auto &arg : wrapper_function->args()) { @@ -643,8 +618,8 @@ static llvm::Function *WrapVarArgsFunction(llvm::Function *va_func) { // Implements a stub for an externally defined function in such a way that, // when executed, this stub redirects control flow into the actual external // function. -static void ImplementLiftedToNativeCallback( - llvm::Function *callback_func, llvm::Function *extern_func) { +static void ImplementLiftedToNativeCallback(llvm::Function *callback_func, + llvm::Function *extern_func) { callback_func->addFnAttr(llvm::Attribute::NoInline); @@ -656,8 +631,8 @@ static void ImplementLiftedToNativeCallback( // because it's likely that whatever was in the CFG makes no sense // in the lifted code. auto args = remill::LiftedFunctionArgs(block); - args[remill::kPCArgNum] = llvm::ConstantExpr::getPtrToInt( - extern_func, gWordType); + args[remill::kPCArgNum] = + llvm::ConstantExpr::getPtrToInt(extern_func, gWordType); llvm::IRBuilder<> ir(block); auto handler_call = ir.CreateCall(DetachCallValueFunc(), args); @@ -667,14 +642,13 @@ static void ImplementLiftedToNativeCallback( // Implements a stub for an externally defined function in such a way that // the external is explicitly called, and arguments from the modeled CPU // state are passed into the external. -static void ImplementExplicitArgsExitPoint( - llvm::Function *callback_func, llvm::Function *extern_func) { +static void ImplementExplicitArgsExitPoint(llvm::Function *callback_func, + llvm::Function *extern_func) { extern_func = WrapVarArgsFunction(extern_func); auto maybe_decl = anvill::FunctionDecl::Create(*extern_func, gArch); if (remill::IsError(maybe_decl)) { - LOG(FATAL) - << remill::GetErrorString(maybe_decl); + LOG(FATAL) << remill::GetErrorString(maybe_decl); } const auto &decl = remill::GetReference(maybe_decl); @@ -682,12 +656,11 @@ static void ImplementExplicitArgsExitPoint( remill::CloneBlockFunctionInto(callback_func); auto block = &(callback_func->getEntryBlock()); - auto pc = remill::NthArgument( - callback_func, remill::kPCArgNum); - auto mem_ptr = remill::NthArgument( - callback_func, remill::kMemoryPointerArgNum); - auto state_ptr = remill::NthArgument( - callback_func, remill::kStatePointerArgNum); + auto pc = remill::NthArgument(callback_func, remill::kPCArgNum); + auto mem_ptr = + remill::NthArgument(callback_func, remill::kMemoryPointerArgNum); + auto state_ptr = + remill::NthArgument(callback_func, remill::kStatePointerArgNum); llvm::IRBuilder<> ir(block); @@ -696,7 +669,8 @@ static void ImplementExplicitArgsExitPoint( gWordType, llvm::Constant::getNullValue(gWordType), "next_pc"); ir.CreateStore(pc, next_pc_ref); - const auto mem_ptr_ref = ir.CreateAlloca(mem_ptr->getType(), nullptr, "MEMORY"); + const auto mem_ptr_ref = + ir.CreateAlloca(mem_ptr->getType(), nullptr, "MEMORY"); const auto pc_ref = ir.CreateAlloca(gWordType, nullptr, "PC"); ir.CreateStore(mem_ptr, mem_ptr_ref); ir.CreateStore(pc, pc_ref); @@ -714,9 +688,9 @@ static void ImplementExplicitArgsExitPoint( callback_func->setLinkage(llvm::GlobalValue::InternalLinkage); remill::IntrinsicTable intrinsics(gModule); - const auto new_mem_ptr = decl.CallFromLiftedBlock( - extern_func->getName().str(), - intrinsics, block, state_ptr, mem_ptr, true); + const auto new_mem_ptr = + decl.CallFromLiftedBlock(extern_func->getName().str(), intrinsics, block, + state_ptr, mem_ptr, true); ir.CreateRet(new_mem_ptr); } @@ -801,8 +775,7 @@ llvm::Function *GetLiftedToNativeExitPoint(ExitPointKind kind) { if (!FLAGS_explicit_args) { switch (kind) { - case kExitPointJump: - return gModule->getFunction("__remill_jump"); + case kExitPointJump: return gModule->getFunction("__remill_jump"); case kExitPointFunctionCall: return gModule->getFunction("__remill_function_call"); } @@ -830,14 +803,13 @@ llvm::Function *GetLiftedToNativeExitPoint(ExitPointKind kind) { func->eraseFromParent(); if (remill::IsError(maybe_decl)) { - LOG(FATAL) - << "Unable to create exit point: " << remill::GetErrorString(maybe_decl); + LOG(FATAL) << "Unable to create exit point: " + << remill::GetErrorString(maybe_decl); return nullptr; } const auto &decl = remill::GetReference(maybe_decl); - func = decl.DeclareInModule( - "__mcsema_do_detach_call_value", *gModule, true); + func = decl.DeclareInModule("__mcsema_do_detach_call_value", *gModule, true); CHECK_NOTNULL(func); // Stub that will marshal lifted state into the native state. @@ -848,20 +820,19 @@ llvm::Function *GetLiftedToNativeExitPoint(ExitPointKind kind) { remill::CloneBlockFunctionInto(callback_func); auto block = &(callback_func->getEntryBlock()); - auto pc = remill::NthArgument( - callback_func, remill::kPCArgNum); - auto mem_ptr = remill::NthArgument( - callback_func, remill::kMemoryPointerArgNum); - auto state_ptr = remill::NthArgument( - callback_func, remill::kStatePointerArgNum); + auto pc = remill::NthArgument(callback_func, remill::kPCArgNum); + auto mem_ptr = + remill::NthArgument(callback_func, remill::kMemoryPointerArgNum); + auto state_ptr = + remill::NthArgument(callback_func, remill::kStatePointerArgNum); llvm::IRBuilder<> ir(block); auto pc_as_func_ptr = ir.CreateIntToPtr(pc, func->getType()); remill::IntrinsicTable intrinsics(gModule); - const auto new_mem_ptr = decl.CallFromLiftedBlock( - "__mcsema_do_detach_call_value", intrinsics, block, - state_ptr, mem_ptr, true); + const auto new_mem_ptr = + decl.CallFromLiftedBlock("__mcsema_do_detach_call_value", intrinsics, + block, state_ptr, mem_ptr, true); func->replaceAllUsesWith(pc_as_func_ptr); func->eraseFromParent(); diff --git a/mcsema/BC/Callback.h b/mcsema/BC/Callback.h index c59365c32..1f912974f 100644 --- a/mcsema/BC/Callback.h +++ b/mcsema/BC/Callback.h @@ -29,10 +29,7 @@ struct NativeFunction; // internal code. llvm::Function *GetLiftedToNativeExitPoint(const NativeFunction *cfg_func); -enum ExitPointKind { - kExitPointJump, - kExitPointFunctionCall -}; +enum ExitPointKind { kExitPointJump, kExitPointFunctionCall }; // Get a function that goes from the current lifted state into native state, // where we don't know where the native destination actually is. diff --git a/mcsema/BC/External.cpp b/mcsema/BC/External.cpp index cbe285c8a..1110c152d 100644 --- a/mcsema/BC/External.cpp +++ b/mcsema/BC/External.cpp @@ -17,23 +17,20 @@ #include "mcsema/BC/External.h" -#include +#include #include - -#include -#include - +#include #include #include #include #include - -#include - #include #include #include +#include +#include + #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/Util.h" @@ -84,8 +81,7 @@ llvm::Constant *NativeExternalFunction::Pointer(void) const { function = llvm::Function::Create( llvm::FunctionType::get(gWordType, param_types, false), - llvm::GlobalValue::ExternalLinkage, - name, gModule.get()); + llvm::GlobalValue::ExternalLinkage, name, gModule.get()); if (is_weak) { function->setLinkage(llvm::GlobalValue::ExternalWeakLinkage); diff --git a/mcsema/BC/External.h b/mcsema/BC/External.h index 5874a8cb2..bc0698f43 100644 --- a/mcsema/BC/External.h +++ b/mcsema/BC/External.h @@ -21,11 +21,9 @@ namespace llvm { namespace CallingConv { - enum { - McSemaCall = 144 - }; -} // namespace CallingConv -} // namespace llvm +enum { McSemaCall = 144 }; +} // namespace CallingConv +} // namespace llvm namespace mcsema { struct NativeModule; diff --git a/mcsema/BC/Function.cpp b/mcsema/BC/Function.cpp index eefd3fb2c..ac19a6962 100644 --- a/mcsema/BC/Function.cpp +++ b/mcsema/BC/Function.cpp @@ -17,25 +17,23 @@ #include "mcsema/BC/Function.h" -#include #include - +#include #include #include #include #include -#include +#include #include +#include #include -#include -#include #include -#include +#include #include +#include #include #include #include - #include #include @@ -43,6 +41,15 @@ #include #include +#include "mcsema/Arch/Arch.h" +#include "mcsema/BC/Callback.h" +#include "mcsema/BC/Instruction.h" +#include "mcsema/BC/Legacy.h" +#include "mcsema/BC/Lift.h" +#include "mcsema/BC/Optimize.h" +#include "mcsema/BC/Segment.h" +#include "mcsema/BC/Util.h" +#include "mcsema/CFG/CFG.h" #include "remill/Arch/Arch.h" #include "remill/Arch/Instruction.h" #include "remill/BC/ABI.h" @@ -54,16 +61,6 @@ #include "remill/BC/Util.h" #include "remill/BC/Version.h" -#include "mcsema/Arch/Arch.h" -#include "mcsema/BC/Callback.h" -#include "mcsema/BC/Instruction.h" -#include "mcsema/BC/Legacy.h" -#include "mcsema/BC/Lift.h" -#include "mcsema/BC/Optimize.h" -#include "mcsema/BC/Segment.h" -#include "mcsema/BC/Util.h" -#include "mcsema/CFG/CFG.h" - DECLARE_bool(legacy_mode); DECLARE_bool(explicit_args); @@ -75,11 +72,12 @@ DEFINE_bool(add_func_state_tracer, false, "Add a debug function that prints out the register state before " "each lifted function execution."); -DEFINE_string(trace_reg_values, "", - "Add a debug function that prints out the specified register values " - "before each lifted instruction execution. The registers printed out " - "always include the current program counter, as well as the registers " - "in specified in this option (as a comma-separated list)."); +DEFINE_string( + trace_reg_values, "", + "Add a debug function that prints out the specified register values " + "before each lifted instruction execution. The registers printed out " + "always include the current program counter, as well as the registers " + "in specified in this option (as a comma-separated list)."); DEFINE_bool(add_pc_tracer, false, "Add a debug function that is invoked just before every lifted " @@ -87,54 +85,57 @@ DEFINE_bool(add_pc_tracer, false, "tracer. This is similar to --add_reg_tracer, but it doesn't " "negatively impact optimizations."); -DEFINE_bool(add_breakpoints, false, - "Add 'breakpoint' functions between every lifted instruction. This " - "allows one to set a breakpoint, in the lifted code, just before a " - "specific lifted instruction is executed. This is a debugging aid."); +DEFINE_bool( + add_breakpoints, false, + "Add 'breakpoint' functions between every lifted instruction. This " + "allows one to set a breakpoint, in the lifted code, just before a " + "specific lifted instruction is executed. This is a debugging aid."); -DEFINE_string(exception_personality_func, "__gxx_personality_v0", - "Add a personality function for lifting exception handling " - "routine. Assigned __gxx_personality_v0 as default for c++ ABTs."); +DEFINE_string( + exception_personality_func, "__gxx_personality_v0", + "Add a personality function for lifting exception handling " + "routine. Assigned __gxx_personality_v0 as default for c++ ABTs."); -DEFINE_bool(stack_protector, false, "Annotate functions so that if the bitcode " +DEFINE_bool(stack_protector, false, + "Annotate functions so that if the bitcode " "is compiled with -fstack-protector-all then the stack protection " "guards will be added."); namespace mcsema { namespace { -static llvm::Value *LoadMemoryPointer( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadMemoryPointer(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegValue(block, "MEMORY"); } -static llvm::Value *LoadMemoryPointerRef( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadMemoryPointerRef(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegAddress(block, "MEMORY"); } -static llvm::Value *LoadStatePointer( - const TranslationContext &, llvm::BasicBlock *block) { +static llvm::Value *LoadStatePointer(const TranslationContext &, + llvm::BasicBlock *block) { return remill::NthArgument(block->getParent(), remill::kStatePointerArgNum); } -static llvm::Value *LoadProgramCounter( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadProgramCounter(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegValue(block, "PC"); } -static llvm::Value *LoadProgramCounterRef( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadProgramCounterRef(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegAddress(block, "PC"); } -static llvm::Value *LoadNextProgramCounter( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadNextProgramCounter(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegValue(block, "NEXT_PC"); } -static llvm::Value *LoadNextProgramCounterRef( - const TranslationContext &ctx, llvm::BasicBlock *block) { +static llvm::Value *LoadNextProgramCounterRef(const TranslationContext &ctx, + llvm::BasicBlock *block) { return ctx.lifter->LoadRegAddress(block, "NEXT_PC"); } @@ -153,9 +154,9 @@ static llvm::Function *GetValueTracer(void) { return gValueTracer; } - gValueTracer = llvm::Function::Create( - gArch->LiftedFunctionType(), llvm::GlobalValue::PrivateLinkage, - "__mcsema_value_tracer", gModule.get()); + gValueTracer = llvm::Function::Create(gArch->LiftedFunctionType(), + llvm::GlobalValue::PrivateLinkage, + "__mcsema_value_tracer", gModule.get()); gValueTracer->removeFnAttr(llvm::Attribute::NoDuplicate); gValueTracer->addFnAttr(llvm::Attribute::AlwaysInline); gValueTracer->addFnAttr(llvm::Attribute::InlineHint); @@ -163,35 +164,33 @@ static llvm::Function *GetValueTracer(void) { gValueTracer->removeFnAttr(llvm::Attribute::OptimizeNone); gValueTracer->removeFnAttr(llvm::Attribute::NoInline); - llvm::Value *mem_ptr = remill::NthArgument( - gValueTracer, remill::kMemoryPointerArgNum); + llvm::Value *mem_ptr = + remill::NthArgument(gValueTracer, remill::kMemoryPointerArgNum); auto printf = gModule->getFunction("__mcsema_printf"); auto i32_type = llvm::Type::getInt8Ty(*gContext); if (!printf) { auto i8_type = llvm::Type::getInt8Ty(*gContext); - llvm::Type *param_types_2[] = { - mem_ptr->getType(), - llvm::PointerType::get(i8_type, 0)}; + llvm::Type *param_types_2[] = {mem_ptr->getType(), + llvm::PointerType::get(i8_type, 0)}; printf = llvm::Function::Create( llvm::FunctionType::get(mem_ptr->getType(), param_types_2, true), - llvm::GlobalValue::ExternalLinkage, - "__mcsema_printf", - gModule.get()); + llvm::GlobalValue::ExternalLinkage, "__mcsema_printf", gModule.get()); } printf->addFnAttr(llvm::Attribute::ReadNone); std::stringstream ss; std::vector args; - args.push_back(remill::NthArgument(gValueTracer, remill::kMemoryPointerArgNum)); + args.push_back( + remill::NthArgument(gValueTracer, remill::kMemoryPointerArgNum)); args.push_back(nullptr); // Format. args.push_back(remill::NthArgument(gValueTracer, remill::kPCArgNum)); auto format = gArch->address_size == 64 ? "=%016llx " : "=%018x "; auto block = llvm::BasicBlock::Create(*gContext, "", gValueTracer); - auto state_ptr = remill::NthArgument( - gValueTracer, remill::kStatePointerArgNum); + auto state_ptr = + remill::NthArgument(gValueTracer, remill::kStatePointerArgNum); auto pc_reg = gArch->RegisterByName(gArch->ProgramCounterRegisterName()); ss << "pc" << format; @@ -209,18 +208,18 @@ static llvm::Function *GetValueTracer(void) { } ss << '\n'; - auto format_str = llvm::ConstantDataArray::getString(*gContext, ss.str(), true); - auto format_var = new llvm::GlobalVariable( - *gModule, format_str->getType(), true, llvm::GlobalValue::InternalLinkage, - format_str); + auto format_str = + llvm::ConstantDataArray::getString(*gContext, ss.str(), true); + auto format_var = + new llvm::GlobalVariable(*gModule, format_str->getType(), true, + llvm::GlobalValue::InternalLinkage, format_str); - llvm::Constant *indices[] = { - llvm::ConstantInt::getNullValue(i32_type), - llvm::ConstantInt::getNullValue(i32_type)}; + llvm::Constant *indices[] = {llvm::ConstantInt::getNullValue(i32_type), + llvm::ConstantInt::getNullValue(i32_type)}; llvm::IRBuilder<> ir(block); - args[1] = llvm::ConstantExpr::getInBoundsGetElementPtr( - format_str->getType(), format_var, indices); + args[1] = llvm::ConstantExpr::getInBoundsGetElementPtr(format_str->getType(), + format_var, indices); mem_ptr = ir.CreateCall(printf, args); ir.CreateRet(mem_ptr); @@ -236,9 +235,9 @@ static llvm::Function *GetRegTracer(void) { if (!gRegTracer) { gRegTracer = gModule->getFunction("__mcsema_reg_tracer"); if (!gRegTracer) { - gRegTracer = llvm::Function::Create( - gArch->LiftedFunctionType(), llvm::GlobalValue::ExternalLinkage, - "__mcsema_reg_tracer", gModule.get()); + gRegTracer = llvm::Function::Create(gArch->LiftedFunctionType(), + llvm::GlobalValue::ExternalLinkage, + "__mcsema_reg_tracer", gModule.get()); gRegTracer->addFnAttr(llvm::Attribute::NoDuplicate); gRegTracer->removeFnAttr(llvm::Attribute::AlwaysInline); gRegTracer->removeFnAttr(llvm::Attribute::InlineHint); @@ -262,11 +261,11 @@ static llvm::Function *GetPCTracer(uint64_t pc) { gPCTracer = gModule->getFunction("__mcsema_pc_tracer"); if (!gPCTracer) { llvm::Type *arg_types[1] = {gWordType}; - auto func_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(*gContext), arg_types, false); - gPCTracer = llvm::Function::Create( - func_type, llvm::GlobalValue::ExternalLinkage, - "__mcsema_pc_tracer", gModule.get()); + auto func_type = llvm::FunctionType::get(llvm::Type::getVoidTy(*gContext), + arg_types, false); + gPCTracer = + llvm::Function::Create(func_type, llvm::GlobalValue::ExternalLinkage, + "__mcsema_pc_tracer", gModule.get()); gPCTracer->addFnAttr(llvm::Attribute::NoDuplicate); gPCTracer->removeFnAttr(llvm::Attribute::AlwaysInline); gPCTracer->removeFnAttr(llvm::Attribute::InlineHint); @@ -294,11 +293,10 @@ static llvm::Function *GetBreakPoint(uint64_t pc) { } static const auto mem_ptr_type = remill::MemoryPointerType(gModule.get()); - llvm::Type * const params[1] = {mem_ptr_type}; + llvm::Type *const params[1] = {mem_ptr_type}; const auto fty = llvm::FunctionType::get(mem_ptr_type, params, false); - func = llvm::Function::Create( - fty, llvm::GlobalValue::ExternalLinkage, - func_name, gModule.get()); + func = llvm::Function::Create(fty, llvm::GlobalValue::ExternalLinkage, + func_name, gModule.get()); // Make sure to keep this function around (along with `ExternalLinkage`). func->addFnAttr(llvm::Attribute::OptimizeNone); @@ -324,14 +322,14 @@ static llvm::Function *GetPersonalityFunction(void) { // The personality function is lifted as global variable. Check and erase the // variable before declaring it as the function. - if (auto personality_func_var = gModule->getGlobalVariable(personality_func_name); + if (auto personality_func_var = + gModule->getGlobalVariable(personality_func_name); personality_func_var) { if (personality_func_var->hasNUsesOrMore(1)) { - LOG(ERROR) - << "Renaming existing exception personality variable " - << FLAGS_exception_personality_func; - personality_func_var->setName( - FLAGS_exception_personality_func + "__original"); + LOG(ERROR) << "Renaming existing exception personality variable " + << FLAGS_exception_personality_func; + personality_func_var->setName(FLAGS_exception_personality_func + + "__original"); } else { personality_func_var->eraseFromParent(); } @@ -353,16 +351,12 @@ static llvm::Function *GetExceptionHandlerPrologue(void) { auto dword_type = llvm::Type::getInt32Ty(*gContext); auto exception_handler = gModule->getFunction("__mcsema_exception_ret"); if (exception_handler == nullptr) { - llvm::Type* args_type[] = { - gWordType, - gWordType, - dword_type - }; - auto func_type = llvm::FunctionType::get( - llvm::Type::getVoidTy(*gContext), args_type, false); - exception_handler = llvm::Function::Create( - func_type, llvm::Function::ExternalWeakLinkage, - "__mcsema_exception_ret", gModule.get()); + llvm::Type *args_type[] = {gWordType, gWordType, dword_type}; + auto func_type = llvm::FunctionType::get(llvm::Type::getVoidTy(*gContext), + args_type, false); + exception_handler = + llvm::Function::Create(func_type, llvm::Function::ExternalWeakLinkage, + "__mcsema_exception_ret", gModule.get()); } return exception_handler; } @@ -372,40 +366,34 @@ static llvm::Function *GetExceptionHandlerPrologue(void) { static llvm::Function *GetExceptionTypeIndex(void) { auto get_index_func = gModule->getFunction("__mcsema_get_type_index"); if (!get_index_func) { - get_index_func = llvm::Function::Create( - llvm::FunctionType::get(gWordType, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__mcsema_get_type_index", gModule.get()); + get_index_func = + llvm::Function::Create(llvm::FunctionType::get(gWordType, false), + llvm::GlobalValue::ExternalWeakLinkage, + "__mcsema_get_type_index", gModule.get()); } return get_index_func; } -enum class PCValueKind { - kSymbolicPC, - kConcretePC, - kUndefPC -}; +enum class PCValueKind { kSymbolicPC, kConcretePC, kUndefPC }; // Add a invoke to another function and then update the memory pointer with the // result of the function. It also needs to stash the stack and frame pointer which // can be restored before handling the exception handler. -static void InlineSubFuncInvoke( - const TranslationContext &ctx, - llvm::BasicBlock *block, - llvm::Function *sub, - llvm::BasicBlock *if_normal, - llvm::BasicBlock *if_exception, - const NativeFunction *cfg_func, - PCValueKind pc_kind=PCValueKind::kSymbolicPC) { - - llvm::IRBuilder <> ir(block); +static void +InlineSubFuncInvoke(const TranslationContext &ctx, llvm::BasicBlock *block, + llvm::Function *sub, llvm::BasicBlock *if_normal, + llvm::BasicBlock *if_exception, + const NativeFunction *cfg_func, + PCValueKind pc_kind = PCValueKind::kSymbolicPC) { + + llvm::IRBuilder<> ir(block); auto get_sp_func = gModule->getFunction("__mcsema_get_stack_pointer"); if (!get_sp_func) { - get_sp_func = llvm::Function::Create( - llvm::FunctionType::get(gWordType, false), - llvm::GlobalValue::ExternalLinkage, - "__mcsema_get_stack_pointer", gModule.get()); + get_sp_func = + llvm::Function::Create(llvm::FunctionType::get(gWordType, false), + llvm::GlobalValue::ExternalLinkage, + "__mcsema_get_stack_pointer", gModule.get()); } auto sp_var = ir.CreateCall(get_sp_func); @@ -413,10 +401,10 @@ static void InlineSubFuncInvoke( auto get_bp_func = gModule->getFunction("__mcsema_get_frame_pointer"); if (!get_bp_func) { - get_bp_func = llvm::Function::Create( - llvm::FunctionType::get(gWordType, false), - llvm::GlobalValue::ExternalLinkage, - "__mcsema_get_frame_pointer", gModule.get()); + get_bp_func = + llvm::Function::Create(llvm::FunctionType::get(gWordType, false), + llvm::GlobalValue::ExternalLinkage, + "__mcsema_get_frame_pointer", gModule.get()); } llvm::Value *args[remill::kNumBlockArgs]; @@ -433,8 +421,7 @@ static void InlineSubFuncInvoke( auto bp_var = ir.CreateCall(get_bp_func); ir.CreateStore(bp_var, ctx.frame_ptr_var); - auto invoke = ir.CreateInvoke( - sub, if_normal, if_exception, args, ""); + auto invoke = ir.CreateInvoke(sub, if_normal, if_exception, args, ""); invoke->setCallingConv(sub->getCallingConv()); // Store the memory pointer down the normal path of the invoked function. @@ -446,11 +433,8 @@ static void InlineSubFuncInvoke( // Add a call to another function, and then update the memory pointer with the // result of the function. static llvm::Value *LiftSubFuncCall( - const TranslationContext &ctx, - llvm::BasicBlock *block, - llvm::Function *sub, - PCValueKind pc_kind=PCValueKind::kSymbolicPC, - uint64_t concrete_pc=0) { + const TranslationContext &ctx, llvm::BasicBlock *block, llvm::Function *sub, + PCValueKind pc_kind = PCValueKind::kSymbolicPC, uint64_t concrete_pc = 0) { llvm::Value *args[remill::kNumBlockArgs]; args[remill::kMemoryPointerArgNum] = LoadMemoryPointer(ctx, block); args[remill::kStatePointerArgNum] = LoadStatePointer(ctx, block); @@ -474,23 +458,22 @@ static llvm::Value *LiftSubFuncCall( // Wrap the lifted function `cfg_func` with its type specification, if any, and // provide a lifted interface to it. -static llvm::Function *CallableLiftedFunc( - const NativeFunction *cfg_func, llvm::Function *fallback) { +static llvm::Function *CallableLiftedFunc(const NativeFunction *cfg_func, + llvm::Function *fallback) { if (cfg_func->callable_lifted_function) { return cfg_func->callable_lifted_function; } else { - LOG(ERROR) - << "Falling back on " << cfg_func->name; + LOG(ERROR) << "Falling back on " << cfg_func->name; cfg_func->callable_lifted_function = fallback; return fallback; } } // Find an external function associated with this indirect jump. -static llvm::Function *DevirtualizeIndirectFlow( - TranslationContext &ctx, llvm::Function *fallback) { +static llvm::Function *DevirtualizeIndirectFlow(TranslationContext &ctx, + llvm::Function *fallback) { if (!ctx.cfg_inst) { return fallback; } @@ -518,25 +501,24 @@ FindFunction(TranslationContext &ctx, uint64_t target_pc) { if (auto flow = ctx.cfg_inst->flow; flow) { cfg_func = ctx.cfg_module->TryGetFunction(flow->target_ea); if (cfg_func) { - return { - cfg_func, - CallableLiftedFunc(cfg_func, ctx.lifter->intrinsics->function_call)}; + return {cfg_func, CallableLiftedFunc( + cfg_func, ctx.lifter->intrinsics->function_call)}; } } } cfg_func = ctx.cfg_module->TryGetFunction(target_pc); if (cfg_func) { - return {cfg_func, - CallableLiftedFunc(cfg_func, ctx.lifter->intrinsics->function_call)}; + return {cfg_func, CallableLiftedFunc( + cfg_func, ctx.lifter->intrinsics->function_call)}; } return {nullptr, nullptr}; } // Try to decode an instruction. -static bool TryDecodeInstruction( - TranslationContext &ctx, uint64_t pc, bool is_delayed) { +static bool TryDecodeInstruction(TranslationContext &ctx, uint64_t pc, + bool is_delayed) { remill::Instruction &inst = is_delayed ? ctx.delayed_inst : ctx.inst; @@ -555,10 +537,9 @@ static bool TryDecodeInstruction( ++i, byte = ctx.cfg_module->FindNextByte(byte)) { auto maybe_val = byte.Value(); if (remill::IsError(maybe_val)) { - LOG(ERROR) - << "Unable to read balue of byte at " << std::hex - << byte.Address() << std::dec << ": " - << remill::GetErrorString(maybe_val); + LOG(ERROR) << "Unable to read balue of byte at " << std::hex + << byte.Address() << std::dec << ": " + << remill::GetErrorString(maybe_val); break; } else { inst_bytes.push_back(static_cast(remill::GetReference(maybe_val))); @@ -572,9 +553,8 @@ static bool TryDecodeInstruction( } } -static llvm::BasicBlock *GetOrCreateBlock(TranslationContext &ctx, - uint64_t pc, - bool force_as_block=false); +static llvm::BasicBlock *GetOrCreateBlock(TranslationContext &ctx, uint64_t pc, + bool force_as_block = false); // Create a landing pad basic block. static void CreateLandingPad(TranslationContext &ctx, @@ -582,15 +562,16 @@ static void CreateLandingPad(TranslationContext &ctx, std::stringstream ss; auto dword_type = llvm::Type::getInt32Ty(*gContext); + // `__mcsema_exception_ret` argument list llvm::Value *args[3]; auto is_catch = (eh_entry->action_index != 0); ss << "landingpad_" << std::hex << eh_entry->lp_ea; - auto landing_bb = llvm::BasicBlock::Create( - *gContext, ss.str(), ctx.lifted_func); + auto landing_bb = + llvm::BasicBlock::Create(*gContext, ss.str(), ctx.lifted_func); - std::vector elem_types = { - llvm::Type::getInt8PtrTy(*gContext), dword_type}; + std::vector elem_types = {llvm::Type::getInt8PtrTy(*gContext), + dword_type}; // TODO(akshayk): Should this struct be packed? llvm::IRBuilder<> ir(landing_bb); @@ -607,11 +588,12 @@ static void CreateLandingPad(TranslationContext &ctx, if (is_catch) { std::stringstream g_variable_name_ss; - std::vectorarray_value_const; + std::vector array_value_const; auto catch_all = false; unsigned long catch_all_index = 0; for (auto &it : eh_entry->type_var) { + // Check the ttype variables are not null auto type = it.second; CHECK_NOTNULL(type); @@ -646,14 +628,13 @@ static void CreateLandingPad(TranslationContext &ctx, // value is a dummy, and it is used to avoid further index computation. g_variable_name_ss << "gvar_landingpad_" << std::hex << eh_entry->lp_ea; auto g_variable_name = g_variable_name_ss.str(); - auto array_type = llvm::ArrayType::get( - dword_type, eh_entry->type_var.size() + 1); + auto array_type = + llvm::ArrayType::get(dword_type, eh_entry->type_var.size() + 1); if (!gModule->getOrInsertGlobal(g_variable_name, array_type)) { - LOG_IF(ERROR, 1) - << "Can't create the global variable " << g_variable_name - << " for the landing pad at" << std::hex << eh_entry->lp_ea - << std::dec; + LOG_IF(ERROR, 1) << "Can't create the global variable " << g_variable_name + << " for the landing pad at" << std::hex + << eh_entry->lp_ea << std::dec; } auto gvar_landingpad = gModule->getGlobalVariable(g_variable_name); @@ -664,8 +645,8 @@ static void CreateLandingPad(TranslationContext &ctx, std::reverse(array_value_const.begin(), array_value_const.end()); llvm::ArrayRef array_value(array_value_const); - llvm::Constant* const_array = llvm::ConstantArray::get( - array_type, array_value); + llvm::Constant *const_array = + llvm::ConstantArray::get(array_type, array_value); gvar_landingpad->setInitializer(const_array); auto type_index_value2 = ir.CreateCall(GetExceptionTypeIndex()); auto type_index_value1 = llvm::ConstantInt::get(dword_type, 0); @@ -740,13 +721,11 @@ static void LiftExceptionFrameLP(TranslationContext &ctx, } static void LiftFuncRestoredRegs(TranslationContext &ctx, - llvm::BasicBlock *block, - bool force=false); + llvm::BasicBlock *block, bool force = false); // Lift an indirect jump into a switch instruction. -static void LiftIndirectJump( - TranslationContext &ctx, llvm::BasicBlock *block, - const remill::Instruction &inst) { +static void LiftIndirectJump(TranslationContext &ctx, llvm::BasicBlock *block, + const remill::Instruction &inst) { auto exit_point = GetLiftedToNativeExitPoint(kExitPointJump); auto fallback = DevirtualizeIndirectFlow(ctx, exit_point); @@ -781,20 +760,18 @@ static void LiftIndirectJump( continue; } else if (!succ_eas.count(block_ea)) { - LOG(WARNING) - << "Adding block " << std::hex << block_ea - << " with no predecessors as additional target of the " - << " indirect jump at " << inst.pc << std::dec; + LOG(WARNING) << "Adding block " << std::hex << block_ea + << " with no predecessors as additional target of the " + << " indirect jump at " << inst.pc << std::dec; block_map.emplace(block_ea, GetOrCreateBlock(ctx, block_ea, true)); // This block is referenced by data, so it also makes a good jump table // target. } else if (cfg_block->is_referenced_by_data && block_ea != ctx.cfg_func->ea) { - LOG(WARNING) - << "Adding block " << std::hex << block_ea - << " referenced by data as additional target of the " - << " indirect jump at " << inst.pc << std::dec; + LOG(WARNING) << "Adding block " << std::hex << block_ea + << " referenced by data as additional target of the " + << " indirect jump at " << inst.pc << std::dec; block_map.emplace(block_ea, GetOrCreateBlock(ctx, block_ea, true)); } } @@ -802,9 +779,9 @@ static void LiftIndirectJump( // We have no jump table information, so assume that it's an indirect tail // call, so just go native. if (block_map.empty()) { - LOG(INFO) - << "Indirect jump at " << std::hex << inst.pc << std::dec - << " looks like a thunk; falling back to " << fallback->getName().str(); + LOG(INFO) << "Indirect jump at " << std::hex << inst.pc << std::dec + << " looks like a thunk; falling back to " + << fallback->getName().str(); remill::AddTerminatingTailCall(block, fallback); return; } @@ -812,45 +789,42 @@ static void LiftIndirectJump( // Create a "default" fall-back block for the switch. The idea here is that // the xrefs might have been lifted to "block addresses" in the lifted // `.text` section. - auto fallback_block1 = llvm::BasicBlock::Create( - *gContext, "", block->getParent()); + auto fallback_block1 = + llvm::BasicBlock::Create(*gContext, "", block->getParent()); // Create a "default" fall-back block for the switch. - auto fallback_block2 = llvm::BasicBlock::Create( - *gContext, "", block->getParent()); + auto fallback_block2 = + llvm::BasicBlock::Create(*gContext, "", block->getParent()); auto num_blocks = static_cast(block_map.size()); auto switch_index = LoadProgramCounter(ctx, block); if (ctx.cfg_inst && ctx.cfg_inst->offset_table) { - LOG(INFO) - << "Indirect jump at " << std::hex << ctx.cfg_inst->ea - << " is a jump through an offset table with offset " - << std::hex << ctx.cfg_inst->offset_table->target_ea << std::dec; + LOG(INFO) << "Indirect jump at " << std::hex << ctx.cfg_inst->ea + << " is a jump through an offset table with offset " << std::hex + << ctx.cfg_inst->offset_table->target_ea << std::dec; llvm::IRBuilder<> ir(block); switch_index = ir.CreateAdd( - ir.CreateSub( - switch_index, - LiftXrefInCode(ctx.cfg_inst->offset_table->target_ea)), - llvm::ConstantInt::get( - gWordType, ctx.cfg_inst->offset_table->target_ea)); + ir.CreateSub(switch_index, + LiftXrefInCode(ctx.cfg_inst->offset_table->target_ea)), + llvm::ConstantInt::get(gWordType, + ctx.cfg_inst->offset_table->target_ea)); -// // TODO(pag): Keep??? -// remill::StoreProgramCounter(block, switch_index); + // // TODO(pag): Keep??? + // remill::StoreProgramCounter(block, switch_index); } // Put the `switch` into its own block. This makes handling indirect jumps // with delay slots easier, because then we can treat them as direct jumps // to the switch block. - auto switch_block = llvm::BasicBlock::Create( - *gContext, "", block->getParent()); - auto switch_inst = llvm::SwitchInst::Create( - switch_index, fallback_block1, num_blocks, switch_block); + auto switch_block = + llvm::BasicBlock::Create(*gContext, "", block->getParent()); + auto switch_inst = llvm::SwitchInst::Create(switch_index, fallback_block1, + num_blocks, switch_block); - LOG(INFO) - << "Indirect jump at " << std::hex << inst.pc - << " has " << std::dec << num_blocks << " targets"; + LOG(INFO) << "Indirect jump at " << std::hex << inst.pc << " has " << std::dec + << num_blocks << " targets"; // Add the cases. std::vector fallback_block_eas; @@ -881,24 +855,25 @@ static void LiftIndirectJump( const auto max_ea = fallback_block_eas.back(); auto lifted_max_ea = LiftXrefInCode(max_ea); - llvm::Value *block_offset = llvm::BinaryOperator::Create( - llvm::Instruction::Sub, lifted_max_ea, switch_index, "", - fallback_block1); + llvm::Value *block_offset = + llvm::BinaryOperator::Create(llvm::Instruction::Sub, lifted_max_ea, + switch_index, "", fallback_block1); // The block addresses will be 64-bit values, but the lifted xrefs in the // jump table may actually be 64-bit xrefs, casted down to 32 bits, so we're // going to deal with truncated values to hopefully make things work. if (gArch->address_size == 64 && !any_are_64_bit) { - block_offset = llvm::TruncInst::Create( - llvm::Instruction::Trunc, block_offset, i32_type, "", fallback_block1); - block_offset = llvm::ZExtInst::Create( - llvm::Instruction::ZExt, block_offset, - gWordType, "", fallback_block1); + block_offset = + llvm::TruncInst::Create(llvm::Instruction::Trunc, block_offset, + i32_type, "", fallback_block1); + block_offset = + llvm::ZExtInst::Create(llvm::Instruction::ZExt, block_offset, + gWordType, "", fallback_block1); } // Fallback switch on lifted block addresses. - switch_inst = llvm::SwitchInst::Create( - block_offset, fallback_block2, num_blocks, fallback_block1); + switch_inst = llvm::SwitchInst::Create(block_offset, fallback_block2, + num_blocks, fallback_block1); for (auto [ea, block] : block_map) { switch_inst->addCase( @@ -925,19 +900,15 @@ static void LiftIndirectJump( func_addr = llvm::ConstantExpr::getZExt(func_addr, gWordType); } - auto cmp = llvm::CmpInst::Create( - llvm::Instruction::ICmp, llvm::CmpInst::ICMP_EQ, - switch_index, func_addr, - "", fallback_block2); + auto cmp = + llvm::CmpInst::Create(llvm::Instruction::ICmp, llvm::CmpInst::ICMP_EQ, + switch_index, func_addr, "", fallback_block2); - auto next_fallback = llvm::BasicBlock::Create( - *gContext, "", block->getParent()); + auto next_fallback = + llvm::BasicBlock::Create(*gContext, "", block->getParent()); - llvm::BranchInst::Create( - block_map[target_func_ea], - next_fallback, - cmp, - fallback_block2); + llvm::BranchInst::Create(block_map[target_func_ea], next_fallback, cmp, + fallback_block2); fallback_block2 = next_fallback; } @@ -952,17 +923,17 @@ static void LiftIndirectJump( } // Call instrumentation. These are useful for debugging. -static void Instrument( - const TranslationContext &ctx, llvm::BasicBlock *block, uint64_t inst_ea) { +static void Instrument(const TranslationContext &ctx, llvm::BasicBlock *block, + uint64_t inst_ea) { if (!FLAGS_trace_reg_values.empty()) { - LiftSubFuncCall( - ctx, block, GetValueTracer(), PCValueKind::kConcretePC, inst_ea); + LiftSubFuncCall(ctx, block, GetValueTracer(), PCValueKind::kConcretePC, + inst_ea); } if (FLAGS_add_state_tracer) { - LiftSubFuncCall( - ctx, block, GetRegTracer(), PCValueKind::kConcretePC, inst_ea); + LiftSubFuncCall(ctx, block, GetRegTracer(), PCValueKind::kConcretePC, + inst_ea); } if (FLAGS_add_breakpoints) { @@ -983,8 +954,7 @@ static void Instrument( // problem lifting. static void LiftInstIntoBlock(TranslationContext &ctx, remill::Instruction &inst, - llvm::BasicBlock *block, - bool is_delayed) { + llvm::BasicBlock *block, bool is_delayed) { const auto inst_ea = inst.pc; auto prev_cfg_inst = ctx.cfg_inst; if (is_delayed) { @@ -1027,8 +997,7 @@ static llvm::Function *GetRestorer(llvm::Type *type) { llvm::Type *param_types[] = {type, type}; func = llvm::Function::Create( llvm::FunctionType::get(type, param_types, false), - llvm::GlobalValue::ExternalLinkage, - name, gModule.get()); + llvm::GlobalValue::ExternalLinkage, name, gModule.get()); // Tell LLVM that this function doesn't access memory; this improves LLVM's // ability to optimize around this function. @@ -1048,9 +1017,9 @@ static llvm::Constant *GetKiller(llvm::Type *type) { auto gv = gModule->getGlobalVariable("__remill_kill"); if (!gv) { - gv = new llvm::GlobalVariable( - *gModule, type, false, llvm::GlobalValue::ExternalLinkage, - nullptr, "__remill_kill"); + gv = new llvm::GlobalVariable(*gModule, type, false, + llvm::GlobalValue::ExternalLinkage, nullptr, + "__remill_kill"); } gc = llvm::ConstantExpr::getPtrToInt(gv, type); @@ -1088,10 +1057,12 @@ static llvm::Constant *GetKiller(llvm::Type *type) { //} // Save and restore registers around the body of a function. -void SaveAndRestoreFunctionPreservedRegs( - TranslationContext &ctx, llvm::BasicBlock *entry_block, - llvm::BasicBlock *inst_block, llvm::Value *state_ptr, - uint64_t end_ea, const NativePreservedRegisters ®s) { +void SaveAndRestoreFunctionPreservedRegs(TranslationContext &ctx, + llvm::BasicBlock *entry_block, + llvm::BasicBlock *inst_block, + llvm::Value *state_ptr, + uint64_t end_ea, + const NativePreservedRegisters ®s) { llvm::IRBuilder<> ir(entry_block); llvm::IRBuilder<> restore_ir(inst_block); @@ -1125,10 +1096,8 @@ void SaveAndRestoreFunctionPreservedRegs( // NOTE(pag): We use volatile stores so that LLVM doesn't eliminate them // if we're saving/restoring an `alloca`d object. const auto restorer = GetRestorer(reg->getType()); - restore_ir.CreateStore( - restore_ir.CreateCall(restorer, restorer_args), - reg_ptr, - true /* IsVolatile */); + restore_ir.CreateStore(restore_ir.CreateCall(restorer, restorer_args), + reg_ptr, true /* IsVolatile */); // Restored ones should be inserted in reverse order. restore_ir.SetInsertPoint(reg_latest); @@ -1136,12 +1105,12 @@ void SaveAndRestoreFunctionPreservedRegs( } static void LiftDelayedInstIntoBlock(TranslationContext &ctx, - llvm::BasicBlock *block, - bool on_taken_path) { + llvm::BasicBlock *block, + bool on_taken_path) { if (ctx.delayed_inst.IsValid() && - gArch->NextInstructionIsDelayed(ctx.inst, ctx.delayed_inst, on_taken_path)) { - LiftInstIntoBlock( - ctx, ctx.delayed_inst, block, true /* is_delayed */); + gArch->NextInstructionIsDelayed(ctx.inst, ctx.delayed_inst, + on_taken_path)) { + LiftInstIntoBlock(ctx, ctx.delayed_inst, block, true /* is_delayed */); } } @@ -1150,8 +1119,7 @@ static void LiftSavedRegs(TranslationContext &ctx, llvm::BasicBlock *block) { llvm::IRBuilder<> ir(block); DCHECK(ctx.inst.IsFunctionCall()); ctx.cfg_module->ForEachInstructionPreservedRegister( - ctx.inst.pc, - [=, &ir, &ctx] (const std::string ®_name) { + ctx.inst.pc, [=, &ir, &ctx](const std::string ®_name) { if (const auto reg = gArch->RegisterByName(reg_name); reg) { const auto reg_ptr = ctx.lifter->LoadRegAddress(block, reg_name); const auto reg_val = ir.CreateLoad(reg_ptr); @@ -1185,9 +1153,9 @@ void LiftFuncRestoredRegs(TranslationContext &ctx, llvm::BasicBlock *block, const auto func = block->getParent(); const auto state_ptr = LoadStatePointer(ctx, block); - SaveAndRestoreFunctionPreservedRegs( - ctx, &(func->getEntryBlock()), block, state_ptr, - ctx.inst.pc, *(regs_it->second)); + SaveAndRestoreFunctionPreservedRegs(ctx, &(func->getEntryBlock()), block, + state_ptr, ctx.inst.pc, + *(regs_it->second)); } static void KillPCAndNextPC(TranslationContext &ctx, llvm::BasicBlock *block) { @@ -1202,21 +1170,20 @@ static void KillPCAndNextPC(TranslationContext &ctx, llvm::BasicBlock *block) { static void LiftKilledRegs(TranslationContext &ctx, llvm::BasicBlock *block) { llvm::IRBuilder<> ir(block); ctx.cfg_module->ForEachInstructionKilledRegister( - ctx.inst.pc, - [=, &ir, &ctx](const std::string ®_name) { - const auto reg_ptr = ctx.lifter->LoadRegAddress(block, reg_name); - if (!reg_ptr) { - return; - } - auto reg_type = reg_ptr->getType()->getPointerElementType(); - ir.CreateStore(GetKiller(reg_type), reg_ptr); - }); + ctx.inst.pc, [=, &ir, &ctx](const std::string ®_name) { + const auto reg_ptr = ctx.lifter->LoadRegAddress(block, reg_name); + if (!reg_ptr) { + return; + } + auto reg_type = reg_ptr->getType()->getPointerElementType(); + ir.CreateStore(GetKiller(reg_type), reg_ptr); + }); } // Get the basic block within this function associated with a specific program // counter. -llvm::BasicBlock *GetOrCreateBlock(TranslationContext &ctx, - uint64_t pc, bool force_as_block) { +llvm::BasicBlock *GetOrCreateBlock(TranslationContext &ctx, uint64_t pc, + bool force_as_block) { auto &block = ctx.ea_to_block[pc]; if (block) { return block; @@ -1242,7 +1209,7 @@ static uint64_t FunctionReturnAddress(TranslationContext &ctx) { // Lift a decoded block into a function. static void LiftInstIntoFunction(TranslationContext &ctx, llvm::BasicBlock *block) { - LiftInstIntoBlock(ctx, ctx.inst, block, false /* is_delayed */); + LiftInstIntoBlock(ctx, ctx.inst, block, false /* is_delayed */); // We might need to lift another instruction and execute it in the delay // slot. `cont` contains enough info to redirect control flow after we've @@ -1254,9 +1221,9 @@ static void LiftInstIntoFunction(TranslationContext &ctx, if (gArch->MayHaveDelaySlot(ctx.inst)) { if (!TryDecodeInstruction(ctx, ctx.inst.delayed_pc, true) || !ctx.delayed_inst.IsValid()) { - LOG(ERROR) - << "Unable to decode or use delayed instruction at " << std::hex - << ctx.inst.delayed_pc << std::dec << " of " << ctx.inst.Serialize(); + LOG(ERROR) << "Unable to decode or use delayed instruction at " + << std::hex << ctx.inst.delayed_pc << std::dec << " of " + << ctx.inst.Serialize(); } } @@ -1290,10 +1257,11 @@ static void LiftInstIntoFunction(TranslationContext &ctx, LiftFuncRestoredRegs(ctx, block); KillPCAndNextPC(ctx, block); LiftKilledRegs(ctx, block); - llvm::ReturnInst::Create( - *gContext, LoadMemoryPointer(ctx, block), block); + llvm::ReturnInst::Create(*gContext, LoadMemoryPointer(ctx, block), + block); } else { - llvm::BranchInst::Create(GetOrCreateBlock(ctx, ctx.inst.next_pc), block); + llvm::BranchInst::Create(GetOrCreateBlock(ctx, ctx.inst.next_pc), + block); } break; } @@ -1301,8 +1269,8 @@ static void LiftInstIntoFunction(TranslationContext &ctx, case remill::Instruction::kCategoryDirectJump: LiftDelayedInstIntoBlock(ctx, block, true); KillPCAndNextPC(ctx, block); - llvm::BranchInst::Create( - GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), block); + llvm::BranchInst::Create(GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), + block); break; case remill::Instruction::kCategoryIndirectJump: @@ -1313,7 +1281,8 @@ static void LiftInstIntoFunction(TranslationContext &ctx, case remill::Instruction::kCategoryDirectFunctionCall: { LiftDelayedInstIntoBlock(ctx, block, true); - if (auto [targ_cfg_func, targ_func] = FindFunction(ctx, ctx.inst.branch_taken_pc); + if (auto [targ_cfg_func, targ_func] = + FindFunction(ctx, ctx.inst.branch_taken_pc); targ_cfg_func && targ_func) { if (!ctx.cfg_inst || !ctx.cfg_inst->lp_ea) { @@ -1332,17 +1301,16 @@ static void LiftInstIntoFunction(TranslationContext &ctx, auto normal_block = GetOrCreateBlock(ctx, FunctionReturnAddress(ctx)); KillPCAndNextPC(ctx, block); LiftKilledRegs(ctx, block); - InlineSubFuncInvoke( - ctx, block, targ_func, normal_block, exception_block, - ctx.cfg_func, PCValueKind::kUndefPC); + InlineSubFuncInvoke(ctx, block, targ_func, normal_block, + exception_block, ctx.cfg_func, + PCValueKind::kUndefPC); } // Treat a `call +5` as not actually needing to call out to a // new subroutine. } else if (ctx.inst.branch_taken_pc != ctx.inst.next_pc) { - LOG(WARNING) - << "Not adding a subroutine self-call at " - << std::hex << ctx.inst.pc << std::dec; + LOG(WARNING) << "Not adding a subroutine self-call at " << std::hex + << ctx.inst.pc << std::dec; llvm::BranchInst::Create( GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), block); @@ -1350,8 +1318,8 @@ static void LiftInstIntoFunction(TranslationContext &ctx, } else { LOG(ERROR) << "Cannot find target of instruction at " << std::hex - << ctx.inst.pc << "; the static target " - << std::hex << ctx.inst.branch_taken_pc + << ctx.inst.pc << "; the static target " << std::hex + << ctx.inst.branch_taken_pc << " is not associated with a lifted subroutine, and it does not " << "have a known call target" << std::dec; @@ -1359,7 +1327,7 @@ static void LiftInstIntoFunction(TranslationContext &ctx, KillPCAndNextPC(ctx, block); LiftKilledRegs(ctx, block); LiftSubFuncCall(ctx, block, intrinsics->function_call, - PCValueKind::kConcretePC, ctx.inst.branch_taken_pc); + PCValueKind::kConcretePC, ctx.inst.branch_taken_pc); LiftRestoredRegs(ctx, block); llvm::BranchInst::Create( GetOrCreateBlock(ctx, ctx.inst.branch_not_taken_pc), block); @@ -1368,10 +1336,9 @@ static void LiftInstIntoFunction(TranslationContext &ctx, } case remill::Instruction::kCategoryIndirectFunctionCall: { - const auto fallback_func = GetLiftedToNativeExitPoint( - kExitPointFunctionCall); - const auto target_func = DevirtualizeIndirectFlow( - ctx, fallback_func); + const auto fallback_func = + GetLiftedToNativeExitPoint(kExitPointFunctionCall); + const auto target_func = DevirtualizeIndirectFlow(ctx, fallback_func); LOG_IF(ERROR, ctx.cfg_inst && ctx.cfg_inst->lp_ea) << "Not treating call from " << std::hex << ctx.inst.pc @@ -1397,16 +1364,15 @@ static void LiftInstIntoFunction(TranslationContext &ctx, auto normal_block = GetOrCreateBlock(ctx, FunctionReturnAddress(ctx)); if (fallback_func == target_func) { - InlineSubFuncInvoke( - ctx, block, target_func, normal_block, exception_block, - ctx.cfg_func); + InlineSubFuncInvoke(ctx, block, target_func, normal_block, + exception_block, ctx.cfg_func); } else { KillPCAndNextPC(ctx, block); LiftKilledRegs(ctx, block); - InlineSubFuncInvoke( - ctx, block, target_func, normal_block, exception_block, - ctx.cfg_func, PCValueKind::kUndefPC); + InlineSubFuncInvoke(ctx, block, target_func, normal_block, + exception_block, ctx.cfg_func, + PCValueKind::kUndefPC); } } break; @@ -1417,23 +1383,21 @@ static void LiftInstIntoFunction(TranslationContext &ctx, LiftFuncRestoredRegs(ctx, block); KillPCAndNextPC(ctx, block); LiftKilledRegs(ctx, block); - llvm::ReturnInst::Create( - *gContext, LoadMemoryPointer(ctx, block), block); + llvm::ReturnInst::Create(*gContext, LoadMemoryPointer(ctx, block), block); break; case remill::Instruction::kCategoryConditionalBranch: case remill::Instruction::kCategoryConditionalAsyncHyperCall: { const auto cond = remill::LoadBranchTaken(block); - const auto taken_block = llvm::BasicBlock::Create( - *gContext, "", ctx.lifted_func); - const auto not_taken_block = llvm::BasicBlock::Create( - *gContext, "", ctx.lifted_func); - llvm::BranchInst::Create( - taken_block, not_taken_block, cond, block); + const auto taken_block = + llvm::BasicBlock::Create(*gContext, "", ctx.lifted_func); + const auto not_taken_block = + llvm::BasicBlock::Create(*gContext, "", ctx.lifted_func); + llvm::BranchInst::Create(taken_block, not_taken_block, cond, block); LiftDelayedInstIntoBlock(ctx, taken_block, true); LiftDelayedInstIntoBlock(ctx, not_taken_block, false); - llvm::BranchInst::Create( - GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), taken_block); + llvm::BranchInst::Create(GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), + taken_block); llvm::BranchInst::Create( GetOrCreateBlock(ctx, ctx.inst.branch_not_taken_pc), not_taken_block); break; @@ -1442,15 +1406,15 @@ static void LiftInstIntoFunction(TranslationContext &ctx, case remill::Instruction::kCategoryAsyncHyperCall: LiftDelayedInstIntoBlock(ctx, block, true); LiftSubFuncCall(ctx, block, ctx.lifter->intrinsics->async_hyper_call); - llvm::BranchInst::Create( - GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), block); + llvm::BranchInst::Create(GetOrCreateBlock(ctx, ctx.inst.branch_taken_pc), + block); break; } } -static llvm::Function *LiftFunction( - const NativeModule *cfg_module, const NativeFunction *cfg_func, - const remill::IntrinsicTable &intrinsics) { +static llvm::Function *LiftFunction(const NativeModule *cfg_module, + const NativeFunction *cfg_func, + const remill::IntrinsicTable &intrinsics) { CHECK(!cfg_func->is_external) << "Should not lift external function " << cfg_func->name; @@ -1463,15 +1427,13 @@ static llvm::Function *LiftFunction( // CFG decoding process. In practice, though, that only really // affects externals. if (!lifted_func->empty()) { - LOG(WARNING) - << "Asking to re-insert function: " << cfg_func->lifted_name - << "; returning current function instead"; + LOG(WARNING) << "Asking to re-insert function: " << cfg_func->lifted_name + << "; returning current function instead"; return lifted_func; } if (cfg_func->blocks.empty()) { - LOG(WARNING) - << "Function " << cfg_func->lifted_name << " is empty!"; + LOG(WARNING) << "Function " << cfg_func->lifted_name << " is empty!"; remill::AddTerminatingTailCall(lifted_func, intrinsics.missing_block); return lifted_func; } @@ -1508,12 +1470,12 @@ static llvm::Function *LiftFunction( // for each of them. for (const auto cfg_block : cfg_func->blocks) { const auto block_ea = cfg_block->ea; - (void) GetOrCreateBlock(ctx, block_ea, true /* force */); + (void) GetOrCreateBlock(ctx, block_ea, true /* force */); } std::sort(ctx.work_list.begin(), ctx.work_list.end(), - [] (std::tuple a, - std::tuple b) { + [](std::tuple a, + std::tuple b) { return std::get<0>(a) < std::get<0>(b); }); auto unique_it = std::unique(ctx.work_list.begin(), ctx.work_list.end()); @@ -1536,18 +1498,18 @@ static llvm::Function *LiftFunction( ir.CreateStore(pc, pc_ref); // Used for exception handling. - ctx.stack_ptr_var = ir.CreateAlloca( - llvm::Type::getInt64Ty(*gContext), - llvm::ConstantInt::get(gWordType, 1), "stack_ptr_var"); + ctx.stack_ptr_var = + ir.CreateAlloca(llvm::Type::getInt64Ty(*gContext), + llvm::ConstantInt::get(gWordType, 1), "stack_ptr_var"); - ctx.frame_ptr_var = ir.CreateAlloca( - llvm::Type::getInt64Ty(*gContext), - llvm::ConstantInt::get(gWordType, 1), "frame_ptr_var"); + ctx.frame_ptr_var = + ir.CreateAlloca(llvm::Type::getInt64Ty(*gContext), + llvm::ConstantInt::get(gWordType, 1), "frame_ptr_var"); // Preserve registers at a function granularity. cfg_module->ForEachRangePreservedRegister( cfg_func->ea, - [=, &ctx] (uint64_t end_ea, const NativePreservedRegisters ®s) { + [=, &ctx](uint64_t end_ea, const NativePreservedRegisters ®s) { ctx.func_preserved_regs.emplace(end_ea, ®s); }); @@ -1571,10 +1533,10 @@ static llvm::Function *LiftFunction( if (inst_ea != cfg_func->ea) { if (auto tail_called_func = cfg_module->TryGetFunction(inst_ea); tail_called_func && !force_as_block) { - LOG(WARNING) - << "Adding tail-call from " << std::hex << inst_ea - << " in function " << ctx.cfg_func->lifted_name << " to " - << tail_called_func->lifted_name << " from " << from_ea << std::dec; + LOG(WARNING) << "Adding tail-call from " << std::hex << inst_ea + << " in function " << ctx.cfg_func->lifted_name << " to " + << tail_called_func->lifted_name << " from " << from_ea + << std::dec; auto mem_ptr = LiftSubFuncCall( ctx, block, @@ -1588,16 +1550,14 @@ static llvm::Function *LiftFunction( if (!TryDecodeInstruction(ctx, inst_ea, false)) { if (from_ea) { - LOG(ERROR) - << "Could not decode instruction at " << std::hex << inst_ea - << " reachable from instruction " << from_ea << " in function " - << cfg_func->name << " at " << cfg_func->ea - << std::dec << ": " << ctx.inst.Serialize(); + LOG(ERROR) << "Could not decode instruction at " << std::hex << inst_ea + << " reachable from instruction " << from_ea + << " in function " << cfg_func->name << " at " + << cfg_func->ea << std::dec << ": " << ctx.inst.Serialize(); } else { - LOG(ERROR) - << "Could not decode instruction at " << std::hex << inst_ea - << " in function " << cfg_func->name << " at " << cfg_func->ea - << std::dec << ": " << ctx.inst.Serialize(); + LOG(ERROR) << "Could not decode instruction at " << std::hex << inst_ea + << " in function " << cfg_func->name << " at " + << cfg_func->ea << std::dec << ": " << ctx.inst.Serialize(); } remill::AddTerminatingTailCall(block, intrinsics.error); @@ -1632,7 +1592,8 @@ static bool ShouldInline(const llvm::CallSite &cs) { return false; } auto callee = cs.getCalledFunction(); - return callee && remill::HasOriginType(callee); + return callee && + remill::HasOriginType(callee); } static Calls_t InlinableCalls(llvm::Function &func) { @@ -1676,16 +1637,13 @@ void DeclareLiftedFunctions(const NativeModule *cfg_module) { auto lifted_func = gModule->getFunction(func_name); if (!lifted_func) { - lifted_func = remill::DeclareLiftedFunction( - gModule.get(), func_name); + lifted_func = remill::DeclareLiftedFunction(gModule.get(), func_name); // make local functions 'static' - LOG(INFO) - << "Inserted function: " << func_name; + LOG(INFO) << "Inserted function: " << func_name; } else { - LOG(INFO) - << "Already inserted function: " << func_name << ", skipping."; + LOG(INFO) << "Already inserted function: " << func_name << ", skipping."; } // All lifted functions are marked as external so they aren't optimized @@ -1719,6 +1677,7 @@ bool DefineLiftedFunctions(const NativeModule *cfg_module) { (void) GetLiftedToNativeExitPoint(cfg_func); } else { + // For local calls between lifted functions, prefer our state-passing // version, even if we generate an entry point cfg_func->callable_lifted_function = cfg_func->lifted_function; @@ -1734,10 +1693,9 @@ bool DefineLiftedFunctions(const NativeModule *cfg_module) { auto lifted_func = LiftFunction(cfg_module, cfg_func, intrinsics); if (!lifted_func) { - LOG(ERROR) - << "Could not lift function: " << cfg_func->name << " at " - << std::hex << cfg_func->ea << " into " << cfg_func->lifted_name - << std::dec; + LOG(ERROR) << "Could not lift function: " << cfg_func->name << " at " + << std::hex << cfg_func->ea << " into " + << cfg_func->lifted_name << std::dec; return false; } diff --git a/mcsema/BC/Instruction.cpp b/mcsema/BC/Instruction.cpp index 0e4e4c625..412ad5164 100644 --- a/mcsema/BC/Instruction.cpp +++ b/mcsema/BC/Instruction.cpp @@ -18,28 +18,26 @@ #include "Instruction.h" #include - -#include -#include -#include - #include #include -#include #include +#include #include #include #include -#include "remill/Arch/Arch.h" -#include "remill/Arch/Instruction.h" -#include "remill/BC/Util.h" +#include +#include +#include #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/Lift.h" #include "mcsema/BC/Util.h" #include "mcsema/CFG/CFG.h" +#include "remill/Arch/Arch.h" +#include "remill/Arch/Instruction.h" +#include "remill/BC/Util.h" namespace mcsema { @@ -48,12 +46,13 @@ InstructionLifter::~InstructionLifter(void) {} InstructionLifter::InstructionLifter(const remill::IntrinsicTable *intrinsics_, TranslationContext &ctx_) - : remill::InstructionLifter(gArch.get(), intrinsics_), - ctx(ctx_) {} + : remill::InstructionLifter(gArch.get(), intrinsics_), + ctx(ctx_) {} // Lift a single instruction into a basic block. -remill::LiftStatus InstructionLifter::LiftIntoBlock( - remill::Instruction &inst, llvm::BasicBlock *block_, bool is_delayed) { +remill::LiftStatus InstructionLifter::LiftIntoBlock(remill::Instruction &inst, + llvm::BasicBlock *block_, + bool is_delayed) { inst_ptr = &inst; block = block_; @@ -72,31 +71,28 @@ remill::LiftStatus InstructionLifter::LiftIntoBlock( disp_ref_used = false; imm_ref_used = false; - auto status = this->remill::InstructionLifter::LiftIntoBlock( - inst, block, is_delayed); + auto status = + this->remill::InstructionLifter::LiftIntoBlock(inst, block, is_delayed); // If we have semantics for the instruction, then make sure that we were // able to match cross-reference information to the instruction's operands. if (remill::kLiftedInstruction == status) { if (mem_ref && !mem_ref_used) { - LOG(ERROR) - << "Unused memory reference operand to " << std::hex - << ctx.cfg_inst->mem->target_ea << " in instruction " - << inst.Serialize() << std::dec; + LOG(ERROR) << "Unused memory reference operand to " << std::hex + << ctx.cfg_inst->mem->target_ea << " in instruction " + << inst.Serialize() << std::dec; } if (imm_ref && !imm_ref_used) { - LOG(ERROR) - << "Unused immediate operand reference to " << std::hex - << ctx.cfg_inst->imm->target_ea << " in instruction " - << inst.Serialize() << std::dec; + LOG(ERROR) << "Unused immediate operand reference to " << std::hex + << ctx.cfg_inst->imm->target_ea << " in instruction " + << inst.Serialize() << std::dec; } if (disp_ref && !disp_ref_used) { - LOG(ERROR) - << "Unused displacement operand reference to " << std::hex - << ctx.cfg_inst->disp->target_ea << " in instruction " - << inst.Serialize() << std::dec; + LOG(ERROR) << "Unused displacement operand reference to " << std::hex + << ctx.cfg_inst->disp->target_ea << " in instruction " + << inst.Serialize() << std::dec; } } @@ -126,8 +122,8 @@ remill::LiftStatus InstructionLifter::LiftIntoBlock( // return entry.xref->target_ea == entry.ea; //} -llvm::Value *InstructionLifter::GetAddress( - const NativeInstructionXref *cfg_xref) { +llvm::Value * +InstructionLifter::GetAddress(const NativeInstructionXref *cfg_xref) { if (!cfg_xref) { return nullptr; } @@ -139,9 +135,10 @@ llvm::Value *InstructionLifter::GetAddress( } } -llvm::Value *InstructionLifter::LiftImmediateOperand( - remill::Instruction &inst, llvm::BasicBlock *block, - llvm::Argument *arg, remill::Operand &op) { +llvm::Value *InstructionLifter::LiftImmediateOperand(remill::Instruction &inst, + llvm::BasicBlock *block, + llvm::Argument *arg, + remill::Operand &op) { auto arg_type = arg->getType(); if (imm_ref && !imm_ref_used) { imm_ref_used = true; @@ -150,10 +147,10 @@ llvm::Value *InstructionLifter::LiftImmediateOperand( auto arg_size = data_layout.getTypeSizeInBits(arg_type); CHECK(arg_size <= arch->address_size) - << "Immediate operand size " << op.size << " of " - << op.Serialize() << " in instuction " << std::hex << inst.pc - << " is wider than the architecture pointer size (" - << std::dec << arch->address_size << ")."; + << "Immediate operand size " << op.size << " of " << op.Serialize() + << " in instuction " << std::hex << inst.pc + << " is wider than the architecture pointer size (" << std::dec + << arch->address_size << ")."; if (arg_type != imm_ref->getType() && arg_size < arch->address_size) { llvm::IRBuilder<> ir(block); @@ -162,31 +159,30 @@ llvm::Value *InstructionLifter::LiftImmediateOperand( return imm_ref; - } else if (op.size == arch->address_size && - 4096 <= op.imm.val) { + } else if (op.size == arch->address_size && 4096 <= op.imm.val) { auto seg = ctx.cfg_module->TryGetSegment(op.imm.val); LOG_IF(WARNING, seg != nullptr) - << "Immediate operand '" << op.Serialize() - << "' of instruction " << inst.Serialize() - << " is a missed cross-reference candidate"; + << "Immediate operand '" << op.Serialize() << "' of instruction " + << inst.Serialize() << " is a missed cross-reference candidate"; } - return this->remill::InstructionLifter::LiftImmediateOperand( - inst, block, arg, op); + return this->remill::InstructionLifter::LiftImmediateOperand(inst, block, arg, + op); } // Lift an indirect memory operand to a value. -llvm::Value *InstructionLifter::LiftAddressOperand( - remill::Instruction &inst, llvm::BasicBlock *block, - llvm::Argument *arg, remill::Operand &op) { +llvm::Value *InstructionLifter::LiftAddressOperand(remill::Instruction &inst, + llvm::BasicBlock *block, + llvm::Argument *arg, + remill::Operand &op) { auto &mem = op.addr; // A higher layer will resolve any code refs; this is a static address and // we want to preserve it in the register state structure. if (mem.IsControlFlowTarget()) { - return this->remill::InstructionLifter::LiftAddressOperand( - inst, block, arg, op); + return this->remill::InstructionLifter::LiftAddressOperand(inst, block, arg, + op); } if ((mem.base_reg.name.empty() && mem.index_reg.name.empty()) || @@ -242,8 +238,8 @@ llvm::Value *InstructionLifter::LiftAddressOperand( } } - return this->remill::InstructionLifter::LiftAddressOperand( - inst, block, arg, op); + return this->remill::InstructionLifter::LiftAddressOperand(inst, block, arg, + op); } } // namespace mcsema diff --git a/mcsema/BC/Instruction.h b/mcsema/BC/Instruction.h index 83c533fdd..a1e89d6ce 100644 --- a/mcsema/BC/Instruction.h +++ b/mcsema/BC/Instruction.h @@ -52,19 +52,17 @@ class InstructionLifter : public remill::InstructionLifter { bool is_delayed) override; protected: - // Lift an immediate operand. - llvm::Value *LiftImmediateOperand( - remill::Instruction &inst, llvm::BasicBlock *block, - llvm::Argument *arg, remill::Operand &op) override; + llvm::Value * + LiftImmediateOperand(remill::Instruction &inst, llvm::BasicBlock *block, + llvm::Argument *arg, remill::Operand &op) override; // Lift an indirect memory operand to a value. - llvm::Value *LiftAddressOperand( - remill::Instruction &inst, llvm::BasicBlock *block, - llvm::Argument *arg, remill::Operand &mem) override; + llvm::Value *LiftAddressOperand(remill::Instruction &inst, + llvm::BasicBlock *block, llvm::Argument *arg, + remill::Operand &mem) override; private: - llvm::Value *GetAddress(const NativeInstructionXref *cfg_xref); TranslationContext &ctx; diff --git a/mcsema/BC/Legacy.cpp b/mcsema/BC/Legacy.cpp index f4179b9cd..8fdd1653e 100644 --- a/mcsema/BC/Legacy.cpp +++ b/mcsema/BC/Legacy.cpp @@ -19,25 +19,23 @@ #include #include - -#include - #include -#include #include +#include #include #include #include -#include "remill/Arch/Arch.h" -#include "remill/BC/ABI.h" -#include "remill/BC/Util.h" -#include "remill/BC/Version.h" +#include #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/Legacy.h" #include "mcsema/BC/Util.h" +#include "remill/Arch/Arch.h" +#include "remill/BC/ABI.h" +#include "remill/BC/Util.h" +#include "remill/BC/Version.h" DEFINE_string(pc_annotation, "", "Name of the metadata to apply to every LLVM instruction. The " diff --git a/mcsema/BC/Legacy.h b/mcsema/BC/Legacy.h index 4af0ff5e5..c8dc87b99 100644 --- a/mcsema/BC/Legacy.h +++ b/mcsema/BC/Legacy.h @@ -34,4 +34,3 @@ void PropagateInstAnnotations(void); } // namespace legacy } // namespace mcsema - diff --git a/mcsema/BC/Lift.cpp b/mcsema/BC/Lift.cpp index 73ff26352..0e2495e97 100644 --- a/mcsema/BC/Lift.cpp +++ b/mcsema/BC/Lift.cpp @@ -19,25 +19,23 @@ #include #include - #include #include #include #include +#include #include #include -#include -#include #include -#include +#include #include +#include #include #include - #include #include -#include #include +#include #include #include @@ -45,14 +43,6 @@ #include #include -#include "remill/Arch/Arch.h" -#include "remill/Arch/Instruction.h" -#include "remill/BC/ABI.h" -#include "remill/BC/Annotate.h" -#include "remill/BC/IntrinsicTable.h" -#include "remill/BC/Lifter.h" -#include "remill/BC/Util.h" - #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/External.h" @@ -62,6 +52,13 @@ #include "mcsema/BC/Segment.h" #include "mcsema/BC/Util.h" #include "mcsema/CFG/CFG.h" +#include "remill/Arch/Arch.h" +#include "remill/Arch/Instruction.h" +#include "remill/BC/ABI.h" +#include "remill/BC/Annotate.h" +#include "remill/BC/IntrinsicTable.h" +#include "remill/BC/Lifter.h" +#include "remill/BC/Util.h" DECLARE_bool(legacy_mode); DECLARE_bool(explicit_args); @@ -81,8 +78,8 @@ static void ExportFunctions(const NativeModule *cfg_module) { if (auto ep = cfg_func->function; ep) { if (cfg_func->is_exported) { - LOG(INFO) - << "Exporting function " << cfg_func->name; + LOG(INFO) << "Exporting function " << cfg_func->name; + // remill::TieFunctions(ep, gModule->getFunction(cfg_func->lifted_name)); remill::Annotate(ep); ep->setLinkage(llvm::GlobalValue::ExternalLinkage); @@ -92,8 +89,7 @@ static void ExportFunctions(const NativeModule *cfg_module) { ep->setVisibility(llvm::GlobalValue::HiddenVisibility); ep->setLinkage(llvm::GlobalValue::PrivateLinkage); if (!ep->hasNUsesOrMore(1)) { - LOG(INFO) - << "Removing function " << cfg_func->name; + LOG(INFO) << "Removing function " << cfg_func->name; ep->eraseFromParent(); } } @@ -107,9 +103,8 @@ static void ExportVariables(const NativeModule *cfg_module) { for (auto ea : cfg_module->exported_vars) { auto cfg_var = cfg_module->ea_to_var.at(ea)->Get(); auto var = gModule->getGlobalVariable(cfg_var->lifted_name); - CHECK(var != nullptr) - << "Cannot find lifted version of exported variable " - << cfg_var->name; + CHECK(var != nullptr) << "Cannot find lifted version of exported variable " + << cfg_var->name; var->setName(cfg_var->name); var->setLinkage(llvm::GlobalValue::ExternalLinkage); @@ -146,11 +141,12 @@ static void DefineDebugGetRegState(void) { auto state_ptr_type = reg_state->getType(); auto reg_func_type = llvm::FunctionType::get(state_ptr_type, false); + // ExternalWeakLinkage causes crash with --explicit_args. The function is not // available in the library - get_reg_state = llvm::Function::Create( - reg_func_type, llvm::GlobalValue::ExternalLinkage, - "__mcsema_debug_get_reg_state", gModule.get()); + get_reg_state = + llvm::Function::Create(reg_func_type, llvm::GlobalValue::ExternalLinkage, + "__mcsema_debug_get_reg_state", gModule.get()); llvm::IRBuilder<> ir(llvm::BasicBlock::Create(*gContext, "", get_reg_state)); ir.CreateRet(reg_state); @@ -171,17 +167,15 @@ static void ImplementErrorIntrinsic(const char *name) { if (!abort_func) { abort_func = llvm::Function::Create( llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::ExternalLinkage, - "abort", - gModule.get()); + llvm::GlobalValue::ExternalLinkage, "abort", gModule.get()); abort_func->addFnAttr(llvm::Attribute::NoReturn); // Might be an externally-defined function :-/ } else if (abort_func->getFunctionType()->getNumParams() || !abort_func->getFunctionType()->getReturnType()->isVoidTy()) { - abort_func = llvm::Intrinsic::getDeclaration( - gModule.get(), llvm::Intrinsic::trap); + abort_func = + llvm::Intrinsic::getDeclaration(gModule.get(), llvm::Intrinsic::trap); } func->setLinkage(llvm::GlobalValue::InternalLinkage); diff --git a/mcsema/BC/Optimize.cpp b/mcsema/BC/Optimize.cpp index e94f997aa..7fa91e2c8 100644 --- a/mcsema/BC/Optimize.cpp +++ b/mcsema/BC/Optimize.cpp @@ -17,39 +17,27 @@ #include "mcsema/BC/Optimize.h" +#include #include #include - -#include -#include -#include -#include -#include -#include - #include - #include #include #include -#include #include -#include +#include #include -#include +#include #include +#include #include #include - #include #include #include -#include #include +#include #include - -#include - #include #include #include @@ -58,6 +46,13 @@ #include #include +#include +#include +#include +#include +#include +#include + #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Optimize.h" #include "mcsema/BC/Util.h" @@ -71,7 +66,8 @@ DEFINE_bool(check_for_lowmem_xrefs, false, "if they might be cross-reference targets. This might be " "reasonable to enable for PIC code, .o files, etc."); -DEFINE_bool(volatile_memops, false, "Mark all lowered loads/stores as volatile"); +DEFINE_bool(volatile_memops, false, + "Mark all lowered loads/stores as volatile"); DEFINE_bool(local_state_pointer, true, "Use the state pointer passed by argument to all lifted functions." @@ -140,10 +136,10 @@ static void RemoveUndefFuncCalls(void) { // Get a list of all ISELs. static std::vector FindISELs(void) { std::vector isels; - remill::ForEachISel( - gModule.get(), [&](llvm::GlobalVariable *isel, llvm::Function *) { - isels.push_back(isel); - }); + remill::ForEachISel(gModule.get(), + [&](llvm::GlobalVariable *isel, llvm::Function *) { + isels.push_back(isel); + }); return isels; } @@ -177,9 +173,8 @@ static void ReplaceBarrier(const char *name) { } } -static llvm::Value *FindPointer( - llvm::IRBuilder<> &ir, llvm::Value *addr, llvm::Type *elem_type, - unsigned addr_space) { +static llvm::Value *FindPointer(llvm::IRBuilder<> &ir, llvm::Value *addr, + llvm::Type *elem_type, unsigned addr_space) { if (auto as_ptr_to_int = llvm::dyn_cast(addr)) { if (!addr_space) { @@ -266,14 +261,14 @@ static llvm::Constant *GetAddress(const NativeModule *cfg_module, uint64_t ea) { return nullptr; } -static llvm::Value *GetPointer( - const NativeModule *cfg_module, llvm::IRBuilder<> &ir, - llvm::Value *addr, llvm::Type *elem_type, unsigned addr_space); +static llvm::Value *GetPointer(const NativeModule *cfg_module, + llvm::IRBuilder<> &ir, llvm::Value *addr, + llvm::Type *elem_type, unsigned addr_space); -static llvm::Value *GetIndexedPointer( - const NativeModule *cfg_module, llvm::IRBuilder<> &ir, - llvm::Value *lhs, llvm::Value *rhs, llvm::Type *dest_type, - unsigned addr_space) { +static llvm::Value *GetIndexedPointer(const NativeModule *cfg_module, + llvm::IRBuilder<> &ir, llvm::Value *lhs, + llvm::Value *rhs, llvm::Type *dest_type, + unsigned addr_space) { auto i32_ty = llvm::Type::getInt32Ty(*gContext); auto i8_ty = llvm::Type::getInt8Ty(*gContext); @@ -297,23 +292,21 @@ static llvm::Value *GetIndexedPointer( if (cfg_module) { if (auto cfg_seg = cfg_module->TryGetSegment(lhs_global->getName())) { - const auto real_ea = static_cast( - static_cast(cfg_seg->ea) + index); + const auto real_ea = + static_cast(static_cast(cfg_seg->ea) + index); if (auto addr = GetAddress(cfg_module, real_ea)) { LOG_IF(WARNING, cfg_module->TryGetSegment(real_ea) != cfg_seg) - << "Fixing cross-reference to " << std::hex - << real_ea << std::dec << " that was misplaced into segment " + << "Fixing cross-reference to " << std::hex << real_ea + << std::dec << " that was misplaced into segment " << cfg_seg->name; - return GetPointer( - nullptr, ir, addr, dest_type->getPointerElementType(), - addr_space); + return GetPointer(nullptr, ir, addr, + dest_type->getPointerElementType(), addr_space); } else { - LOG(ERROR) - << "Out-of-bounds reference to " << std::hex << real_ea - << std::dec << " tied to segment " << cfg_seg->name; + LOG(ERROR) << "Out-of-bounds reference to " << std::hex << real_ea + << std::dec << " tied to segment " << cfg_seg->name; } } } @@ -383,9 +376,9 @@ static llvm::Value *GetIndexedPointer( // Try to get a pointer for the address operand of a remill memory access // intrinsic. -static llvm::Value *GetPointerFromInt( - llvm::IRBuilder<> &ir, llvm::Value *addr, llvm::Type *elem_type, - unsigned addr_space) { +static llvm::Value *GetPointerFromInt(llvm::IRBuilder<> &ir, llvm::Value *addr, + llvm::Type *elem_type, + unsigned addr_space) { auto dest_type = llvm::PointerType::get(elem_type, addr_space); if (auto phi = llvm::dyn_cast(addr)) { @@ -421,9 +414,9 @@ static llvm::Value *GetPointerFromInt( // Try to get a pointer for the address operand of a remill memory access // intrinsic. -llvm::Value *GetPointer( - const NativeModule *cfg_module, llvm::IRBuilder<> &ir, - llvm::Value *addr, llvm::Type *elem_type, unsigned addr_space) { +llvm::Value *GetPointer(const NativeModule *cfg_module, llvm::IRBuilder<> &ir, + llvm::Value *addr, llvm::Type *elem_type, + unsigned addr_space) { addr_space = GetPointerAddressSpace(addr, addr_space); const auto addr_type = addr->getType(); @@ -434,14 +427,15 @@ llvm::Value *GetPointer( // intrinsics. if (auto as_itp = llvm::dyn_cast(addr); as_itp) { llvm::IRBuilder<> sub_ir(as_itp); - return GetPointer( - cfg_module, sub_ir, as_itp->getOperand(0), elem_type, addr_space); + return GetPointer(cfg_module, sub_ir, as_itp->getOperand(0), elem_type, + addr_space); // It's a `ptrtoint`, but of the wrong type; lets go back and try to use // that pointer. - } else if (auto as_pti = llvm::dyn_cast(addr); as_pti) { - return GetPointer( - cfg_module, ir, as_pti->getPointerOperand(), elem_type, addr_space); + } else if (auto as_pti = llvm::dyn_cast(addr); + as_pti) { + return GetPointer(cfg_module, ir, as_pti->getPointerOperand(), elem_type, + addr_space); // We've found a pointer of the desired type; return :-D } else if (addr_type == dest_type) { @@ -454,9 +448,8 @@ llvm::Value *GetPointer( return GetPointer(cfg_module, ir, addr, elem_type, addr_space); } else { - LOG(ERROR) - << "Missed cross-reference target " << std::hex - << ea << " to pointer"; + LOG(ERROR) << "Missed cross-reference target " << std::hex << ea + << " to pointer"; return llvm::ConstantExpr::getIntToPtr(ci, dest_type); } @@ -464,8 +457,8 @@ llvm::Value *GetPointer( // as we've already handled `ptrtoint` above. } else if (auto ce = llvm::dyn_cast(addr); ce) { if (ce->getOpcode() == llvm::Instruction::IntToPtr) { - return GetPointer( - cfg_module, ir, ce->getOperand(0), elem_type, addr_space); + return GetPointer(cfg_module, ir, ce->getOperand(0), elem_type, + addr_space); } else if (addr_type->isIntegerTy()) { return llvm::ConstantExpr::getIntToPtr(ce, dest_type); @@ -529,24 +522,22 @@ llvm::Value *GetPointer( if (lhs && rhs) { const auto bb = ir.GetInsertBlock(); - LOG(ERROR) - << "Two pointers " - << remill::LLVMThingToString(lhs) << " and " - << remill::LLVMThingToString(rhs) << " are added together " - << remill::LLVMThingToString(addr) << " in block " - << bb->getName().str() << " in function " - << bb->getParent()->getName().str(); + LOG(ERROR) << "Two pointers " << remill::LLVMThingToString(lhs) << " and " + << remill::LLVMThingToString(rhs) << " are added together " + << remill::LLVMThingToString(addr) << " in block " + << bb->getName().str() << " in function " + << bb->getParent()->getName().str(); return ir.CreateIntToPtr(addr, dest_type); } if (rhs) { - return GetIndexedPointer( - cfg_module, ir, rhs, lhs_op, dest_type, addr_space); + return GetIndexedPointer(cfg_module, ir, rhs, lhs_op, dest_type, + addr_space); } else { - return GetIndexedPointer( - cfg_module, ir, lhs, rhs_op, dest_type, addr_space); + return GetIndexedPointer(cfg_module, ir, lhs, rhs_op, dest_type, + addr_space); } } else if (auto as_sub = llvm::dyn_cast(addr); as_sub) { @@ -559,19 +550,19 @@ llvm::Value *GetPointer( } else { auto i32_ty = llvm::Type::getInt32Ty(*gContext); - auto neg_index = static_cast( - -static_cast(rhs->getZExtValue())); + auto neg_index = + static_cast(-static_cast(rhs->getZExtValue())); auto const_index = llvm::ConstantInt::get( i32_ty, static_cast(neg_index), true); addr_space = GetPointerAddressSpace(lhs, addr_space); dest_type = llvm::PointerType::get(elem_type, addr_space); - return GetIndexedPointer( - cfg_module, ir, lhs, const_index, dest_type, addr_space); + return GetIndexedPointer(cfg_module, ir, lhs, const_index, dest_type, + addr_space); } } else if (auto as_bc = llvm::dyn_cast(addr); as_bc) { - return GetPointer(cfg_module, ir, as_bc->getOperand(0), - elem_type, addr_space); + return GetPointer(cfg_module, ir, as_bc->getOperand(0), elem_type, + addr_space); // E.g. loading an address-sized integer register. } else if (addr_type->isIntegerTy()) { @@ -583,14 +574,12 @@ llvm::Value *GetPointer( // `inttoptr` conversions instead of adding new ones. for (auto user : addr->users()) { const auto inst_user = llvm::dyn_cast(user); - if (!inst_user || - inst_user == addr_inst || + if (!inst_user || inst_user == addr_inst || inst_user->getParent() != bb) { continue; } - for (auto next_inst = inst_user->getNextNode(); - next_inst; + for (auto next_inst = inst_user->getNextNode(); next_inst; next_inst = next_inst->getNextNode()) { DCHECK_EQ(next_inst->getParent(), bb); @@ -715,7 +704,7 @@ static void LowerMemOps(const NativeModule *cfg_module) { ReplaceMemReadOp(cfg_module, "__remill_read_memory_f80", llvm::Type::getX86_FP80Ty(*gContext)); ReplaceMemReadOp(cfg_module, "__remill_write_memory_f128", - llvm::Type::getFP128Ty(*gContext)); + llvm::Type::getFP128Ty(*gContext)); ReplaceMemWriteOp(cfg_module, "__remill_write_memory_f80", llvm::Type::getX86_FP80Ty(*gContext)); @@ -740,7 +729,8 @@ static bool RemoveDeadRestores(llvm::Function *restorer) { } else if (auto invoke_inst = llvm::dyn_cast(user); invoke_inst && invoke_inst->getCalledFunction() == &func) { - functions_with_noreturn.insert(invoke_inst->getParent()->getParent()); + functions_with_noreturn.insert( + invoke_inst->getParent()->getParent()); } } } @@ -780,8 +770,8 @@ static bool RemoveDeadRestores(llvm::Function *restorer) { // NOTE(pag): If a function has an unreachable instruction, then it might // miss out on some optimizations, and so we want to always // force some restores. - if (first_arg == second_arg && - (!FLAGS_restore_all_on_unreachable || !functions_with_noreturn.count(func))) { + if (first_arg == second_arg && (!FLAGS_restore_all_on_unreachable || + !functions_with_noreturn.count(func))) { auto all_users_are_stores = true; // Go find the store of the return value to the state structure, and @@ -813,7 +803,8 @@ static bool RemoveDeadRestores(llvm::Function *restorer) { // Go look for any stores of the first argument into the state structure, // and remove them. If we find these, then they are likely leftovers from // after function calls to other lifted functions. - if (auto reg_load = llvm::dyn_cast(first_arg); reg_load) { + if (auto reg_load = llvm::dyn_cast(first_arg); + reg_load) { for (auto reg_user : first_arg->users()) { if (auto reg_restore = llvm::dyn_cast(reg_user); reg_restore) { @@ -971,7 +962,8 @@ static void RemoveSavingKilledStores(void) { } for (auto [kill_val, reg_val] : to_replace) { - if (auto store_inst = llvm::dyn_cast(kill_val->getNextNode()); + if (auto store_inst = + llvm::dyn_cast(kill_val->getNextNode()); store_inst && store_inst->getValueOperand() == kill_val) { to_remove.push_back(store_inst); } @@ -1015,17 +1007,17 @@ static llvm::Constant *AdaptToType(llvm::Constant *src, llvm::Type *dest_type) { return llvm::ConstantExpr::getIntToPtr(src, dest_type); } } else { - LOG(FATAL) - << "Unsupported destination type: " - << remill::LLVMThingToString(dest_type); + LOG(FATAL) << "Unsupported destination type: " + << remill::LLVMThingToString(dest_type); return nullptr; } } // The add-on pass to merge the `GEP` instructions if they are operating // on the same instruction operand static void MergeGEPInstructions(llvm::Function &func) { - std::map, - std::vector> gep_map; + std::map, + std::vector> + gep_map; for (auto &block : func) { for (auto &inst : block) { @@ -1035,8 +1027,9 @@ static void MergeGEPInstructions(llvm::Function &func) { if ((inst.getOpcode() == llvm::Instruction::GetElementPtr) && (llvm::isa(inst.getOperand(0))) && (llvm::isa(inst.getOperand(1)))) { - gep_map[std::pair( - inst.getOperand(0), inst.getOperand(1))].push_back(&inst); + gep_map[std::pair(inst.getOperand(0), + inst.getOperand(1))] + .push_back(&inst); } } } @@ -1073,10 +1066,9 @@ static void LowerXrefs(const NativeModule *cfg_module) { anvill::XrefExprFolder folder(*cfg_module, *gModule); - auto get_fixup = [=, &folder, &done_fixups] (llvm::User *user, - llvm::Constant *ce) - -> llvm::Constant * { - + auto get_fixup = [=, &folder, &done_fixups]( + llvm::User *user, + llvm::Constant *ce) -> llvm::Constant * { bool is_bitwise = false; if (auto op = llvm::dyn_cast(user); op) { switch (op->getOpcode()) { @@ -1086,10 +1078,10 @@ static void LowerXrefs(const NativeModule *cfg_module) { case llvm::Instruction::And: case llvm::Instruction::Xor: case llvm::Instruction::Or: + //is_bitwise = true; break; - default: - break; + default: break; } } @@ -1103,8 +1095,7 @@ static void LowerXrefs(const NativeModule *cfg_module) { const auto ea = folder.VisitConst(ce); if (remill::IsError(folder.error)) { - LOG(ERROR) - << remill::GetErrorString(folder.error); + LOG(ERROR) << remill::GetErrorString(folder.error); } // Common to have a shift left by one, two, or three for common @@ -1126,13 +1117,13 @@ static void LowerXrefs(const NativeModule *cfg_module) { // It doesn't reference anything known; treat it as a constant. } else { if (auto inst = llvm::dyn_cast(user); inst) { - LOG(WARNING) - << "Treating " << std::hex << ea << std::dec << " as a constant" - << " in " << inst->getParent()->getName().str(); + LOG(WARNING) << "Treating " << std::hex << ea << std::dec + << " as a constant" + << " in " << inst->getParent()->getName().str(); } else { - LOG(WARNING) - << "Treating " << std::hex << ea << std::dec << " as a constant"; + LOG(WARNING) << "Treating " << std::hex << ea << std::dec + << " as a constant"; } fixup = llvm::ConstantInt::get(ce_type, ea); @@ -1143,10 +1134,10 @@ static void LowerXrefs(const NativeModule *cfg_module) { if (llvm::isa(fixup)) { return fixup; } else { - LOG(ERROR) - << "Previously lifted cross-reference to " << std::hex - << ea << std::dec << " is used in subsequent bitwise operations; " - << "assuming it is actually a constant in this instance"; + LOG(ERROR) << "Previously lifted cross-reference to " << std::hex + << ea << std::dec + << " is used in subsequent bitwise operations; " + << "assuming it is actually a constant in this instance"; return llvm::ConstantInt::get(ce_type, ea); } @@ -1161,17 +1152,15 @@ static void LowerXrefs(const NativeModule *cfg_module) { fixup = llvm::ConstantInt::get(ce_type, ea); if (auto inst = llvm::dyn_cast(user); inst) { - LOG(ERROR) - << "Cross-reference to " << std::hex << ea << std::dec - << " in " << inst->getParent()->getName().str() - << " is computed via a XOR; assuming it is a constant: " - << remill::LLVMThingToString(ce); + LOG(ERROR) << "Cross-reference to " << std::hex << ea << std::dec + << " in " << inst->getParent()->getName().str() + << " is computed via a XOR; assuming it is a constant: " + << remill::LLVMThingToString(ce); } else { - LOG(ERROR) - << "Cross-reference to " << std::hex << ea << std::dec - << " is computed via a XOR; assuming it is a constant: " - << remill::LLVMThingToString(ce); + LOG(ERROR) << "Cross-reference to " << std::hex << ea << std::dec + << " is computed via a XOR; assuming it is a constant: " + << remill::LLVMThingToString(ce); } } @@ -1221,9 +1210,8 @@ static void LowerXrefs(const NativeModule *cfg_module) { continue; } else { - LOG(ERROR) - << "Unexpected user of cross-reference: " - << remill::LLVMThingToString(user); + LOG(ERROR) << "Unexpected user of cross-reference: " + << remill::LLVMThingToString(user); } } } @@ -1233,7 +1221,7 @@ static void LowerXrefs(const NativeModule *cfg_module) { use->set(replacement); } - auto find_missed_fixup = [&] (const char *func_name, llvm::Type *val_type) { + auto find_missed_fixup = [&](const char *func_name, llvm::Type *val_type) { const auto func = gModule->getFunction(func_name); if (!func) { return; @@ -1253,17 +1241,17 @@ static void LowerXrefs(const NativeModule *cfg_module) { if (auto addr_int = llvm::dyn_cast(addr_val)) { const auto new_addr_val = get_fixup(user, addr_int); if (llvm::isa(new_addr_val)) { - LOG(ERROR) - << "Missed cross-reference to absolute address " << std::hex - << addr_int->getZExtValue() << std::dec << " in block " - << ci->getParent()->getName().str() << " in function " - << ci->getParent()->getParent()->getName().str(); + LOG(ERROR) << "Missed cross-reference to absolute address " + << std::hex << addr_int->getZExtValue() << std::dec + << " in block " << ci->getParent()->getName().str() + << " in function " + << ci->getParent()->getParent()->getName().str(); } else { - LOG(WARNING) - << "Fixing absolute address " << std::hex - << addr_int->getZExtValue() << std::dec << " to be reference " - << remill::LLVMThingToString(new_addr_val); + LOG(WARNING) << "Fixing absolute address " << std::hex + << addr_int->getZExtValue() << std::dec + << " to be reference " + << remill::LLVMThingToString(new_addr_val); } fixups.emplace_back(&addr_use, new_addr_val); @@ -1272,8 +1260,8 @@ static void LowerXrefs(const NativeModule *cfg_module) { // instruction that computes an integer. } else { llvm::IRBuilder<> ir(ci); - llvm::Value *ptr = GetPointer( - cfg_module, ir, addr_use.get(), val_type, 0); + llvm::Value *ptr = + GetPointer(cfg_module, ir, addr_use.get(), val_type, 0); fixups.emplace_back(&addr_use, ir.CreatePtrToInt(ptr, gWordType)); } } @@ -1407,8 +1395,7 @@ static llvm::Value *TryGetRegAlias(llvm::Value *ptr, unsigned offset) { alias = llvm::GlobalAlias::create( elem_type, ptr_type->getPointerAddressSpace(), - llvm::GlobalValue::PrivateLinkage, alias_name, ptr_const, - gModule.get()); + llvm::GlobalValue::PrivateLinkage, alias_name, ptr_const, gModule.get()); alias->setThreadLocalMode(llvm::GlobalValue::InitialExecTLSModel); return alias; } @@ -1428,6 +1415,7 @@ static llvm::Value *TryGetRegAlias(llvm::Value *ptr, unsigned offset) { static void GlobalizeStateStructures(void) { const auto state_ptr = ::mcsema::GetStatePointer(); const auto state_ptr_type = state_ptr->getType(); + //const auto undef_state = llvm::UndefValue::get(state_ptr_type); std::vector> work_list; @@ -1446,11 +1434,13 @@ static void GlobalizeStateStructures(void) { continue; } - auto func_state_ptr = remill::NthArgument(&func, remill::kStatePointerArgNum); + auto func_state_ptr = + remill::NthArgument(&func, remill::kStatePointerArgNum); if (func_state_ptr->getType() != state_ptr_type) { continue; } #if 0 + // Replace all state pointer args with `undef`. for (auto user : func.users()) { if (auto call_inst = llvm::dyn_cast(user); @@ -1474,11 +1464,12 @@ static void GlobalizeStateStructures(void) { next_work_list.emplace_back(bc, offset); to_remove.push_back(bc); - } else if (auto gep = llvm::dyn_cast(user); gep) { + } else if (auto gep = llvm::dyn_cast(user); + gep) { llvm::APInt sub_offset(gArch->address_size, 0); if (gep->accumulateConstantOffset(dl, sub_offset)) { - next_work_list.emplace_back( - gep, offset + sub_offset.getZExtValue()); + next_work_list.emplace_back(gep, + offset + sub_offset.getZExtValue()); } else { to_replace.emplace_back(&use, offset); @@ -1490,7 +1481,8 @@ static void GlobalizeStateStructures(void) { llvm::isa(user)) { to_replace.emplace_back(&use, offset); - } else if (auto inst = llvm::dyn_cast(user); inst) { + } else if (auto inst = llvm::dyn_cast(user); + inst) { to_replace.emplace_back(&use, offset); to_remove.push_back(inst); @@ -1518,12 +1510,12 @@ static void GlobalizeStateStructures(void) { llvm::PointerType::get(pti->getPointerOperandType(), 0)); ptr = TryGetRegAlias(ptr, offset); - if (auto pti_inst = llvm::dyn_cast(pti); pti_inst) { + if (auto pti_inst = llvm::dyn_cast(pti); + pti_inst) { to_remove.push_back(pti_inst); } - (void) new llvm::StoreInst( - pti->getPointerOperand(), ptr, store); + (void) new llvm::StoreInst(pti->getPointerOperand(), ptr, store); to_remove.push_back(store); continue; } @@ -1544,8 +1536,8 @@ static void GlobalizeStateStructures(void) { } } - auto ptr = remill::BuildPointerToOffset( - ir, state_ptr, offset, use->get()->getType()); + auto ptr = remill::BuildPointerToOffset(ir, state_ptr, offset, + use->get()->getType()); ptr = TryGetRegAlias(ptr, offset); use->set(ptr); @@ -1586,8 +1578,7 @@ void OptimizeModule(const NativeModule *cfg_module) { MuteStateEscape("__remill_async_hyper_call"); auto isels = FindISELs(); - LOG(INFO) - << "Optimizing module."; + LOG(INFO) << "Optimizing module."; PrivatizeISELs(isels); @@ -1604,9 +1595,9 @@ void OptimizeModule(const NativeModule *cfg_module) { llvm::legacy::FunctionPassManager pm(gModule.get()); -// pm.add(llvm::createGVNHoistPass()); -// pm.add(llvm::createGVNSinkPass()); -// pm.add(llvm::createMergedLoadStoreMotionPass()); + // pm.add(llvm::createGVNHoistPass()); + // pm.add(llvm::createGVNSinkPass()); + // pm.add(llvm::createMergedLoadStoreMotionPass()); pm.add(llvm::createEarlyCSEPass(true)); pm.add(llvm::createDeadCodeEliminationPass()); @@ -1651,7 +1642,7 @@ void OptimizeModule(const NativeModule *cfg_module) { RemoveSavingKilledStores(); } -// anvill::RecoverMemoryAccesses(*cfg_module, *gModule); + // anvill::RecoverMemoryAccesses(*cfg_module, *gModule); LowerXrefs(cfg_module); for (auto &[ea, cfg_func] : cfg_module->ea_to_func) { @@ -1664,11 +1655,11 @@ void OptimizeModule(const NativeModule *cfg_module) { cfg_func->lifted_function = gModule->getFunction(cfg_func->lifted_name); -// if (!cfg_func->is_exported && cfg_func->function) { -// if (cfg_func->function->hasNUsesOrMore(1)) { -// continue; -// } -// } + // if (!cfg_func->is_exported && cfg_func->function) { + // if (cfg_func->function->hasNUsesOrMore(1)) { + // continue; + // } + // } } pm.doInitialization(); @@ -1732,24 +1723,24 @@ void CleanUpModule(const NativeModule *cfg_module) { } -// // Go try to inline -// for (const auto &func : cfg_module->functions) { -// if (func->lifted_function) { -// func->lifted_function = gModule->getFunction(func->lifted_name); -// } -// -// if (func->lifted_function) -// -// if (func->function) { -// func->function = gModule->getFunction(func->name); -// } -// -// if (func->function && -// func->lifted_function && -// func->lifted_function->hasNUses(1)) { -// -// } -// } + // // Go try to inline + // for (const auto &func : cfg_module->functions) { + // if (func->lifted_function) { + // func->lifted_function = gModule->getFunction(func->lifted_name); + // } + // + // if (func->lifted_function) + // + // if (func->function) { + // func->function = gModule->getFunction(func->name); + // } + // + // if (func->function && + // func->lifted_function && + // func->lifted_function->hasNUses(1)) { + // + // } + // } std::vector to_remove; do { diff --git a/mcsema/BC/Segment.cpp b/mcsema/BC/Segment.cpp index 5a6dfd808..f36f7756a 100644 --- a/mcsema/BC/Segment.cpp +++ b/mcsema/BC/Segment.cpp @@ -19,14 +19,6 @@ #include #include - -#include -#include -#include -#include -#include -#include - #include #include #include @@ -34,11 +26,17 @@ #include #include #include - #include #include #include +#include +#include +#include +#include +#include +#include + #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Callback.h" #include "mcsema/BC/Util.h" @@ -120,9 +118,8 @@ static llvm::StructType *GetSegmentType(const NativeSegment *cfg_seg) { } } else { - LOG(FATAL) - << "Missing blob or xref segment entry value for segment " - << cfg_seg->name << " data at " << std::hex << entry.ea; + LOG(FATAL) << "Missing blob or xref segment entry value for segment " + << cfg_seg->name << " data at " << std::hex << entry.ea; } } @@ -134,14 +131,14 @@ static llvm::StructType *GetSegmentType(const NativeSegment *cfg_seg) { llvm::DataLayout data_layout(gModule.get()); auto seg_size = data_layout.getTypeAllocSize(seg_type); CHECK_EQ(seg_size, (cfg_seg->size + cfg_seg->padding)) - << "Size of structure type of segment " << cfg_seg->name - << " is " << seg_size << " but was expected to be " << cfg_seg->size; + << "Size of structure type of segment " << cfg_seg->name << " is " + << seg_size << " but was expected to be " << cfg_seg->size; return seg_type; } -static llvm::GlobalValue::ThreadLocalMode ThreadLocalMode( - const NativeObject *cfg_obj) { +static llvm::GlobalValue::ThreadLocalMode +ThreadLocalMode(const NativeObject *cfg_obj) { if (cfg_obj->is_thread_local) { return llvm::GlobalValue::InitialExecTLSModel; } else { @@ -151,19 +148,17 @@ static llvm::GlobalValue::ThreadLocalMode ThreadLocalMode( // Create a McSema-specific constructor/destructor function, and add it to the // corresponding LLVM-specific array. -static llvm::Function *CreateMcSemaInitFiniImpl( - const char *func_name, const char *arr_name) { - LOG(INFO) - << "Creating " << func_name << " function to initialize runtime."; +static llvm::Function *CreateMcSemaInitFiniImpl(const char *func_name, + const char *arr_name) { + LOG(INFO) << "Creating " << func_name << " function to initialize runtime."; auto func = llvm::Function::Create( llvm::FunctionType::get(llvm::Type::getVoidTy(*gContext), false), - llvm::GlobalValue::InternalLinkage, - func_name, gModule.get()); + llvm::GlobalValue::InternalLinkage, func_name, gModule.get()); auto bool_type = llvm::Type::getInt1Ty(*gContext); - auto check_var = new llvm::GlobalVariable( - bool_type, false, llvm::GlobalValue::InternalLinkage); + auto check_var = new llvm::GlobalVariable(bool_type, false, + llvm::GlobalValue::InternalLinkage); check_var->setInitializer(llvm::Constant::getNullValue(bool_type)); auto entry = llvm::BasicBlock::Create(*gContext, "", func); @@ -191,11 +186,10 @@ static llvm::Function *CreateMcSemaInitFiniImpl( auto global_ctors = gModule->getGlobalVariable(arr_name); if (global_ctors) { - LOG(INFO) - << "Module already has a " << arr_name << " array."; + LOG(INFO) << "Module already has a " << arr_name << " array."; - auto arr = llvm::dyn_cast( - global_ctors->getInitializer()); + auto arr = + llvm::dyn_cast(global_ctors->getInitializer()); auto num_ops = arr->getNumOperands(); for (auto i = 0U; i < num_ops; ++i) { new_elems.push_back(arr->getOperand(i)); @@ -206,10 +200,10 @@ static llvm::Function *CreateMcSemaInitFiniImpl( auto arr_type = llvm::ArrayType::get(el_type, new_elems.size()); auto arr_init = llvm::ConstantArray::get(arr_type, new_elems); - auto arr = new llvm::GlobalVariable( - *gModule, arr_type, false /* isConstant */, - llvm::GlobalVariable::AppendingLinkage, - arr_init, global_ctors ? "__mcsema.temp_array" : arr_name); + auto arr = + new llvm::GlobalVariable(*gModule, arr_type, false /* isConstant */, + llvm::GlobalVariable::AppendingLinkage, arr_init, + global_ctors ? "__mcsema.temp_array" : arr_name); if (global_ctors) { arr->takeName(global_ctors); @@ -226,8 +220,8 @@ static llvm::Function *GetOrCreateMcSemaConstructor(void) { return gInitFunc; } - gInitFunc = CreateMcSemaInitFiniImpl( - "__mcsema_constructor", "llvm.global_ctors"); + gInitFunc = + CreateMcSemaInitFiniImpl("__mcsema_constructor", "llvm.global_ctors"); return gInitFunc; } @@ -235,8 +229,8 @@ static llvm::Function *GetOrCreateMcSemaConstructor(void) { static llvm::Function *GetOrCreateMcSemaDestructor(void) { static llvm::Function *gFiniFunc = nullptr; if (!gFiniFunc) { - gFiniFunc = CreateMcSemaInitFiniImpl( - "__mcsema_destructor", "llvm.global_dtors"); + gFiniFunc = + CreateMcSemaInitFiniImpl("__mcsema_destructor", "llvm.global_dtors"); } return gFiniFunc; } @@ -267,20 +261,18 @@ static void LazyInitXRef(const NativeXref *xref, ir.SetInsertPoint(&block->front()); if (xref->segment->is_external) { - LOG(ERROR) - << "Ignoring lazy initialization of cross-reference to " - << std::hex << xref->target_ea << " at " << xref->ea - << " in external segment '" << xref->segment->name << "' at " - << xref->segment->ea << std::dec; + LOG(ERROR) << "Ignoring lazy initialization of cross-reference to " + << std::hex << xref->target_ea << " at " << xref->ea + << " in external segment '" << xref->segment->name << "' at " + << xref->segment->ea << std::dec; return; } auto seg = llvm::dyn_cast(xref->segment->Pointer()); if (seg->isConstant()) { - LOG(WARNING) - << "Marking " << seg->getName().str() << " as non-constant to " - << "support lazy initialization of reference to " << std::hex - << xref->target_ea << " from " << xref->ea << std::dec; + LOG(WARNING) << "Marking " << seg->getName().str() << " as non-constant to " + << "support lazy initialization of reference to " << std::hex + << xref->target_ea << " from " << xref->ea << std::dec; seg->setConstant(false); } @@ -294,21 +286,22 @@ static void LazyInitXRef(const NativeXref *xref, case NativeXref::kAbsoluteFixup: { CHECK(!xref->var || !xref->var->is_thread_local) << "Cannot do absolute fixup from " << std::hex << xref->ea - << " to thread-local variable at " - << std::hex << xref->target_ea << std::dec; + << " to thread-local variable at " << std::hex << xref->target_ea + << std::dec; + // `target_addr` already has the right value. break; } case NativeXref::kThreadLocalOffsetFixup: { CHECK(xref->var != nullptr) - << "Non-variable thread-local cross-reference from " - << std::hex << xref->ea << " to " << xref->target_ea << std::dec; + << "Non-variable thread-local cross-reference from " << std::hex + << xref->ea << " to " << xref->target_ea << std::dec; CHECK(xref->var->is_thread_local) << "Cannot do thread-local fixup from " << std::hex << xref->ea - << " to non-thread-local variable at " - << std::hex << xref->target_ea << std::dec; + << " to non-thread-local variable at " << std::hex << xref->target_ea + << std::dec; static llvm::Value *thread_base = nullptr; if (!thread_base) { @@ -352,25 +345,25 @@ static llvm::Constant *FillDataSegment(const NativeModule *cfg_module, if (entry.blob->is_zero) { entry_vals.push_back(llvm::ConstantAggregateZero::get(entry_type)); - } else if (auto bytes = cfg_module->FindBytes(entry.blob->ea, entry.blob->size); + } else if (auto bytes = + cfg_module->FindBytes(entry.blob->ea, entry.blob->size); bytes && bytes.Size() == entry.blob->size) { const llvm::StringRef str_data(bytes.ToString().data(), bytes.Size()); - auto data = llvm::ConstantDataArray::getString( - *gContext, str_data, false /* AddNull */); + auto data = llvm::ConstantDataArray::getString(*gContext, str_data, + false /* AddNull */); CHECK(data->getType() == entry_type) << "Type mismatch: Got " - << remill::LLVMThingToString(data->getType()) - << " but expected " + << remill::LLVMThingToString(data->getType()) << " but expected " << remill::LLVMThingToString(entry_type); entry_vals.push_back(data); } else { - LOG(ERROR) - << "Could not find data backing " << std::hex << entry.blob->ea - << std::dec << " in segment " << cfg_seg->name; + LOG(ERROR) << "Could not find data backing " << std::hex + << entry.blob->ea << std::dec << " in segment " + << cfg_seg->name; entry_vals.push_back(llvm::ConstantAggregateZero::get(entry_type)); } @@ -381,9 +374,9 @@ static llvm::Constant *FillDataSegment(const NativeModule *cfg_module, llvm::Constant *val = nullptr; CHECK((entry.xref->width * 8) <= gArch->address_size) - << "Cross-reference at " << std::hex - << xref->ea << " to " << std::hex << xref->target_ea - << " is too wide at " << entry.xref->width << " bytes"; + << "Cross-reference at " << std::hex << xref->ea << " to " << std::hex + << xref->target_ea << " is too wide at " << entry.xref->width + << " bytes"; auto be_lazy = false; @@ -440,17 +433,14 @@ static llvm::Constant *FillDataSegment(const NativeModule *cfg_module, } CHECK_EQ(val->getType(), entry_type) - << "Type mismatch: Got " - << remill::LLVMThingToString(val->getType()) - << " but expected " - << remill::LLVMThingToString(entry_type); + << "Type mismatch: Got " << remill::LLVMThingToString(val->getType()) + << " but expected " << remill::LLVMThingToString(entry_type); entry_vals.push_back(val); } else { - LOG(FATAL) - << "Empty entry at " << std::hex << entry.ea - << " in segment " << cfg_seg->name; + LOG(FATAL) << "Empty entry at " << std::hex << entry.ea << " in segment " + << cfg_seg->name; } } @@ -495,7 +485,7 @@ llvm::Constant *NativeVariable::Pointer(void) const { return alias; } - auto ret = LiftXrefInData(segment, ea, false /* cast_to_int */); + auto ret = LiftXrefInData(segment, ea, false /* cast_to_int */); if (!FLAGS_disable_aliases && is_exported) { auto ptr_type = llvm::dyn_cast(ret->getType()); auto alias = llvm::GlobalAlias::create( @@ -528,8 +518,8 @@ llvm::Constant *NativeSegment::Address(void) const { llvm::Constant *NativeSegment::Pointer(void) const { const auto &var_name = (is_exported || is_external) ? name : lifted_name; - auto lifted_var = gModule->getGlobalVariable( - var_name, true /* AllowInternal */); + auto lifted_var = + gModule->getGlobalVariable(var_name, true /* AllowInternal */); if (lifted_var) { return lifted_var; @@ -538,60 +528,56 @@ llvm::Constant *NativeSegment::Pointer(void) const { module->AddNameToAddress(var_name, ea); if (is_external) { - LOG(INFO) - << "Adding external segment " << name << " at " - << std::hex << ea << std::dec; + LOG(INFO) << "Adding external segment " << name << " at " << std::hex << ea + << std::dec; - llvm::Type* var_type = nullptr; + llvm::Type *var_type = nullptr; - CHECK_NE(0, size) - << "The size of the external variable '" << name << "' at " - << std::hex << ea << std::dec << " cannot be zero"; + CHECK_NE(0, size) << "The size of the external variable '" << name + << "' at " << std::hex << ea << std::dec + << " cannot be zero"; // Handle external variables of up to 128 bits as intgers // Anything else is treated as an array of bytes - switch(size) { + switch (size) { case 0: + // Why is this zero length? This should never happen // Attempt a fix and output a warning - LOG(ERROR) - << "The variable '" << name << "' at " << std::hex << ea - << std::dec << " has size of zero; Assuming it should be size 1"; + LOG(ERROR) << "The variable '" << name << "' at " << std::hex << ea + << std::dec + << " has size of zero; Assuming it should be size 1"; var_type = llvm::Type::getInt8Ty(*gContext); break; - case 1: // 8 bit integer - case 2: // 16 bit integer - case 4: // 32 bit integer - case 8: // 64 bit integer - case 16: // 128 bit integer - var_type = llvm::Type::getIntNTy( - *gContext, static_cast(size * 8u)); + case 1: // 8 bit integer + case 2: // 16 bit integer + case 4: // 32 bit integer + case 8: // 64 bit integer + case 16: // 128 bit integer + var_type = + llvm::Type::getIntNTy(*gContext, static_cast(size * 8u)); break; // An array of bytes default: { auto byte_type = llvm::Type::getInt8Ty(*gContext); - var_type = llvm::ArrayType::get( - byte_type, static_cast(size)); + var_type = llvm::ArrayType::get(byte_type, static_cast(size)); break; } } lifted_var = new llvm::GlobalVariable( - *gModule, var_type, false, llvm::GlobalValue::ExternalLinkage, - nullptr, var_name, nullptr, ThreadLocalMode(this)); + *gModule, var_type, false, llvm::GlobalValue::ExternalLinkage, nullptr, + var_name, nullptr, ThreadLocalMode(this)); } else { - const auto linkage = is_exported ? - llvm::GlobalValue::ExternalLinkage : - llvm::GlobalValue::InternalLinkage; - LOG(INFO) - << "Adding internal segment " << name; + const auto linkage = is_exported ? llvm::GlobalValue::ExternalLinkage + : llvm::GlobalValue::InternalLinkage; + LOG(INFO) << "Adding internal segment " << name; lifted_var = new llvm::GlobalVariable( - *gModule, GetSegmentType(this), is_read_only, - linkage, nullptr, var_name, nullptr, - ThreadLocalMode(this)); + *gModule, GetSegmentType(this), is_read_only, linkage, nullptr, + var_name, nullptr, ThreadLocalMode(this)); } if (ea) { @@ -613,12 +599,11 @@ llvm::Function *GetOrCreateMcSemaInitializer(void) { } LOG(INFO) - << "Creating __mcsema_early_init function to pre-initialize runtime."; + << "Creating __mcsema_early_init function to pre-initialize runtime."; gInitFunc = llvm::Function::Create( llvm::FunctionType::get(llvm::Type::getVoidTy(*gContext), false), - llvm::GlobalValue::InternalLinkage, - "__mcsema_early_init", gModule.get()); + llvm::GlobalValue::InternalLinkage, "__mcsema_early_init", gModule.get()); auto bool_type = llvm::Type::getInt1Ty(*gContext); auto check_var = new llvm::GlobalVariable( @@ -653,16 +638,18 @@ void DefineDataSegments(const NativeModule *cfg_module) { // Try to deduce what constructor and destructor functions should be used bool DetectAndSetInitFiniCode(const NativeModule *cfg_module) { + // init_fini_pairs.size % 2 == 0 must hold // constructor is first std::vector> init_fini_pairs = { - // Stripped binaries - {"init", false}, - {"fini", false}, - // Not stripped binaries - {"__libc_csu_init", false}, - {"__libc_csu_fini", false}, + // Stripped binaries + {"init", false}, + {"fini", false}, + + // Not stripped binaries + {"__libc_csu_init", false}, + {"__libc_csu_fini", false}, }; for (const auto &cfg_func : cfg_module->ea_to_func) { @@ -677,9 +664,8 @@ bool DetectAndSetInitFiniCode(const NativeModule *cfg_module) { if (init_fini_pairs[i].second && init_fini_pairs[i + 1].second) { FLAGS_libc_constructor = init_fini_pairs[i].first; FLAGS_libc_destructor = init_fini_pairs[i + 1].first; - LOG(INFO) << "Deduced libc ctor/dtor to " - << FLAGS_libc_constructor << " / " - << FLAGS_libc_destructor; + LOG(INFO) << "Deduced libc ctor/dtor to " << FLAGS_libc_constructor + << " / " << FLAGS_libc_destructor; return true; } } diff --git a/mcsema/BC/Util.cpp b/mcsema/BC/Util.cpp index 72abe51ce..e2e9d950c 100644 --- a/mcsema/BC/Util.cpp +++ b/mcsema/BC/Util.cpp @@ -17,19 +17,15 @@ #include "mcsema/BC/Util.h" -#include #include - -#include - +#include #include #include #include -#include #include +#include #include #include - #include #include #include @@ -37,9 +33,13 @@ #include #include +#include + #include "mcsema/Arch/Arch.h" -DEFINE_bool(disable_aliases, false, "Disable using global aliases for accessing data/registers in the bitcode"); +DEFINE_bool( + disable_aliases, false, + "Disable using global aliases for accessing data/registers in the bitcode"); namespace mcsema { @@ -50,15 +50,13 @@ std::unique_ptr gModule = nullptr; llvm::Constant *gZero = nullptr; llvm::Value *GetConstantInt(unsigned size, uint64_t value) { - return llvm::ConstantInt::get( - llvm::Type::getIntNTy(*gContext, size), value); + return llvm::ConstantInt::get(llvm::Type::getIntNTy(*gContext, size), value); } // Get a lifted representation of a reference (in code) to `ea`. llvm::Constant *LiftXrefInCode(uint64_t ea) { return llvm::ConstantExpr::getAdd( - gZero, - llvm::ConstantInt::get(gWordType, ea & gWordMask, false)); + gZero, llvm::ConstantInt::get(gWordType, ea & gWordMask, false)); } // Get a lifted representation of a reference (in data) to `ea`. @@ -77,8 +75,8 @@ llvm::Constant *LiftXrefInData(const NativeSegment *cfg_seg, uint64_t ea, ptr = alias; } else { - auto seg_var = llvm::dyn_cast( - cfg_seg->Get()->Pointer()); + auto seg_var = + llvm::dyn_cast(cfg_seg->Get()->Pointer()); auto seg_type = remill::GetValueType(seg_var); llvm::DataLayout dl(gModule.get()); @@ -87,20 +85,20 @@ llvm::Constant *LiftXrefInData(const NativeSegment *cfg_seg, uint64_t ea, auto i32_type = llvm::Type::getInt32Ty(*gContext); gep_index_list.push_back(llvm::ConstantInt::get(i32_type, 0)); const auto goal_offset = (ea - cfg_seg->ea) + cfg_seg->padding; - auto [offset, type] = remill::BuildIndexes( - dl, seg_type, 0, goal_offset, gep_index_list); + auto [offset, type] = + remill::BuildIndexes(dl, seg_type, 0, goal_offset, gep_index_list); ptr = seg_var; if (offset) { (void) type; - ptr = llvm::ConstantExpr::getInBoundsGetElementPtr( - seg_type, seg_var, gep_index_list); + ptr = llvm::ConstantExpr::getInBoundsGetElementPtr(seg_type, seg_var, + gep_index_list); } if (offset < goal_offset) { auto i8_type = llvm::Type::getInt8Ty(*gContext); - ptr = llvm::ConstantExpr::getBitCast( - ptr, llvm::PointerType::get(i8_type, 0)); + ptr = llvm::ConstantExpr::getBitCast(ptr, + llvm::PointerType::get(i8_type, 0)); ptr = llvm::ConstantExpr::getInBoundsGetElementPtr( i8_type, ptr, llvm::ConstantInt::get(i32_type, goal_offset - offset, false)); @@ -162,12 +160,11 @@ llvm::Value *GetTLSBaseAddress(llvm::IRBuilder<> &ir) { if (gArch->IsAArch64()) { #if LLVM_VERSION(3, 7) >= LLVM_VERSION_NUMBER - LOG(ERROR) - << "LLVM 3.7 and below have no thread pointer-related " - << "intrinsics; using NULL as the base of TLS."; + LOG(ERROR) << "LLVM 3.7 and below have no thread pointer-related " + << "intrinsics; using NULL as the base of TLS."; return llvm::ConstantInt::get(gWordType, 0); #else -# if LLVM_VERSION(3, 8) >= LLVM_VERSION_NUMBER +# if LLVM_VERSION(3, 8) >= LLVM_VERSION_NUMBER if (gArch->IsAArch64()) { LOG(ERROR) << "Assuming the `llvm.arm.thread.pointer` intrinsic gets us the base " @@ -178,10 +175,9 @@ llvm::Value *GetTLSBaseAddress(llvm::IRBuilder<> &ir) { return ir.CreatePtrToInt(ir.CreateCall(func), gWordType); } } -# endif - LOG(ERROR) - << "Assuming the `thread.pointer` intrinsic gets us the base " - << "of thread-local storage."; +# endif + LOG(ERROR) << "Assuming the `thread.pointer` intrinsic gets us the base " + << "of thread-local storage."; auto func = llvm::Intrinsic::getDeclaration( gModule.get(), llvm::Intrinsic::thread_pointer); return ir.CreatePtrToInt(ir.CreateCall(func), gWordType); @@ -224,10 +220,9 @@ llvm::Value *GetTLSBaseAddress(llvm::IRBuilder<> &ir) { } } - LOG(FATAL) - << "Cannot generate code to find the thread base pointer for arch " - << remill::GetArchName(gArch->arch_name) << " and OS " - << remill::GetOSName(gArch->os_name); + LOG(FATAL) << "Cannot generate code to find the thread base pointer for arch " + << remill::GetArchName(gArch->arch_name) << " and OS " + << remill::GetOSName(gArch->os_name); return nullptr; } diff --git a/mcsema/BC/Util.h b/mcsema/BC/Util.h index 255ba899b..6d23252e6 100644 --- a/mcsema/BC/Util.h +++ b/mcsema/BC/Util.h @@ -17,12 +17,12 @@ #pragma once +#include + #include #include #include -#include - #include "mcsema/CFG/CFG.h" namespace llvm { @@ -53,7 +53,7 @@ llvm::Constant *LiftXrefInCode(uint64_t ea); // Get a lifted representation of a reference (in data) to `ea`. llvm::Constant *LiftXrefInData(const NativeSegment *cfg_seg, uint64_t ea, - bool cast_to_int=true); + bool cast_to_int = true); // Create a global register state pointer to pass to lifted functions. llvm::Constant *GetStatePointer(void); diff --git a/mcsema/CFG/CFG.cpp b/mcsema/CFG/CFG.cpp index 056206e58..a7e5ac624 100644 --- a/mcsema/CFG/CFG.cpp +++ b/mcsema/CFG/CFG.cpp @@ -15,30 +15,27 @@ * along with this program. If not, see . */ -#include #include +#include +#include #include +#include #include #include -#include #include #include #include -#include - // Auto-generated by cmake/protobuf inside the build directory. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wshorten-64-to-32" #include #pragma clang diagnostic pop -#include -#include - #include #include - +#include +#include #include #include #include @@ -51,12 +48,13 @@ DECLARE_bool(explicit_args); -DEFINE_bool(disable_adjacent_segment_merging, false, - "Should we disable merging of adjacent segments? Adjacent segment " - "merging is performed in order to improve the reliability of cross-" - "reference lifting and comparisons, e.g. if a pointer comparison is " - "used to test if a loop should terminate, then sometimes that " - "pointer might be one element past the end of a segment."); +DEFINE_bool( + disable_adjacent_segment_merging, false, + "Should we disable merging of adjacent segments? Adjacent segment " + "merging is performed in order to improve the reliability of cross-" + "reference lifting and comparisons, e.g. if a pointer comparison is " + "used to test if a loop should terminate, then sometimes that " + "pointer might be one element past the end of a segment."); namespace mcsema { namespace { @@ -93,14 +91,13 @@ static std::string LiftedSegmentName(const Segment &cfg_segment) { if (has_name && cfg_segment.is_exported()) { ss << cfg_segment.variable_name(); } else { - ss << "seg_var_" << std::hex << cfg_segment.ea() - << "_" << SaneName(cfg_segment.variable_name()) - << "_" << cfg_segment.data().size(); + ss << "seg_var_" << std::hex << cfg_segment.ea() << "_" + << SaneName(cfg_segment.variable_name()) << "_" + << cfg_segment.data().size(); } } else { - ss << "seg_" << std::hex << cfg_segment.ea() - << "_" << SaneName(cfg_segment.name()) - << "_" << cfg_segment.data().size(); + ss << "seg_" << std::hex << cfg_segment.ea() << "_" + << SaneName(cfg_segment.name()) << "_" << cfg_segment.data().size(); } return ss.str(); } @@ -116,8 +113,7 @@ static std::string LiftedVarName(const Variable &cfg_var) { static std::string ExternalFuncName(const ExternalFunction &cfg_func) { std::stringstream ss; - ss << "ext_" << std::hex << cfg_func.ea() - << "_" << SaneName(cfg_func.name()); + ss << "ext_" << std::hex << cfg_func.ea() << "_" << SaneName(cfg_func.name()); return ss.str(); } @@ -143,12 +139,11 @@ static bool ResolveReference(NativeModule *module, NativeXref *xref) { } if (xref->target_segment) { - LOG(WARNING) - << "Data cross reference at " << std::hex << xref->ea - << " in segment " << xref->segment->name - << " targeting " << xref->target_ea << " in segment " - << xref->target_segment->name - << " is not associated with a function or variable"; + LOG(WARNING) << "Data cross reference at " << std::hex << xref->ea + << " in segment " << xref->segment->name << " targeting " + << xref->target_ea << " in segment " + << xref->target_segment->name + << " is not associated with a function or variable"; return true; } @@ -195,8 +190,8 @@ static bool FillXref(NativeModule *module, NativeInstruction *inst, case CodeReference_OperandType_ControlFlowOperand: LOG_IF(WARNING, inst->flow != nullptr) - << "Overwriting existing flow reference at instruction " - << std::hex << inst->ea << std::dec; + << "Overwriting existing flow reference at instruction " << std::hex + << inst->ea << std::dec; inst->flow = xref; break; @@ -221,8 +216,8 @@ NativeExternalFunction::NativeExternalFunction(NativeModule *module_) : NativeFunction(module_), cc(gArch->DefaultCallingConv()) {} -NativeSegment::Entry::Entry( - uint64_t o_ea, uint64_t o_next_ea, NativeXref *o_xref, NativeBlob *o_blob) +NativeSegment::Entry::Entry(uint64_t o_ea, uint64_t o_next_ea, + NativeXref *o_xref, NativeBlob *o_blob) : ea(o_ea), next_ea(o_next_ea), xref(o_xref), @@ -252,14 +247,12 @@ NativeObject *NativeObject::Get(void) { } llvm::Constant *NativeObject::Pointer(void) const { - LOG(FATAL) - << "Invalid use."; + LOG(FATAL) << "Invalid use."; return nullptr; } llvm::Constant *NativeObject::Address(void) const { - LOG(FATAL) - << "Invalid use."; + LOG(FATAL) << "Invalid use."; return nullptr; } @@ -292,9 +285,8 @@ bool RecoverValueDecl(const NativeFunction *func, anvill::ValueDecl &decl, const ValueDecl &cfg_decl) { auto maybe_type = anvill::ParseType(*gContext, cfg_decl.type()); if (remill::IsError(maybe_type)) { - LOG(ERROR) - << "Could not parse type in value spec of function " - << func->name << ": " << remill::GetErrorString(maybe_type); + LOG(ERROR) << "Could not parse type in value spec of function " + << func->name << ": " << remill::GetErrorString(maybe_type); return false; } @@ -302,10 +294,9 @@ bool RecoverValueDecl(const NativeFunction *func, anvill::ValueDecl &decl, if (cfg_decl.has_memory()) { decl.mem_reg = gArch->RegisterByName(cfg_decl.memory().register_()); if (!decl.mem_reg) { - LOG(ERROR) - << "Bad register name '" << cfg_decl.memory().register_() - << "' in function spec for " << func->name << " at " << std::hex - << func->ea << std::dec; + LOG(ERROR) << "Bad register name '" << cfg_decl.memory().register_() + << "' in function spec for " << func->name << " at " + << std::hex << func->ea << std::dec; return false; } decl.mem_offset = cfg_decl.memory().offset(); @@ -314,10 +305,9 @@ bool RecoverValueDecl(const NativeFunction *func, anvill::ValueDecl &decl, } else if (cfg_decl.has_register_()) { decl.reg = gArch->RegisterByName(cfg_decl.register_()); if (!decl.reg) { - LOG(ERROR) - << "Bad register name '" << cfg_decl.register_() - << "' in function spec for " << func->name << " at " << std::hex - << func->ea << std::dec; + LOG(ERROR) << "Bad register name '" << cfg_decl.register_() + << "' in function spec for " << func->name << " at " + << std::hex << func->ea << std::dec; return false; } return true; @@ -345,10 +335,9 @@ bool RecoverRetDecl(const NativeFunction *func, anvill::FunctionDecl &decl, } // Recover a `FunctionDecl` from the CFG. -void RecoverFunctionDecl(NativeModule *module, - NativeFunction *func, +void RecoverFunctionDecl(NativeModule *module, NativeFunction *func, const FunctionDecl &cfg_decl, - llvm::Function *ll_func=nullptr) { + llvm::Function *ll_func = nullptr) { anvill::FunctionDecl decl; decl.address = func->ea; decl.arch = gArch.get(); @@ -364,13 +353,12 @@ void RecoverFunctionDecl(NativeModule *module, } } - decl.calling_convention = static_cast( - cfg_decl.calling_convention()); + decl.calling_convention = + static_cast(cfg_decl.calling_convention()); if (!cfg_decl.has_return_stack_pointer()) { - LOG(ERROR) - << "Function spec for " << func->name << " at " << std::hex - << func->ea << std::dec << " is missing a return stack pointer"; + LOG(ERROR) << "Function spec for " << func->name << " at " << std::hex + << func->ea << std::dec << " is missing a return stack pointer"; return; } @@ -383,26 +371,25 @@ void RecoverFunctionDecl(NativeModule *module, cfg_decl.return_stack_pointer().memory().offset(); } else if (cfg_decl.return_stack_pointer().has_register_()) { - decl.return_stack_pointer = gArch->RegisterByName( - cfg_decl.return_stack_pointer().register_()); + decl.return_stack_pointer = + gArch->RegisterByName(cfg_decl.return_stack_pointer().register_()); } else { - LOG(ERROR) - << "Function spec for " << func->name << " at " << std::hex - << func->ea << std::dec << " is missing a return stack pointer"; + LOG(ERROR) << "Function spec for " << func->name << " at " << std::hex + << func->ea << std::dec << " is missing a return stack pointer"; return; } if (!decl.return_stack_pointer) { if (cfg_decl.return_stack_pointer().has_memory()) { - LOG(ERROR) - << "Function spec for " << func->name << " at " << std::hex - << func->ea << std::dec << " has an invalid return stack pointer name '" - << cfg_decl.return_stack_pointer().memory().register_() << "'"; + LOG(ERROR) << "Function spec for " << func->name << " at " << std::hex + << func->ea << std::dec + << " has an invalid return stack pointer name '" + << cfg_decl.return_stack_pointer().memory().register_() << "'"; } else { - LOG(ERROR) - << "Function spec for " << func->name << " at " << std::hex - << func->ea << std::dec << " has an invalid return stack pointer name '" - << cfg_decl.return_stack_pointer().register_() << "'"; + LOG(ERROR) << "Function spec for " << func->name << " at " << std::hex + << func->ea << std::dec + << " has an invalid return stack pointer name '" + << cfg_decl.return_stack_pointer().register_() << "'"; } return; } @@ -430,8 +417,7 @@ void RecoverFunctionDecl(NativeModule *module, auto maybe_func = module->DeclareFunction(decl, true); if (remill::IsError(maybe_func)) { - LOG(ERROR) - << remill::GetErrorString(maybe_func); + LOG(ERROR) << remill::GetErrorString(maybe_func); return; } else { @@ -456,8 +442,7 @@ NativeModule *ReadProtoBuf(const std::string &file_name, GOOGLE_PROTOBUF_VERIFY_VERSION; std::ifstream fstream(file_name, std::ios::binary); - CHECK(fstream.good()) - << "Unable to open CFG file " << file_name; + CHECK(fstream.good()) << "Unable to open CFG file " << file_name; google::protobuf::io::IstreamInputStream pstream(&fstream); google::protobuf::io::CodedInputStream cstream(&pstream); @@ -466,9 +451,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, CHECK(cfg.ParseFromCodedStream(&cstream)) << "Unable to read module from CFG file " << file_name; - LOG(INFO) - << "Lifting program " << cfg.name() << " via CFG protobuf in " - << file_name; + LOG(INFO) << "Lifting program " << cfg.name() << " via CFG protobuf in " + << file_name; auto module = new NativeModule; @@ -480,6 +464,7 @@ NativeModule *ReadProtoBuf(const std::string &file_name, const auto cfg_func = cfg.mutable_funcs(f); const auto func_ea = static_cast(cfg_func->ea()); if (auto found_func = module->TryGetFunction(func_ea)) { + // TODO(pag): Add some kind of name->var mapping so that we can // cover this. @@ -498,9 +483,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, } LOG_IF(WARNING, found_func->name != cfg_func->name()) - << "Two or more names for function at " << std::hex - << found_func->ea << std::dec << ": '" << found_func->name - << "' and '" << cfg_func->name() << "'"; + << "Two or more names for function at " << std::hex << found_func->ea + << std::dec << ": '" << found_func->name << "' and '" + << cfg_func->name() << "'"; continue; } @@ -515,18 +500,17 @@ NativeModule *ReadProtoBuf(const std::string &file_name, func->is_exported = cfg_func->is_entrypoint(); module->ea_to_func[func->ea] = func; - LOG(INFO) - << "Found function " << func->name << " at " << std::hex - << func->ea << std::dec; + LOG(INFO) << "Found function " << func->name << " at " << std::hex + << func->ea << std::dec; if (func->is_exported) { CHECK(!func->name.empty()) << "Exported function at address " << std::hex << func->ea << std::dec << " does not have a name"; - LOG(INFO) - << "Exported function " << func->name << " at " << std::hex - << func->ea << std::dec << " is implemented by " << func->lifted_name; + LOG(INFO) << "Exported function " << func->name << " at " << std::hex + << func->ea << std::dec << " is implemented by " + << func->lifted_name; } module->AddNameToAddress(func->name, func->ea); @@ -550,14 +534,12 @@ NativeModule *ReadProtoBuf(const std::string &file_name, auto maybe_decl = anvill::FunctionDecl::Create(*ll_func, gArch); if (remill::IsError(maybe_decl)) { - LOG(ERROR) - << remill::GetErrorString(maybe_decl); + LOG(ERROR) << remill::GetErrorString(maybe_decl); } else { maybe_decl->address = func->ea; auto maybe_decl_ptr = module->DeclareFunction(*maybe_decl, true); if (remill::IsError(maybe_decl_ptr)) { - LOG(ERROR) - << remill::GetErrorString(maybe_decl_ptr); + LOG(ERROR) << remill::GetErrorString(maybe_decl_ptr); } else { LOG_IF(WARNING, func->decl != nullptr) << "Overwriting CFG-specified function specification for " @@ -581,9 +563,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, const auto func_ea = static_cast(cfg_extern_func->ea()); if (!cfg_extern_func->has_name()) { - LOG(WARNING) - << "Ignoring external function at " << std::hex - << func_ea << std::dec << " with no name."; + LOG(WARNING) << "Ignoring external function at " << std::hex << func_ea + << std::dec << " with no name."; continue; } @@ -592,22 +573,19 @@ NativeModule *ReadProtoBuf(const std::string &file_name, found_func->is_exported = true; found_func->name = std::move(*(cfg_extern_func->mutable_name())); - LOG(INFO) - << "Exported function " << found_func->name << " at " << std::hex - << found_func->ea << std::dec << " is implemented by " - << found_func->lifted_name; + LOG(INFO) << "Exported function " << found_func->name << " at " + << std::hex << found_func->ea << std::dec + << " is implemented by " << found_func->lifted_name; } else if (found_func->name != cfg_extern_func->name()) { - LOG(ERROR) - << "Duplicate conflicting names for function at " << std::hex - << func_ea << std::dec << ": '" << found_func->name << "' and '" - << cfg_extern_func->name() << "'"; + LOG(ERROR) << "Duplicate conflicting names for function at " << std::hex + << func_ea << std::dec << ": '" << found_func->name + << "' and '" << cfg_extern_func->name() << "'"; } else { - LOG(WARNING) - << "Ignoring external function '" << found_func->name - << "' at " << std::hex << func_ea << std::dec - << " that shadows internal function at same address"; + LOG(WARNING) << "Ignoring external function '" << found_func->name + << "' at " << std::hex << func_ea << std::dec + << " that shadows internal function at same address"; } continue; } @@ -631,9 +609,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // about the function. const auto ll_func = gModule->getFunction(func->name); - LOG(INFO) - << "Found external function " << func->name << " at " - << std::hex << func->ea << std::dec; + LOG(INFO) << "Found external function " << func->name << " at " << std::hex + << func->ea << std::dec; // Extract the function decl. This might declare the extern in the module. if (cfg_extern_func->has_decl()) { @@ -649,15 +626,13 @@ NativeModule *ReadProtoBuf(const std::string &file_name, ll_func_cc = ll_func->getCallingConv(); if (remill::IsError(maybe_decl)) { - LOG(ERROR) - << remill::GetErrorString(maybe_decl); + LOG(ERROR) << remill::GetErrorString(maybe_decl); } else { maybe_decl->address = func->ea; auto maybe_decl_ptr = module->DeclareFunction(*maybe_decl, true); if (remill::IsError(maybe_decl_ptr)) { - LOG(ERROR) - << remill::GetErrorString(maybe_decl_ptr); + LOG(ERROR) << remill::GetErrorString(maybe_decl_ptr); } else { LOG_IF(WARNING, func->decl != nullptr) @@ -719,9 +694,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, << "Internal variable at " << std::hex << func->ea << " has the same name as the external function " << func->name; - LOG(INFO) - << "Found external function " << func->name << " via " - << std::hex << func->ea; + LOG(INFO) << "Found external function " << func->name << " via " << std::hex + << func->ea; // Check to see if an external function with the same name was already // added. This is possible if there are things like thunks calling thunks, @@ -733,9 +707,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, CHECK_NE(dup_func->ea, func->ea); - LOG(WARNING) - << "External function " << func->name << " at " << std::hex - << func->ea << " is also defined at " << std::hex << dup_func->ea; + LOG(WARNING) << "External function " << func->name << " at " << std::hex + << func->ea << " is also defined at " << std::hex + << dup_func->ea; } module->ea_to_func[func->ea] = func; @@ -749,9 +723,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, const auto cfg_extern_var = cfg.mutable_external_vars(v); const auto var_ea = static_cast(cfg_extern_var->ea()); if (!cfg_extern_var->has_name()) { - LOG(WARNING) - << "Ignoring unnamed external variable at " << std::hex - << var_ea << std::dec; + LOG(WARNING) << "Ignoring unnamed external variable at " << std::hex + << var_ea << std::dec; continue; } @@ -760,22 +733,20 @@ NativeModule *ReadProtoBuf(const std::string &file_name, found_func->is_exported = true; found_func->name = std::move(*(cfg_extern_var->mutable_name())); - LOG(INFO) - << "Exported function " << found_func->name << " at " << std::hex - << found_func->ea << std::dec << " is implemented by " - << found_func->lifted_name << " using hint from external variable"; + LOG(INFO) << "Exported function " << found_func->name << " at " + << std::hex << found_func->ea << std::dec + << " is implemented by " << found_func->lifted_name + << " using hint from external variable"; } else if (found_func->name != cfg_extern_var->name()) { - LOG(ERROR) - << "Duplicate conflicting names for function at " << std::hex - << var_ea << std::dec << " '" << found_func->name - << "' and variable '" << cfg_extern_var->name() << "'"; + LOG(ERROR) << "Duplicate conflicting names for function at " << std::hex + << var_ea << std::dec << " '" << found_func->name + << "' and variable '" << cfg_extern_var->name() << "'"; } else { - LOG(WARNING) - << "Ignoring external variable '" << found_func->name - << "' at " << std::hex << var_ea << std::dec - << " that shadows function at same address"; + LOG(WARNING) << "Ignoring external variable '" << found_func->name + << "' at " << std::hex << var_ea << std::dec + << " that shadows function at same address"; } continue; } @@ -789,10 +760,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, auto seg_size = static_cast(cfg_extern_var->size()); auto &seg_ptr = module->ea_to_seg[var_ea]; if (seg_ptr) { - LOG(ERROR) - << "Segment '" << seg_ptr->name << "' at " << std::hex << seg_ptr->ea - << " is being redefined as '" << cfg_extern_var->name() - << "' at " << var_ea << std::dec; + LOG(ERROR) << "Segment '" << seg_ptr->name << "' at " << std::hex + << seg_ptr->ea << " is being redefined as '" + << cfg_extern_var->name() << "' at " << var_ea << std::dec; if (seg_ptr->as_extern_var) { seg_ptr->as_extern_var->ForwardTo(var); @@ -826,9 +796,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, var->is_weak = cfg_extern_var->is_weak(); var->size = seg_size; - LOG(INFO) - << "Found external variable " << var->name << " at " - << std::hex << var->ea << std::dec; + LOG(INFO) << "Found external variable " << var->name << " at " << std::hex + << var->ea << std::dec; // Look for two extern variables with the same name. auto extern_var_it = name_to_extern_var.find(var->name); @@ -839,9 +808,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, CHECK_NE(dup_var->ea, var->ea); - LOG(WARNING) - << "External variable " << var->name << " at " << std::hex - << var->ea << " is also defined at " << dup_var->ea << std::dec; + LOG(WARNING) << "External variable " << var->name << " at " << std::hex + << var->ea << " is also defined at " << dup_var->ea + << std::dec; } module->ea_to_var[var->ea] = var; @@ -856,9 +825,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, if (cfg_segment->has_variable_name()) { if (name_to_extern_var.count(cfg_segment->variable_name())) { - LOG(ERROR) - << "Skipping segment '" << cfg_segment->variable_name() - << " as it's already associated with an extern var";; + LOG(ERROR) << "Skipping segment '" << cfg_segment->variable_name() + << " as it's already associated with an extern var"; + ; continue; } } @@ -893,22 +862,20 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // cover this. LOG_IF(WARNING, found_var->name != cfg_var->name()) - << "Two or more names for variable at " << std::hex - << found_var->ea << std::dec << ": '" << found_var->name - << "' and '" << cfg_var->name() << "'"; + << "Two or more names for variable at " << std::hex << found_var->ea + << std::dec << ": '" << found_var->name << "' and '" + << cfg_var->name() << "'"; UpdateVariable(found_var, segment); } else if (auto found_func = module->TryGetFunction(var_ea)) { - LOG(WARNING) - << "Ignoring variable '" << cfg_var->name() << "' at " << std::hex - << var_ea << std::dec << " that shadows function '" - << found_func->name << "'"; + LOG(WARNING) << "Ignoring variable '" << cfg_var->name() << "' at " + << std::hex << var_ea << std::dec + << " that shadows function '" << found_func->name << "'"; } else if (!cfg_var->has_name()) { - LOG(ERROR) - << "Unnamed variable at " << std::hex << cfg_var->ea() << std::dec - << " in segment " << segment->name; + LOG(ERROR) << "Unnamed variable at " << std::hex << cfg_var->ea() + << std::dec << " in segment " << segment->name; } else { auto var = new NativeVariable(module); @@ -927,15 +894,14 @@ NativeModule *ReadProtoBuf(const std::string &file_name, segment->name = var->name; } - LOG(INFO) - << "Found variable " << var->name << " at " << std::hex - << var->ea << std::dec; + LOG(INFO) << "Found variable " << var->name << " at " << std::hex + << var->ea << std::dec; } } - LOG(INFO) - << "Found segment " << segment->name << " [" << std::hex << segment->ea - << ", " << (segment->ea + segment->size) << std::dec << ")"; + LOG(INFO) << "Found segment " << segment->name << " [" << std::hex + << segment->ea << ", " << (segment->ea + segment->size) + << std::dec << ")"; auto &seg_ptr = module->ea_to_seg[segment->ea]; LOG_IF(WARNING, !!seg_ptr) @@ -960,9 +926,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, xref->target_segment = FindSegment(module, xref->target_ea); CHECK(xref->width <= pointer_size) - << "Cross reference at " << std::hex << xref->ea << " to " - << std::hex << xref->target_ea << " is too wide at " - << xref->width << " bytes"; + << "Cross reference at " << std::hex << xref->ea << " to " << std::hex + << xref->target_ea << " is too wide at " << xref->width << " bytes"; switch (cfg_xref.target_fixup_kind()) { case DataReference_TargetFixupKind_Absolute: @@ -1003,9 +968,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, range.begin = reinterpret_cast(cfg_segment.data().data()); range.end = &(range.begin[cfg_segment.data().size()]); if (auto err = module->MapRange(range); remill::IsError(err)) { - LOG(FATAL) - << "Unable to map segment " << segment->name - << ": " << remill::GetErrorString(err); + LOG(FATAL) << "Unable to map segment " << segment->name << ": " + << remill::GetErrorString(err); } for (const auto &xref_entry : segment->entries) { @@ -1055,8 +1019,7 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // Merge zero blobs with zero blobs, and non-zero blobs with non-zero // blobs. - if (!blobs.empty() && - blobs.back().next_ea == blob_ea && + if (!blobs.empty() && blobs.back().next_ea == blob_ea && blobs.back().blob && blob->is_zero == blobs.back().blob->is_zero) { @@ -1064,8 +1027,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, blobs.back().next_ea = blob_end_ea; } else { - blobs.push_back(NativeSegment::Entry{ - blob_ea, blob_end_ea, nullptr, blob.release()}); + blobs.push_back(NativeSegment::Entry{blob_ea, blob_end_ea, nullptr, + blob.release()}); } } @@ -1084,8 +1047,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, for (ea += 1; ea < entry.next_ea; ++ea) { auto var_it = module->ea_to_var.find(ea); LOG_IF(ERROR, var_it != module->ea_to_var.end()) - << "Variable " << var_it->second->name << " at " - << std::hex << var_it->second->ea + << "Variable " << var_it->second->name << " at " << std::hex + << var_it->second->ea << " points into a cross reference, located at " << std::hex << entry.xref->ea << " and targeting " << std::hex << entry.xref->target_ea; @@ -1104,9 +1067,9 @@ NativeModule *ReadProtoBuf(const std::string &file_name, unsigned entry_num = 0; for (const auto &entry : segment->entries) { CHECK(entry.first == ea) - << "Invalid partitioning of segment " << segment->name - << "; entry #" << std::dec << entry_num << " EA address " - << std::hex << entry.first << " does not match " + << "Invalid partitioning of segment " << segment->name << "; entry #" + << std::dec << entry_num << " EA address " << std::hex << entry.first + << " does not match " << "up with expected entry EA " << std::hex << ea; CHECK(entry.second.ea == ea) @@ -1131,10 +1094,11 @@ NativeModule *ReadProtoBuf(const std::string &file_name, continue; } - if (auto func_byte = module->FindByte(func->ea); !func_byte.IsExecutable()) { + if (auto func_byte = module->FindByte(func->ea); + !func_byte.IsExecutable()) { LOG(ERROR) << "Could not find any executable bytes associated with function " - << std::hex << func->ea << std::dec; + << std::hex << func->ea << std::dec; continue; } @@ -1187,7 +1151,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // Merge in successors. std::sort(block->successor_eas.begin(), block->successor_eas.end()); - auto it = std::unique(block->successor_eas.begin(), block->successor_eas.end()); + auto it = + std::unique(block->successor_eas.begin(), block->successor_eas.end()); block->successor_eas.erase(it, block->successor_eas.end()); func->blocks.push_back(block.get()); @@ -1266,7 +1231,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, } } - auto num_preserved_reg_sets = cfg.preserved_regs_size() + cfg.dead_regs_size(); + auto num_preserved_reg_sets = + cfg.preserved_regs_size() + cfg.dead_regs_size(); module->preserved_regs.resize(static_cast(num_preserved_reg_sets)); auto i = 0; for (; i < cfg.preserved_regs_size(); ++i) { @@ -1300,7 +1266,7 @@ NativeModule *ReadProtoBuf(const std::string &file_name, } } - auto prune_segments = [=] (void) { + auto prune_segments = [=](void) { for (auto &seg : module->segments) { if (seg.get() != seg->Get()) { module->unused_segments.emplace_back(std::move(seg)); @@ -1308,8 +1274,8 @@ NativeModule *ReadProtoBuf(const std::string &file_name, } std::sort(module->segments.begin(), module->segments.end(), - [] (const std::unique_ptr &a, - const std::unique_ptr &b) { + [](const std::unique_ptr &a, + const std::unique_ptr &b) { return a.get() > b.get(); }); @@ -1327,35 +1293,33 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // external vars, together, and internal segments together, so that we // don't miss merging opportunities. std::sort(module->segments.begin(), module->segments.end(), - [] (const std::unique_ptr &a, - const std::unique_ptr &b) { - if (a->is_external == b->is_external) { - return a->ea < b->ea; - } else { - return a->is_external < b->is_external; - } - }); + [](const std::unique_ptr &a, + const std::unique_ptr &b) { + if (a->is_external == b->is_external) { + return a->ea < b->ea; + } else { + return a->is_external < b->is_external; + } + }); auto merged = false; - for (auto i = module->segments.size(); i > 1u; ) { + for (auto i = module->segments.size(); i > 1u;) { auto &seg = module->segments[--i]; auto &prev_seg = module->segments[i - 1u]; if ((prev_seg->ea + prev_seg->size) == seg->ea && !prev_seg->is_external && !seg->is_external) { merged = true; - LOG(WARNING) - << "Merging adjacent segments " << prev_seg->name << " at " - << std::hex << prev_seg->ea << " and " - << seg->name << " at " << seg->ea << std::dec; + LOG(WARNING) << "Merging adjacent segments " << prev_seg->name << " at " + << std::hex << prev_seg->ea << " and " << seg->name + << " at " << seg->ea << std::dec; prev_seg->size += seg->size; seg->size = 0; - prev_seg->entries.insert( - std::make_move_iterator(seg->entries.begin()), - std::make_move_iterator(seg->entries.end())); + prev_seg->entries.insert(std::make_move_iterator(seg->entries.begin()), + std::make_move_iterator(seg->entries.end())); seg->entries.clear(); if (!seg->is_read_only) { @@ -1377,10 +1341,10 @@ NativeModule *ReadProtoBuf(const std::string &file_name, // Order the segments in increasing order of size. std::sort(module->segments.begin(), module->segments.end(), - [] (const std::unique_ptr &a, - const std::unique_ptr &b) { - return a->Get()->size < b->Get()->size; - }); + [](const std::unique_ptr &a, + const std::unique_ptr &b) { + return a->Get()->size < b->Get()->size; + }); for (auto &entry : module->ea_to_seg) { entry.second = entry.second->Get(); @@ -1404,21 +1368,19 @@ NativeModule *ReadProtoBuf(const std::string &file_name, } if (!ll_func->hasNUsesOrMore(1)) { - LOG(INFO) - << "Erasing " << ll_func->getName().str(); + LOG(INFO) << "Erasing " << ll_func->getName().str(); ll_func->eraseFromParent(); } else { - LOG(ERROR) - << "Renaming existing LLVM function " << func->name - << " to avoid future name clashes with external function at " - << std::hex << func->ea << std::dec; + LOG(ERROR) << "Renaming existing LLVM function " << func->name + << " to avoid future name clashes with external function at " + << std::hex << func->ea << std::dec; ll_func->setName(func->name + "__original"); } } } for (auto &entry : module->ea_to_var) { - auto &var = const_cast(entry.second); + auto &var = const_cast(entry.second); var = var->Get(); var->segment = var->segment->Get(); } @@ -1480,11 +1442,11 @@ const NativeVariable *NativeModule::TryGetVariable(uint64_t ea) const { } // Try to get the block containing `inst_ea`. -const NativeBlock *NativeModule::TryGetBlock( - uint64_t inst_ea, const NativeBlock *curr) const { +const NativeBlock *NativeModule::TryGetBlock(uint64_t inst_ea, + const NativeBlock *curr) const { - for (uint64_t block_ea = inst_ea, i = 0u; - block_ea && i < 256u; block_ea -= 1, ++i) { + for (uint64_t block_ea = inst_ea, i = 0u; block_ea && i < 256u; + block_ea -= 1, ++i) { if (curr && curr->ea <= inst_ea && inst_ea <= curr->last_inst_ea) { return curr; } diff --git a/mcsema/CFG/CFG.h b/mcsema/CFG/CFG.h index 2aaf7c7bf..55b168e34 100644 --- a/mcsema/CFG/CFG.h +++ b/mcsema/CFG/CFG.h @@ -17,6 +17,11 @@ #pragma once +#include +#include +#include +#include + #include #include #include @@ -25,12 +30,6 @@ #include #include -#include -#include -#include - -#include - namespace llvm { class Constant; class Function; @@ -90,7 +89,7 @@ struct NativeObject { virtual ~NativeObject(void) = default; // Module containing this object. - NativeModule * const module; + NativeModule *const module; // Forwarding pointer to resolve duplicates and such. mutable NativeObject *forward; @@ -206,7 +205,8 @@ struct NativeExternalFunction : public NativeFunction { } NativeExternalFunction *Get(void) { - return reinterpret_cast(this->NativeObject::Get()); + return reinterpret_cast( + this->NativeObject::Get()); } // Defined in `External.cpp`. @@ -231,7 +231,8 @@ struct NativeExternalVariable : public NativeVariable { } NativeExternalVariable *Get(void) { - return reinterpret_cast(this->NativeObject::Get()); + return reinterpret_cast( + this->NativeObject::Get()); } // Defined in `External.cpp`. @@ -244,10 +245,7 @@ struct NativeExternalVariable : public NativeVariable { // A cross-reference (xref) from data to something. struct NativeXref { - enum FixupKind : uint32_t { - kAbsoluteFixup, - kThreadLocalOffsetFixup - }; + enum FixupKind : uint32_t { kAbsoluteFixup, kThreadLocalOffsetFixup }; // Width (in bytes) of this cross-reference. This only makes sense for xrefs // embedded in the data section. @@ -364,8 +362,8 @@ struct NativeModule : anvill::Program { const NativeVariable *TryGetVariable(uint64_t ea) const; // Try to get the block containing `inst_ea`. - const NativeBlock *TryGetBlock( - uint64_t inst_ea, const NativeBlock *curr) const; + const NativeBlock *TryGetBlock(uint64_t inst_ea, + const NativeBlock *curr) const; // Try to get the instruction at `ea`. const NativeInstruction *TryGetInstruction(uint64_t ea) const; @@ -394,7 +392,8 @@ struct NativeModule : anvill::Program { // Maps effective addresses to sets of registers that are preserved around // the instruction at this address. This corresponds to registers preserved // around a function call. - std::unordered_multimap> + std::unordered_multimap> ea_to_range_preserved_regs; template @@ -428,7 +427,6 @@ struct NativeModule : anvill::Program { } }; -NativeModule *ReadProtoBuf(const std::string &file_name, - uint64_t pointer_size); +NativeModule *ReadProtoBuf(const std::string &file_name, uint64_t pointer_size); } // namespace mcsema diff --git a/mcsema/OS/Linux/X86/ABI_exceptions.cpp b/mcsema/OS/Linux/X86/ABI_exceptions.cpp index 361e9d74f..36170c54e 100644 --- a/mcsema/OS/Linux/X86/ABI_exceptions.cpp +++ b/mcsema/OS/Linux/X86/ABI_exceptions.cpp @@ -1,54 +1,79 @@ namespace __cxxabiv1 {} +#include + #include #include #include -#include using namespace __cxxabiv1; extern "C" { -void* __cxa_allocate_exception(size_t thrown_size); -void __cxa_free_exception(void * thrown_exception) ; -void* __cxa_allocate_dependent_exception() ; -void __cxa_free_dependent_exception (void* dependent_exception); -void __cxa_throw(void* thrown_exception, class std::type_info * tinfo, void (*dest)(void*)); -void* __cxa_get_exception_ptr(void* exceptionObject); -void* __cxa_begin_catch(void* exceptionObject); +void *__cxa_allocate_exception(size_t thrown_size); +void __cxa_free_exception(void *thrown_exception); +void *__cxa_allocate_dependent_exception(); +void __cxa_free_dependent_exception(void *dependent_exception); +void __cxa_throw(void *thrown_exception, class std::type_info *tinfo, + void (*dest)(void *)); +void *__cxa_get_exception_ptr(void *exceptionObject); +void *__cxa_begin_catch(void *exceptionObject); void __cxa_end_catch(); -std::type_info* __cxa_current_exception_type(); +std::type_info *__cxa_current_exception_type(); void __cxa_rethrow(); -void* __cxa_current_primary_exception(); -void __cxa_decrement_exception_refcount(void* primary_exception); +void *__cxa_current_primary_exception(); +void __cxa_decrement_exception_refcount(void *primary_exception); struct __cxa_eh_globals; -__cxa_eh_globals* __cxa_get_globals(); -__cxa_eh_globals* __cxa_get_globals_fast(); -void __cxa_increment_exception_refcount(void* primary_exception); -void __cxa_rethrow_primary_exception(void* primary_exception); +__cxa_eh_globals *__cxa_get_globals(); +__cxa_eh_globals *__cxa_get_globals_fast(); +void __cxa_increment_exception_refcount(void *primary_exception); +void __cxa_rethrow_primary_exception(void *primary_exception); bool __cxa_uncaught_exception(); -_Unwind_Reason_Code __gxx_personality_v0 (int, _Unwind_Action, _Unwind_Exception_Class, struct _Unwind_Exception *, struct _Unwind_Context *); -int __cxa_guard_acquire(uint64_t* guard_object); -void __cxa_guard_release(uint64_t*); -void __cxa_guard_abort(uint64_t*); -void* __cxa_vec_new(size_t element_count, size_t element_size, size_t padding_size, void (*constructor)(void*), void (*destructor)(void*) ); -void* __cxa_vec_new2(size_t element_count, size_t element_size, size_t padding_size, void (*constructor)(void*), void (*destructor)(void*), void* (*alloc)(size_t), void (*dealloc)(void*) ); -void* __cxa_vec_new3(size_t element_count, size_t element_size, size_t padding_size, void (*constructor)(void*), void (*destructor)(void*), void* (*alloc)(size_t), void (*dealloc)(void*, size_t) ); -void __cxa_vec_ctor(void* array_address, size_t element_count, size_t element_size, void (*constructor)(void*), void (*destructor)(void*) ); -void __cxa_vec_dtor(void* array_address, size_t element_count, size_t element_size, void (*destructor)(void*) ); -void __cxa_vec_cleanup(void* array_address, size_t element_count, size_t element_size, void (*destructor)(void*) ); -void __cxa_vec_delete(void* array_address, size_t element_size, size_t padding_size, void (*destructor)(void*) ); -void __cxa_vec_delete2(void* array_address, size_t element_size, size_t padding_size, void (*destructor)(void*), void (*dealloc)(void*) ); -void __cxa_vec_delete3(void* __array_address, size_t element_size, size_t padding_size, void (*destructor)(void*), void (*dealloc) (void*, size_t)); -void __cxa_vec_cctor(void* dest_array, void* src_array, size_t element_count, size_t element_size, void (*constructor) (void*, void*), void (*destructor)(void*) ); +_Unwind_Reason_Code +__gxx_personality_v0(int, _Unwind_Action, _Unwind_Exception_Class, + struct _Unwind_Exception *, struct _Unwind_Context *); +int __cxa_guard_acquire(uint64_t *guard_object); +void __cxa_guard_release(uint64_t *); +void __cxa_guard_abort(uint64_t *); +void *__cxa_vec_new(size_t element_count, size_t element_size, + size_t padding_size, void (*constructor)(void *), + void (*destructor)(void *)); +void *__cxa_vec_new2(size_t element_count, size_t element_size, + size_t padding_size, void (*constructor)(void *), + void (*destructor)(void *), void *(*alloc)(size_t), + void (*dealloc)(void *)); +void *__cxa_vec_new3(size_t element_count, size_t element_size, + size_t padding_size, void (*constructor)(void *), + void (*destructor)(void *), void *(*alloc)(size_t), + void (*dealloc)(void *, size_t)); +void __cxa_vec_ctor(void *array_address, size_t element_count, + size_t element_size, void (*constructor)(void *), + void (*destructor)(void *)); +void __cxa_vec_dtor(void *array_address, size_t element_count, + size_t element_size, void (*destructor)(void *)); +void __cxa_vec_cleanup(void *array_address, size_t element_count, + size_t element_size, void (*destructor)(void *)); +void __cxa_vec_delete(void *array_address, size_t element_size, + size_t padding_size, void (*destructor)(void *)); +void __cxa_vec_delete2(void *array_address, size_t element_size, + size_t padding_size, void (*destructor)(void *), + void (*dealloc)(void *)); +void __cxa_vec_delete3(void *__array_address, size_t element_size, + size_t padding_size, void (*destructor)(void *), + void (*dealloc)(void *, size_t)); +void __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, + size_t element_size, void (*constructor)(void *, void *), + void (*destructor)(void *)); void (*__cxa_new_handler)(); void (*__cxa_terminate_handler)(); void (*__cxa_unexpected_handler)(); void __cxa_bad_cast() __attribute__((noreturn)); void __cxa_bad_typeid() __attribute__((noreturn)); void __cxa_pure_virtual(void); -void __cxa_call_unexpected (void*) __attribute__((noreturn)); -char* __cxa_demangle(const char* mangled_name, char* output_buffer, size_t* length, int* status); -void* __dynamic_cast(const void* __src_ptr, const __class_type_info* __src_type, const __class_type_info* __dst_type, ptrdiff_t __src2dst); +void __cxa_call_unexpected(void *) __attribute__((noreturn)); +char *__cxa_demangle(const char *mangled_name, char *output_buffer, + size_t *length, int *status); +void *__dynamic_cast(const void *__src_ptr, const __class_type_info *__src_type, + const __class_type_info *__dst_type, ptrdiff_t __src2dst); void _Unwind_Resume(struct _Unwind_Exception *object); -int __cxa_atexit ( void (*f)(void *), void *p, void *d ); +int __cxa_atexit(void (*f)(void *), void *p, void *d); void *malloc(size_t size); void *realloc(void *ptr, size_t size); @@ -56,50 +81,49 @@ void free(void *ptr); void *memset(void *str, int c, size_t n); } // extern C -__attribute__((used)) -void *__mcsema_externs[] = { - reinterpret_cast(__cxa_allocate_exception), - reinterpret_cast(__cxa_free_exception), - reinterpret_cast(__cxa_allocate_dependent_exception), - reinterpret_cast(__cxa_free_dependent_exception), - reinterpret_cast(__cxa_throw), - reinterpret_cast(__cxa_get_exception_ptr), - reinterpret_cast(__cxa_begin_catch), - reinterpret_cast(__cxa_end_catch), - reinterpret_cast(__cxa_current_exception_type), - reinterpret_cast(__cxa_rethrow), - reinterpret_cast(__cxa_current_primary_exception), - reinterpret_cast(__cxa_decrement_exception_refcount), - reinterpret_cast(__cxa_get_globals), - reinterpret_cast(__cxa_get_globals_fast), - reinterpret_cast(__cxa_increment_exception_refcount), - reinterpret_cast(__cxa_rethrow_primary_exception), - reinterpret_cast(__cxa_uncaught_exception), - reinterpret_cast(__cxa_guard_acquire), - reinterpret_cast(__cxa_guard_release), - reinterpret_cast(__cxa_guard_abort), - reinterpret_cast(__cxa_vec_new), - reinterpret_cast(__cxa_vec_new2), - reinterpret_cast(__cxa_vec_new3), - reinterpret_cast(__cxa_vec_ctor), - reinterpret_cast(__cxa_vec_dtor), - reinterpret_cast(__cxa_vec_cleanup), - reinterpret_cast(__cxa_vec_delete), - reinterpret_cast(__cxa_vec_delete2), - reinterpret_cast(__cxa_vec_delete3), - reinterpret_cast(__cxa_vec_cctor), - reinterpret_cast(__cxa_new_handler), - reinterpret_cast(__cxa_terminate_handler), - reinterpret_cast(__cxa_unexpected_handler), - reinterpret_cast(__cxa_bad_cast), - reinterpret_cast(__cxa_bad_typeid), - reinterpret_cast(__cxa_pure_virtual), - reinterpret_cast(__cxa_call_unexpected), - reinterpret_cast(__cxa_demangle), - reinterpret_cast(__cxa_atexit), - reinterpret_cast(_Unwind_Resume), - reinterpret_cast(malloc), - reinterpret_cast(realloc), - reinterpret_cast(free), - reinterpret_cast(memset), +__attribute__((used)) void *__mcsema_externs[] = { + reinterpret_cast(__cxa_allocate_exception), + reinterpret_cast(__cxa_free_exception), + reinterpret_cast(__cxa_allocate_dependent_exception), + reinterpret_cast(__cxa_free_dependent_exception), + reinterpret_cast(__cxa_throw), + reinterpret_cast(__cxa_get_exception_ptr), + reinterpret_cast(__cxa_begin_catch), + reinterpret_cast(__cxa_end_catch), + reinterpret_cast(__cxa_current_exception_type), + reinterpret_cast(__cxa_rethrow), + reinterpret_cast(__cxa_current_primary_exception), + reinterpret_cast(__cxa_decrement_exception_refcount), + reinterpret_cast(__cxa_get_globals), + reinterpret_cast(__cxa_get_globals_fast), + reinterpret_cast(__cxa_increment_exception_refcount), + reinterpret_cast(__cxa_rethrow_primary_exception), + reinterpret_cast(__cxa_uncaught_exception), + reinterpret_cast(__cxa_guard_acquire), + reinterpret_cast(__cxa_guard_release), + reinterpret_cast(__cxa_guard_abort), + reinterpret_cast(__cxa_vec_new), + reinterpret_cast(__cxa_vec_new2), + reinterpret_cast(__cxa_vec_new3), + reinterpret_cast(__cxa_vec_ctor), + reinterpret_cast(__cxa_vec_dtor), + reinterpret_cast(__cxa_vec_cleanup), + reinterpret_cast(__cxa_vec_delete), + reinterpret_cast(__cxa_vec_delete2), + reinterpret_cast(__cxa_vec_delete3), + reinterpret_cast(__cxa_vec_cctor), + reinterpret_cast(__cxa_new_handler), + reinterpret_cast(__cxa_terminate_handler), + reinterpret_cast(__cxa_unexpected_handler), + reinterpret_cast(__cxa_bad_cast), + reinterpret_cast(__cxa_bad_typeid), + reinterpret_cast(__cxa_pure_virtual), + reinterpret_cast(__cxa_call_unexpected), + reinterpret_cast(__cxa_demangle), + reinterpret_cast(__cxa_atexit), + reinterpret_cast(_Unwind_Resume), + reinterpret_cast(malloc), + reinterpret_cast(realloc), + reinterpret_cast(free), + reinterpret_cast(memset), }; diff --git a/scripts/format-added-files b/scripts/format-added-files new file mode 100755 index 000000000..d17c389a4 --- /dev/null +++ b/scripts/format-added-files @@ -0,0 +1,58 @@ +#!/usr/bin/env bash +# Copyright 2020, Trail of Bits, Inc. All rights reserved. + +# Get the list of changed C++ header and source files. +STAGED_FILES=$( git diff --cached --name-only --diff-filter=ACM | grep -e '\.\(h\)\|\(cpp\)$' ) + +if [[ "${STAGED_FILES}" = "" ]]; then + exit 0 +fi + +PYTHON3_EXE=$( which python3 ) +if [[ "$?" == 1 ]]; then + echo "\t\033[41mPlease install python3\033[0m" + exit 1 +fi + +CLANG_FORMAT_EXE=$( which clang-format ) +if [[ "$?" == 1 ]]; then + echo "\t\033[41mPlease install clang-format\033[0m" + exit 1 +fi + +THIS_FILE_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd ) +NAME_OF_THIS_FILE_DIR=$( basename "${THIS_FILE_DIR}" ) +IN_SCRIPTS_DIR=0 + +# This script being executed is located in the `scripts/` directory. +if [[ "${NAME_OF_THIS_FILE_DIR}" == "scripts" ]] ; then + SCRIPTS_DIR="${THIS_FILE_DIR}" + SOURCE_DIR=$( cd "$( dirname "${SCRIPTS_DIR}" )" && pwd ) + IN_SCRIPTS_DIR=1 + +# This script being executed is located in the `.git/hooks` directory. +elif [[ "${NAME_OF_THIS_FILE_DIR}" == "hooks" ]] ; then + GIT_DIR=$( cd "$( dirname "${SCRIPTS_DIR}" )" && pwd ) + SOURCE_DIR=$( cd "$( dirname "${GIT_DIR}" )" && pwd ) + SCRIPTS_DIR="${SOURCE_DIR}/scripts" + +# Not sure where this script is. +else + echo "\t\033[41mScript '${BASH_SOURCE[0]}' is in an unexpected location\033[0m" + echo 1 +fi + +# Run our wrapper of `clang-format` on the files that have changed. +${PYTHON3_EXE} "${SCRIPTS_DIR}/format-files" \ + --source_dir "${SOURCE_DIR}" \ + --format_exe "${CLANG_FORMAT_EXE}" \ + --files ${STAGED_FILES} \ + --check + +if [[ "$?" == 0 ]] ; then + for staged_file in ${STAGED_FILES} ; do + git add "${staged_file}" + done +else + exit 1 +fi diff --git a/scripts/format-files b/scripts/format-files new file mode 100755 index 000000000..d4feb1ed4 --- /dev/null +++ b/scripts/format-files @@ -0,0 +1,193 @@ +#!/usr/bin/env python3 +# Copyright 2020, Trail of Bits, Inc. All rights reserved. + + +import argparse +import itertools +import os +import pathlib +import subprocess +import sys +import traceback +import shutil + + +REFLOW_COMMENT = "// !!! REFLOW-COMMENT" + + +def find_comment_lines(path): + new_lines = [] + old_comments = [] + needs_fixes = False + with open(path, "r") as lines: + num_leading_comment_lines = 0 + for line_ in lines: + line = line_.rstrip("\n\r\t ") + unindented_line = line.lstrip("\t ") + + new_lines.append(line) + + if unindented_line.startswith("//"): + + # Make sure that every line that begins a comment block + # is preceded by a new line or a closing brace. + if not num_leading_comment_lines and 1 < len(new_lines): + prev_line = new_lines[-2].strip() + if prev_line != "" and prev_line != "}": + new_lines[-1] = "" + new_lines.append(line) + needs_fixes = True + + num_leading_comment_lines += 1 + + # The code style has it so that the comment on an `else` or `else if` statement + # appears on the line before the `else` or `else if`. + elif num_leading_comment_lines: + if unindented_line.startswith("} else"): + comment_lines = list(new_lines[-(num_leading_comment_lines + 1):-1]) + del new_lines[-(num_leading_comment_lines+1):] + new_lines.append(REFLOW_COMMENT) + new_lines.append(line) + old_comments.append(comment_lines) + needs_fixes = True + + num_leading_comment_lines = 0 + else: + num_leading_comment_lines = 0 + + # Force an empty newline at the end of the file. + if len(new_lines) and new_lines[-1]: + new_lines.append("") + needs_fixes = True + + return new_lines, old_comments, needs_fixes + + +def run_clang_format_on_files(format_exe, format_file, paths): + args = [format_exe, '-i'] + args.extend(paths) + try: + subprocess.check_call(args) + except: + return + + +def run_clang_format_on_lines(format_exe, format_file, path, lines): + p = subprocess.Popen( + [format_exe, + '--assume-filename={}'.format(path), + '--style=file'], + stdin=subprocess.PIPE, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True) + try: + stdout_data, stderr_data = p.communicate("\n".join(lines)) + return stdout_data.split("\n"), False + except: + p.kill() + stdout_data, stderr_data = p.communicate() + return stdout_data.split("\n"), True + + +def fixup_file(path, lines, old_comments): + new_lines = [] + i = 0 + for line in lines: + if line.strip() == REFLOW_COMMENT: + num_spaces = max(0, (len(line) - len(line.lstrip())) - 2) + new_indent = " " * num_spaces + for old_comment_line in old_comments[i]: + old_comment_line = old_comment_line.strip("\r\n\t ") + new_lines.append("{}{}".format(new_indent, old_comment_line)) + i += 1 + else: + new_lines.append(line) + + with open(path, "w") as file: + file.write("\n".join(new_lines)) + + +def main(): + clang_format_exe = shutil.which('clang-format') + + arg_parser = argparse.ArgumentParser() + + if clang_format_exe: + arg_parser.add_argument( + '--format_exe', + help='Path to clang-format executable.', + required=False, + default=str(clang_format_exe)) + else: + arg_parser.add_argument( + '--format_exe', + help='Path to clang-format executable.', + required=True) + + arg_parser.add_argument( + '--source_dir', + help='Path to root of source directory.', + required=False, + default=str(os.path.dirname(os.path.dirname(__file__)))) + + arg_parser.add_argument( + '--files', + help='Specific files to format', + nargs='*') + + args, _ = arg_parser.parse_known_args() + + try: + source_dir = os.path.abspath(args.source_dir) + os.chdir(source_dir) + except: + print("'{}' passed to --source_dir is not a directory".format(args.source_dir)) + return 1 + + format_file = os.path.abspath(os.path.join(source_dir, ".clang-format")) + if not os.path.isfile(format_file): + print("Could not find clang-format file at '{}'".format(format_file)) + return 1 + + if not os.path.isfile(args.format_exe): + print("'{}' passed to --format_exe does not exist".format(args.format_exe)) + return 1 + + # NOTE(pag): Go get the abs paths of the files here before we change the current + # working directory. + cxx_files = args.files + if cxx_files: + cxx_files = list(os.path.abspath(cxx_file) for cxx_file in cxx_files) + + if not cxx_files: + cxx_header_files = pathlib.Path(source_dir).rglob("*.h") + cxx_source_files = pathlib.Path(source_dir).rglob("*.cpp") + cxx_files = itertools.chain(cxx_header_files, cxx_source_files) + + in_place_files = [] + for cxx_file_ in cxx_files: + cxx_file = os.path.abspath(cxx_file_) + if not (cxx_file.endswith(".h") or cxx_file.endswith(".cpp")): + continue + + try: + new_lines, old_comments, needs_fixes = find_comment_lines(cxx_file) + except: + continue + + if not needs_fixes: + in_place_files.append(cxx_file) + else: + new_lines, has_error = run_clang_format_on_lines( + args.format_exe, format_file, cxx_file, new_lines) + if not has_error: + fixup_file(cxx_file, new_lines, old_comments) + + if in_place_files: + run_clang_format_on_files(args.format_exe, format_file, in_place_files) + + return 0 + +if __name__ == "__main__": + exit(main()) diff --git a/tests/integration_tests/src/fmodf.cpp b/tests/integration_tests/src/fmodf.cpp index 2b320a45d..153346639 100644 --- a/tests/integration_tests/src/fmodf.cpp +++ b/tests/integration_tests/src/fmodf.cpp @@ -17,23 +17,23 @@ * limitations under the License. */ +#include #include #include -#include - -void do_calc( float first, float second ) { - float result = fmodf( first, second ); - printf( "%i\n", (int)result ); - if ( fabsf( result - 0.4f ) < FLT_EPSILON ) printf( "Okay.\n" ); - else printf( "Nok.\n" ); +void do_calc(float first, float second) { + float result = fmodf(first, second); + printf("%i\n", (int) result); + if (fabsf(result - 0.4f) < FLT_EPSILON) + printf("Okay.\n"); + else + printf("Nok.\n"); } int main() { - printf( "Begin %i %i %i\n\t***\n", (int)123.456f, 2, 4); - float fix = 5.4f; - for ( float i = 0.1f; i <= 0.5f; i += 0.1f ) { - do_calc( fix, i ); - } - + printf("Begin %i %i %i\n\t***\n", (int) 123.456f, 2, 4); + float fix = 5.4f; + for (float i = 0.1f; i <= 0.5f; i += 0.1f) { + do_calc(fix, i); + } } diff --git a/tests/integration_tests/src/global_var.cpp b/tests/integration_tests/src/global_var.cpp index da031daec..bc3260419 100644 --- a/tests/integration_tests/src/global_var.cpp +++ b/tests/integration_tests/src/global_var.cpp @@ -17,11 +17,12 @@ * limitations under the License. */ -#include #include +#include + class A { - public: + public: char name[256]; A(const char *nameIn) { @@ -40,5 +41,3 @@ int main(void) { printf("Variable name %s\n", global.name); return 0; } - - diff --git a/tests/integration_tests/src/iostream_basics.cpp b/tests/integration_tests/src/iostream_basics.cpp index 9dc89278b..38a950b37 100644 --- a/tests/integration_tests/src/iostream_basics.cpp +++ b/tests/integration_tests/src/iostream_basics.cpp @@ -20,20 +20,20 @@ #include struct A { - std::string value; - - A( std::string&& str ) : value( std::move( str ) ) { - std::cout << "I was stolen from!:" << str << std::endl; - } + std::string value; - void shout() { - std::cout << value << std::endl; - } + A(std::string &&str) : value(std::move(str)) { + std::cout << "I was stolen from!:" << str << std::endl; + } + + void shout() { + std::cout << value << std::endl; + } }; int main() { - std::cout << "Hello World!" << std::endl; - std::string precious = "My little precious"; - A a( std::move( precious ) ); - a.shout(); + std::cout << "Hello World!" << std::endl; + std::string precious = "My little precious"; + A a(std::move(precious)); + a.shout(); } diff --git a/tests/integration_tests/src/operator_new.cpp b/tests/integration_tests/src/operator_new.cpp index a07e6df97..8d98847de 100644 --- a/tests/integration_tests/src/operator_new.cpp +++ b/tests/integration_tests/src/operator_new.cpp @@ -21,22 +21,22 @@ #include struct A { - std::string message; + std::string message; - void shout( const std::string& target ) { - std::cout << "He shouted at " << target << " with this words:" << std::endl; - std::cout << "\t" << message << std::endl; - } + void shout(const std::string &target) { + std::cout << "He shouted at " << target << " with this words:" << std::endl; + std::cout << "\t" << message << std::endl; + } }; -void challenge( A*& a ) { - a = new A( { "How dare you touch my duck?" } ); - std::cout << "INFO: challenge is prepared" << std::endl; +void challenge(A *&a) { + a = new A({"How dare you touch my duck?"}); + std::cout << "INFO: challenge is prepared" << std::endl; } int main() { - A* ptr; - challenge( ptr ); - ptr->shout( "Ivan" ); - delete ptr; + A *ptr; + challenge(ptr); + ptr->shout("Ivan"); + delete ptr; } diff --git a/tests/integration_tests/src/printf_floats.cpp b/tests/integration_tests/src/printf_floats.cpp index f646e4e8e..54967cc72 100644 --- a/tests/integration_tests/src/printf_floats.cpp +++ b/tests/integration_tests/src/printf_floats.cpp @@ -20,5 +20,6 @@ #include int main() { - printf("Hello %.2f %.2f %i %.2f %.2f %.2f %.2f %.2f %i %.2f and World!\n", 4.40f, 4.41f, -30, 4.424324f, 4.43f, 4.44f, 4.45f, 4.46f, 30, 4.47f ); + printf("Hello %.2f %.2f %i %.2f %.2f %.2f %.2f %.2f %i %.2f and World!\n", + 4.40f, 4.41f, -30, 4.424324f, 4.43f, 4.44f, 4.45f, 4.46f, 30, 4.47f); } diff --git a/tests/integration_tests/src/pthread.cpp b/tests/integration_tests/src/pthread.cpp index d31b01f11..6d1b28150 100644 --- a/tests/integration_tests/src/pthread.cpp +++ b/tests/integration_tests/src/pthread.cpp @@ -18,9 +18,9 @@ * limitations under the License. */ +#include #include #include -#include static pthread_cond_t gCond; static pthread_mutex_t gLock; @@ -30,8 +30,8 @@ __thread int tls_data1; __thread int tls_data2; typedef struct { - int data1; - int data2; + int data1; + int data2; } thread_parm_t; void bar() { @@ -44,16 +44,15 @@ void foo() { bar(); } -void *theThread(void *parm) -{ - thread_parm_t *gData; +void *theThread(void *parm) { + thread_parm_t *gData; pthread_mutex_lock(&gLock); pthread_cond_wait(&gCond, &gLock); gFlag += 1; - gData = (thread_parm_t*)parm; + gData = (thread_parm_t *) parm; tls_data1 = gData->data1; tls_data2 = gData->data2; foo(); @@ -63,16 +62,16 @@ void *theThread(void *parm) } int main(int argc, char **argv) { - int rc=0, i; + int rc = 0, i; pthread_t thread[2]; thread_parm_t gData[2]; printf("Create threads\n"); pthread_mutex_init(&gLock, NULL); pthread_cond_init(&gCond, NULL); - for (i=0; i < 2; i++) { + for (i = 0; i < 2; i++) { gData[i].data1 = i; - gData[i].data2 = (i+1)*2; + gData[i].data2 = (i + 1) * 2; rc = pthread_create(&thread[i], NULL, theThread, &gData[i]); if (rc) { printf("Failed with %d at pthread_create()", rc); @@ -86,7 +85,7 @@ int main(int argc, char **argv) { while (gFlag < 2) { pthread_cond_signal(&gCond); } - for (i=0; i < 2; i++) { + for (i = 0; i < 2; i++) { rc = pthread_join(thread[i], NULL); if (rc) { printf("Failed with %d at pthread_join()", rc); diff --git a/tests/integration_tests/src/qsort_function_ptrs.cpp b/tests/integration_tests/src/qsort_function_ptrs.cpp index 1522b1ed2..12717f7d2 100644 --- a/tests/integration_tests/src/qsort_function_ptrs.cpp +++ b/tests/integration_tests/src/qsort_function_ptrs.cpp @@ -46,13 +46,13 @@ int many() { } -using zTy = int(*)(); +using zTy = int (*)(); -template -using fTy = int(baseTy*, size_t, int); +template +using fTy = int(baseTy *, size_t, int); -int compare(const void* a, const void* b) { +int compare(const void *a, const void *b) { printf("Comparing:\n"); zTy arg1 = *(zTy *) a; printf("\tArg1 %i\n", arg1()); @@ -62,17 +62,19 @@ int compare(const void* a, const void* b) { int rhs = arg1(); int lhs = arg2(); - if (rhs < lhs) return -1; - if (rhs > lhs) return 1; + if (rhs < lhs) + return -1; + if (rhs > lhs) + return 1; return 0; } -template +template int firstLevel(Func *f, size_t size, int iter) { int base = f[0](); for (auto i = 0U; i < iter; ++i) { - base += f[i % size](); - printf("Iter: %i \tbase: %i\n", i, base); + base += f[i % size](); + printf("Iter: %i \tbase: %i\n", i, base); } printf("Before sort:\n"); @@ -90,9 +92,8 @@ int firstLevel(Func *f, size_t size, int iter) { return base; } -int main(int argc, char* argv[]) { +int main(int argc, char *argv[]) { int a = atoi(argv[1]); - int(*funcs[])() = {two, many, four, zero, one}; - int result = firstLevel(funcs, 5, a); + int (*funcs[])() = {two, many, four, zero, one}; + int result = firstLevel(funcs, 5, a); } - diff --git a/tests/integration_tests/src/struct_func_ptr.cpp b/tests/integration_tests/src/struct_func_ptr.cpp index 39c4f0005..59947b417 100644 --- a/tests/integration_tests/src/struct_func_ptr.cpp +++ b/tests/integration_tests/src/struct_func_ptr.cpp @@ -24,26 +24,28 @@ #include #include -template< typename F > +template struct Holder { - F a; - F b; + F a; + F b; }; -int foo( std::string str ) { - std::cout << "Foo: " << str << std::endl; - return 1; +int foo(std::string str) { + std::cout << "Foo: " << str << std::endl; + return 1; } -int boo( std::string str ) { - std::cout << "Boo: " << str << std::endl; - return 2; +int boo(std::string str) { + std::cout << "Boo: " << str << std::endl; + return 2; } int main() { - Holder< int(*)(std::string) > h { foo, boo }; - int a; - std::cin >> a; - if ( a % 2 ) h.a( "hello" ); - else h.b( "world" ); + Holder h{foo, boo}; + int a; + std::cin >> a; + if (a % 2) + h.a("hello"); + else + h.b("world"); } diff --git a/tests/integration_tests/src/template_function_ptrs.cpp b/tests/integration_tests/src/template_function_ptrs.cpp index b244e8173..ed87c14fe 100644 --- a/tests/integration_tests/src/template_function_ptrs.cpp +++ b/tests/integration_tests/src/template_function_ptrs.cpp @@ -22,54 +22,59 @@ #include #include + #include -template< typename FuncPtr, typename Num = int > -int specialSum( Num* arr, int size, FuncPtr ptr, int base = 0 ) { - int result = base; - for ( int i = 0; i < size; ++i ) { - result = ptr( result, arr[i] ); - } - return result; +template +int specialSum(Num *arr, int size, FuncPtr ptr, int base = 0) { + int result = base; + for (int i = 0; i < size; ++i) { + result = ptr(result, arr[i]); + } + return result; } -int add( int a, int b ) { - return a + b; +int add(int a, int b) { + return a + b; } -int dec( int a, int b ) { - return a - 1; -} +int dec(int a, int b) { + return a - 1; +} -int joker( int a, int b ) { - if ( a > b ) return dec ( a, b ); - if ( a < b ) return add ( a, b ); - return 0; +int joker(int a, int b) { + if (a > b) + return dec(a, b); + if (a < b) + return add(a, b); + return 0; } -template< typename ordFunc, typename getFunc > -auto specialFunc( ordFunc ord, getFunc get, int input ) { - int salt = 42; +template +auto specialFunc(ordFunc ord, getFunc get, int input) { + int salt = 42; + + auto g = get(input, salt); + int arr[3] = {input, salt, g}; - auto g = get( input, salt ); - int arr[3] = { input, salt, g }; - - if ( specialSum( arr, 3, ord) > 0 ) return add; - else return dec; + if (specialSum(arr, 3, ord) > 0) + return add; + else + return dec; } -int main( int argc, char* argv[] ) { - int arr[10] = { 1, 4, 32, -54, 5, 6, 76, 12, 45, -89 }; - int res = specialSum( arr, 10, add ); - printf( "%i\n", res ); +int main(int argc, char *argv[]) { + int arr[10] = {1, 4, 32, -54, 5, 6, 76, 12, 45, -89}; + int res = specialSum(arr, 10, add); + printf("%i\n", res); - res = specialSum( arr, 10, dec ); - printf( "%i\n", res ); + res = specialSum(arr, 10, dec); + printf("%i\n", res); - res = specialSum( arr, 10, joker ); - printf( "%i\n", res ); + res = specialSum(arr, 10, joker); + printf("%i\n", res); - auto special = specialFunc( add, dec, std::stoi( argv[1] ) ); - printf( "%i\n", special( 37, 5 ) ); + auto special = specialFunc(add, dec, std::stoi(argv[1])); + printf("%i\n", special(37, 5)); } diff --git a/tests/integration_tests/src/virtual.cpp b/tests/integration_tests/src/virtual.cpp index f194b984d..72bc05a46 100644 --- a/tests/integration_tests/src/virtual.cpp +++ b/tests/integration_tests/src/virtual.cpp @@ -17,54 +17,56 @@ * limitations under the License. */ +#include #include #include -#include struct Parent { -protected: - std::string name; -public: - Parent( const std::string& str ) : name( str ) { - std::cout << "Parent is setting name!" << std::endl; - } + protected: + std::string name; + + public: + Parent(const std::string &str) : name(str) { + std::cout << "Parent is setting name!" << std::endl; + } - virtual ~Parent() = default; + virtual ~Parent() = default; - virtual void shout() = 0; + virtual void shout() = 0; }; struct Angry : Parent { -protected: - int age = 42; -public: - Angry( const std::string& str ) : Parent( str ) { - std::cout << "Angry person was born" << std::endl; - } + protected: + int age = 42; - void shout() override { - std::cout << "I am angry! I am: " << name << std::endl; - } + public: + Angry(const std::string &str) : Parent(str) { + std::cout << "Angry person was born" << std::endl; + } + + void shout() override { + std::cout << "I am angry! I am: " << name << std::endl; + } }; struct Calm : Parent { - Calm( const std::string& str ) : Parent( str ) { - std::cout << "Calm person was born" << std::endl; - } + Calm(const std::string &str) : Parent(str) { + std::cout << "Calm person was born" << std::endl; + } - void shout() override { - std::cout << "Me calm. Me: " << name << std::endl; - } + void shout() override { + std::cout << "Me calm. Me: " << name << std::endl; + } }; int main() { - Calm a( "Caleb" ); - Parent* oldMan = new Angry( "Ivan" ); - - // This is the troublesome one - oldMan->shout(); - - std::cout << "And so shout happened" << std::endl; - delete oldMan; - std::cout << "Story is now over" << std::endl; + Calm a("Caleb"); + Parent *oldMan = new Angry("Ivan"); + + // This is the troublesome one + oldMan->shout(); + + std::cout << "And so shout happened" << std::endl; + delete oldMan; + std::cout << "Story is now over" << std::endl; } diff --git a/tests/integration_tests/src/virtual_simpler.cpp b/tests/integration_tests/src/virtual_simpler.cpp index 3e6dc566a..54c23cd62 100644 --- a/tests/integration_tests/src/virtual_simpler.cpp +++ b/tests/integration_tests/src/virtual_simpler.cpp @@ -17,49 +17,52 @@ * limitations under the License. */ +#include #include #include -#include struct Parent { -protected: - std::string name; -public: - Parent( const std::string& str ) : name( str ) { - std::cout << "Parent is setting name!" << std::endl; - } + protected: + std::string name; - virtual ~Parent() = default; + public: + Parent(const std::string &str) : name(str) { + std::cout << "Parent is setting name!" << std::endl; + } - virtual void shout() = 0; + virtual ~Parent() = default; + + virtual void shout() = 0; }; struct Angry : Parent { -protected: - int age = 42; -public: - Angry( const std::string& str ) : Parent( str ) { - //Empty - } + protected: + int age = 42; + + public: + Angry(const std::string &str) : Parent(str) { - void shout() override { - std::cout << "I am angry! I am: " << name << std::endl; - } + //Empty + } + + void shout() override { + std::cout << "I am angry! I am: " << name << std::endl; + } }; struct Calm : Parent { - Calm( const std::string& str ) : Parent( str ) { - //Empty - } + Calm(const std::string &str) : Parent(str) { + + //Empty + } - void shout() override { - std::cout << "Me calm. Me: " << name << std::endl; - } + void shout() override { + std::cout << "Me calm. Me: " << name << std::endl; + } }; int main() { - Parent* oldMan = new Angry( "Ivan" ); - oldMan->shout(); - delete oldMan; - + Parent *oldMan = new Angry("Ivan"); + oldMan->shout(); + delete oldMan; } diff --git a/tests/test_suite_generator/src/linux/cpp_constructor/main.cpp b/tests/test_suite_generator/src/linux/cpp_constructor/main.cpp index c3b184561..a61fd3108 100644 --- a/tests/test_suite_generator/src/linux/cpp_constructor/main.cpp +++ b/tests/test_suite_generator/src/linux/cpp_constructor/main.cpp @@ -14,11 +14,11 @@ * limitations under the License. */ -#include #include +#include class A { - public: + public: char name[256]; A(const char *nameIn) { @@ -26,9 +26,7 @@ class A { strcpy(name, nameIn); } - ~A(void) { - printf("Class A destructor!\n"); - } + ~A(void) { printf("Class A destructor!\n"); } }; A global("Global"); @@ -37,5 +35,3 @@ int main(void) { printf("Variable name %s\n", global.name); return 0; } - - diff --git a/tests/test_suite_generator/src/linux/exception_test/main.cpp b/tests/test_suite_generator/src/linux/exception_test/main.cpp index 81bcccbae..f2c2d2222 100644 --- a/tests/test_suite_generator/src/linux/exception_test/main.cpp +++ b/tests/test_suite_generator/src/linux/exception_test/main.cpp @@ -1,51 +1,49 @@ -#include -#include #include +#include #include +#include using namespace std; -void test_throw_double() { - throw 4.3; -} +void test_throw_double() { throw 4.3; } void test_throw_out_of_range() { - printf(" Throwing out_of_range()\n"); - throw out_of_range("out_of_range comment"); + printf(" Throwing out_of_range()\n"); + throw out_of_range("out_of_range comment"); } void test_throw_runtime_error() { - printf(" Throwing runtime_error()\n"); - throw runtime_error("runtime_error comment"); + printf(" Throwing runtime_error()\n"); + throw runtime_error("runtime_error comment"); } unsigned int num_tests; int main(int argc, char *argv[]) { - int p = 0; - try { - if (argc > 1) { - int input = atoi(argv[1]); - if(input == 1) { - test_throw_out_of_range(); - } else if(input == 2) { - test_throw_double(); - } else if (input == 3) { - test_throw_runtime_error(); - } - } else { - printf("Fallback mode, Not throwing exception\n"); - } - } catch (double smess) { - p = p + 2; - printf("Catching: double\n"); - } catch (out_of_range orex) { - p = p + 4; - printf("Catching: out_of_range %s\n", orex.what()); - } catch (runtime_error rex) { - p = p + 6; - printf("Catching: runtime_error %s\n", rex.what()); - } + int p = 0; + try { + if (argc > 1) { + int input = atoi(argv[1]); + if (input == 1) { + test_throw_out_of_range(); + } else if (input == 2) { + test_throw_double(); + } else if (input == 3) { + test_throw_runtime_error(); + } + } else { + printf("Fallback mode, Not throwing exception\n"); + } + } catch (double smess) { + p = p + 2; + printf("Catching: double\n"); + } catch (out_of_range orex) { + p = p + 4; + printf("Catching: out_of_range %s\n", orex.what()); + } catch (runtime_error rex) { + p = p + 6; + printf("Catching: runtime_error %s\n", rex.what()); + } - printf("Throw test finished! %d\n", p); - return 0; + printf("Throw test finished! %d\n", p); + return 0; } diff --git a/tests/test_suite_generator/src/linux/pthread_worker/main.cpp b/tests/test_suite_generator/src/linux/pthread_worker/main.cpp index 6d3bbd9c8..ba0a95425 100644 --- a/tests/test_suite_generator/src/linux/pthread_worker/main.cpp +++ b/tests/test_suite_generator/src/linux/pthread_worker/main.cpp @@ -14,12 +14,11 @@ * limitations under the License. */ +#include #include #include -#include -class Buffer -{ +class Buffer { public: Buffer(void); ~Buffer(); @@ -99,13 +98,14 @@ void *consumer(void *arg) { return arg; } -int main(int argc, char * argv[]) { +int main(int argc, char *argv[]) { (void)argc; int iter_counter = atoi(argv[1]); pthread_t pro_th; pthread_t cons_th; - pthread_create(&pro_th, NULL, producer, reinterpret_cast(iter_counter)); + pthread_create(&pro_th, NULL, producer, + reinterpret_cast(iter_counter)); pthread_create(&cons_th, NULL, consumer, NULL); pthread_join(pro_th, NULL); pthread_join(cons_th, NULL); diff --git a/tests/var_recovery/src/linux/cpp_exceptions/cpp_exceptions.cpp b/tests/var_recovery/src/linux/cpp_exceptions/cpp_exceptions.cpp index cf65a8526..09ff6712c 100644 --- a/tests/var_recovery/src/linux/cpp_exceptions/cpp_exceptions.cpp +++ b/tests/var_recovery/src/linux/cpp_exceptions/cpp_exceptions.cpp @@ -1,47 +1,47 @@ -#include #include +#include #include bool is_admin = false; void set_admin(int uid) { - is_admin = 0 == uid; + is_admin = 0 == uid; } int sum_of_squares(int a, int b) { - int a2 = a * a; - int b2 = b * b; - return a2+b2; + int a2 = a * a; + int b2 = b * b; + return a2 + b2; } int main(int argc, const char *argv[]) { - std::cout << "Starting example program\n"; - - try { - if(argc != 3) { - throw std::out_of_range("Supply two arguments, please"); - } - int a = std::atoi(argv[1]); - int b = std::atoi(argv[2]); - - if(a == b && b == 5) { - throw std::runtime_error("Lucky number 5"); - } - - set_admin(sum_of_squares(a, b)); - - std::cout << "You are " << (is_admin ? "now" : "not") << " admin.\n"; - } catch(std::out_of_range& e) { - std::cerr << "Index out of range: " << e.what() << std::endl; - return 1; - } catch(std::runtime_error& e) { - std::cerr << "Runtime error: " << e.what() << std::endl; - return 1; - } catch (...) { - std::cerr << "An unknown exception occurred!\n"; - return 1; + std::cout << "Starting example program\n"; + + try { + if (argc != 3) { + throw std::out_of_range("Supply two arguments, please"); + } + int a = std::atoi(argv[1]); + int b = std::atoi(argv[2]); + + if (a == b && b == 5) { + throw std::runtime_error("Lucky number 5"); } - return 0; + set_admin(sum_of_squares(a, b)); + + std::cout << "You are " << (is_admin ? "now" : "not") << " admin.\n"; + } catch (std::out_of_range &e) { + std::cerr << "Index out of range: " << e.what() << std::endl; + return 1; + } catch (std::runtime_error &e) { + std::cerr << "Runtime error: " << e.what() << std::endl; + return 1; + } catch (...) { + std::cerr << "An unknown exception occurred!\n"; + return 1; + } + + return 0; } diff --git a/tools/mcsema_disass/dyninst/CFGWriter.cpp b/tools/mcsema_disass/dyninst/CFGWriter.cpp index cfab2f8c7..3900cca90 100644 --- a/tools/mcsema_disass/dyninst/CFGWriter.cpp +++ b/tools/mcsema_disass/dyninst/CFGWriter.cpp @@ -16,27 +16,27 @@ */ #include "CFGWriter.h" -#include "Maybe.h" -#include "Util.h" -#include "SectionParser.h" - -#include -#include -#include -#include #include #include -#include -#include #include +#include #include #include #include #include - -#include +#include #include +#include + +#include +#include +#include +#include + +#include "Maybe.h" +#include "SectionParser.h" +#include "Util.h" DECLARE_string(entrypoint); DECLARE_string(binary); @@ -52,20 +52,19 @@ mcsema::Module gModule; namespace { // Try to eval Dyninst expression -Maybe
TryEval(InstructionAPI::Expression *expr, - const Address ip, - Address instruction_size=0) { +Maybe
TryEval(InstructionAPI::Expression *expr, const Address ip, + Address instruction_size = 0) { if (auto bin = dynamic_cast(expr)) { std::vector args; bin->getChildren(args); - auto left = TryEval( - dynamic_cast(args[0].get()), - ip, instruction_size); - auto right = TryEval( - dynamic_cast(args[1].get()), - ip, instruction_size); + auto left = + TryEval(dynamic_cast(args[0].get()), ip, + instruction_size); + auto right = + TryEval(dynamic_cast(args[1].get()), ip, + instruction_size); if (!(left && right)) { return {}; @@ -78,7 +77,6 @@ Maybe
TryEval(InstructionAPI::Expression *expr, if (bin->isMultiply()) { return {*left * *right}; } - } if (auto imm = dynamic_cast(expr)) { @@ -100,8 +98,7 @@ Maybe
TryEval(InstructionAPI::Expression *expr, // Find call to __libc_start_main@plt and try to recover addresses from it Address TryRetrieveAddrFromStart(ParseAPI::CodeObject &code_object, - Address start, - size_t index) { + Address start, size_t index) { if (!start) { LOG(WARNING) << "Binary starts at 0x0"; return 0; @@ -134,8 +131,8 @@ Address TryRetrieveAddrFromStart(ParseAPI::CodeObject &code_object, if (mov_inst->second->getOperation().getID() == entryID::e_lea) { rip += mov_inst->second->size(); } - auto offset = - TryEval(second_operand.getValue().get(), rip, mov_inst->second->size()); + auto offset = TryEval(second_operand.getValue().get(), rip, + mov_inst->second->size()); if (!offset) { LOG(WARNING) << "Could not eval basic start addresses!"; @@ -153,7 +150,8 @@ Address TryRetrieveAddrFromStart(ParseAPI::CodeObject &code_object, return 0; } -void RenameFunc(DisassContext &ctx, Dyninst::Address ea, const std::string& new_name) { +void RenameFunc(DisassContext &ctx, Dyninst::Address ea, + const std::string &new_name) { auto internal_func = ctx.getInternalFunction(ea); if (!internal_func) { return; @@ -164,6 +162,7 @@ void RenameFunc(DisassContext &ctx, Dyninst::Address ea, const std::string& new_ void ResolveOffsetTable(const std::set &successors, mcsema::Block *cfg_block, const std::vector &offset_tables) { + // For 2 targets offset table should not be generated? if (successors.size() < 3) { return; @@ -186,22 +185,19 @@ void ResolveOffsetTable(const std::set &successors, } if (table_ea) { - LOG(INFO) << "Block contains reference to offset table at 0x" - << std::hex << table_ea.value(); - auto cfg_inst = cfg_block->mutable_instructions( - cfg_block->instructions_size() - 1); + LOG(INFO) << "Block contains reference to offset table at 0x" << std::hex + << table_ea.value(); + auto cfg_inst = + cfg_block->mutable_instructions(cfg_block->instructions_size() - 1); if (!cfg_inst->xrefs_size()) { - AddCodeXref(cfg_inst, CodeReference::OffsetTable, - table_ea.value()); + AddCodeXref(cfg_inst, CodeReference::OffsetTable, table_ea.value()); } } - } -} //namespace +} //namespace -CFGWriter::CFGWriter(mcsema::Module &m, - SymtabAPI::Symtab &symtab, +CFGWriter::CFGWriter(mcsema::Module &m, SymtabAPI::Symtab &symtab, ParseAPI::CodeObject &code_obj, ExternalFunctionManager &ext_funcs) : module(m), @@ -209,7 +205,7 @@ CFGWriter::CFGWriter(mcsema::Module &m, code_object(code_obj), ext_funcs_m(ext_funcs), magic_section(ctx.magic_section), - ptr_byte_size(symtab.getAddressWidth()){ + ptr_byte_size(symtab.getAddressWidth()) { LOG(INFO) << "Binary is stripped: " << symtab.isStripped(); LOG(INFO) << "Pie_mode: " << FLAGS_pie_mode; @@ -218,10 +214,10 @@ CFGWriter::CFGWriter(mcsema::Module &m, symtab.getAllRegions(regions); for (auto reg : regions) { - section_m.AddRegion(reg); - if (reg->getMemOffset()) { - ctx.segment_eas.push_back(reg->getMemOffset()); - } + section_m.AddRegion(reg); + if (reg->getMemOffset()) { + ctx.segment_eas.push_back(reg->getMemOffset()); + } } // We need to get main! Heuristic for stripped binaries is that main is @@ -317,6 +313,7 @@ void CFGWriter::Write() { WriteExternalFunctions(); WriteExternalVariables(); WriteInternalData(); + //WriteGlobalVariables(); SweepStubs(); @@ -368,6 +365,7 @@ void CFGWriter::WriteExternalVariables() { LOG(INFO) << "Writing " << symbols.size() << " external variables"; for (const auto &s : symbols) { + // Is this dynamic? if (!s->isInDynSymtab()) { continue; @@ -377,8 +375,8 @@ void CFGWriter::WriteExternalVariables() { if (!s->getOffset() && !s->getSize()) { LOG(INFO) << "External var " << s->getMangledName() << " had no ea, allocating it in magic section"; - auto external_var = magic_section.WriteExternalVariable( - module, s->getMangledName()); + auto external_var = + magic_section.WriteExternalVariable(module, s->getMangledName()); ctx.external_vars.insert({external_var->ea(), external_var}); continue; } @@ -400,7 +398,6 @@ void CFGWriter::WriteExternalVariables() { external_var->set_is_weak( s->getLinkage() == Dyninst::SymtabAPI::Symbol::SymbolLinkage::SL_WEAK); external_var->set_is_thread_local(false); - } } @@ -413,8 +410,8 @@ void CFGWriter::WriteGlobalVariables() { } if (a->getRegion() && (a->getRegion()->getRegionName() == ".bss" || a->getRegion()->getRegionName() == ".rodata")) { - LOG(INFO) << "Found global variable " << a->getMangledName() - << " at " << std::hex << a->getOffset() << std::dec; + LOG(INFO) << "Found global variable " << a->getMangledName() << " at " + << std::hex << a->getOffset() << std::dec; auto global_var = module.add_global_vars(); global_var->set_ea(a->getOffset()); global_var->set_name(a->getMangledName()); @@ -431,19 +428,18 @@ void CFGWriter::WriteGlobalVariables() { void CFGWriter::SweepStubs() { for (ParseAPI::Function *func : code_object.funcs()) { if (section_m.IsInRegions({".plt.got"}, func->entry()->start())) { - auto inst = func->entry()->getInsn(func->addr()); + auto inst = func->entry()->getInsn(func->addr()); if (inst->getCategory() == InstructionAPI::c_BranchInsn) { - auto xref_addr = TryEval( - inst->getOperand(0).getValue().get(), - func->addr(), inst->size()); + auto xref_addr = TryEval(inst->getOperand(0).getValue().get(), + func->addr(), inst->size()); auto cfg_xref = ctx.data_xrefs.find(*xref_addr); if (cfg_xref == ctx.data_xrefs.end()) { continue; } auto cfg_ext_func = - ctx.external_funcs.find(cfg_xref->second->target_ea()); + ctx.external_funcs.find(cfg_xref->second->target_ea()); if (cfg_ext_func == ctx.external_funcs.end()) { continue; @@ -457,9 +453,10 @@ void CFGWriter::SweepStubs() { void CFGWriter::WriteInternalFunctions() { - // I don't want this to be in recompiled binary as compiler will - // add them as well, sub_* is enough - std::unordered_set< std::string > not_entrypoints = { + + // I don't want this to be in recompiled binary as compiler will + // add them as well, sub_* is enough + std::unordered_set not_entrypoints = { "_dl_relocate_static_pie", "register_tm_clones", "deregister_tm_clones", @@ -474,7 +471,7 @@ void CFGWriter::WriteInternalFunctions() { "_GLOBAL__sub_I_main.cpp", "__cxx_global_var_init", "__cxa_finalize", - }; + }; for (ParseAPI::Function *func : code_object.funcs()) { if (IsExternal(func->entry()->start())) { @@ -484,9 +481,9 @@ void CFGWriter::WriteInternalFunctions() { // We want to ignore the .got.plt stubs, since they are not needed // and cfg file would grow significantly else if (section_m.IsInRegions({".got.plt", "plt.got"}, - func->entry()->start())) { - LOG(INFO) << "Function " << func->name() - << " is getting skipped because it is .got.plt stub"; + func->entry()->start())) { + LOG(INFO) << "Function " << func->name() + << " is getting skipped because it is .got.plt stub"; continue; } @@ -496,8 +493,8 @@ void CFGWriter::WriteInternalFunctions() { CHECK(entryBlock->start() == static_cast
(cfg_internal_func->ea())) << "Start of the block is not equal to function ea"; - cfg_internal_func->set_is_entrypoint( - not_entrypoints.find(func->name()) == not_entrypoints.end()); + cfg_internal_func->set_is_entrypoint(not_entrypoints.find(func->name()) == + not_entrypoints.end()); WriteFunctionBlocks(func, cfg_internal_func); } @@ -510,39 +507,39 @@ void CFGWriter::WriteInternalFunctions() { void CFGWriter::WriteFunctionBlocks(ParseAPI::Function *func, mcsema::Function *cfg_internal_func) { - std::set written; - std::set
unknown; - for (ParseAPI::Block *block : func->blocks()) { - auto found = WriteBlock(block, func, cfg_internal_func, written); - unknown.insert(found.begin(), found.end()); - } + std::set written; + std::set
unknown; + for (ParseAPI::Block *block : func->blocks()) { + auto found = WriteBlock(block, func, cfg_internal_func, written); + unknown.insert(found.begin(), found.end()); + } - // TODO: More efficient implementation - for (auto &f : code_object.funcs()) { - if (unknown.count(f->addr())) { - for (auto bb : f->blocks()) { - // This may require calling WriteFunctionBlocks, possible CFG bloat? - WriteBlock(bb, f, cfg_internal_func, written); - unknown.erase(f->addr()); - } + // TODO: More efficient implementation + for (auto &f : code_object.funcs()) { + if (unknown.count(f->addr())) { + for (auto bb : f->blocks()) { + + // This may require calling WriteFunctionBlocks, possible CFG bloat? + WriteBlock(bb, f, cfg_internal_func, written); + unknown.erase(f->addr()); } } + } - if (!unknown.empty()) { - std::stringstream targets; - for (const auto trg: unknown) { - targets << std::hex << trg << " "; - } - LOG(ERROR) - << "Unresolved succ of bb was not match to a func: " << std::hex - << func->addr() << "[ " << targets.str() << " ]"; + if (!unknown.empty()) { + std::stringstream targets; + for (const auto trg : unknown) { + targets << std::hex << trg << " "; } + LOG(ERROR) << "Unresolved succ of bb was not match to a func: " << std::hex + << func->addr() << "[ " << targets.str() << " ]"; + } } -std::set
-CFGWriter::WriteBlock(ParseAPI::Block *block, ParseAPI::Function *func, - mcsema::Function *cfg_internal_func, - std::set &written) { +std::set
CFGWriter::WriteBlock(ParseAPI::Block *block, + ParseAPI::Function *func, + mcsema::Function *cfg_internal_func, + std::set &written) { if (written.count(block)) { return {}; @@ -573,8 +570,8 @@ CFGWriter::WriteBlock(ParseAPI::Block *block, ParseAPI::Function *func, auto rip = std::prev(instructions.end())->first; // Try to compute succ manually, as it can happen that ParseAPI returns -1 - auto manual = TryEval(last_inst->getOperand(0).getValue().get(), - rip, last_inst->size()); + auto manual = TryEval(last_inst->getOperand(0).getValue().get(), rip, + last_inst->size()); // We cannot statically tell anything about this edge if (!manual && next == -1) { @@ -605,9 +602,9 @@ CFGWriter::WriteBlock(ParseAPI::Block *block, ParseAPI::Function *func, // It is possible 2 is good enough if (successors.size() > 2) { - bool all = std::all_of(successors.cbegin(), successors.cend(), [&](auto succ){ - return code_xrefs_to_resolve.count(succ); - }); + bool all = std::all_of( + successors.cbegin(), successors.cend(), + [&](auto succ) { return code_xrefs_to_resolve.count(succ); }); if (all) { for (const auto &succ : successors) { @@ -637,7 +634,7 @@ void CFGWriter::WriteInstruction(InstructionAPI::Instruction *instruction, std::string instBytes; for (auto offset = 0U; offset < instruction->size(); ++offset) { - instBytes += (int)instruction->rawByte(offset); + instBytes += (int) instruction->rawByte(offset); } cfg_instruction->set_ea(addr); @@ -648,23 +645,23 @@ void CFGWriter::WriteInstruction(InstructionAPI::Instruction *instruction, if (instruction->getCategory() == InstructionAPI::c_CallInsn) { HandleCallInstruction(instruction, addr, cfg_instruction, is_last); } else { - HandleNonCallInstruction(instruction, addr, cfg_instruction, cfg_block, is_last); + HandleNonCallInstruction(instruction, addr, cfg_instruction, cfg_block, + is_last); } } -void WriteDisplacement( - DisassContext &ctx, SectionManager §ion_m, - mcsema::Instruction *cfg_instruction, Address &address) { +void WriteDisplacement(DisassContext &ctx, SectionManager §ion_m, + mcsema::Instruction *cfg_instruction, Address &address) { // Memory displacement only makes sense if (+ constant) is some xref, otherwise // McSema just fills the constant there and there is no need to specify it in cfg - if (ctx.HandleCodeXref( - {static_cast
(cfg_instruction->ea()), - address, cfg_instruction}, section_m)) { + if (ctx.HandleCodeXref({static_cast
(cfg_instruction->ea()), address, + cfg_instruction}, + section_m)) { - GetLastXref(cfg_instruction)->set_operand_type( - CodeReference::MemoryDisplacementOperand); + GetLastXref(cfg_instruction) + ->set_operand_type(CodeReference::MemoryDisplacementOperand); } } @@ -683,23 +680,22 @@ Maybe
DisplacementHelper(Dyninst::InstructionAPI::Expression *expr) { InstructionAPI::BinaryFunction *mid_op = nullptr; InstructionAPI::Immediate *mid_imm = nullptr; - for (auto & inner_op : inner_operands) { + for (auto &inner_op : inner_operands) { if (auto middle_level = - dynamic_cast(inner_op.get())) { + dynamic_cast(inner_op.get())) { mid_op = middle_level; } if (auto middle_level = - dynamic_cast(inner_op.get())) { + dynamic_cast(inner_op.get())) { mid_imm = middle_level; } } if (mid_op && mid_imm) { - return { mid_imm->eval().convert
() }; + return {mid_imm->eval().convert
()}; } - } return {}; } @@ -766,23 +762,19 @@ void CFGWriter::HandleCallInstruction(InstructionAPI::Instruction *instruction, // That's weird, quite possibly we are missing a function! if (!ctx.getInternalFunction(*target)) { LOG(INFO) << "Unresolved inst_xref " << *target; - inst_xrefs_to_resolve.insert( - {*target , {addr, *target, cfg_instruction}}); + inst_xrefs_to_resolve.insert({*target, {addr, *target, cfg_instruction}}); } } - } -Address CFGWriter::immediateNonCall(InstructionAPI::Immediate* imm, +Address CFGWriter::immediateNonCall(InstructionAPI::Immediate *imm, Address addr, - mcsema::Instruction* cfg_instruction ) { + mcsema::Instruction *cfg_instruction) { Address a = imm->eval().convert
(); if (!ctx.HandleCodeXref({addr, a, cfg_instruction}, section_m, false)) { if (section_m.IsCode(a)) { - AddCodeXref(cfg_instruction, - CodeReference::ImmediateOperand, - a); + AddCodeXref(cfg_instruction, CodeReference::ImmediateOperand, a); LOG(INFO) << std::hex << "IMM may be working with new function starting at" << a; @@ -792,14 +784,14 @@ Address CFGWriter::immediateNonCall(InstructionAPI::Immediate* imm, return 0; } - GetLastXref(cfg_instruction)->set_operand_type(CodeReference::ImmediateOperand); + GetLastXref(cfg_instruction) + ->set_operand_type(CodeReference::ImmediateOperand); return a; - } -Address CFGWriter::dereferenceNonCall(InstructionAPI::Dereference* deref, - Address addr, - mcsema::Instruction* cfg_instruction) { +Address CFGWriter::dereferenceNonCall(InstructionAPI::Dereference *deref, + Address addr, + mcsema::Instruction *cfg_instruction) { std::vector children; deref->getChildren(children); @@ -815,32 +807,28 @@ Address CFGWriter::dereferenceNonCall(InstructionAPI::Dereference* deref, ctx.HandleCodeXref({addr, *a, cfg_instruction}, section_m); return *a; - } //TODO(lukas): Remove -bool CFGWriter::HandleXref(mcsema::Instruction *cfg_instruction, - Address addr, +bool CFGWriter::HandleXref(mcsema::Instruction *cfg_instruction, Address addr, bool force) { if (ctx.HandleCodeXref({0, addr, cfg_instruction}, section_m, false)) { return true; } - if (section_m.IsCode(addr) && - !ctx.getInternalFunction(addr)) { + if (section_m.IsCode(addr) && !ctx.getInternalFunction(addr)) { inst_xrefs_to_resolve.insert( - {addr, {static_cast(cfg_instruction->ea()), - addr, cfg_instruction}}); + {addr, + {static_cast(cfg_instruction->ea()), addr, + cfg_instruction}}); } return ctx.HandleCodeXref({0, addr, cfg_instruction}, section_m, force); } void CFGWriter::HandleNonCallInstruction( - Dyninst::InstructionAPI::Instruction *instruction, - Address addr, - mcsema::Instruction *cfg_instruction, - mcsema::Block *cfg_block, + Dyninst::InstructionAPI::Instruction *instruction, Address addr, + mcsema::Instruction *cfg_instruction, mcsema::Block *cfg_block, bool is_last) { std::vector operands; @@ -861,14 +849,14 @@ void CFGWriter::HandleNonCallInstruction( if (auto imm = dynamic_cast(expr.get())) { direct_values[i] = - (FLAGS_pie_mode) ? 0 : immediateNonCall(imm, addr, cfg_instruction); + (FLAGS_pie_mode) ? 0 : immediateNonCall(imm, addr, cfg_instruction); - } else if ( - auto deref = dynamic_cast(expr.get())) { + } else if (auto deref = + dynamic_cast(expr.get())) { direct_values[i] = dereferenceNonCall(deref, addr, cfg_instruction); - } else if ( - auto bf = dynamic_cast(expr.get())) { + } else if (auto bf = + dynamic_cast(expr.get())) { auto instruction_id = instruction->getOperation().getID(); if (instruction_id == entryID::e_lea) { @@ -876,8 +864,10 @@ void CFGWriter::HandleNonCallInstruction( HandleXref(cfg_instruction, *a); if (section_m.IsCode(*a)) { + // get last one and change it to code - GetLastXref(cfg_instruction)->set_operand_type(CodeReference::MemoryOperand); + GetLastXref(cfg_instruction) + ->set_operand_type(CodeReference::MemoryOperand); } direct_values[i] = *a; } @@ -910,12 +900,10 @@ void CFGWriter::HandleNonCallInstruction( // something we should treat as function in cfg if (direct_values[0] && direct_values[1]) { addr -= instruction->size(); - bool is_in_data = section_m.IsInRegions( - {".bss", ".data", ".rodata"}, - direct_values[0]); + bool is_in_data = + section_m.IsInRegions({".bss", ".data", ".rodata"}, direct_values[0]); - if (section_m.IsCode(direct_values[1]) && - is_in_data) { + if (section_m.IsCode(direct_values[1]) && is_in_data) { if (!ctx.getInternalFunction(direct_values[0])) { LOG(INFO) @@ -931,7 +919,7 @@ void CFGWriter::WriteExternalFunctions() { auto symbols = section_m.GetExternalRelocs( Dyninst::SymtabAPI::Symbol::SymbolType::ST_FUNCTION); - auto known = ext_funcs_m.GetAllUsed( unknown ); + auto known = ext_funcs_m.GetAllUsed(unknown); LOG(INFO) << "Found " << known.size() << " known external functions and " << unknown.size() << " unknown"; @@ -948,7 +936,8 @@ void CFGWriter::WriteExternalFunctions() { } } - LOG_IF(WARNING, !found) << "External function was not found in CodeSource::linkage()"; + LOG_IF(WARNING, !found) + << "External function was not found in CodeSource::linkage()"; func.ea = a; auto cfg_external_func = magic_section.WriteExternalFunction(module, func); @@ -956,11 +945,11 @@ void CFGWriter::WriteExternalFunctions() { } } -void WriteRawData(std::string& data, SymtabAPI::Region* region) { +void WriteRawData(std::string &data, SymtabAPI::Region *region) { auto i = 0U; for (; i < region->getDiskSize(); ++i) { - data += ((const char *)region->getPtrToRawData())[i]; + data += ((const char *) region->getPtrToRawData())[i]; } // Zero padding @@ -971,7 +960,7 @@ void WriteRawData(std::string& data, SymtabAPI::Region* region) { // Writes into section on specified offset // If offset points beyond section, it is resized to contain it -void WriteAsRaw(std::string& data, uint64_t number, int64_t offset) { +void WriteAsRaw(std::string &data, uint64_t number, int64_t offset) { if (offset < 0) { LOG(FATAL) << "Trying to Write raw on negative offset"; @@ -988,8 +977,8 @@ void WriteAsRaw(std::string& data, uint64_t number, int64_t offset) { //TODO(lukas): Relic of old PR, not sure if needed // -fPIC & -pie? -void CFGWriter::WriteGOT(SymtabAPI::Region* region, - mcsema::Segment* cfg_segment) { +void CFGWriter::WriteGOT(SymtabAPI::Region *region, + mcsema::Segment *cfg_segment) { auto rela_dyn = section_m.GetRegion(".rela.dyn"); if (!rela_dyn) { @@ -1011,27 +1000,24 @@ void CFGWriter::WriteGOT(SymtabAPI::Region* region, if (reloc.name() == ext_var->name()) { LOG(INFO) << "Writing cfg_xref in got 0x" << std::hex << reloc.rel_addr() << " -> 0x" << ext_var->ea(); - auto cfg_xref = ctx.WriteAndAccount({ - reloc.rel_addr(), - static_cast(ext_var->ea()), - cfg_segment, - ext_var->name()}, false); + auto cfg_xref = ctx.WriteAndAccount( + {reloc.rel_addr(), static_cast(ext_var->ea()), + cfg_segment, ext_var->name()}, + false); found = true; ctx.data_xrefs.insert({reloc.rel_addr(), cfg_xref}); WriteAsRaw(data, ext_var->ea(), reloc.rel_addr() - cfg_segment->ea()); } } if (!found && !reloc.name().empty()) { - LOG(WARNING) - << "Giving magic_space to" << reloc.name(); + LOG(WARNING) << "Giving magic_space to" << reloc.name(); auto unreal_ea = magic_section.AllocSpace(ptr_byte_size); ctx.WriteAndAccount( - {reloc.rel_addr(), unreal_ea, cfg_segment, reloc.name()}, - true); + {reloc.rel_addr(), unreal_ea, cfg_segment, reloc.name()}, true); WriteAsRaw(data, unreal_ea, reloc.rel_addr() - cfg_segment->ea()); - if (ext_funcs_m.IsExternal(reloc.name())) { + if (ext_funcs_m.IsExternal(reloc.name())) { auto func = ext_funcs_m.GetExternalFunction(reloc.name()); func.imag_ea = unreal_ea; auto cfg_func = func.WriteHelper(module, unreal_ea); @@ -1043,8 +1029,8 @@ void CFGWriter::WriteGOT(SymtabAPI::Region* region, cfg_segment->set_data(data); } -void CFGWriter::WriteRelocations(SymtabAPI::Region* region, - mcsema::Segment *segment) { +void CFGWriter::WriteRelocations(SymtabAPI::Region *region, + mcsema::Segment *segment) { auto rela_dyn = section_m.GetRegion(".rela.plt"); if (!rela_dyn) { @@ -1057,29 +1043,24 @@ void CFGWriter::WriteRelocations(SymtabAPI::Region* region, LOG(INFO) << "Trying to resolve reloc " << reloc.name(); for (auto ext_func : magic_section.ext_funcs) { if (reloc.name() == ext_func->name()) { - LOG(INFO) << "Writing xref in got 0x" << std::hex - << reloc.rel_addr() << " -> 0x" << ext_func->ea(); - ctx.WriteAndAccount({ - reloc.rel_addr(), - static_cast(ext_func->ea()), - segment, - ext_func->name()}); + LOG(INFO) << "Writing xref in got 0x" << std::hex << reloc.rel_addr() + << " -> 0x" << ext_func->ea(); + ctx.WriteAndAccount({reloc.rel_addr(), + static_cast(ext_func->ea()), + segment, ext_func->name()}); WriteAsRaw(*data, ext_func->ea(), reloc.rel_addr() - segment->ea()); } } } } -void WriteBssXrefs( - DisassContext &ctx, - SectionManager §ion_m, - SymtabAPI::Region *region, - mcsema::Segment *segment) { +void WriteBssXrefs(DisassContext &ctx, SectionManager §ion_m, + SymtabAPI::Region *region, mcsema::Segment *segment) { for (auto &external : ctx.external_vars) { if (section_m.IsInRegion(region, external.first)) { ctx.WriteAndAccount( {external.first, external.first, segment, external.second->name()}, - false/*, external.second->size()*/); + false /*, external.second->size()*/); } } } @@ -1095,9 +1076,9 @@ void CFGWriter::WriteInternalData() { // IDA does not include some of these, so neither should we const static std::set no_parse = { - ".dynamic", - ".dynstr", - ".dynsym", + ".dynamic", + ".dynstr", + ".dynsym", }; if (no_parse.find(region->getRegionName()) != no_parse.end()) { @@ -1121,7 +1102,7 @@ void CFGWriter::WriteInternalData() { // .init & .fini should be together if (region->getRegionName() == ".init_array") { - SymtabAPI::Region* fini; + SymtabAPI::Region *fini; symtab.findRegion(fini, ".fini_array"); WriteRawData(data, fini); WriteDataVariables(fini, cfg_internal_data, section_parser); @@ -1132,33 +1113,34 @@ void CFGWriter::WriteInternalData() { cfg_internal_data->set_ea(region->getMemOffset()); cfg_internal_data->set_data(data); cfg_internal_data->set_read_only(region->getRegionPermissions() == - SymtabAPI::Region::RP_R); + SymtabAPI::Region::RP_R); cfg_internal_data->set_is_external(false); cfg_internal_data->set_name(region->getRegionName()); - cfg_internal_data->set_is_exported(false); /* TODO: As for now, ignored */ - cfg_internal_data->set_is_thread_local(false); /* TODO: As for now, ignored */ + cfg_internal_data->set_is_exported(false); /* TODO: As for now, ignored */ + cfg_internal_data->set_is_thread_local( + false); /* TODO: As for now, ignored */ const static std::set dont_parse = { - ".eh_frame", - ".rela.dyn", - ".rela.plt", - ".dynamic", - ".dynstr", - ".dynsym", - ".got", - ".got.plt", - ".plt", - ".plt.got", - ".gnu.hash", - ".gnu.version", - ".gcc_except_table", - ".jcr", + ".eh_frame", + ".rela.dyn", + ".rela.plt", + ".dynamic", + ".dynstr", + ".dynsym", + ".got", + ".got.plt", + ".plt", + ".plt.got", + ".gnu.hash", + ".gnu.version", + ".gcc_except_table", + ".jcr", }; if (dont_parse.find(region->getRegionName()) == dont_parse.end()) { WriteDataVariables(region, cfg_internal_data, section_parser); - section_parser.XrefsInSegment( region, cfg_internal_data ); + section_parser.XrefsInSegment(region, cfg_internal_data); } // IDA output of .bss produced some "self xrefs" @@ -1190,8 +1172,7 @@ void CFGWriter::WriteDataVariables(Dyninst::SymtabAPI::Region *region, if ((a->getRegion() && a->getRegion() == region) || (a->getOffset() == region->getMemOffset())) { - if (ctx.external_vars.find(a->getOffset()) != - ctx.external_vars.end() || + if (ctx.external_vars.find(a->getOffset()) != ctx.external_vars.end() || ctx.segment_vars.count(a->getOffset())) { continue; } @@ -1216,7 +1197,6 @@ void CFGWriter::WriteDataVariables(Dyninst::SymtabAPI::Region *region, bool CFGWriter::IsExternal(Address addr) const { - return - ctx.external_vars.find(addr) != ctx.external_vars.end() || - ctx.external_funcs.find(addr) != ctx.external_funcs.end(); + return ctx.external_vars.find(addr) != ctx.external_vars.end() || + ctx.external_funcs.find(addr) != ctx.external_funcs.end(); } diff --git a/tools/mcsema_disass/dyninst/CFGWriter.h b/tools/mcsema_disass/dyninst/CFGWriter.h index 39272d7b6..f1c3df840 100644 --- a/tools/mcsema_disass/dyninst/CFGWriter.h +++ b/tools/mcsema_disass/dyninst/CFGWriter.h @@ -17,37 +17,36 @@ #pragma once -#include "SectionManager.h" -#include "ExternalFunctionManager.h" -#include "MagicSection.h" -#include "Util.h" -#include "OffsetTable.h" - #include #include +#include #include -#include #include -#include +#include -#include -#include #include +#include +#include + +#include "ExternalFunctionManager.h" +#include "MagicSection.h" +#include "OffsetTable.h" +#include "SectionManager.h" +#include "Util.h" using SymbolMap = std::unordered_map; struct SectionParser; class CFGWriter { -public: - CFGWriter(mcsema::Module &m, - Dyninst::SymtabAPI::Symtab &symtab, + public: + CFGWriter(mcsema::Module &m, Dyninst::SymtabAPI::Symtab &symtab, Dyninst::ParseAPI::CodeObject &codeObj, ExternalFunctionManager &extFuncM); void Write(); -private: + private: void WriteDataVariables(Dyninst::SymtabAPI::Region *region, mcsema::Segment *segment, SectionParser §ion_parser); @@ -60,42 +59,39 @@ class CFGWriter { void WriteFunctionBlocks(Dyninst::ParseAPI::Function *func, mcsema::Function *cfg_internal_func); - std::set WriteBlock( - Dyninst::ParseAPI::Block *block, - Dyninst::ParseAPI::Function *func, - mcsema::Function *cfg_internal_func, - std::set &written); + std::set + WriteBlock(Dyninst::ParseAPI::Block *block, Dyninst::ParseAPI::Function *func, + mcsema::Function *cfg_internal_func, + std::set &written); void WriteInstruction(Dyninst::InstructionAPI::Instruction *instruction, Dyninst::Address addr, mcsema::Block *cfgBlock, - bool is_last=false); + bool is_last = false); void HandleCallInstruction(Dyninst::InstructionAPI::Instruction *instruction, Dyninst::Address addr, mcsema::Instruction *cfgInstruction, - bool is_last=false); + bool is_last = false); void HandleNonCallInstruction(Dyninst::InstructionAPI::Instruction *instruction, Dyninst::Address addr, mcsema::Instruction *cfgInstruction, - mcsema::Block *cfg_block, - bool is_last=false); + mcsema::Block *cfg_block, bool is_last = false); void WriteFunction(Dyninst::ParseAPI::Function *func, mcsema::Function *cfg_internal_func); void WriteExternalFunctions(); void WriteInternalData(); - void WriteRelocations(Dyninst::SymtabAPI::Region*, mcsema::Segment *); - void WriteGOT(Dyninst::SymtabAPI::Region*, mcsema::Segment *); + void WriteRelocations(Dyninst::SymtabAPI::Region *, mcsema::Segment *); + void WriteGOT(Dyninst::SymtabAPI::Region *, mcsema::Segment *); Dyninst::Address immediateNonCall(Dyninst::InstructionAPI::Immediate *imm, Dyninst::Address addr, mcsema::Instruction *cfgInstruction); Dyninst::Address dereferenceNonCall(Dyninst::InstructionAPI::Dereference *, - Dyninst::Address, - mcsema::Instruction *); + Dyninst::Address, mcsema::Instruction *); - bool HandleXref(mcsema::Instruction *, Dyninst::Address, bool force=true); + bool HandleXref(mcsema::Instruction *, Dyninst::Address, bool force = true); void CheckDisplacement(Dyninst::InstructionAPI::Expression *, mcsema::Instruction *); @@ -111,7 +107,8 @@ class CFGWriter { SectionManager section_m; std::map> code_xrefs_to_resolve; - std::map> inst_xrefs_to_resolve; + std::map> + inst_xrefs_to_resolve; std::vector offset_tables; diff --git a/tools/mcsema_disass/dyninst/ExternalFunctionManager.cpp b/tools/mcsema_disass/dyninst/ExternalFunctionManager.cpp index 4e6fcfac6..d88001418 100644 --- a/tools/mcsema_disass/dyninst/ExternalFunctionManager.cpp +++ b/tools/mcsema_disass/dyninst/ExternalFunctionManager.cpp @@ -19,9 +19,8 @@ #include -mcsema::ExternalFunction *ExternalFunction::WriteHelper( - mcsema::Module &module, - uint64_t ea) { +mcsema::ExternalFunction *ExternalFunction::WriteHelper(mcsema::Module &module, + uint64_t ea) { auto cfg_external_func = module.add_external_funcs(); cfg_external_func->set_name(symbol_name); @@ -35,8 +34,7 @@ mcsema::ExternalFunction *ExternalFunction::WriteHelper( return cfg_external_func; } -mcsema::ExternalFunction *ExternalFunction::Write( - mcsema::Module &module) { +mcsema::ExternalFunction *ExternalFunction::Write(mcsema::Module &module) { WriteHelper(module, ea); return WriteHelper(module, imag_ea); } @@ -47,8 +45,7 @@ ExternalFunction::CfgCC ExternalFunction::CfgCallingConvention() const { return mcsema::ExternalFunction::CallerCleanup; case CallingConvention::CalleeCleanup: return mcsema::ExternalFunction::CalleeCleanup; - default: - return mcsema::ExternalFunction::FastCall; + default: return mcsema::ExternalFunction::FastCall; } } @@ -59,11 +56,11 @@ void ExternalFunctionManager::AddExternalSymbol(const std::string &name, void ExternalFunctionManager::AddExternalSymbol(const std::string &s) { if (s.empty()) { - return; // Empty line + return; // Empty line } else if (s.front() == '#') { - return; // Comment line + return; // Comment line } else if (s.substr(0, 5) == "DATA:") { - return; // Refers to external data, not a function + return; // Refers to external data, not a function } std::string rest = s; @@ -120,8 +117,8 @@ void ExternalFunctionManager::AddExternalSymbol(const std::string &s) { bool is_weak = true; - ExternalFunction func{symbolName, callConv, !noReturn, argCount, - is_weak, signature}; + ExternalFunction func{symbolName, callConv, !noReturn, + argCount, is_weak, signature}; external_funcs[symbolName] = std::move(func); return; @@ -159,14 +156,16 @@ ExternalFunctionManager::GetExternalFunction(const std::string &name) { return external_func->second; } -void ExternalFunctionManager::ClearUsed() { used_funcs.clear(); } +void ExternalFunctionManager::ClearUsed() { + used_funcs.clear(); +} void ExternalFunctionManager::MarkAsUsed(const std::string &name) { used_funcs.insert(name); } -std::vector ExternalFunctionManager::GetAllUsed( - std::vector& unknowns) const { +std::vector +ExternalFunctionManager::GetAllUsed(std::vector &unknowns) const { std::vector result; diff --git a/tools/mcsema_disass/dyninst/ExternalFunctionManager.h b/tools/mcsema_disass/dyninst/ExternalFunctionManager.h index ee62862d7..2efc103d0 100644 --- a/tools/mcsema_disass/dyninst/ExternalFunctionManager.h +++ b/tools/mcsema_disass/dyninst/ExternalFunctionManager.h @@ -21,8 +21,8 @@ #include #include -#include #include +#include #include #include "Maybe.h" @@ -55,7 +55,7 @@ struct ExternalFunction { }; class ExternalFunctionManager { -public: + public: using ExternalFunction = ExternalFunction; /* The following methods can be used to register external * functions with the ExternalFunctionManager. If the same name is @@ -87,9 +87,10 @@ class ExternalFunctionManager { */ void ClearUsed(); void MarkAsUsed(const std::string &name); - std::vector GetAllUsed( std::vector& uknowns) const; + std::vector + GetAllUsed(std::vector &uknowns) const; -private: + private: std::unordered_map external_funcs; std::set used_funcs; }; diff --git a/tools/mcsema_disass/dyninst/MagicSection.cpp b/tools/mcsema_disass/dyninst/MagicSection.cpp index 1b4dc2223..1fd6a64a3 100644 --- a/tools/mcsema_disass/dyninst/MagicSection.cpp +++ b/tools/mcsema_disass/dyninst/MagicSection.cpp @@ -17,19 +17,19 @@ #include "MagicSection.h" -#include "ExternalFunctionManager.h" - #include -mcsema::ExternalVariable *MagicSection::WriteExternalVariable( - mcsema::Module &module, - const std::string &name) { +#include "ExternalFunctionManager.h" + +mcsema::ExternalVariable * +MagicSection::WriteExternalVariable(mcsema::Module &module, + const std::string &name) { CHECK(start_ea) << "Magic section cannot start with 0!"; Dyninst::Address unreal_ea = AllocSpace(ptr_byte_size); - LOG(INFO) << "External var " << name - << " is in magic_section at " << unreal_ea; + LOG(INFO) << "External var " << name << " is in magic_section at " + << unreal_ea; auto external_var = module.add_external_vars(); external_var->set_name(name); external_var->set_ea(unreal_ea); @@ -45,14 +45,15 @@ mcsema::ExternalVariable *MagicSection::WriteExternalVariable( return external_var; } -mcsema::ExternalFunction *MagicSection::WriteExternalFunction( - mcsema::Module &module, - ExternalFunction &function) { +mcsema::ExternalFunction * +MagicSection::WriteExternalFunction(mcsema::Module &module, + ExternalFunction &function) { CHECK(start_ea) << "Magic section cannot start with 0!"; Dyninst::Address unreal_ea = AllocSpace(ptr_byte_size); - LOG(INFO) << "External function " << function.symbol_name << " at 0x" << std::hex - << function.ea << " got magic_address at 0x" << unreal_ea; + LOG(INFO) << "External function " << function.symbol_name << " at 0x" + << std::hex << function.ea << " got magic_address at 0x" + << unreal_ea; function.imag_ea = unreal_ea; real_to_imag.insert({function.ea, unreal_ea}); ext_funcs.push_back(function.Write(module)); @@ -72,8 +73,8 @@ Dyninst::Address MagicSection::AllocSpace(uint64_t byte_width) { Dyninst::Address MagicSection::GetAllocated(Dyninst::Address ea) { auto entry = real_to_imag.find(ea); if (entry == real_to_imag.end()) { - LOG(INFO) << "Trying to get magicSection address for not registered ea"; - return 0; + LOG(INFO) << "Trying to get magicSection address for not registered ea"; + return 0; } return entry->second; } diff --git a/tools/mcsema_disass/dyninst/MagicSection.h b/tools/mcsema_disass/dyninst/MagicSection.h index 7e24764a8..44ec44232 100644 --- a/tools/mcsema_disass/dyninst/MagicSection.h +++ b/tools/mcsema_disass/dyninst/MagicSection.h @@ -17,25 +17,23 @@ #pragma once -#include -#include -#include - -#include - #include - +#include #include +#include +#include +#include + struct ExternalFunction; struct MagicSection { mcsema::ExternalVariable *WriteExternalVariable(mcsema::Module &module, - const std::string &name=""); + const std::string &name = ""); mcsema::ExternalFunction *WriteExternalFunction(mcsema::Module &module, - ExternalFunction &function); + ExternalFunction &function); - Dyninst::Address AllocSpace(uint64_t byte_width=8); + Dyninst::Address AllocSpace(uint64_t byte_width = 8); Dyninst::Address GetAllocated(Dyninst::Address ea); @@ -62,7 +60,7 @@ struct MagicSection { } //TODO(lukas): Rework as ctor - void init(Dyninst::Address start_ea, int ptr_byte_size=8) { + void init(Dyninst::Address start_ea, int ptr_byte_size = 8) { this->start_ea = start_ea; this->ptr_byte_size = ptr_byte_size; } @@ -79,5 +77,4 @@ struct MagicSection { // This will serve when searching for function xrefs, IDA uses everywhere // imaginary address while Dyninst catches the .plt stub one std::unordered_map real_to_imag; - }; diff --git a/tools/mcsema_disass/dyninst/Maybe.h b/tools/mcsema_disass/dyninst/Maybe.h index 94985633b..0fbc786a4 100644 --- a/tools/mcsema_disass/dyninst/Maybe.h +++ b/tools/mcsema_disass/dyninst/Maybe.h @@ -18,7 +18,7 @@ #pragma once // Replace with std::optional once C++17 is supported -template +template struct Maybe { T val; bool contains; @@ -28,11 +28,12 @@ struct Maybe { Maybe(const Maybe &other) : val(other.val), contains(other.contains) {} Maybe(Maybe &&other) noexcept(std::is_nothrow_move_constructible::value) - : val(std::move(other.val)), contains(other.contains) { + : val(std::move(other.val)), + contains(other.contains) { other.contains = false; } - Maybe& operator=(Maybe other) { + Maybe &operator=(Maybe other) { using std::swap; swap(val, other.val); swap(contains, other.contains); @@ -51,27 +52,27 @@ struct Maybe { return contains; } - const T* operator->() const { + const T *operator->() const { return &val; } - T* operator->() { + T *operator->() { return &val; } - const T& operator*() const { + const T &operator*() const { return val; } - T& operator*() { + T &operator*() { return val; } - constexpr T& value() { + constexpr T &value() { return val; } - constexpr const T& value() const { + constexpr const T &value() const { return val; } }; diff --git a/tools/mcsema_disass/dyninst/OffsetTable.cpp b/tools/mcsema_disass/dyninst/OffsetTable.cpp index 107bcb9c3..a8f8c04da 100644 --- a/tools/mcsema_disass/dyninst/OffsetTable.cpp +++ b/tools/mcsema_disass/dyninst/OffsetTable.cpp @@ -15,18 +15,18 @@ * along with this program. If not, see . */ +#include "OffsetTable.h" + +#include #include #include -#include - -#include "OffsetTable.h" #include "SectionManager.h" // Sometimes there are no good candidates -> try every possibility -Maybe OffsetTable::BlindMatch( - const std::set &succ) const { +Maybe +OffsetTable::BlindMatch(const std::set &succ) const { auto it = start_ea; @@ -37,7 +37,6 @@ Maybe OffsetTable::BlindMatch( } // TODO: Entries are smaller (maybe move by 8?) it += 4; - } return {}; @@ -53,9 +52,9 @@ bool OffsetTable::contains(Dyninst::Address addr) const { return true; } -Maybe OffsetTable::Match( - const std::set &succs, - const std::set &xrefs) const { +Maybe +OffsetTable::Match(const std::set &succs, + const std::set &xrefs) const { if (xrefs.empty()) { return BlindMatch(succs); @@ -125,12 +124,10 @@ bool OffsetTable::Match(const std::set &succs) const { } // This is just a bunch of 64-bit ELF specific heuristics -Maybe OffsetTable::Parse( - const SectionManager §ion_m, - Dyninst::Address start_ea, - int32_t *reader, - Dyninst::SymtabAPI::Region *region, - size_t size) { +Maybe +OffsetTable::Parse(const SectionManager §ion_m, Dyninst::Address start_ea, + int32_t *reader, Dyninst::SymtabAPI::Region *region, + size_t size) { // It has to be alligned if (start_ea % 4) { @@ -142,7 +139,7 @@ Maybe OffsetTable::Parse( OffsetTable table{start_ea, region, size}; for (Dyninst::Address it_ea = start_ea; it_ea < start_ea + size; - it_ea += 4, ++reader) { + it_ea += 4, ++reader) { // Get what is that entry truly pointing to auto target_ea = table.start_ea - ~(*reader) - 1; @@ -155,6 +152,7 @@ Maybe OffsetTable::Parse( table.start_ea += 4; } else { + // It doesn't point into text, it is not a jump table return {}; } diff --git a/tools/mcsema_disass/dyninst/OffsetTable.h b/tools/mcsema_disass/dyninst/OffsetTable.h index 08d638272..1b9d8c918 100644 --- a/tools/mcsema_disass/dyninst/OffsetTable.h +++ b/tools/mcsema_disass/dyninst/OffsetTable.h @@ -25,31 +25,27 @@ #include "Maybe.h" namespace Dyninst { - namespace SymtabAPI { - class Region; - } +namespace SymtabAPI { +class Region; } +} // namespace Dyninst struct SectionManager; // Holds information about possible jump tables // For 64, and possibly 32, bit ELF struct OffsetTable { - static Maybe Parse( - const SectionManager §ion_m, - Dyninst::Address start_ea, - int32_t *reader, - Dyninst::SymtabAPI::Region *region, - size_t size); + static Maybe + Parse(const SectionManager §ion_m, Dyninst::Address start_ea, + int32_t *reader, Dyninst::SymtabAPI::Region *region, size_t size); Dyninst::Address ea() const { return start_ea; } bool contains(Dyninst::Address addr) const; - Maybe Match( - const std::set &succ, - const std::set &xrefs) const; + Maybe Match(const std::set &succ, + const std::set &xrefs) const; OffsetTable Recompute(Dyninst::Address new_start_ea) const; @@ -58,12 +54,15 @@ struct OffsetTable { // TODO: This only exists so that Maybe can be constructed OffsetTable() = default; -private: - OffsetTable(Dyninst::Address start_ea, - Dyninst::SymtabAPI::Region *region, - size_t size) : start_ea(start_ea), region(region), size(size) {} + private: + OffsetTable(Dyninst::Address start_ea, Dyninst::SymtabAPI::Region *region, + size_t size) + : start_ea(start_ea), + region(region), + size(size) {} - Maybe BlindMatch(const std::set &succ) const; + Maybe + BlindMatch(const std::set &succ) const; Dyninst::Address start_ea; Dyninst::SymtabAPI::Region *region; @@ -71,7 +70,7 @@ struct OffsetTable { // For now I want them ordered {ea, in form start_ea - *ea - 1} std::map entries; + // Set of all values in entries std::set targets; - }; diff --git a/tools/mcsema_disass/dyninst/SectionManager.cpp b/tools/mcsema_disass/dyninst/SectionManager.cpp index 5e7a564e8..2b34fb879 100644 --- a/tools/mcsema_disass/dyninst/SectionManager.cpp +++ b/tools/mcsema_disass/dyninst/SectionManager.cpp @@ -16,12 +16,12 @@ */ #include "SectionManager.h" -#include "Util.h" #include - #include +#include "Util.h" + using namespace Dyninst; using namespace SymtabAPI; @@ -38,12 +38,13 @@ bool SectionManager::IsInRegion(const SymtabAPI::Region *r, Address a) const { return true; } -bool SectionManager::IsInRegion(const std::string ®ion_name, Address addr) const { +bool SectionManager::IsInRegion(const std::string ®ion_name, + Address addr) const { return IsInRegion(GetRegion(region_name), addr); } bool SectionManager::IsInRegions(std::vector sections, - Dyninst::Address addr) const { + Dyninst::Address addr) const { for (auto &s : regions) { for (auto &name : sections) { if (name == s.name) { @@ -83,8 +84,7 @@ SectionManager::GetRegion(const std::string &name) const { return GetRegion_impl(*this, name); } -Dyninst::SymtabAPI::Region * -SectionManager::GetRegion(const std::string &name) { +Dyninst::SymtabAPI::Region *SectionManager::GetRegion(const std::string &name) { return GetRegion_impl(*this, name); } @@ -97,7 +97,7 @@ void SectionManager::AddRegion(Dyninst::SymtabAPI::Region *r) { } } static std::array no_write = { - ".fini_array", + ".fini_array", }; bool should_write = true; diff --git a/tools/mcsema_disass/dyninst/SectionManager.h b/tools/mcsema_disass/dyninst/SectionManager.h index 588e0c22a..e9354d9f2 100644 --- a/tools/mcsema_disass/dyninst/SectionManager.h +++ b/tools/mcsema_disass/dyninst/SectionManager.h @@ -18,15 +18,14 @@ #pragma once #include +#include #include #include #include -#include - namespace mcsema { - class Segment; +class Segment; } struct Section { @@ -36,12 +35,14 @@ struct Section { }; struct SectionManager { -public: + public: void AddRegion(Dyninst::SymtabAPI::Region *r); - bool IsInRegion(const Dyninst::SymtabAPI::Region *r, Dyninst::Address a) const; - bool IsInRegions(std::vector sections, Dyninst::Address addr) const; - bool IsInRegion(const std::string& region, Dyninst::Address addr) const; + bool IsInRegion(const Dyninst::SymtabAPI::Region *r, + Dyninst::Address a) const; + bool IsInRegions(std::vector sections, + Dyninst::Address addr) const; + bool IsInRegion(const std::string ®ion, Dyninst::Address addr) const; // Is it in .text? bool IsCode(Dyninst::Address addr) const; @@ -54,11 +55,10 @@ struct SectionManager { Dyninst::SymtabAPI::Region *GetRegion(const std::string &name); const Dyninst::SymtabAPI::Region *GetRegion(const std::string &name) const; - std::vector GetExternalRelocs( - Dyninst::SymtabAPI::Symbol::SymbolType type); + std::vector + GetExternalRelocs(Dyninst::SymtabAPI::Symbol::SymbolType type); - void SetCFG(const Dyninst::SymtabAPI::Region *reg, - mcsema::Segment *segment) { + void SetCFG(const Dyninst::SymtabAPI::Region *reg, mcsema::Segment *segment) { for (auto &r : regions) { if (r.region == reg) { r.cfg_segment = segment; @@ -84,11 +84,11 @@ struct SectionManager { return nullptr; } -private: + private: // There won't be big enough number of regions to justify // std::map - template + template static Out GetRegion_impl(T &self, const std::string &name) { for (auto &r : self.regions) { if (r.name == name) { diff --git a/tools/mcsema_disass/dyninst/SectionParser.cpp b/tools/mcsema_disass/dyninst/SectionParser.cpp index d9d561590..9eeafc81e 100644 --- a/tools/mcsema_disass/dyninst/SectionParser.cpp +++ b/tools/mcsema_disass/dyninst/SectionParser.cpp @@ -26,9 +26,9 @@ SectionParser::CrossXrefMap SectionParser::ResolveCrossXrefs() { continue; } - if(!disass_context->HandleDataXref(xref)) { + if (!disass_context->HandleDataXref(xref)) { if (section_manager.IsInRegions({".data", ".rodata", ".bss"}, - xref.target_ea)) { + xref.target_ea)) { disass_context->WriteAndAccount(xref); } } @@ -44,9 +44,9 @@ SectionParser::CrossXrefMap SectionParser::ResolveCrossXrefs() { return unresolved_code_xrefs; } -bool SectionParser::TryXref(uint64_t offset, - Dyninst::SymtabAPI::Region *region, +bool SectionParser::TryXref(uint64_t offset, Dyninst::SymtabAPI::Region *region, mcsema::Segment *cfg_segment) { + // Allignment if (offset % 8) { return false; @@ -58,14 +58,14 @@ bool SectionParser::TryXref(uint64_t offset, Dyninst::Address ea = region->getMemOffset() + offset; if (disass_context->HandleDataXref({ea, target_ea, cfg_segment})) { - LOG(INFO) << "Fished up " << std::hex - << region->getMemOffset() + offset << " => " << target_ea; + LOG(INFO) << "Fished up " << std::hex << region->getMemOffset() + offset + << " => " << target_ea; return true; } if (section_manager.IsInRegion(region, target_ea)) { - std::string name = region->getRegionName() + "_unnamed_" + - std::to_string(++unnamed); + std::string name = + region->getRegionName() + "_unnamed_" + std::to_string(++unnamed); disass_context->WriteAndAccount({ea, target_ea, cfg_segment, name}); // TODO(lukas): If we once try lift variables again @@ -85,15 +85,16 @@ bool SectionParser::TryXref(uint64_t offset, bool SectionParser::TryOffsetTable(uint64_t &offset, Dyninst::SymtabAPI::Region *region) { + // Allignment if (offset % 4) { return false; } Dyninst::Address ea = region->getMemOffset() + offset; - auto *reader = - reinterpret_cast( - static_cast(region->getPtrToRawData()) + offset); + auto *reader = reinterpret_cast( + static_cast(region->getPtrToRawData()) + offset); auto entry_reader = reader; + // While it is a valid offset // TODO(lukas): Last entry can actually be an xref auto size = 0U; @@ -104,9 +105,8 @@ bool SectionParser::TryOffsetTable(uint64_t &offset, } // Try to build the table from it, depending on number of entries should succeed. - auto table = OffsetTable::Parse(section_manager, ea, - reinterpret_cast(reader), - region, size); + auto table = OffsetTable::Parse( + section_manager, ea, reinterpret_cast(reader), region, size); if (table) { offset_tables.push_back(std::move(table.value())); offset += size; @@ -115,15 +115,13 @@ bool SectionParser::TryOffsetTable(uint64_t &offset, return false; } -bool SectionParser::TryVar(uint64_t &offset, - Dyninst::SymtabAPI::Region *region, +bool SectionParser::TryVar(uint64_t &offset, Dyninst::SymtabAPI::Region *region, mcsema::Segment *cfg_segment) { - auto *byte_reader = - reinterpret_cast( - static_cast(region->getPtrToRawData()) + offset); + auto *byte_reader = reinterpret_cast( + static_cast(region->getPtrToRawData()) + offset); auto entry = 4; - while(!*byte_reader && offset < region->getMemSize() && entry) { + while (!*byte_reader && offset < region->getMemSize() && entry) { ++offset; --entry; } @@ -138,9 +136,10 @@ bool SectionParser::TryVar(uint64_t &offset, } std::string name = region->getRegionName() + "_" + std::to_string(++counter); - LOG(INFO) << "Found var " << name << " at 0x" - << std::hex << region->getMemOffset() + offset << " of size " - << std::dec << size; + LOG(INFO) << "Found var " << name << " at 0x" << std::hex + << region->getMemOffset() + offset << " of size " << std::dec + << size; + // TODO(lukas): Var related //auto var = cfg_segment->add_vars(); //var->set_ea(region->getMemOffset() + offset); @@ -148,7 +147,8 @@ bool SectionParser::TryVar(uint64_t &offset, //disass_context->segment_vars.insert({region->getMemOffset() + offset, var}); // Clean all 0s that may have been added due to mem allign - while (!*byte_reader && size + offset < region->getMemSize() && ((offset + size) % 8)) { + while (!*byte_reader && size + offset < region->getMemSize() && + ((offset + size) % 8)) { ++byte_reader; ++size; } @@ -193,15 +193,15 @@ void SectionParser::XrefsInSegment(Dyninst::SymtabAPI::Region *region, // Both are using something smarter, as they may contain other // data as static strings - auto offset = static_cast(region->getPtrToRawData()); + auto offset = static_cast(region->getPtrToRawData()); for (auto j = 0U; j < region->getDiskSize(); j += 8, offset++) { if (!disass_context->HandleDataXref( - {region->getMemOffset() + j, *offset, segment})) { + {region->getMemOffset() + j, *offset, segment})) { if (section_manager.IsInRegion(".text", *offset)) { LOG(INFO) << "\tXref is pointing into .text"; unresolved_code_xrefs.insert( - {*offset,{region->getMemOffset() + j, *offset, segment}}); + {*offset, {region->getMemOffset() + j, *offset, segment}}); } } } diff --git a/tools/mcsema_disass/dyninst/SectionParser.h b/tools/mcsema_disass/dyninst/SectionParser.h index 4340eb9df..84723fbc7 100644 --- a/tools/mcsema_disass/dyninst/SectionParser.h +++ b/tools/mcsema_disass/dyninst/SectionParser.h @@ -17,36 +17,34 @@ #pragma once -#include "Util.h" #include "OffsetTable.h" +#include "Util.h" struct SectionManager; namespace Dyninst { - namespace SymtabAPI { - class Region; - } +namespace SymtabAPI { +class Region; } +} // namespace Dyninst namespace mcsema { - class Segment; +class Segment; } - struct SectionParser { using CrossXrefMap = std::map>; - SectionParser(DisassContext *disass_context, - SectionManager §ion_manager) : - disass_context(disass_context), - section_manager(section_manager) { + SectionParser(DisassContext *disass_context, SectionManager §ion_manager) + : disass_context(disass_context), + section_manager(section_manager){ - }; + }; // More detailed parse for .data, .rodata void ParseVariables(Dyninst::SymtabAPI::Region *region, - mcsema::Segment *segment); + mcsema::Segment *segment); // Simple parse looking only for alligned xrefs void XrefsInSegment(Dyninst::SymtabAPI::Region *region, @@ -60,16 +58,14 @@ struct SectionParser { } -private: + private: DisassContext *disass_context; SectionManager §ion_manager; bool TryXref(uint64_t offset, Dyninst::SymtabAPI::Region *region, mcsema::Segment *cfg_segment); - bool TryOffsetTable(uint64_t &offset, - Dyninst::SymtabAPI::Region *region); - bool TryVar(uint64_t &offset, - Dyninst::SymtabAPI::Region *region, + bool TryOffsetTable(uint64_t &offset, Dyninst::SymtabAPI::Region *region); + bool TryVar(uint64_t &offset, Dyninst::SymtabAPI::Region *region, mcsema::Segment *cfg_segment); // For variable names diff --git a/tools/mcsema_disass/dyninst/Util.cpp b/tools/mcsema_disass/dyninst/Util.cpp index d0f8ed1c4..add1a7f82 100644 --- a/tools/mcsema_disass/dyninst/Util.cpp +++ b/tools/mcsema_disass/dyninst/Util.cpp @@ -17,12 +17,12 @@ #include "Util.h" -mcsema::CodeReference *AddCodeXref(mcsema::Instruction * instruction, - mcsema::CodeReference_OperandType opTy, - Dyninst::Address addr) { +mcsema::CodeReference *AddCodeXref(mcsema::Instruction *instruction, + mcsema::CodeReference_OperandType opTy, + Dyninst::Address addr) { - auto xref = instruction->add_xrefs(); - xref->set_operand_type(opTy); - xref->set_ea(addr); - return xref; + auto xref = instruction->add_xrefs(); + xref->set_operand_type(opTy); + xref->set_ea(addr); + return xref; } diff --git a/tools/mcsema_disass/dyninst/Util.h b/tools/mcsema_disass/dyninst/Util.h index 6a7d59eb0..f24e1bac5 100644 --- a/tools/mcsema_disass/dyninst/Util.h +++ b/tools/mcsema_disass/dyninst/Util.h @@ -17,14 +17,13 @@ #pragma once -#include -#include -#include - #include - #include #include + +#include +#include +#include #include #include "MagicSection.h" @@ -32,18 +31,18 @@ struct DisassContext; -template< typename T > +template auto *GetLastXref(T *cfg) { - CHECK(cfg->xrefs_size() >= 1) << "Cannot retrieve last xref when there is none"; + CHECK(cfg->xrefs_size() >= 1) + << "Cannot retrieve last xref when there is none"; return cfg->mutable_xrefs(cfg->xrefs_size() - 1); } -mcsema::CodeReference *AddCodeXref( - mcsema::Instruction * instruction, - mcsema::CodeReference_OperandType opTy, - Dyninst::Address addr); +mcsema::CodeReference *AddCodeXref(mcsema::Instruction *instruction, + mcsema::CodeReference_OperandType opTy, + Dyninst::Address addr); -template +template struct CrossXref { Dyninst::Address ea = 0; Dyninst::Address target_ea = 0; @@ -58,13 +57,13 @@ struct CrossXref { return *this != other; } - mcsema::DataReference *WriteDataXref( - uint64_t width=8) const { + mcsema::DataReference *WriteDataXref(uint64_t width = 8) const { LOG(INFO) << "\tFound xref targeting " << std::hex << target_ea; auto cfg_xref = segment->add_xrefs(); cfg_xref->set_ea(ea); cfg_xref->set_width(width); cfg_xref->set_target_ea(target_ea); + // TODO(lukas): This will almost certainly cause problems once cfg_xref->set_target_fixup_kind(mcsema::DataReference::Absolute); return cfg_xref; @@ -75,7 +74,7 @@ struct CrossXref { // It could be avoided since all info can be reached from mcsema::Module // but it would be much slower and more ugly struct DisassContext { - template + template using SymbolMap = std::map; // TODO(lukas): I want heterogeneous container :'{! @@ -94,25 +93,23 @@ struct DisassContext { // Writes and stores xref.ea into known data_xrefs mcsema::DataReference *WriteAndAccount(CrossXref xref, - bool is_code=false, - uint64_t width=8) { + bool is_code = false, + uint64_t width = 8) { width = std::min(width, 8ul); auto cfg_xref = xref.WriteDataXref(width); data_xrefs.insert({xref.ea, cfg_xref}); return cfg_xref; } - template - bool FishForXref(const Container &facts, - CrossXref &xref, - bool is_code=false, - uint64_t width=8) { + template + bool FishForXref(const Container &facts, CrossXref &xref, + bool is_code = false, uint64_t width = 8) { auto fact = facts.find(xref.target_ea); if (fact != facts.end()) { xref.target_name = fact->second->name(); - WriteAndAccount(xref,is_code, width); - LOG(INFO) << "\tResolved 0x" << std::hex << xref.ea - << " -> 0x" << xref.target_ea; + WriteAndAccount(xref, is_code, width); + LOG(INFO) << "\tResolved 0x" << std::hex << xref.ea << " -> 0x" + << xref.target_ea; return true; } return false; @@ -121,13 +118,12 @@ struct DisassContext { bool HandleDataXref(CrossXref xref) { if (FishForXref(global_vars, xref) || FishForXref(external_funcs, xref, true) || - FishForXref(external_vars, xref) || - FishForXref(segment_vars, xref) || + FishForXref(external_vars, xref) || FishForXref(segment_vars, xref) || FishForXref(func_map, xref, true)) { if (xref.segment->xrefs_size()) { - data_xrefs.insert( - {static_cast(xref.ea), GetLastXref(xref.segment)}); + data_xrefs.insert({static_cast(xref.ea), + GetLastXref(xref.segment)}); } return true; } @@ -136,34 +132,29 @@ struct DisassContext { bool WriteFact(const CrossXref &xref, mcsema::Function *fact) { - AddCodeXref(xref.segment, - mcsema::CodeReference::ControlFlowOperand, + AddCodeXref(xref.segment, mcsema::CodeReference::ControlFlowOperand, fact->ea()); return true; } bool WriteFact(const CrossXref &xref, mcsema::GlobalVariable *fact) { - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, - fact->ea()); + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, fact->ea()); return true; } bool WriteFact(const CrossXref &xref, mcsema::ExternalFunction *fact) { + // Mapping to magic_section - AddCodeXref(xref.segment, - mcsema::CodeReference::ControlFlowOperand, + AddCodeXref(xref.segment, mcsema::CodeReference::ControlFlowOperand, magic_section.GetAllocated(xref.target_ea)); return true; } bool WriteFact(const CrossXref &xref, mcsema::Variable *fact) { - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, - fact->ea()); + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, fact->ea()); return true; } @@ -173,22 +164,18 @@ struct DisassContext { if (!addr) { addr = fact->ea(); } - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, - addr); + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, addr); return true; } bool WriteFact(const CrossXref &xref, mcsema::DataReference *fact) { - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, - fact->ea()); + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, fact->ea()); return true; } - template + template bool FishForXref(const Container &facts, const CrossXref &xref) { @@ -203,14 +190,10 @@ struct DisassContext { // If force=true function writes the xref even if target_ea // cannot be resolved in something reasonable bool HandleCodeXref(const CrossXref &xref, - SectionManager §ion_m, - bool force=false) { - if (FishForXref(global_vars, xref) || - FishForXref(external_funcs, xref) || - FishForXref(external_vars, xref) || - FishForXref(segment_vars, xref) || - FishForXref(data_xrefs, xref) || - FishForXref(func_map, xref)) { + SectionManager §ion_m, bool force = false) { + if (FishForXref(global_vars, xref) || FishForXref(external_funcs, xref) || + FishForXref(external_vars, xref) || FishForXref(segment_vars, xref) || + FishForXref(data_xrefs, xref) || FishForXref(func_map, xref)) { return true; } @@ -219,10 +202,8 @@ struct DisassContext { // E.g printf("%s: %s\n", "partial string test", "string test"); // .rodata will contain only partial string test and proper offset // will be used when "string test" is needed - if (section_m.IsInRegions({".data", ".rodata", ".bss"}, - xref.target_ea)) { - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, + if (section_m.IsInRegions({".data", ".rodata", ".bss"}, xref.target_ea)) { + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, xref.target_ea); return true; } @@ -230,18 +211,16 @@ struct DisassContext { // Beginning of .jcr in framme_dummy for example for (auto a : segment_eas) { if (a == xref.target_ea) { - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, xref.target_ea); return true; } } if (force) { - LOG(INFO) << "Could not regonize xref anywhere target_ea 0x" - << std::hex << xref.target_ea << " forcing it"; - AddCodeXref(xref.segment, - mcsema::CodeReference::MemoryOperand, + LOG(INFO) << "Could not regonize xref anywhere target_ea 0x" << std::hex + << xref.target_ea << " forcing it"; + AddCodeXref(xref.segment, mcsema::CodeReference::MemoryOperand, xref.target_ea); return true; } @@ -256,4 +235,3 @@ struct DisassContext { return internal_func->second; } }; - diff --git a/tools/mcsema_disass/dyninst/main.cpp b/tools/mcsema_disass/dyninst/main.cpp index a17a381f7..0408074d5 100644 --- a/tools/mcsema_disass/dyninst/main.cpp +++ b/tools/mcsema_disass/dyninst/main.cpp @@ -15,9 +15,7 @@ * along with this program. If not, see . */ -#include "CFGWriter.h" -#include "ExternalFunctionManager.h" - +#include #include #include #include @@ -25,15 +23,16 @@ #include #include #include -#include -#include +#include +#include -#include +#include #include +#include #include -#include -#include +#include "CFGWriter.h" +#include "ExternalFunctionManager.h" DEFINE_string(std_defs, "", "Path to file containing external definitions"); DEFINE_bool(dump_cfg, false, "Dump produced cfg on stdout"); @@ -54,14 +53,14 @@ static std::vector Split(const std::string &s, const char delim) { std::string rem; std::istringstream instream(s); - while(std::getline(instream, rem, delim)) { + while (std::getline(instream, rem, delim)) { res.push_back(rem); } return res; } -} +} // namespace /* There is a global context right now consisting of two groups * - gflags @@ -83,8 +82,8 @@ int main(int argc, char **argv) { ss << " " << argv[0] << "\\" << std::endl << " --binary INPUT_FILE \\" << std::endl << " --output OUTPUT CFG FILE \\" << std::endl - << " --std_defs FILE_NAME[" << kPathDelim << - "FILE_NAME,...] \\" << std::endl + << " --std_defs FILE_NAME[" << kPathDelim << "FILE_NAME,...] \\" + << std::endl << " [--pretty_print] \\" << std::endl << " [--dump_cfg] \\" << std::endl; @@ -93,6 +92,7 @@ int main(int argc, char **argv) { google::InitGoogleLogging(argv[0]); google::SetUsageMessage(ss.str()); google::ParseCommandLineFlags(&argc, &argv, true); + //FLAGS_logtostderr = 1; CHECK(!FLAGS_binary.empty()) << "Input file need to be specified"; @@ -100,6 +100,7 @@ int main(int argc, char **argv) { auto input_file = const_cast(input_string.data()); ExternalFunctionManager extFuncManager; + // Load external symbol definitions if (!FLAGS_std_defs.empty()) { auto std_defs = Split(FLAGS_std_defs, kPathDelim); @@ -111,8 +112,7 @@ int main(int argc, char **argv) { } // Set up Dyninst stuff - auto symtab_cs = - std::make_shared(input_file); + auto symtab_cs = std::make_shared(input_file); CHECK(symtab_cs) << "Error during creation of ParseAPI::SymtabCodeSource!"; auto code_object = std::make_shared(symtab_cs.get()); diff --git a/tools/mcsema_lift/Lift.cpp b/tools/mcsema_lift/Lift.cpp index fc92d2bbf..5e2617fee 100644 --- a/tools/mcsema_lift/Lift.cpp +++ b/tools/mcsema_lift/Lift.cpp @@ -17,39 +17,37 @@ #include "mcsema/BC/Lift.h" -#include #include - -#include -#include -#include -#include -#include - +#include #include #include #include #include #include - #include #include #include #include +#include +#include +#include +#include +#include + #include "mcsema/Arch/Arch.h" #include "mcsema/BC/Util.h" #ifndef LLVM_VERSION_STRING -# define LLVM_VERSION_STRING LLVM_VERSION_MAJOR << "." << LLVM_VERSION_MINOR +# define LLVM_VERSION_STRING LLVM_VERSION_MAJOR << "." << LLVM_VERSION_MINOR #endif #ifndef MCSEMA_VERSION_STRING -# define MCSEMA_VERSION_STRING "unknown" +# define MCSEMA_VERSION_STRING "unknown" #endif // MCSEMA_VERSION_STRING #ifndef MCSEMA_BRANCH_NAME -# define MCSEMA_BRANCH_NAME "unknown" +# define MCSEMA_BRANCH_NAME "unknown" #endif // MCSEMA_BRANCH_NAME DECLARE_string(arch); @@ -61,14 +59,15 @@ DEFINE_string(output, "", "Output bitcode file name."); DEFINE_string(log, "", "Output log filename for lifter."); -DEFINE_int32(loglevel, 2, "Minimum log level for GLOG" ); +DEFINE_int32(loglevel, 2, "Minimum log level for GLOG"); // Using ',' as it will work well enough on Windows and Linux // Other suggestions were ':', which is a path character on Windows // and ';', which is an end of statement escape on Linux shells static const char kPathDelimeter = ','; -DEFINE_string(abi_libraries, "", "Path to one or more bitcode files that contain " - "external library definitions for the C/C++ ABI."); +DEFINE_string(abi_libraries, "", + "Path to one or more bitcode files that contain " + "external library definitions for the C/C++ ABI."); DECLARE_bool(version); @@ -77,18 +76,17 @@ DECLARE_bool(explicit_args); DECLARE_string(pc_annotation); DECLARE_uint32(explicit_args_count); -DEFINE_bool(list_supported, false, - "List instructions that can be lifted."); +DEFINE_bool(list_supported, false, "List instructions that can be lifted."); DEFINE_bool(legacy_mode, false, "Try to make the output bitcode resemble the original McSema."); namespace { static void PrintVersion(void) { - std::cout - << "This is mcsema-lift version: " << MCSEMA_VERSION_STRING << std::endl - << "Built from branch: " << MCSEMA_BRANCH_NAME << std::endl - << "Using LLVM " << LLVM_VERSION_STRING << std::endl; + std::cout << "This is mcsema-lift version: " << MCSEMA_VERSION_STRING + << std::endl + << "Built from branch: " << MCSEMA_BRANCH_NAME << std::endl + << "Using LLVM " << LLVM_VERSION_STRING << std::endl; } // Print a list of instructions that Remill can lift. @@ -103,15 +101,15 @@ static void PrintSupportedInstructions(void) { // used to separate comma separated arguments static std::vector Split(const std::string &s, const char delim) { - std::vector res; - std::string rem; - std::istringstream instream(s); + std::vector res; + std::string rem; + std::istringstream instream(s); - while(std::getline(instream, rem, delim)) { - res.push_back(rem); - } + while (std::getline(instream, rem, delim)) { + res.push_back(rem); + } - return res; + return res; } #define _S(x) #x @@ -131,25 +129,24 @@ struct ABILibsLoader { const Options &opts; - static constexpr const char * g_var_kind = "mcsema.abi.libraries"; + static constexpr const char *g_var_kind = "mcsema.abi.libraries"; std::array abi_search_paths = { - // TODO(pag): Use build and CMake install dirs to find the libraries too. - "/usr/local/share/mcsema/" MAJOR_MINOR "/ABI/", - "/usr/share/mcsema/" MAJOR_MINOR "/ABI/", - "/share/mcsema/" MAJOR_MINOR "/ABI/", + + // TODO(pag): Use build and CMake install dirs to find the libraries too. + "/usr/local/share/mcsema/" MAJOR_MINOR "/ABI/", + "/usr/share/mcsema/" MAJOR_MINOR "/ABI/", + "/share/mcsema/" MAJOR_MINOR "/ABI/", }; ABILibsLoader(llvm::Module &module_, const Options &opts_) - : module(module_), - ctx(module.getContext()), - opts(opts_) - {} + : module(module_), + ctx(module.getContext()), + opts(opts_) {} bool IsBlacklisted(const llvm::Function &func) { auto func_name = func.getName(); - if (func_name.startswith("__mcsema") - || func_name.startswith("__remill")) { + if (func_name.startswith("__mcsema") || func_name.startswith("__remill")) { return true; } @@ -171,7 +168,7 @@ struct ABILibsLoader { } void Load(const std::string &paths, char delim) { - Load( Split(FLAGS_abi_libraries, kPathDelimeter) ); + Load(Split(FLAGS_abi_libraries, kPathDelimeter)); } void Load(const std::string &path) { @@ -189,7 +186,7 @@ struct ABILibsLoader { bool HasFunctionPtrArg(const llvm::Function &func) { for (auto &arg : func.args()) { auto ptr = llvm::dyn_cast(arg.getType()); - if(!ptr || !ptr->getElementType()->isFunctionTy()) { + if (!ptr || !ptr->getElementType()->isFunctionTy()) { return true; } } @@ -201,8 +198,8 @@ struct ABILibsLoader { void Copy(llvm::Function &func, llvm::FunctionType *fn_t, const std::string &name) { - auto dest_func = llvm::Function::Create(fn_t, func.getLinkage(), - name, &module); + auto dest_func = + llvm::Function::Create(fn_t, func.getLinkage(), name, &module); dest_func->copyAttributesFrom(&func); dest_func->setVisibility(func.getVisibility()); @@ -211,8 +208,7 @@ struct ABILibsLoader { } bool ShouldCopy(llvm::Function &func, const std::string &name) { - return !mcsema::gModule->getFunction(name) && - !IsBlacklisted(func) && + return !mcsema::gModule->getFunction(name) && !IsBlacklisted(func) && (name != "main" && name != "_main" && name != "DllMain"); } @@ -226,14 +222,15 @@ struct ABILibsLoader { auto ret_type = func.getReturnType(); auto old_type = func.getFunctionType(); - std::vector args = { old_type->param_begin(), old_type->param_end() }; + std::vector args = {old_type->param_begin(), + old_type->param_end()}; while (args.size() < opts.explicit_args_count) - args.push_back( llvm::Type::getInt64Ty( ctx ) ); + args.push_back(llvm::Type::getInt64Ty(ctx)); return llvm::FunctionType::get(ret_type, args, false); } - void CloneFunction(llvm::Function &func, const std::string &name="") { + void CloneFunction(llvm::Function &func, const std::string &name = "") { auto new_name = (name.empty()) ? func.getName().str() : name; @@ -245,7 +242,7 @@ struct ABILibsLoader { Copy(func, new_type, new_name); } - template + template std::unique_ptr LoadABILib(const std::string &path, const C &search_paths) { @@ -258,8 +255,8 @@ struct ABILibsLoader { // Go searching for a library. for (auto base_path : search_paths) { std::stringstream ss; - ss << base_path << FLAGS_os << "/ABI_" << path << "_" - << FLAGS_arch << ".bc"; + ss << base_path << FLAGS_os << "/ABI_" << path << "_" << FLAGS_arch + << ".bc"; const auto inferred_path = ss.str(); abi_lib = remill::LoadModuleFromFile(&ctx, inferred_path, true); @@ -278,8 +275,7 @@ struct ABILibsLoader { void LoadLibraryIntoModule(const std::string &path) { auto abi_lib = LoadABILib(path, abi_search_paths); - LOG_IF(FATAL, !abi_lib) - << "Could not load ABI library " << path; + LOG_IF(FATAL, !abi_lib) << "Could not load ABI library " << path; mcsema::gArch->PrepareModuleDataLayout(abi_lib); @@ -297,8 +293,7 @@ struct ABILibsLoader { // Declare the global variables from the library in McSema's target module. for (auto &var : abi_lib->globals()) { auto var_name = var.getName(); - if (var_name.startswith("__mcsema") || - var_name.startswith("__remill")) { + if (var_name.startswith("__mcsema") || var_name.startswith("__remill")) { continue; } @@ -311,10 +306,9 @@ struct ABILibsLoader { } auto dest_var = new llvm::GlobalVariable( - module, var.getType()->getElementType(), - var.isConstant(), var.getLinkage(), nullptr, - var_name, nullptr, var.getThreadLocalMode(), - var.getType()->getAddressSpace()); + module, var.getType()->getElementType(), var.isConstant(), + var.getLinkage(), nullptr, var_name, nullptr, + var.getThreadLocalMode(), var.getType()->getAddressSpace()); dest_var->copyAttributesFrom(&var); auto node = llvm::MDNode::get(ctx, llvm::MDString::get(ctx, path)); @@ -346,146 +340,97 @@ static void InitBaselineDecls(void) { auto i8_type = llvm::Type::getInt8Ty(context); auto i32_type = llvm::Type::getInt32Ty(context); auto void_type = llvm::Type::getVoidTy(context); - auto argv_type = llvm::PointerType::get(llvm::PointerType::get(i8_type, 0), 0); + auto argv_type = + llvm::PointerType::get(llvm::PointerType::get(i8_type, 0), 0); llvm::Type *param_types_3[3]; param_types_3[0] = i32_type; param_types_3[1] = argv_type; param_types_3[2] = argv_type; // envp. - const auto main_func_type = llvm::FunctionType::get( - i32_type, param_types_3, false); + const auto main_func_type = + llvm::FunctionType::get(i32_type, param_types_3, false); auto main_func = llvm::Function::Create( - main_func_type, - llvm::GlobalValue::ExternalLinkage, - "main", - module); + main_func_type, llvm::GlobalValue::ExternalLinkage, "main", module); - llvm::Function::Create( - main_func_type, - llvm::GlobalValue::InternalLinkage, - "__libc_init", - module); + llvm::Function::Create(main_func_type, llvm::GlobalValue::InternalLinkage, + "__libc_init", module); - llvm::Function::Create( - main_func_type, - llvm::GlobalValue::InternalLinkage, - "__libc_first", - module); + llvm::Function::Create(main_func_type, llvm::GlobalValue::InternalLinkage, + "__libc_first", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "_start", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "_start", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__libc_csu_init", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "__libc_csu_init", + module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__libc_csu_fini", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "__libc_csu_fini", + module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "init", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "init", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "fini", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "fini", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "frame_dummy", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "frame_dummy", + module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "call_frame_dummy", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, "call_frame_dummy", + module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__do_global_dtors", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "__do_global_dtors", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__do_global_dtors_aux", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "__do_global_dtors_aux", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "call___do_global_dtors_aux", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "call___do_global_dtors_aux", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__do_global_ctors", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "__do_global_ctors", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__do_global_ctors_1", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "__do_global_ctors_1", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "__do_global_ctors_aux", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "__do_global_ctors_aux", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "call___do_global_ctors_aux", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, + "call___do_global_ctors_aux", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__gmon_start__", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::ExternalWeakLinkage, + "__gmon_start__", module); auto init_func = llvm::Function::Create( llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "_init_proc", - module); + llvm::GlobalValue::InternalLinkage, "_init_proc", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - ".init_proc", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, ".init_proc", + module); auto term_func = llvm::Function::Create( llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - "_term_proc", - module); + llvm::GlobalValue::InternalLinkage, "_term_proc", module); - llvm::Function::Create( - llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::InternalLinkage, - ".term_proc", - module); + llvm::Function::Create(llvm::FunctionType::get(void_type, false), + llvm::GlobalValue::InternalLinkage, ".term_proc", + module); llvm::Type *param_types_7[7]; param_types_7[0] = main_func->getType(); @@ -498,15 +443,13 @@ static void InitBaselineDecls(void) { llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_7, false), - llvm::GlobalValue::ExternalLinkage, - "__uClibc_main", - module); + llvm::GlobalValue::ExternalLinkage, "__uClibc_main", module); llvm::Type *param_types_8[8]; param_types_8[0] = main_func->getType(); param_types_8[1] = i32_type; param_types_8[2] = argv_type; - param_types_8[3] = llvm::PointerType::get(i8_type, 0); // ELF auxv. + param_types_8[3] = llvm::PointerType::get(i8_type, 0); // ELF auxv. param_types_8[4] = main_func->getType(); param_types_8[5] = term_func->getType(); param_types_8[6] = term_func->getType(); @@ -514,58 +457,43 @@ static void InitBaselineDecls(void) { llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_8, false), - llvm::GlobalValue::ExternalLinkage, - "__libc_start_main", - module); + llvm::GlobalValue::ExternalLinkage, "__libc_start_main", module); auto abort_func = llvm::Function::Create( llvm::FunctionType::get(void_type, false), - llvm::GlobalValue::ExternalLinkage, - "abort", - module); + llvm::GlobalValue::ExternalLinkage, "abort", module); abort_func->addFnAttr(llvm::Attribute::NoReturn); llvm::Type *param_types_1[1]; param_types_1[0] = i32_type; auto exit_func = llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalLinkage, - "exit", - module); + llvm::GlobalValue::ExternalLinkage, "exit", module); exit_func->addFnAttr(llvm::Attribute::NoReturn); exit_func = llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalLinkage, - "_Exit", - module); + llvm::GlobalValue::ExternalLinkage, "_Exit", module); exit_func->addFnAttr(llvm::Attribute::NoReturn); param_types_1[0] = llvm::PointerType::get(i8_type, 0); llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalWeakLinkage, - "_Jv_RegisterClasses", - module); + llvm::GlobalValue::ExternalWeakLinkage, "_Jv_RegisterClasses", module); llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__deregister_frame_info_bases", + llvm::GlobalValue::ExternalWeakLinkage, "__deregister_frame_info_bases", module); llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__deregister_frame_info", + llvm::GlobalValue::ExternalWeakLinkage, "__deregister_frame_info", module); param_types_1[0] = llvm::PointerType::get(i8_type, 0); - llvm::Function::Create( - llvm::FunctionType::get(i32_type, param_types_1, true), - llvm::GlobalValue::ExternalLinkage, - "printf", - module); + llvm::Function::Create(llvm::FunctionType::get(i32_type, param_types_1, true), + llvm::GlobalValue::ExternalLinkage, "printf", module); llvm::Type *param_types_2[2]; param_types_2[0] = llvm::PointerType::get(i8_type, 0); @@ -573,24 +501,18 @@ static void InitBaselineDecls(void) { auto longjmp_func = llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_2, false), - llvm::GlobalValue::ExternalLinkage, - "longjmp", - module); + llvm::GlobalValue::ExternalLinkage, "longjmp", module); longjmp_func->addFnAttr(llvm::Attribute::NoReturn); longjmp_func = llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_2, false), - llvm::GlobalValue::ExternalLinkage, - "siglongjmp", - module); + llvm::GlobalValue::ExternalLinkage, "siglongjmp", module); longjmp_func->addFnAttr(llvm::Attribute::NoReturn); param_types_2[1] = param_types_2[0]; llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__register_frame_info", - module); + llvm::GlobalValue::ExternalWeakLinkage, "__register_frame_info", module); llvm::Type *param_types_4[4]; param_types_4[0] = llvm::PointerType::get(i8_type, 0); @@ -599,8 +521,7 @@ static void InitBaselineDecls(void) { param_types_4[3] = param_types_4[0]; llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_1, false), - llvm::GlobalValue::ExternalWeakLinkage, - "__register_frame_info_bases", + llvm::GlobalValue::ExternalWeakLinkage, "__register_frame_info_bases", module); param_types_4[1] = param_types_4[0]; @@ -608,9 +529,7 @@ static void InitBaselineDecls(void) { param_types_4[3] = param_types_4[0]; auto assert_func = llvm::Function::Create( llvm::FunctionType::get(void_type, param_types_4, false), - llvm::GlobalValue::ExternalLinkage, - "__assert_fail", - module); + llvm::GlobalValue::ExternalLinkage, "__assert_fail", module); assert_func->addFnAttr(llvm::Attribute::NoReturn); } @@ -618,12 +537,14 @@ static void InitBaselineDecls(void) { int main(int argc, char *argv[]) { std::stringstream ss; - ss << std::endl << std::endl + ss << std::endl + << std::endl << " " << argv[0] << " \\" << std::endl << " --output OUTPUT_BC_FILE \\" << std::endl << " --arch ARCH_NAME \\" << std::endl << " --os OS_NAME \\" << std::endl - << " --cfg CFG_FILE \\" << std::endl + << " --cfg CFG_FILE \\" + << std::endl // This option is very useful for debugging McSema-lifted bitcode. It // injects so-called breakpoint functions before every lifted instruction. @@ -631,7 +552,8 @@ int main(int argc, char *argv[]) { // option will inject a call to `breakpoint_f00`. With this feature, we // can add breakpoints in a debugger on these breakpoint functions, and // know that they correspond to locations in the original program. - << " [--add_breakpoints] \\" << std::endl + << " [--add_breakpoints] \\" + << std::endl // This option injects a function call before every lifted instruction. // This function is implemented in the McSema runtime and it prints the @@ -640,11 +562,13 @@ int main(int argc, char *argv[]) { << " [--add_func_state_tracer] \\" << std::endl << " [--add_pc_tracer] \\" << std::endl - << " [--trace_reg_values=reg1[,reg2[,...]]] \\" << std::endl + << " [--trace_reg_values=reg1[,reg2[,...]]] \\" + << std::endl // This option tells McSema not to lower Remill's memory access intrinsic // functions into LLVM `load` and `store` instructions. - << " [--keep_memops] \\" << std::endl + << " [--keep_memops] \\" + << std::endl // There are roughly two ways of using McSema-lifted bitcode. The default // use case is to compile the bitcode into an executable that behaves like @@ -656,7 +580,8 @@ int main(int argc, char *argv[]) { // argument counts expected by an external function, we fall back on // passing `--explicit_args_count` number of arguments to that function. << " [--explicit_args] \\" << std::endl - << " [--explicit_args_count NUM_ARGS_FOR_EXTERNALS] \\" << std::endl + << " [--explicit_args_count NUM_ARGS_FOR_EXTERNALS] \\" + << std::endl // McSema doesn't have type information about externals, and so it assumes all // externals operate on integer-typed arguments, and return integer values. @@ -678,28 +603,34 @@ int main(int argc, char *argv[]) { // One may want multiple such files, such as one for libc, one for exception // handling and one for zlib, and so on. McSema supports loading multiple // ABI library definitions via a ';' separated list of paths - << " [--abi_libraries BITCODE_FILE[" << kPathDelimeter << - "BITCODE_FILE" << kPathDelimeter << "...] ] \\" << std::endl + << " [--abi_libraries BITCODE_FILE[" << kPathDelimeter << "BITCODE_FILE" + << kPathDelimeter << "...] ] \\" + << std::endl // Annotate each LLVM IR instruction with some metadata that includes the // original program counter. The name of the LLVM metadats is // `PC_METADATA_ID`. This is enabled by default with `--legacy_mode`, // which sets `--pc_annotation` to be `mcsema_real_eip`. - << " [--pc_annotation PC_METADATA_ID] \\" << std::endl + << " [--pc_annotation PC_METADATA_ID] \\" + << std::endl // Try to produce bitcode that looks like McSema version 1. This enables // `--explicit_args` and `--pc_annotation`. - << " [--legacy_mode] \\" << std::endl - + << " [--legacy_mode] \\" + << std::endl + // Print a list of the instructions that can be lifted. - << " [--list_supported]" << std::endl + << " [--list_supported]" + << std::endl // Assign the personality function for exception handling ABIs. It is // `__gxx_personality_v0` for libstdc++ and `__gnat_personality_v0` for ADA ABIs. - << " [--exception_personality_func]" << std::endl + << " [--exception_personality_func]" + << std::endl // Print the version and exit. - << " [--version]" << std::endl + << " [--version]" + << std::endl // Log file name for the lifter. << " [--log]" << std::endl @@ -707,17 +638,14 @@ int main(int argc, char *argv[]) { << " [--loglevel]" << std::endl << std::endl; - const char * const llvm_argv[] = { - "-memdep-block-scan-limit=500", - nullptr - }; + const char *const llvm_argv[] = {"-memdep-block-scan-limit=500", nullptr}; llvm::cl::ParseCommandLineOptions(1, llvm_argv); google::SetUsageMessage(ss.str()); google::ParseCommandLineFlags(&argc, &argv, true); - if (FLAGS_log.empty()){ + if (FLAGS_log.empty()) { google::InitGoogleLogging(argv[0]); } else { google::InitGoogleLogging(FLAGS_log.c_str()); @@ -730,25 +658,23 @@ int main(int argc, char *argv[]) { return EXIT_SUCCESS; } - if (FLAGS_os.empty() || FLAGS_arch.empty() || FLAGS_cfg.empty()){ + if (FLAGS_os.empty() || FLAGS_arch.empty() || FLAGS_cfg.empty()) { std::cout << google::ProgramUsage() << std::endl; return EXIT_FAILURE; } - CHECK(!FLAGS_os.empty()) - << "Must specify an operating system name to --os."; + CHECK(!FLAGS_os.empty()) << "Must specify an operating system name to --os."; CHECK(!FLAGS_arch.empty()) << "Must specify a machine code architecture name to --arch."; - CHECK(!FLAGS_cfg.empty()) - << "Must specify the path to a CFG file to --cfg."; + CHECK(!FLAGS_cfg.empty()) << "Must specify the path to a CFG file to --cfg."; mcsema::gContext = std::make_shared(); CHECK(mcsema::InitArch(FLAGS_os, FLAGS_arch)) - << "Cannot initialize for arch " << FLAGS_arch - << " and OS " << FLAGS_os << std::endl; + << "Cannot initialize for arch " << FLAGS_arch << " and OS " << FLAGS_os + << std::endl; if (FLAGS_legacy_mode) { LOG_IF(WARNING, FLAGS_keep_memops) @@ -769,17 +695,18 @@ int main(int argc, char *argv[]) { InitBaselineDecls(); const auto zero_var = new llvm::GlobalVariable( - *mcsema::gModule, llvm::Type::getInt8Ty(*mcsema::gContext), - true, llvm::GlobalValue::ExternalLinkage, - nullptr, "__anvill_pc"); + *mcsema::gModule, llvm::Type::getInt8Ty(*mcsema::gContext), true, + llvm::GlobalValue::ExternalLinkage, nullptr, "__anvill_pc"); mcsema::gZero = llvm::ConstantExpr::getPtrToInt(zero_var, mcsema::gWordType); // Load in a special library before CFG processing. This affects the // renaming of exported functions. - ABILibsLoader abi_loader(*mcsema::gModule, {FLAGS_explicit_args, FLAGS_explicit_args_count}); + ABILibsLoader abi_loader(*mcsema::gModule, + {FLAGS_explicit_args, FLAGS_explicit_args_count}); abi_loader.Load(FLAGS_abi_libraries, kPathDelimeter); - auto cfg_module = mcsema::ReadProtoBuf(FLAGS_cfg, (mcsema::gArch->address_size / 8)); + auto cfg_module = + mcsema::ReadProtoBuf(FLAGS_cfg, (mcsema::gArch->address_size / 8)); if (FLAGS_list_supported) { PrintSupportedInstructions(); diff --git a/tools/regtrace/Trace.cpp b/tools/regtrace/Trace.cpp index acef04413..303ff6b73 100644 --- a/tools/regtrace/Trace.cpp +++ b/tools/regtrace/Trace.cpp @@ -15,21 +15,20 @@ * along with this program. If not, see . */ -#include "pin.H" - #include #include #include #include #include -KNOB gEntrypoint( - KNOB_MODE_WRITEONCE, "pintool", "entrypoint", "0", - "Entrypoint of lifted program. Usually address of `main`."); +#include "pin.H" + +KNOB + gEntrypoint(KNOB_MODE_WRITEONCE, "pintool", "entrypoint", "0", + "Entrypoint of lifted program. Usually address of `main`."); -KNOB gStopAt( - KNOB_MODE_WRITEONCE, "pintool", "stop_at", "0", - "Address of code for when tracing should stop."); +KNOB gStopAt(KNOB_MODE_WRITEONCE, "pintool", "stop_at", "0", + "Address of code for when tracing should stop."); struct RegInfo final { const char *name; @@ -44,37 +43,25 @@ static uintptr_t gHighExcludeAddr = 0; #ifdef __x86_64__ static const struct RegInfo gGprs[] = { - {"RIP", LEVEL_BASE::REG_RIP}, - {"RAX", LEVEL_BASE::REG_RAX}, - {"RBX", LEVEL_BASE::REG_RBX}, - {"RCX", LEVEL_BASE::REG_RCX}, - {"RDX", LEVEL_BASE::REG_RDX}, - {"RSI", LEVEL_BASE::REG_RSI}, - {"RDI", LEVEL_BASE::REG_RDI}, - {"RBP", LEVEL_BASE::REG_RBP}, - {"RSP", LEVEL_BASE::REG_RSP}, - {"R8", LEVEL_BASE::REG_R8}, - {"R9", LEVEL_BASE::REG_R9}, - {"R10", LEVEL_BASE::REG_R10}, - {"R11", LEVEL_BASE::REG_R11}, - {"R12", LEVEL_BASE::REG_R12}, - {"R13", LEVEL_BASE::REG_R13}, - {"R14", LEVEL_BASE::REG_R14}, - {"R15", LEVEL_BASE::REG_R15}, + {"RIP", LEVEL_BASE::REG_RIP}, {"RAX", LEVEL_BASE::REG_RAX}, + {"RBX", LEVEL_BASE::REG_RBX}, {"RCX", LEVEL_BASE::REG_RCX}, + {"RDX", LEVEL_BASE::REG_RDX}, {"RSI", LEVEL_BASE::REG_RSI}, + {"RDI", LEVEL_BASE::REG_RDI}, {"RBP", LEVEL_BASE::REG_RBP}, + {"RSP", LEVEL_BASE::REG_RSP}, {"R8", LEVEL_BASE::REG_R8}, + {"R9", LEVEL_BASE::REG_R9}, {"R10", LEVEL_BASE::REG_R10}, + {"R11", LEVEL_BASE::REG_R11}, {"R12", LEVEL_BASE::REG_R12}, + {"R13", LEVEL_BASE::REG_R13}, {"R14", LEVEL_BASE::REG_R14}, + {"R15", LEVEL_BASE::REG_R15}, }; #else static const struct RegInfo gGprs[] = { - {"EIP", LEVEL_BASE::REG_EIP}, - {"EAX", LEVEL_BASE::REG_EAX}, - {"EBX", LEVEL_BASE::REG_EBX}, - {"ECX", LEVEL_BASE::REG_ECX}, - {"EDX", LEVEL_BASE::REG_EDX}, - {"ESI", LEVEL_BASE::REG_ESI}, - {"EDI", LEVEL_BASE::REG_EDI}, - {"EBP", LEVEL_BASE::REG_EBP}, - {"ESP", LEVEL_BASE::REG_ESP}, + {"EIP", LEVEL_BASE::REG_EIP}, {"EAX", LEVEL_BASE::REG_EAX}, + {"EBX", LEVEL_BASE::REG_EBX}, {"ECX", LEVEL_BASE::REG_ECX}, + {"EDX", LEVEL_BASE::REG_EDX}, {"ESI", LEVEL_BASE::REG_ESI}, + {"EDI", LEVEL_BASE::REG_EDI}, {"EBP", LEVEL_BASE::REG_EBP}, + {"ESP", LEVEL_BASE::REG_ESP}, }; #endif // __x86_64__ @@ -110,9 +97,8 @@ VOID PrintRegState(CONTEXT *ctx) { std::stringstream ss; const char *sep = ""; for (auto &gpr : gGprs) { - ss - << sep << gpr.name << "=" << std::hex << std::setw(0) - << PIN_GetContextReg(ctx, gpr.reg); + ss << sep << gpr.name << "=" << std::hex << std::setw(0) + << PIN_GetContextReg(ctx, gpr.reg); sep = ","; } @@ -123,27 +109,24 @@ VOID PrintRegState(CONTEXT *ctx) { VOID InstrumentInstruction(INS ins, VOID *) { auto addr = INS_Address(ins); - + if (addr >= gLowAddr && addr < gHighAddr) { - + // A thunk; only include the address of the first instruction. if (addr >= gLowExcludeAddr && addr < gHighExcludeAddr) { - INS_InsertCall( - ins, IPOINT_BEFORE, (AFUNPTR)CountReps, IARG_END); - + INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) CountReps, IARG_END); + // Normal code. } else { if (INS_HasRealRep(ins)) { - INS_InsertCall( - ins, IPOINT_BEFORE, (AFUNPTR)CountReps, IARG_END); + INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) CountReps, IARG_END); } else { - INS_InsertCall( - ins, IPOINT_BEFORE, (AFUNPTR)ClearReps, IARG_END); + INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) ClearReps, IARG_END); } } - INS_InsertCall( - ins, IPOINT_BEFORE, (AFUNPTR)PrintRegState, IARG_CONTEXT, IARG_END); + INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR) PrintRegState, IARG_CONTEXT, + IARG_END); } } @@ -153,8 +136,8 @@ VOID FindEntrypoint(IMG img, void *) { if (low <= gEntrypoint.Value() && gEntrypoint.Value() <= high) { gLowAddr = low; gHighAddr = high; - - // Find + + // Find for (SEC sec = IMG_SecHead(img); SEC_Valid(sec); sec = SEC_Next(sec)) { if (SEC_Name(sec) == ".plt" || SEC_Name(sec) == ".PLT") { gLowExcludeAddr = SEC_Address(sec);