From fe9275250e2558ebdd30aaa65d5072b10ede797b Mon Sep 17 00:00:00 2001 From: Evgeny Karpov Date: Thu, 16 Nov 2023 16:37:39 +0100 Subject: [PATCH 1/3] * use gtest to execute tests with aarch64-x64-mingw changes --- {tests => examples}/build-tests.sh | 0 {tests => examples}/dll.c | 0 {tests => examples}/dll.def | 0 {tests => examples}/readme.md | 0 {tests => examples}/run-tests.bat | 0 {tests => examples}/test-bigdata.cpp | 0 {tests => examples}/test-dll.c | 0 {tests => examples}/test-iostream.cpp | 40 ++-- {tests => examples}/test-math.c | 0 {tests => examples}/test-omp.c | 0 {tests => examples}/test-openblas.c | 42 ++--- {tests => examples}/test-pdata.c | 0 {tests => examples}/test-sjlj.c | 0 {tests => examples}/test-struct.c | 0 {tests => examples}/test-throw.cpp | 0 {tests => examples}/test-varargs.c | 0 tests/BUILD.txt | 7 + tests/CMakeLists.txt | 47 +++++ tests/bigdata_test.cpp | 127 +++++++++++++ tests/dll_test.c | 27 +++ tests/dll_test.cpp | 10 + tests/iostream_test.cpp | 22 +++ tests/math_test.c | 38 ++++ tests/math_test.cpp | 10 + tests/omp_test.c | 11 ++ tests/omp_test.cpp | 10 + tests/openblas_test.c | 22 +++ tests/openblas_test.cpp | 10 + tests/pdata_test.c | 258 ++++++++++++++++++++++++++ tests/pdata_test.cpp | 10 + tests/sjlj_test.c | 27 +++ tests/sjlj_test.cpp | 10 + tests/struct_test.c | 42 +++++ tests/struct_test.cpp | 10 + tests/throw_test.cpp | 51 +++++ tests/varargs_test.c | 34 ++++ tests/varargs_test.cpp | 10 + 37 files changed, 834 insertions(+), 41 deletions(-) rename {tests => examples}/build-tests.sh (100%) mode change 100755 => 100644 rename {tests => examples}/dll.c (100%) rename {tests => examples}/dll.def (100%) rename {tests => examples}/readme.md (100%) rename {tests => examples}/run-tests.bat (100%) rename {tests => examples}/test-bigdata.cpp (100%) rename {tests => examples}/test-dll.c (100%) rename {tests => examples}/test-iostream.cpp (96%) rename {tests => examples}/test-math.c (100%) rename {tests => examples}/test-omp.c (100%) rename {tests => examples}/test-openblas.c (96%) rename {tests => examples}/test-pdata.c (100%) rename {tests => examples}/test-sjlj.c (100%) rename {tests => examples}/test-struct.c (100%) rename {tests => examples}/test-throw.cpp (100%) rename {tests => examples}/test-varargs.c (100%) create mode 100644 tests/BUILD.txt create mode 100644 tests/CMakeLists.txt create mode 100644 tests/bigdata_test.cpp create mode 100644 tests/dll_test.c create mode 100644 tests/dll_test.cpp create mode 100644 tests/iostream_test.cpp create mode 100644 tests/math_test.c create mode 100644 tests/math_test.cpp create mode 100644 tests/omp_test.c create mode 100644 tests/omp_test.cpp create mode 100644 tests/openblas_test.c create mode 100644 tests/openblas_test.cpp create mode 100644 tests/pdata_test.c create mode 100644 tests/pdata_test.cpp create mode 100644 tests/sjlj_test.c create mode 100644 tests/sjlj_test.cpp create mode 100644 tests/struct_test.c create mode 100644 tests/struct_test.cpp create mode 100644 tests/throw_test.cpp create mode 100644 tests/varargs_test.c create mode 100644 tests/varargs_test.cpp diff --git a/tests/build-tests.sh b/examples/build-tests.sh old mode 100755 new mode 100644 similarity index 100% rename from tests/build-tests.sh rename to examples/build-tests.sh diff --git a/tests/dll.c b/examples/dll.c similarity index 100% rename from tests/dll.c rename to examples/dll.c diff --git a/tests/dll.def b/examples/dll.def similarity index 100% rename from tests/dll.def rename to examples/dll.def diff --git a/tests/readme.md b/examples/readme.md similarity index 100% rename from tests/readme.md rename to examples/readme.md diff --git a/tests/run-tests.bat b/examples/run-tests.bat similarity index 100% rename from tests/run-tests.bat rename to examples/run-tests.bat diff --git a/tests/test-bigdata.cpp b/examples/test-bigdata.cpp similarity index 100% rename from tests/test-bigdata.cpp rename to examples/test-bigdata.cpp diff --git a/tests/test-dll.c b/examples/test-dll.c similarity index 100% rename from tests/test-dll.c rename to examples/test-dll.c diff --git a/tests/test-iostream.cpp b/examples/test-iostream.cpp similarity index 96% rename from tests/test-iostream.cpp rename to examples/test-iostream.cpp index 22f4f77ee..f8dcefd38 100644 --- a/tests/test-iostream.cpp +++ b/examples/test-iostream.cpp @@ -1,21 +1,21 @@ -#include -#include -#include - -int main() -{ - std::cout << "Hello World!" << std::endl; - - std::cout << "==" << -17 << "==" << std::endl; - std::cout << "==" << std::setw(6) << -17 << "==" << std::endl; - std::cout << std::left; - std::cout << "==" << std::setw(6) << -17 << "==" << std::endl << std::endl; - - std::cout << "==" << "hello" << "==" << std::endl; - std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; - std::cout << std::right; - std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; - - std::cout << "ok" << std::endl; - return 0; +#include +#include +#include + +int main() +{ + std::cout << "Hello World!" << std::endl; + + std::cout << "==" << -17 << "==" << std::endl; + std::cout << "==" << std::setw(6) << -17 << "==" << std::endl; + std::cout << std::left; + std::cout << "==" << std::setw(6) << -17 << "==" << std::endl << std::endl; + + std::cout << "==" << "hello" << "==" << std::endl; + std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; + std::cout << std::right; + std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; + + std::cout << "ok" << std::endl; + return 0; } \ No newline at end of file diff --git a/tests/test-math.c b/examples/test-math.c similarity index 100% rename from tests/test-math.c rename to examples/test-math.c diff --git a/tests/test-omp.c b/examples/test-omp.c similarity index 100% rename from tests/test-omp.c rename to examples/test-omp.c diff --git a/tests/test-openblas.c b/examples/test-openblas.c similarity index 96% rename from tests/test-openblas.c rename to examples/test-openblas.c index 332839575..e1b09d599 100644 --- a/tests/test-openblas.c +++ b/examples/test-openblas.c @@ -1,22 +1,22 @@ -// This is a small test app for openblas. -// git clone https://github.com/xianyi/OpenBLAS.git -// cd OpenBLAS -// make BINARY=64 CC=~/cross/bin/aarch64-w64-mingw32-gcc HOSTCC=gcc TARGET=ARMV8 -// ~/cross/bin/aarch64-w64-mingw32-gcc -I. -L. test-openblas.c -lopenblas -o test-openblas.exe - -#include -#include - -void main() -{ - int i=0; - double A[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; - double B[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; - double C[9] = {.5,.5,.5,.5,.5,.5,.5,.5,.5}; - cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,3,3,2,1,A, 3, B, 3,2,C,3); - - for(i=0; i<9; i++) - printf("%lf ", C[i]); - printf("\n"); - printf("ok\n"); +// This is a small test app for openblas. +// git clone https://github.com/xianyi/OpenBLAS.git +// cd OpenBLAS +// make BINARY=64 CC=~/cross/bin/aarch64-w64-mingw32-gcc HOSTCC=gcc TARGET=ARMV8 +// ~/cross/bin/aarch64-w64-mingw32-gcc -I. -L. test-openblas.c -lopenblas -o test-openblas.exe + +#include +#include + +void main() +{ + int i=0; + double A[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; + double B[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; + double C[9] = {.5,.5,.5,.5,.5,.5,.5,.5,.5}; + cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,3,3,2,1,A, 3, B, 3,2,C,3); + + for(i=0; i<9; i++) + printf("%lf ", C[i]); + printf("\n"); + printf("ok\n"); } \ No newline at end of file diff --git a/tests/test-pdata.c b/examples/test-pdata.c similarity index 100% rename from tests/test-pdata.c rename to examples/test-pdata.c diff --git a/tests/test-sjlj.c b/examples/test-sjlj.c similarity index 100% rename from tests/test-sjlj.c rename to examples/test-sjlj.c diff --git a/tests/test-struct.c b/examples/test-struct.c similarity index 100% rename from tests/test-struct.c rename to examples/test-struct.c diff --git a/tests/test-throw.cpp b/examples/test-throw.cpp similarity index 100% rename from tests/test-throw.cpp rename to examples/test-throw.cpp diff --git a/tests/test-varargs.c b/examples/test-varargs.c similarity index 100% rename from tests/test-varargs.c rename to examples/test-varargs.c diff --git a/tests/BUILD.txt b/tests/BUILD.txt new file mode 100644 index 000000000..fbecf7777 --- /dev/null +++ b/tests/BUILD.txt @@ -0,0 +1,7 @@ +Building aarch64-w64-mingw32 tests on WSL + +cmake -S . -B build +cmake --build build + +it generates Arm64 Windows executable +build/aarch64_mingw_tests \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 000000000..0cfdd2af0 --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,47 @@ +set(CMAKE_VERBOSE_MAKEFILE ON) +set(CMAKE_C_COMPILER "/home/user/cross/bin/aarch64-w64-mingw32-gcc") +set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_COMPILER "/home/user/cross/bin/aarch64-w64-mingw32-c++") +set(CMAKE_RANLIB "/home/user/cross/bin/aarch64-w64-mingw32-ranlib") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fopenmp") + +include(FetchContent) +FetchContent_Declare( + googletest + URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip +) + +FetchContent_MakeAvailable(googletest) + +cmake_minimum_required(VERSION 3.14) +project(aarch64_mingw_tests) + +enable_testing() + +add_executable( + aarch64_mingw_tests + bigdata_test.cpp + iostream_test.cpp + math_test.c + math_test.cpp + omp_test.c + omp_test.cpp + pdata_test.c + pdata_test.cpp + sjlj_test.c + sjlj_test.cpp + struct_test.c + struct_test.cpp + throw_test.cpp + varargs_test.c + varargs_test.cpp +) + +set_source_files_properties(test-dll.c PROPERTIES COMPILE_FLAGS "-DIMPORT_API=") + +target_link_libraries( + aarch64_mingw_tests + GTest::gtest_main + dbghelp +) diff --git a/tests/bigdata_test.cpp b/tests/bigdata_test.cpp new file mode 100644 index 000000000..a93620532 --- /dev/null +++ b/tests/bigdata_test.cpp @@ -0,0 +1,127 @@ +#include +#include +#include + +#include + + +#define MAX_SAMPLES 0x1000000 + + +static void big_text() +{ + // Print out more than one page of text. + puts("The Commodore 64, also known as the C64, is an 8-bit home"); + puts("computer introduced in January 1982 by Commodore"); + puts("International (first shown at the Consumer Electronics"); + puts("Show, January 7-10, 1982, in Las Vegas). It has been"); + puts("listed in the Guinness World Records as the"); + puts("highest-selling single computer model of all time, with"); + puts("independent estimates placing the number sold between"); + puts("12.5 and 17 million units. Volume production started in"); + puts("early 1982, marketing in August for US$595 (equivalent to"); + puts("$1,800 in 2022). Preceded by the VIC-20 and Commodore"); + puts("PET, the C64 took its name from its 64 kilobytes (65,536"); + puts("bytes) of RAM. With support for multicolor sprites and a"); + puts("custom chip for waveform generation, the C64 could create"); + puts("superior visuals and audio compared to systems without"); + puts("such custom hardware."); + puts(""); + puts("The C64 dominated the low-end computer market (except in"); + puts("the UK and Japan, lasting only about six months in Japan)"); + puts("for most of the later years of the 1980s. For a"); + puts("substantial period (1983-1986), the C64 had between 30%"); + puts("and 40% share of the US market and two million units sold"); + puts("per year, outselling IBM PC compatibles, Apple computers,"); + puts("and the Atari 8-bit family of computers. Sam Tramiel, a"); + puts("later Atari president and the son of Commodore's founder,"); + puts("said in a 1989 interview, When I was at Commodore we"); + puts("were building 400,000 C64s a month for a couple of"); + puts("years. In the UK market, the C64 faced competition from"); + puts("the BBC Micro, the ZX Spectrum, and later the Amstrad CPC"); + puts("464. but the C64 was still the second-most-popular"); + puts("computer in the UK after the ZX Spectrum. The Commodore"); + puts("64 failed to make any impact in Japan, as their market"); + puts("was dominated by Japanese computers, such as the NEC"); + puts("PC-8801, Sharp X1, Fujitsu FM-7, and MSX."); + puts(""); + puts("Part of the Commodore 64's success was its sale in"); + puts("regular retail stores instead of only electronics or"); + puts("computer hobbyist specialty stores. Commodore produced"); + puts("many of its parts in-house to control costs, including"); + puts("custom integrated circuit chips from MOS Technology. In"); + puts("the United States, it has been compared to the Ford Model"); + puts("T automobile for its role in bringing a new technology to"); + puts("middle-class households via creative and affordable"); + puts("mass-production. Approximately 10,000 commercial software"); + puts("titles have been made for the Commodore 64, including"); + puts("development tools, office productivity applications, and"); + puts("video games. C64 emulators allow anyone with a modern"); + puts("computer, or a compatible video game console, to run"); + puts("these programs today. The C64 is also credited with"); + puts("popularizing the computer demoscene and is still used"); + puts("today by some computer hobbyists. In 2011, 17 years after"); + puts("it was taken off the market, research showed that brand"); + puts("recognition for the model was still at 87%."); +} + +void big_bss() +{ + static size_t values[MAX_SAMPLES]; + static size_t sorted[MAX_SAMPLES]; + static size_t ref[MAX_SAMPLES]; + + printf("bigger %lx %d\n", MAX_SAMPLES, 0x1919); + printf("1 %lx\n", values); + printf("2 %lx\n", sorted); + printf("3 %lx\n", ref); + + memset(values, 0, sizeof(values)); + memset(sorted, 0, sizeof(sorted)); + memset(ref, 0, sizeof(ref)); +} + +int get_len() +{ + return 100; +} + +int calc_func2(int x, int y) +{ + printf("calc-func\n"); + int i = x; + int j = y; + return i + j; +} + +int throw_func1(void) +{ + printf("throw-func\n"); + int x = calc_func2(13, 19); + return x; +} + +void big_stack_func(void) +{ + printf("big-stack-func\n"); + char sz[0x4000] =""; + strcpy(sz,"hello"); + + int num = get_len(); + + { + int scopes[num]; + int temps[num]; + + throw_func1(); + } +} + +TEST(Aarch64MinGW, BigDataTest) +{ + printf("main\n"); + big_stack_func(); + big_bss(); + big_text(); + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/dll_test.c b/tests/dll_test.c new file mode 100644 index 000000000..9f8f1b070 --- /dev/null +++ b/tests/dll_test.c @@ -0,0 +1,27 @@ +/* + Tests using the function imported from a DLL + IMPORT_API must be defined externally +*/ + +#include +#include + +/* Declare imported function so that we can actually use it. */ +IMPORT_API int __cdecl funcc(int a, int b); +IMPORT_API int __stdcall funcstd(int a, int b); + +int test_func_pointer( int __cdecl (*f)(int , int), int marker) +{ + printf("test_func_pointer start %lx\n", test_func_pointer); + printf("f address %lx\n", f); + f(6, 23); +} + +void dll_test() +{ + printf("%d\n", funcc(6, 23)); + printf("%d\n", funcstd(6, 23)); + + test_func_pointer(funcc, 0x1919); + printf("ok\n"); +} diff --git a/tests/dll_test.cpp b/tests/dll_test.cpp new file mode 100644 index 000000000..117d47695 --- /dev/null +++ b/tests/dll_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void dll_test(); + +TEST(Aarch64MinGW, DllTest) +{ + dll_test(); +} + + diff --git a/tests/iostream_test.cpp b/tests/iostream_test.cpp new file mode 100644 index 000000000..79759e97f --- /dev/null +++ b/tests/iostream_test.cpp @@ -0,0 +1,22 @@ +#include +#include +#include + +#include + +TEST(Aarch64MinGW, IOStreamTest) +{ + std::cout << "Hello World!" << std::endl; + + std::cout << "==" << -17 << "==" << std::endl; + std::cout << "==" << std::setw(6) << -17 << "==" << std::endl; + std::cout << std::left; + std::cout << "==" << std::setw(6) << -17 << "==" << std::endl << std::endl; + + std::cout << "==" << "hello" << "==" << std::endl; + std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; + std::cout << std::right; + std::cout << "==" << std::setw(20) << "hello" << "==" << std::endl; + + std::cout << "ok" << std::endl; +} \ No newline at end of file diff --git a/tests/math_test.c b/tests/math_test.c new file mode 100644 index 000000000..f88f26b75 --- /dev/null +++ b/tests/math_test.c @@ -0,0 +1,38 @@ +#include + + +_Float128 foo (_Float128 x) +{ + _Complex _Float128 z1, z2; + + z1 = x; + z2 = x / 7.F128; + z2 /= z1; + + return (_Float128) z2; +} + +_Float128 bar (_Float128 x) +{ + return x * __builtin_huge_valf128 (); +} + +_Float128 baz (_Float128 x) +{ + return x * __builtin_huge_valf128 (); +} + + +void math_test() +{ + foo (1.2Q); + bar (1.2Q); + foo (1.2F128); + bar (1.2F128); + baz (1.2F128); + foo (1.2Q); + bar (1.2Q); + baz (1.2Q); + + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/math_test.cpp b/tests/math_test.cpp new file mode 100644 index 000000000..fef947228 --- /dev/null +++ b/tests/math_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void math_test(); + +TEST(Aarch64MinGW, MathTest) +{ + math_test(); +} + + diff --git a/tests/omp_test.c b/tests/omp_test.c new file mode 100644 index 000000000..2bcd6f140 --- /dev/null +++ b/tests/omp_test.c @@ -0,0 +1,11 @@ +#include +#include + +void omp_test(void) +{ + #pragma omp parallel + { + printf("Hello from process: %d\n", omp_get_thread_num()); + } + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/omp_test.cpp b/tests/omp_test.cpp new file mode 100644 index 000000000..5f4c027ec --- /dev/null +++ b/tests/omp_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void omp_test(); + +TEST(Aarch64MinGW, OmpTest) +{ + omp_test(); +} + + diff --git a/tests/openblas_test.c b/tests/openblas_test.c new file mode 100644 index 000000000..7f4e5d5fc --- /dev/null +++ b/tests/openblas_test.c @@ -0,0 +1,22 @@ +// This is a small test app for openblas. +// git clone https://github.com/xianyi/OpenBLAS.git +// cd OpenBLAS +// make BINARY=64 CC=~/cross/bin/aarch64-w64-mingw32-gcc HOSTCC=gcc TARGET=ARMV8 +// ~/cross/bin/aarch64-w64-mingw32-gcc -I. -L. test-openblas.c -lopenblas -o test-openblas.exe + +#include +#include + +void openblas_test() +{ + int i=0; + double A[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; + double B[6] = {1.0,2.0,1.0,-3.0,4.0,-1.0}; + double C[9] = {.5,.5,.5,.5,.5,.5,.5,.5,.5}; + cblas_dgemm(CblasColMajor, CblasNoTrans, CblasTrans,3,3,2,1,A, 3, B, 3,2,C,3); + + for(i=0; i<9; i++) + printf("%lf ", C[i]); + printf("\n"); + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/openblas_test.cpp b/tests/openblas_test.cpp new file mode 100644 index 000000000..3ecab4d06 --- /dev/null +++ b/tests/openblas_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void openblas_test(); + +TEST(Aarch64MinGW, OpenBLASTest) +{ + openblas_test(); +} + + diff --git a/tests/pdata_test.c b/tests/pdata_test.c new file mode 100644 index 000000000..525fa7b08 --- /dev/null +++ b/tests/pdata_test.c @@ -0,0 +1,258 @@ +#define UNICODE 1 +#define _UNICODE 1 + +#include +#include +#include + +#pragma comment(lib, "dbghelp.lib") + +// build with +// ~/cross/bin/aarch64-w64-mingw32-gcc test-pdata.c -ldbghelp -o test-pdata.exe +// +// View pdata +// ~/cross/bin/aarch64-w64-mingw32-objdump -s -j .pdata test-pdata.exe + +#define STACK_MAX 16 +#define SYMBOL_MAXLEN 256 + +static void print_symbol(HANDLE hp, DWORD64 offset) +{ + IMAGEHLP_MODULEW64 module; + memset(&module, 0, sizeof(module)); + module.SizeOfStruct = sizeof(module); + SymGetModuleInfoW64(hp, offset, &module); + + if (wcslen(module.ModuleName) > 0) + { + //wprintf(L"%-8s", module.ModuleName); + wprintf(module.ModuleName); + } + + BYTE buffer[sizeof(IMAGEHLP_SYMBOL64) + SYMBOL_MAXLEN]; + memset(buffer, 0, sizeof(buffer)); + + const char* symbolName = ""; + DWORD64 dwDisplacement = 0; + IMAGEHLP_SYMBOL64* p = (IMAGEHLP_SYMBOL64*)buffer; + p->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + p->MaxNameLength = SYMBOL_MAXLEN; + + if (SymGetSymFromAddr64(hp, offset, &dwDisplacement, p)) + { + printf(" %s+0x%.04llX", p->Name, dwDisplacement); + } + else + { + DWORD64 base; + UNWIND_HISTORY_TABLE history; + PRUNTIME_FUNCTION func = RtlLookupFunctionEntry(offset, &base, &history); + + if (func) + { + printf(" %llX", (DWORD64)func); + } + } +} + + +static void dump_xdata(PULONG Xdata) +{ + ULONG Size = 0; + ULONG EpilogScopes = 0; + ULONG UnwindWords = 0; + + + if ((Xdata[0] >> 22) != 0) { + Size = 4; + EpilogScopes = (Xdata[0] >> 22) & 0x1f; + UnwindWords = (Xdata[0] >> 27) & 0x1f; + } + else { + Size = 8; + EpilogScopes = Xdata[1] & 0xffff; + UnwindWords = (Xdata[1] >> 16) & 0xff; + } + + if (!(Xdata[0] & (1 << 21))) { + Size += 4 * EpilogScopes; + } + + wprintf(L" epilog scopes = %d\n", EpilogScopes); + wprintf(L" unwind words = %d\n", UnwindWords); + + Size += 4 * UnwindWords; + + if (Xdata[0] & (1 << 20)) { + ULONG exception_rva = Xdata[Size / 4]; + wprintf(L" exception rva = %x\n", exception_rva); + Size += 4; // Exception handler RVA + } + + wprintf(L" size = %d\n", Size); +} + +void walk_stack_rtl() +{ + CONTEXT ctx; + memset(&ctx, 0, sizeof(CONTEXT)); + ctx.ContextFlags = CONTEXT_ALL; + RtlCaptureContext(&ctx); + + HANDLE hp = GetCurrentProcess(); + HANDLE ht = GetCurrentThread(); + BOOL sym_initialized = SymInitialize(hp, NULL, TRUE); + printf("walk_stack\n"); + + UNWIND_HISTORY_TABLE ms_history; + DISPATCHER_CONTEXT disp_context; + ULONG64 ip; + + disp_context.ContextRecord = &ctx; + disp_context.HistoryTable = &ms_history; + + for (int i = 0; i < STACK_MAX; i++) + { +#ifdef _M_AMD64 + ip = ctx.Rip; +#elif defined(_M_ARM64) + ip = ctx.Pc; +#endif + + wprintf(L" %2d: 0x%.08llX ", i, ip); + + if (sym_initialized) + { + print_symbol(hp, ip); + } + + printf("\n"); + + disp_context.ControlPc = ip; + disp_context.FunctionEntry = RtlLookupFunctionEntry(ip, &disp_context.ImageBase, &ms_history); + + if (!disp_context.FunctionEntry) + return; + + disp_context.LanguageHandler = RtlVirtualUnwind(0, disp_context.ImageBase, ip, + disp_context.FunctionEntry, &ctx, + &disp_context.HandlerData, + &disp_context.EstablisherFrame, NULL); + + if (ip == 0) + return; + } + + if (sym_initialized) + SymCleanup(hp); +} + + + +void list_pdata() +{ + printf("list_pdata sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY) = %d\n", sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY)); + +#ifdef _M_AMD64 + printf("_M_AMD64\n"); +#elif defined(_M_ARM64) + printf("_M_ARM64\n"); +#endif + + PVOID base = GetModuleHandle(NULL); + HANDLE hp = GetCurrentProcess(); + HANDLE ht = GetCurrentThread(); + BOOL sym_initialized = SymInitialize(hp, NULL, TRUE); + + IMAGEHLP_MODULEW64 module; + memset(&module, 0, sizeof(module)); + module.SizeOfStruct = sizeof(module); + SymGetModuleInfoW64(hp, (DWORD64)base, &module); + printf("SymType = %d\n", module.SymType); + printf("\n"); + + + PIMAGE_NT_HEADERS image = ImageNtHeader(base); + + //CONTEXT ctx; + //memset(&ctx, 0, sizeof(CONTEXT)); + //ctx.ContextFlags = CONTEXT_ALL; + //RtlCaptureContext(&ctx); + + // + //PIMAGE_NT_HEADERS image = (PIMAGE_NT_HEADERS)RtlPcToFileHeader((PVOID)ctx.Rip, &base); + + if (image) + { + //ULONG exception_size; + //IMAGE_RUNTIME_FUNCTION_ENTRY* funcs = (IMAGE_RUNTIME_FUNCTION_ENTRY*) + // ImageDirectoryEntryToData(base, TRUE, + // IMAGE_DIRECTORY_ENTRY_EXCEPTION, &exception_size); + + + PIMAGE_OPTIONAL_HEADER64 optional_header = &image->OptionalHeader; + if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) { + return; + } + + DWORD exception_rva = + optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION] + .VirtualAddress; + + DWORD exception_size = + optional_header->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size; + + IMAGE_RUNTIME_FUNCTION_ENTRY* funcs = (IMAGE_RUNTIME_FUNCTION_ENTRY*)(module.BaseOfImage + exception_rva); + + //auto funcs = (PIMAGE_RUNTIME_FUNCTION_ENTRY)ImageRvaToVa(image, h, exception_rva, NULL); + ////auto funcs = (PIMAGE_RUNTIME_FUNCTION_ENTRY)RvaToVa(exception_rva); + //if (!funcs) { + // return; + //} + + DWORD count = exception_size / sizeof(IMAGE_RUNTIME_FUNCTION_ENTRY); + + for (DWORD i = 0; i < count; i++) + { + IMAGE_RUNTIME_FUNCTION_ENTRY entry = funcs[i]; + //PVOID va = ImageRvaToVa(image, base, entry.BeginAddress, NULL); + PVOID va = (PVOID)(module.BaseOfImage + entry.BeginAddress); + + wprintf(L" %2d: %.08X:%.08X -- %.08llX ", i, entry.BeginAddress, entry.UnwindData, (ULONG64)va); + + if (sym_initialized) + { + print_symbol(hp, (DWORD64)va); + } + + printf("\n"); + + if ((entry.UnwindData & 0x03) == 0) + { + PVOID va = (PVOID)(module.BaseOfImage + entry.UnwindData); + dump_xdata(va); + } + } + } + + printf("\n"); + + if (sym_initialized) + SymCleanup(hp); +} + +void level4(void) +{ + list_pdata(); + walk_stack_rtl(); +} +void level3(void) { level4(); } +void level2(void) { level3(); } +void level1(void) { level2(); } + + +void pdata_test() +{ + level1(); + printf("ok\n"); +} diff --git a/tests/pdata_test.cpp b/tests/pdata_test.cpp new file mode 100644 index 000000000..2f6668e73 --- /dev/null +++ b/tests/pdata_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void pdata_test(); + +TEST(Aarch64MinGW, PDATATest) +{ + pdata_test(); +} + + diff --git a/tests/sjlj_test.c b/tests/sjlj_test.c new file mode 100644 index 000000000..1681b1fa4 --- /dev/null +++ b/tests/sjlj_test.c @@ -0,0 +1,27 @@ +#include +#include +#include +#include + +static jmp_buf env; + +int jumper(int val) +{ + printf("jumper\n"); + longjmp(env, val); +} + +void sjlj_test() +{ + int val = setjmp(env); + + if (val==0) + { + printf("setjmp %d\n", val); + jumper(99); + } + else + { + printf("setjmp %d\n", val); + } +} \ No newline at end of file diff --git a/tests/sjlj_test.cpp b/tests/sjlj_test.cpp new file mode 100644 index 000000000..fa81c328a --- /dev/null +++ b/tests/sjlj_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void sjlj_test(); + +TEST(Aarch64MinGW, SJLJTest) +{ + sjlj_test(); +} + + diff --git a/tests/struct_test.c b/tests/struct_test.c new file mode 100644 index 000000000..97291a1ea --- /dev/null +++ b/tests/struct_test.c @@ -0,0 +1,42 @@ +/* + Tests data in a structure is addressed correctrly +*/ + +#include +#include + +struct aaa +{ + int a; + int b; + int space[2000]; + int c; + int d; +}; + +struct bbb +{ + int space[2000]; + int a; + int b; + int c; + int d; +}; + +void copy_parts(struct aaa *a, struct bbb *b) +{ + b->a = a->a; + b->b = a->b; + b->c = a->c; + b->d = a->d; +} + +void struct_test() +{ + struct aaa a = { 11, 22, { 0 }, 33, 44 }; + struct bbb *b = (struct bbb*)malloc(sizeof(struct bbb)); + + copy_parts(&a, b); + printf("result %d %d %d %d\n", b->a, b->b, b->c, b->d); + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/struct_test.cpp b/tests/struct_test.cpp new file mode 100644 index 000000000..80bce4c8a --- /dev/null +++ b/tests/struct_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void struct_test(); + +TEST(Aarch64MinGW, StructTest) +{ + struct_test(); +} + + diff --git a/tests/throw_test.cpp b/tests/throw_test.cpp new file mode 100644 index 000000000..254eb5b89 --- /dev/null +++ b/tests/throw_test.cpp @@ -0,0 +1,51 @@ +#include +#include +#include + +#include + +#ifdef __USING_SJLJ_EXCEPTIONS__ +#error "__USING_SJLJ_EXCEPTIONS__ cannot be defined." +#endif + +#ifndef __SEH__ +#error "__SEH__ must be defined." +#endif + +struct scope +{ + scope() + { + printf("construct\n"); + } + + ~scope() + { + printf("destruct\n"); + } +}; + +int throw_func(void) +{ + scope s; + printf("throw-func\n"); + throw 32; +} + +TEST(Aarch64MinGW, ThrowTest) +{ + GTEST_SKIP(); + + printf("main start\n"); + + try + { + throw_func(); + } + catch(...) + { + printf("catch\n"); + } + + printf("ok\n"); +} diff --git a/tests/varargs_test.c b/tests/varargs_test.c new file mode 100644 index 000000000..6928f5afb --- /dev/null +++ b/tests/varargs_test.c @@ -0,0 +1,34 @@ +#include +#include + +static void xprintf(char *buf, size_t length, const char *fmt, ...) +{ + va_list argv; + va_start( argv, fmt ); + register int retval = _vsnprintf( buf, length, fmt, argv ); + va_end( argv ); +} + +static inline __attribute__(( __always_inline__)) void yprintf (const char *format, ...) +{ + printf (format, __builtin_va_arg_pack ()); +} + +void varargs_test() +{ + printf("expected %s %d %x %f\n", "string", 11, 0x1919, 111.111); + + char sz[100]; + sprintf(sz, "sprintf actual %s %d %x %f\n", "string", 11, 0x1919, 111.111); + puts(sz); + + snprintf(sz, 100, "snprintf actual %s %d %x %f\n", "string", 11, 0x1919, 111.111); + puts(sz); + + xprintf(sz, 100, "va_list actual %s %d %x %f\n", "string", 11, 0x1919, 111.111); + puts(sz); + + yprintf("__builtin_va_arg_pack actual %s %d %x %f\n", "string", 11, 0x1919, 111.111); + + printf("ok\n"); +} \ No newline at end of file diff --git a/tests/varargs_test.cpp b/tests/varargs_test.cpp new file mode 100644 index 000000000..fefb591a1 --- /dev/null +++ b/tests/varargs_test.cpp @@ -0,0 +1,10 @@ +#include + +extern "C" void varargs_test(); + +TEST(Aarch64MinGW, VarargsTest) +{ + varargs_test(); +} + + From c96e667efd902d19fc8c754172228a574e5249e5 Mon Sep 17 00:00:00 2001 From: Evgeny Karpov Date: Thu, 16 Nov 2023 17:42:50 +0100 Subject: [PATCH 2/3] * add refactoring --- tests/BUILD.txt | 2 +- tests/CMakeLists.txt | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/BUILD.txt b/tests/BUILD.txt index fbecf7777..c6b6e6faa 100644 --- a/tests/BUILD.txt +++ b/tests/BUILD.txt @@ -1,4 +1,4 @@ -Building aarch64-w64-mingw32 tests on WSL +Building aarch64-w64-mingw32 tests on Linux or WSL cmake -S . -B build cmake --build build diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 0cfdd2af0..b744cc2d4 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,15 +1,15 @@ set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_COMPILER "/home/user/cross/bin/aarch64-w64-mingw32-gcc") +set(CMAKE_C_COMPILER "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-gcc") set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_COMPILER "/home/user/cross/bin/aarch64-w64-mingw32-c++") -set(CMAKE_RANLIB "/home/user/cross/bin/aarch64-w64-mingw32-ranlib") +set(CMAKE_CXX_COMPILER "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-c++") +set(CMAKE_RANLIB "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-ranlib") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fopenmp") include(FetchContent) FetchContent_Declare( googletest - URL https://github.com/google/googletest/archive/03597a01ee50ed33e9dfd640b249b4be3799d395.zip + URL https://github.com/google/googletest/archive/b10fad38c4026a29ea6561ab15fc4818170d1c10.zip ) FetchContent_MakeAvailable(googletest) From 7a01b52f167f3ad762c86551edb5e2245b9db06b Mon Sep 17 00:00:00 2001 From: Evgeny Karpov Date: Mon, 20 Nov 2023 15:30:42 +0100 Subject: [PATCH 3/3] * refactor PR based on reviews --- tests/.gitignore | 1 + tests/BUILD.txt | 4 +- tests/CMakeLists.txt | 52 +++++++++++-------- tests/{bigdata_test.cpp => bigdata-test.cpp} | 0 tests/{dll_test.c => dll-test.c} | 0 tests/{dll_test.cpp => dll-test.cpp} | 0 .../{iostream_test.cpp => iostream-test.cpp} | 0 tests/{math_test.c => math-test.c} | 0 tests/{math_test.cpp => math-test.cpp} | 0 tests/{omp_test.c => omp-test.c} | 0 tests/{omp_test.cpp => omp-test.cpp} | 0 tests/{openblas_test.c => openblas-test.c} | 0 .../{openblas_test.cpp => openblas-test.cpp} | 0 tests/{pdata_test.c => pdata-test.c} | 2 +- tests/{pdata_test.cpp => pdata-test.cpp} | 0 tests/{sjlj_test.c => sjlj-test.c} | 0 tests/{sjlj_test.cpp => sjlj-test.cpp} | 0 tests/{struct_test.c => struct-test.c} | 0 tests/{struct_test.cpp => struct-test.cpp} | 0 tests/{throw_test.cpp => throw-test.cpp} | 0 tests/{varargs_test.c => varargs-test.c} | 0 tests/{varargs_test.cpp => varargs-test.cpp} | 0 22 files changed, 34 insertions(+), 25 deletions(-) create mode 100644 tests/.gitignore rename tests/{bigdata_test.cpp => bigdata-test.cpp} (100%) rename tests/{dll_test.c => dll-test.c} (100%) rename tests/{dll_test.cpp => dll-test.cpp} (100%) rename tests/{iostream_test.cpp => iostream-test.cpp} (100%) rename tests/{math_test.c => math-test.c} (100%) rename tests/{math_test.cpp => math-test.cpp} (100%) rename tests/{omp_test.c => omp-test.c} (100%) rename tests/{omp_test.cpp => omp-test.cpp} (100%) rename tests/{openblas_test.c => openblas-test.c} (100%) rename tests/{openblas_test.cpp => openblas-test.cpp} (100%) rename tests/{pdata_test.c => pdata-test.c} (99%) rename tests/{pdata_test.cpp => pdata-test.cpp} (100%) rename tests/{sjlj_test.c => sjlj-test.c} (100%) rename tests/{sjlj_test.cpp => sjlj-test.cpp} (100%) rename tests/{struct_test.c => struct-test.c} (100%) rename tests/{struct_test.cpp => struct-test.cpp} (100%) rename tests/{throw_test.cpp => throw-test.cpp} (100%) rename tests/{varargs_test.c => varargs-test.c} (100%) rename tests/{varargs_test.cpp => varargs-test.cpp} (100%) diff --git a/tests/.gitignore b/tests/.gitignore new file mode 100644 index 000000000..c795b054e --- /dev/null +++ b/tests/.gitignore @@ -0,0 +1 @@ +build \ No newline at end of file diff --git a/tests/BUILD.txt b/tests/BUILD.txt index c6b6e6faa..633a1de60 100644 --- a/tests/BUILD.txt +++ b/tests/BUILD.txt @@ -3,5 +3,5 @@ Building aarch64-w64-mingw32 tests on Linux or WSL cmake -S . -B build cmake --build build -it generates Arm64 Windows executable -build/aarch64_mingw_tests \ No newline at end of file +It generates Arm64 Windows executable. +build/bin/aarch64_mingw_tests.exe \ No newline at end of file diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b744cc2d4..cdb045591 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -1,10 +1,18 @@ set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_C_COMPILER "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-gcc") + +if (NOT DEFINED ENV{TARGET}) + set(ENV{TARGET} "aarch64-w64-mingw32") +endif() +if (NOT DEFINED ENV{INSTALL_PATH}) + set(ENV{INSTALL_PATH} "$ENV{HOME}/cross") +endif() + +set(CMAKE_C_COMPILER "$ENV{INSTALL_PATH}/bin/$ENV{TARGET}-gcc") set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_STANDARD 14) -set(CMAKE_CXX_COMPILER "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-c++") -set(CMAKE_RANLIB "$ENV{HOME}/cross/bin/aarch64-w64-mingw32-ranlib") +set(CMAKE_CXX_COMPILER "$ENV{INSTALL_PATH}/bin/$ENV{TARGET}-c++") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fopenmp") +set(CMAKE_RANLIB "$ENV{INSTALL_PATH}/bin/$ENV{TARGET}-ranlib") include(FetchContent) FetchContent_Declare( @@ -20,28 +28,28 @@ project(aarch64_mingw_tests) enable_testing() add_executable( - aarch64_mingw_tests - bigdata_test.cpp - iostream_test.cpp - math_test.c - math_test.cpp - omp_test.c - omp_test.cpp - pdata_test.c - pdata_test.cpp - sjlj_test.c - sjlj_test.cpp - struct_test.c - struct_test.cpp - throw_test.cpp - varargs_test.c - varargs_test.cpp + aarch64-mingw-tests.exe + bigdata-test.cpp + iostream-test.cpp + math-test.c + math-test.cpp + omp-test.c + omp-test.cpp + pdata-test.c + pdata-test.cpp + sjlj-test.c + sjlj-test.cpp + struct-test.c + struct-test.cpp + throw-test.cpp + varargs-test.c + varargs-test.cpp ) -set_source_files_properties(test-dll.c PROPERTIES COMPILE_FLAGS "-DIMPORT_API=") - target_link_libraries( - aarch64_mingw_tests + aarch64-mingw-tests.exe GTest::gtest_main dbghelp ) + +set_target_properties(aarch64-mingw-tests.exe PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin") \ No newline at end of file diff --git a/tests/bigdata_test.cpp b/tests/bigdata-test.cpp similarity index 100% rename from tests/bigdata_test.cpp rename to tests/bigdata-test.cpp diff --git a/tests/dll_test.c b/tests/dll-test.c similarity index 100% rename from tests/dll_test.c rename to tests/dll-test.c diff --git a/tests/dll_test.cpp b/tests/dll-test.cpp similarity index 100% rename from tests/dll_test.cpp rename to tests/dll-test.cpp diff --git a/tests/iostream_test.cpp b/tests/iostream-test.cpp similarity index 100% rename from tests/iostream_test.cpp rename to tests/iostream-test.cpp diff --git a/tests/math_test.c b/tests/math-test.c similarity index 100% rename from tests/math_test.c rename to tests/math-test.c diff --git a/tests/math_test.cpp b/tests/math-test.cpp similarity index 100% rename from tests/math_test.cpp rename to tests/math-test.cpp diff --git a/tests/omp_test.c b/tests/omp-test.c similarity index 100% rename from tests/omp_test.c rename to tests/omp-test.c diff --git a/tests/omp_test.cpp b/tests/omp-test.cpp similarity index 100% rename from tests/omp_test.cpp rename to tests/omp-test.cpp diff --git a/tests/openblas_test.c b/tests/openblas-test.c similarity index 100% rename from tests/openblas_test.c rename to tests/openblas-test.c diff --git a/tests/openblas_test.cpp b/tests/openblas-test.cpp similarity index 100% rename from tests/openblas_test.cpp rename to tests/openblas-test.cpp diff --git a/tests/pdata_test.c b/tests/pdata-test.c similarity index 99% rename from tests/pdata_test.c rename to tests/pdata-test.c index 525fa7b08..1b23be9fb 100644 --- a/tests/pdata_test.c +++ b/tests/pdata-test.c @@ -40,7 +40,7 @@ static void print_symbol(HANDLE hp, DWORD64 offset) if (SymGetSymFromAddr64(hp, offset, &dwDisplacement, p)) { - printf(" %s+0x%.04llX", p->Name, dwDisplacement); + // printf(" %s+0x%.04llX", p->Name, dwDisplacement); } else { diff --git a/tests/pdata_test.cpp b/tests/pdata-test.cpp similarity index 100% rename from tests/pdata_test.cpp rename to tests/pdata-test.cpp diff --git a/tests/sjlj_test.c b/tests/sjlj-test.c similarity index 100% rename from tests/sjlj_test.c rename to tests/sjlj-test.c diff --git a/tests/sjlj_test.cpp b/tests/sjlj-test.cpp similarity index 100% rename from tests/sjlj_test.cpp rename to tests/sjlj-test.cpp diff --git a/tests/struct_test.c b/tests/struct-test.c similarity index 100% rename from tests/struct_test.c rename to tests/struct-test.c diff --git a/tests/struct_test.cpp b/tests/struct-test.cpp similarity index 100% rename from tests/struct_test.cpp rename to tests/struct-test.cpp diff --git a/tests/throw_test.cpp b/tests/throw-test.cpp similarity index 100% rename from tests/throw_test.cpp rename to tests/throw-test.cpp diff --git a/tests/varargs_test.c b/tests/varargs-test.c similarity index 100% rename from tests/varargs_test.c rename to tests/varargs-test.c diff --git a/tests/varargs_test.cpp b/tests/varargs-test.cpp similarity index 100% rename from tests/varargs_test.cpp rename to tests/varargs-test.cpp