diff options
author | Nirbheek Chauhan <nirbheek@centricular.com> | 2020-07-01 19:03:53 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek@centricular.com> | 2020-07-01 21:00:22 +0530 |
commit | 02a99ad597d32994ee58d9dfcc354b3a4bb5a6ed (patch) | |
tree | b60abb49010b411bb13439743efc1c72cd07dbbe /recipes/orc | |
parent | 109430d12a12fbca22c98f917c94fdbb73771d6e (diff) |
orc.recipe: Add patches needed for UWP support
These are already merged upstream into origin/master, but we need to
manually patch these to use the 0.4.31 tarball.
Part-of: <https://gitlab.freedesktop.org/gstreamer/cerbero/-/merge_requests/533>
Diffstat (limited to 'recipes/orc')
3 files changed, 431 insertions, 0 deletions
diff --git a/recipes/orc/0001-orc-Implement-a-windows-helper-for-getenv.patch b/recipes/orc/0001-orc-Implement-a-windows-helper-for-getenv.patch new file mode 100644 index 00000000..984312ba --- /dev/null +++ b/recipes/orc/0001-orc-Implement-a-windows-helper-for-getenv.patch @@ -0,0 +1,143 @@ +From e990f2e17a1eb6c195583db15b25dd1bba88dfa9 Mon Sep 17 00:00:00 2001 +From: Nirbheek Chauhan <nirbheek@centricular.com> +Date: Tue, 30 Jun 2020 15:30:35 +0530 +Subject: [PATCH 1/4] orc: Implement a windows helper for getenv() + +On Windows, getenv() is deprecated and does not work in all cases. On +the Universal Windows Platform (UWP) it always returns NULL. Add +a wrapper orc_getenv() that calls GetEnvironmentVariable on Windows. + +Also change semantics to always make a copy before returning. + +Part-of: <https://gitlab.freedesktop.org/gstreamer/orc/-/merge_requests/42> +--- + orc/orc.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + orc/orccompiler.c | 5 +++-- + orc/orcdebug.c | 6 ++++-- + orc/orcinternal.h | 2 ++ + 4 files changed, 51 insertions(+), 4 deletions(-) + +diff --git a/orc/orc.c b/orc/orc.c +index 2acf522..7b4808c 100644 +--- a/orc/orc.c ++++ b/orc/orc.c +@@ -5,6 +5,11 @@ + #include <string.h> + #include <stdlib.h> + ++#ifdef _WIN32 ++#include <windows.h> ++#include <processenv.h> ++#endif ++ + #include <orc/orcprogram.h> + #include <orc/orcdebug.h> + #include <orc/orconce.h> +@@ -83,3 +88,40 @@ orc_version_string (void) + { + return (const char *) VERSION; + } ++ ++/* getenv() is deprecated on Windows and always returns NULL on UWP */ ++#ifdef _WIN32 ++char* ++_orc_getenv (const char *key) ++{ ++ int len; ++ char check[1], *value; ++ ++ /* Get the len */ ++ len = GetEnvironmentVariableA (key, check, 1); ++ if (len == 0) ++ /* env var is not set or is "" (empty string) */ ++ return NULL; ++ ++ /* max size of len is 32767, cannot overflow */ ++ value = malloc (sizeof (value) * len); ++ ++ if (GetEnvironmentVariableA (key, value, len) != (len - 1)) { ++ free (value); ++ return NULL; ++ } ++ ++ return value; ++} ++#else ++char* ++_orc_getenv (const char *key) ++{ ++ char *value = getenv (key); ++ ++ if (value) ++ value = strdup (value); ++ ++ return value; ++} ++#endif +diff --git a/orc/orccompiler.c b/orc/orccompiler.c +index 8d92cbe..de2555d 100644 +--- a/orc/orccompiler.c ++++ b/orc/orccompiler.c +@@ -51,11 +51,12 @@ int _orc_compiler_flag_randomize; + void + _orc_compiler_init (void) + { +- const char *envvar; ++ char *envvar; + +- envvar = getenv ("ORC_CODE"); ++ envvar = _orc_getenv ("ORC_CODE"); + if (envvar != NULL) { + _orc_compiler_flag_list = strsplit (envvar, ','); ++ free (envvar); + } + + _orc_compiler_flag_backup = orc_compiler_flag_check ("backup"); +diff --git a/orc/orcdebug.c b/orc/orcdebug.c +index 2e69464..1cefd07 100644 +--- a/orc/orcdebug.c ++++ b/orc/orcdebug.c +@@ -29,6 +29,7 @@ + #include "config.h" + #endif + #include <orc/orcdebug.h> ++#include <orc/orcinternal.h> + + #include <stdio.h> + #include <string.h> +@@ -55,9 +56,9 @@ static OrcDebugPrintFunc _orc_debug_print_func = orc_debug_print_valist; + void + _orc_debug_init(void) + { +- const char *envvar; ++ char *envvar; + +- envvar = getenv ("ORC_DEBUG"); ++ envvar = _orc_getenv ("ORC_DEBUG"); + if (envvar != NULL) { + char *end = NULL; + int level; +@@ -65,6 +66,7 @@ _orc_debug_init(void) + if (end > envvar) { + _orc_debug_level = level; + } ++ free (envvar); + } + + ORC_INFO ("orc-" VERSION " debug init"); +diff --git a/orc/orcinternal.h b/orc/orcinternal.h +index cd778c3..b86f698 100644 +--- a/orc/orcinternal.h ++++ b/orc/orcinternal.h +@@ -36,6 +36,8 @@ extern const char *_orc_cpu_name; + + void orc_compiler_emit_invariants (OrcCompiler *compiler); + int orc_program_has_float (OrcCompiler *compiler); ++ ++char* _orc_getenv (const char *var); + #endif + + ORC_END_DECLS +-- +2.26.2 + diff --git a/recipes/orc/0002-orccodemem-Add-support-for-Universal-Windows-Platfor.patch b/recipes/orc/0002-orccodemem-Add-support-for-Universal-Windows-Platfor.patch new file mode 100644 index 00000000..26174fa2 --- /dev/null +++ b/recipes/orc/0002-orccodemem-Add-support-for-Universal-Windows-Platfor.patch @@ -0,0 +1,213 @@ +From cd8eabf041a14b5cdcc13c5436dbccdd66d558bb Mon Sep 17 00:00:00 2001 +From: Nirbheek Chauhan <nirbheek@centricular.com> +Date: Tue, 30 Jun 2020 16:16:39 +0530 +Subject: [PATCH 2/4] orccodemem: Add support for Universal Windows Platform + apps + +VirtualAlloc is VirtualAllocFromApp when targeting UWP, and you can +only allocate executable pages if you have the codeGeneration +capability set in the app manifest. Check for that capability in +_orc_compiler_init() and switch to backup code or emulation if it +isn't available instead of crashing when VirtualAllocFromApp +returns NULL. + +Also you cannot allocate pages that are both READWRITE and EXECUTE, so +we allocate as read-write first, then set the memory as execute-only +after the code has been compiled and copied over. + +Part-of: <https://gitlab.freedesktop.org/gstreamer/orc/-/merge_requests/42> +--- + meson.build | 10 ++++++ + orc/orccodemem.c | 12 ++++++- + orc/orccompiler.c | 91 +++++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 112 insertions(+), 1 deletion(-) + +diff --git a/meson.build b/meson.build +index c4d955b..eeb3f17 100644 +--- a/meson.build ++++ b/meson.build +@@ -94,6 +94,16 @@ if host_os == 'windows' + cdata.set('HAVE_CODEMEM_VIRTUALALLOC', true) + cdata.set('HAVE_OS_WIN32', true) + cdata.set('HAVE_THREAD_WIN32', true) ++ ++ code = ''' ++ #include <windows.h> ++ #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)) ++ #error "Not building for UWP" ++ #endif''' ++ if cc.compiles(code, name : 'building for UWP') ++ cdata.set('ORC_WINAPI_ONLY_APP', true) ++ endif ++ + pc_conf.set('EXEEXT', '.exe') + pc_conf.set('PTHREAD_LIBS', '') + else +diff --git a/orc/orccodemem.c b/orc/orccodemem.c +index 14aadbd..0081835 100644 +--- a/orc/orccodemem.c ++++ b/orc/orccodemem.c +@@ -11,11 +11,18 @@ + #include <sys/types.h> + #include <sys/stat.h> + #include <fcntl.h> ++ + #ifdef HAVE_CODEMEM_MMAP + #include <sys/mman.h> + #endif ++ + #ifdef HAVE_CODEMEM_VIRTUALALLOC + #include <windows.h> ++ #ifdef ORC_WINAPI_ONLY_APP ++ #define _virtualalloc VirtualAllocFromApp ++ #else ++ #define _virtualalloc VirtualAlloc ++ #endif + #endif + + #include <orc/orcinternal.h> +@@ -299,7 +306,10 @@ orc_code_region_allocate_codemem (OrcCodeRegion *region) + void + orc_code_region_allocate_codemem (OrcCodeRegion *region) + { +- region->write_ptr = VirtualAlloc(NULL, SIZE, MEM_COMMIT, PAGE_EXECUTE_READWRITE); ++ /* On UWP, we can't allocate memory as executable from the start. We can only ++ * set that later after compiling and copying the code over. This is a good ++ * idea in general to avoid security issues, so we do it on win32 too. */ ++ region->write_ptr = _virtualalloc (NULL, SIZE, MEM_COMMIT, PAGE_READWRITE); + region->exec_ptr = region->write_ptr; + region->size = SIZE; + } +diff --git a/orc/orccompiler.c b/orc/orccompiler.c +index de2555d..600e66b 100644 +--- a/orc/orccompiler.c ++++ b/orc/orccompiler.c +@@ -6,6 +6,15 @@ + #include <stdlib.h> + #include <stdarg.h> + ++#if defined(HAVE_CODEMEM_VIRTUALALLOC) ++#include <windows.h> ++ #ifdef ORC_WINAPI_ONLY_APP ++ #define _virtualprotect VirtualProtectFromApp ++ #else ++ #define _virtualprotect VirtualProtect ++ #endif ++#endif ++ + #include <orc/orcprogram.h> + #include <orc/orcdebug.h> + #include <orc/orcinternal.h> +@@ -63,6 +72,38 @@ _orc_compiler_init (void) + _orc_compiler_flag_emulate = orc_compiler_flag_check ("emulate"); + _orc_compiler_flag_debug = orc_compiler_flag_check ("debug"); + _orc_compiler_flag_randomize = orc_compiler_flag_check ("randomize"); ++ ++#if defined(HAVE_CODEMEM_VIRTUALALLOC) && defined(ORC_WINAPI_ONLY_APP) ++ if (!_orc_compiler_flag_backup && !_orc_compiler_flag_emulate) { ++ int can_jit = FALSE; ++ size_t page_size; ++ SYSTEM_INFO info; ++ GetNativeSystemInfo(&info); ++ ++ page_size = info.dwPageSize; ++ /* If backup code is not enabled and emulation is not enabled, that means ++ * we will do JIT compilation and call orc_code_region_allocate_codemem(). ++ * When targeting Windows Store apps, the codeGeneration capability must ++ * be enabled in the app manifest, or passing PAGE_EXECUTE to ++ * VirtualProtectFromApp will return NULL. In this case, we must force ++ * backup C code, and if that's not available, we must emulate. */ ++ void *mem = VirtualAllocFromApp (NULL, page_size, MEM_COMMIT, ++ PAGE_READWRITE); ++ if (mem) { ++ int old_protect; ++ if (VirtualProtectFromApp (mem, page_size, PAGE_EXECUTE, &old_protect) > 0) ++ can_jit = TRUE; ++ VirtualFree (mem, 0, MEM_RELEASE); ++ } ++ ++ if (!can_jit) { ++ ORC_WARNING ("Unable to allocate executable pages: using backup code or " ++ "emulation: codeGeneration capability isn't set in the app manifest?"); ++ _orc_compiler_flag_backup = TRUE; ++ _orc_compiler_flag_emulate = TRUE; ++ } ++ } ++#endif + } + + int +@@ -175,6 +216,44 @@ orc_program_compile_for_target (OrcProgram *program, OrcTarget *target) + return orc_program_compile_full (program, target, flags); + } + ++#if defined(HAVE_CODEMEM_VIRTUALALLOC) ++static const char* ++_get_protect_name (int protect) ++{ ++ switch (protect) { ++ /* These are the only two memory protection constants we use */ ++ case PAGE_EXECUTE: ++ return "execute"; ++ case PAGE_READWRITE: ++ return "readwrite"; ++ default: ++ return "unknown"; ++ } ++} ++ ++static orc_bool ++_set_virtual_protect (void * mem, size_t size, int code_protect) ++{ ++ char *msg; ++ DWORD old_protect; ++ ++ if (!mem) ++ return FALSE; ++ ++ if (_virtualprotect (mem, size, code_protect, &old_protect) > 0) ++ return TRUE; ++ ++ FormatMessageA (FORMAT_MESSAGE_ALLOCATE_BUFFER ++ | FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ++ GetLastError (), 0, (LPTSTR) &msg, 0, NULL); ++ ORC_ERROR ("Couldn't set memory protect on %p from %s to %s: %s", mem, ++ _get_protect_name (old_protect), _get_protect_name (code_protect), msg); ++ LocalFree (msg); ++ ++ return FALSE; ++} ++#endif ++ + /** + * orc_program_compile_full: + * @program: the OrcProgram to compile +@@ -360,6 +439,11 @@ orc_program_compile_full (OrcProgram *program, OrcTarget *target, + program->orccode->code_size = compiler->codeptr - compiler->code; + orc_code_allocate_codemem (program->orccode, program->orccode->code_size); + ++#if defined(HAVE_CODEMEM_VIRTUALALLOC) ++ /* Ensure that code region is writable before memcpy */ ++ _set_virtual_protect (program->orccode->code, program->orccode->code_size, ++ PAGE_READWRITE); ++#endif + memcpy (program->orccode->code, compiler->code, program->orccode->code_size); + + #ifdef VALGRIND_DISCARD_TRANSLATIONS +@@ -371,6 +455,13 @@ orc_program_compile_full (OrcProgram *program, OrcTarget *target, + compiler->target->flush_cache (program->orccode); + } + ++#if defined(HAVE_CODEMEM_VIRTUALALLOC) ++ /* Code region is now ready for execution */ ++ if (!_set_virtual_protect (program->orccode->exec, program->orccode->code_size, ++ PAGE_EXECUTE)) ++ /* Can't set code as executable, force emulation */ ++ program->orccode->exec = (void *)orc_executor_emulate; ++#endif + program->code_exec = program->orccode->exec; + + program->asm_code = compiler->asm_code; +-- +2.26.2 + diff --git a/recipes/orc/0003-orc-Fix-some-warnings-on-MSVC-and-enable-werror.patch b/recipes/orc/0003-orc-Fix-some-warnings-on-MSVC-and-enable-werror.patch new file mode 100644 index 00000000..2c68fec0 --- /dev/null +++ b/recipes/orc/0003-orc-Fix-some-warnings-on-MSVC-and-enable-werror.patch @@ -0,0 +1,75 @@ +From 408e7fa36fbc46e128b680d7b7bf49f694c1aee0 Mon Sep 17 00:00:00 2001 +From: Nirbheek Chauhan <nirbheek@centricular.com> +Date: Tue, 30 Jun 2020 17:12:54 +0530 +Subject: [PATCH 3/4] orc: Fix some warnings on MSVC and enable --werror + +Part-of: <https://gitlab.freedesktop.org/gstreamer/orc/-/merge_requests/42> +--- + .gitlab-ci.yml | 4 ++-- + examples/example2.c | 2 +- + orc/orcemulateopcodes.c | 4 ++-- + testsuite/memcpy_speed.c | 6 +++--- + 4 files changed, 8 insertions(+), 8 deletions(-) + +diff --git a/examples/example2.c b/examples/example2.c +index c2d03e4..8382771 100644 +--- a/examples/example2.c ++++ b/examples/example2.c +@@ -21,7 +21,7 @@ main (int argc, char *argv[]) + } + + /* Call a function that uses Orc */ +- audio_add_mono_to_stereo_scaled_s16 (c, a, b, volume*4096, N); ++ audio_add_mono_to_stereo_scaled_s16 (c, a, b, (int) (volume*4096), N); + + /* Print the results */ + for(i=0;i<N;i++){ +diff --git a/orc/orcemulateopcodes.c b/orc/orcemulateopcodes.c +index a0f1aa8..ff09dd2 100644 +--- a/orc/orcemulateopcodes.c ++++ b/orc/orcemulateopcodes.c +@@ -4896,7 +4896,7 @@ emulate_convlf (OrcOpcodeExecutor *ex, int offset, int n) + /* 0: loadl */ + var32 = ptr4[i]; + /* 1: convlf */ +- var33.f = var32.i; ++ var33.f = (float) var32.i; + /* 2: storel */ + ptr0[i] = var33; + } +@@ -5279,7 +5279,7 @@ emulate_convdl (OrcOpcodeExecutor *ex, int offset, int n) + /* 1: convdl */ + { + int tmp; +- tmp = var32.f; ++ tmp = (int) var32.f; + if (tmp == 0x80000000 && !(var32.i & ORC_UINT64_C(0x8000000000000000))) tmp = 0x7fffffff; + var33.i = tmp; + } +diff --git a/testsuite/memcpy_speed.c b/testsuite/memcpy_speed.c +index 4cf1c39..9f4f247 100644 +--- a/testsuite/memcpy_speed.c ++++ b/testsuite/memcpy_speed.c +@@ -95,16 +95,16 @@ main(int argc, char *argv[]) + #endif + orc_get_data_cache_sizes (&level1, &level2, &level3); + if (level3 > 0) { +- max = (log(level3)/M_LN2 - 6.0) * 10 + 20; ++ max = (int) ((log(level3)/M_LN2 - 6.0) * 10 + 20); + } else if (level2 > 0) { +- max = (log(level2)/M_LN2 - 6.0) * 10 + 20; ++ max = (int) ((log(level2)/M_LN2 - 6.0) * 10 + 20); + } else { + max = 140; + } + + for(i=0;i<max;i+=2){ + double x = i*0.1 + 6.0; +- int size = pow(2.0, x); ++ int size = (int) pow(2.0, x); + + if (size > MAX_SIZE_TO_CHECK) { + printf ("Stopping test, exceeding maximum size to check (%d, could do above %d)\n", +-- +2.26.2 + |