Last active
February 1, 2023 22:20
-
-
Save ek0/a7f9bf7805874ab33ec1211333c2d5a0 to your computer and use it in GitHub Desktop.
Various functions to test different lifting/disassembly/decompilation from static analysis tools.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// adder.cpp : This file contains the 'main' function. Program execution begins and ends there. | |
// | |
#include <iostream> | |
#include <cstdint> | |
#include <intrin.h> | |
//#include <mmintrin.h> | |
//#include <emmintrin.h> | |
uint64_t add(uint64_t a, uint64_t b) | |
{ | |
return a + b; | |
} | |
uint64_t mul(uint64_t a, uint64_t b) | |
{ | |
return a * b; | |
} | |
uint64_t sub(uint64_t a, uint64_t b) | |
{ | |
return a - b; | |
} | |
uint64_t div(uint64_t a, uint64_t b) | |
{ | |
return a / b; | |
} | |
uint64_t mod(uint64_t a, uint64_t b) | |
{ | |
return a % b; | |
} | |
uint64_t shl(uint64_t a, uint64_t b) | |
{ | |
return a << b; | |
} | |
uint64_t shr(uint64_t a, uint64_t b) | |
{ | |
return a >> b; | |
} | |
uint64_t and_(uint64_t a, uint64_t b) | |
{ | |
return a & b; | |
} | |
uint64_t or_(uint64_t a, uint64_t b) | |
{ | |
return a | b; | |
} | |
uint64_t and_or(uint64_t a, uint64_t b, uint64_t c) | |
{ | |
return a | b & c; | |
} | |
uint64_t xor_(uint64_t a, uint64_t b) | |
{ | |
return a ^ b; | |
} | |
uint64_t not_(uint64_t a) | |
{ | |
return ~a; | |
} | |
int64_t neg(int64_t a) | |
{ | |
return -a; | |
} | |
double fadd(double arg) | |
{ | |
return arg + 2.0; | |
} | |
double fsub(double arg) | |
{ | |
return arg - 2.0; | |
} | |
double fmul(double arg) | |
{ | |
return arg - 2.0; | |
} | |
double fdiv(double arg) | |
{ | |
return arg / 2.0; | |
} | |
double fneg(double arg) | |
{ | |
return -arg; | |
} | |
uint64_t cast_double_to_int(double x) | |
{ | |
return static_cast<uint64_t>(x); | |
} | |
uint64_t sign_extend(uint32_t a) | |
{ | |
return static_cast<uint64_t>(a); | |
} | |
int64_t sign_extend(int32_t a) | |
{ | |
return static_cast<int64_t>(a); | |
} | |
int32_t low1(uint64_t a) | |
{ | |
return static_cast<int32_t>(a); | |
} | |
uint64_t* ptr_add(uint64_t* a, uint64_t b) | |
{ | |
return a + b; | |
} | |
uint64_t ldx(uint64_t* a) | |
{ | |
return *a; | |
} | |
void stx(uint64_t* a) | |
{ | |
*a = 2; | |
} | |
uint64_t jump_eq(uint64_t a, uint64_t b) | |
{ | |
if(a == b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_neq(uint64_t a, uint64_t b) | |
{ | |
if(a != b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jg(int64_t a, int64_t b) | |
{ | |
if (a > b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jge(int64_t a, int64_t b) | |
{ | |
if (a >= b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_ja(uint64_t a, uint64_t b) | |
{ | |
if (a > b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jae(uint64_t a, uint64_t b) | |
{ | |
if (a >= b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jl(int64_t a, int64_t b) | |
{ | |
if (a < b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jle(int64_t a, int64_t b) | |
{ | |
if (a <= b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint64_t jump_jb(uint64_t a, uint64_t b) | |
{ | |
if (a < b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
uint32_t fake_cfg() | |
{ | |
uint32_t a = 32; | |
switch (a) | |
{ | |
case 1: | |
return 1; | |
case 3: | |
return 3; | |
case 32: | |
return 32; | |
} | |
} | |
#pragma optimize("", off) | |
uint32_t jtbl_test(uint32_t a) | |
{ | |
uint32_t b = a; | |
uint32_t p = a; | |
while(true) | |
{ | |
switch (b) | |
{ | |
case 1: | |
b = 2; | |
continue; | |
case 2: | |
b = 3; | |
continue; | |
case 3: | |
b = 4; | |
continue; | |
case 4: | |
b = 5; | |
continue; | |
case 5: | |
b = 6; | |
continue; | |
case 6: | |
b = 7; | |
continue; | |
case 7: | |
b = 8; | |
continue; | |
case 8: | |
b = 9; | |
continue; | |
case 9: | |
b = 10; | |
continue; | |
case 10: | |
case 11: | |
b = 12; | |
continue; | |
case 12: | |
b = 13; | |
if (a == 0) | |
b = 13; | |
else | |
b = 14; | |
p = b + a; | |
continue; | |
case 13: | |
{ | |
b = 14; | |
continue; | |
} | |
case 14: | |
{ | |
b = 9876; | |
//uint32_t c = 1; | |
//c = b * 2; | |
//uint64_t d = c / 3; | |
if (a == 0) | |
b = 123; | |
else | |
b = 12345; | |
p = b + a; | |
continue; | |
} | |
default: | |
b = 123; | |
return b; | |
} | |
} | |
return b; | |
} | |
#pragma optimize("", on) | |
double test_double_comisd(double a, double b) | |
{ | |
if (a > b) | |
return a; | |
if (a < b) | |
return b; | |
return std::numeric_limits<double>::max(); | |
} | |
double test_double_nan(double a) | |
{ | |
constexpr double qnan = std::numeric_limits<double>::quiet_NaN(); | |
constexpr double snan = std::numeric_limits<double>::signaling_NaN(); | |
if (snan == snan) | |
return qnan; | |
if (a == snan) | |
return snan; | |
return a; | |
} | |
double test_double_eq(double a, double b) | |
{ | |
if (a == b) | |
return a; | |
return b; | |
} | |
double test_double_lt(double a, double b) | |
{ | |
if (a < b) | |
return a; | |
else | |
return b; | |
} | |
double test_double_le(double a, double b) | |
{ | |
if (a <= b) | |
return a; | |
else | |
return b; | |
} | |
void test_unordered_cmp() | |
{ | |
double a = 0.; | |
double b = 0.; | |
__m128d x = _mm_set1_pd(a / b); // NaN | |
__m128d y = _mm_set1_pd(1.0); // 1.0 | |
__m128d z = _mm_set1_pd(1.0); // 1.0 | |
__m128d c0 = _mm_cmpord_pd(x, y); // NaN vs. 1.0 | |
__m128d c1 = _mm_cmpunord_pd(x, y); // NaN vs. 1.0 | |
__m128d c2 = _mm_cmpord_pd(y, z); // 1.0 vs. 1.0 | |
__m128d c3 = _mm_cmpunord_pd(y, z); // 1.0 vs. 1.0 | |
__m128d c4 = _mm_cmpord_pd(x, x); // NaN vs. NaN | |
__m128d c5 = _mm_cmpunord_pd(x, x); // NaN vs. NaN | |
std::cout << _mm_castpd_si128(c0).m128i_i64[0] << std::endl; | |
std::cout << _mm_castpd_si128(c1).m128i_i64[0] << std::endl; | |
std::cout << _mm_castpd_si128(c2).m128i_i64[0] << std::endl; | |
std::cout << _mm_castpd_si128(c3).m128i_i64[0] << std::endl; | |
std::cout << _mm_castpd_si128(c4).m128i_i64[0] << std::endl; | |
std::cout << _mm_castpd_si128(c5).m128i_i64[0] << std::endl; | |
} | |
double test_double_gt(double a, double b) | |
{ | |
if (a > b) | |
return a; | |
else | |
return b; | |
} | |
double test_double_ge(double a, double b) | |
{ | |
if (a >= b) | |
return a; | |
else | |
return b; | |
} | |
#ifndef _WIN64 | |
__m64 test_por(__m64 arg1, __m64 arg2) | |
{ | |
return _m_por(arg1, arg2); | |
} | |
#endif | |
uint32_t test_f2i(float a) | |
{ | |
return static_cast<uint32_t>(a); | |
} | |
uint64_t test_f2i_bigger(float a) | |
{ | |
return static_cast<uint64_t>(a); | |
} | |
uint32_t test_f2i_smaller(double a) | |
{ | |
return static_cast<uint32_t>(a); | |
} | |
uint64_t ptr_add_const(uint64_t* a) | |
{ | |
return a[2]; | |
} | |
uint64_t jump_jbe(uint64_t a, uint64_t b) | |
{ | |
if (a <= b) | |
{ | |
return a; | |
} | |
return b; | |
} | |
char** pointer_chain_args(char*** a) | |
{ | |
return *a; | |
} | |
int main(int argc, char **argv) | |
{ | |
if(argc != 3) | |
return -1; | |
std::cout << "NaN? " << test_double_nan(0.1234) << std::endl; | |
std::cout << add(atoi(argv[1]), atoi(argv[2])); | |
} | |
// Run program: Ctrl + F5 or Debug > Start Without Debugging menu | |
// Debug program: F5 or Debug > Start Debugging menu | |
// Tips for Getting Started: | |
// 1. Use the Solution Explorer window to add/manage files | |
// 2. Use the Team Explorer window to connect to source control | |
// 3. Use the Output window to see build output and other messages | |
// 4. Use the Error List window to view errors | |
// 5. Go to Project > Add New Item to create new code files, or Project > Add Existing Item to add existing code files to the project | |
// 6. In the future, to open this project again, go to File > Open > Project and select the .sln file |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment