diff --git a/src/runtime_asan.js b/src/runtime_asan.js index dd32df2aab2b7..d6e522c2d41b7 100644 --- a/src/runtime_asan.js +++ b/src/runtime_asan.js @@ -8,111 +8,22 @@ #error "should only be inclded in USE_ASAN mode" #endif -// C versions of asan_js_{load|store}_* will be used from compiled code, which have +// C versions of asan_js_{load|store} will be used from compiled code, which have // ASan instrumentation on them. However, until the wasm module is ready, we // must access things directly. -/** @suppress{duplicate} */ -function _asan_js_load_1(ptr) { - if (runtimeInitialized) return __asan_c_load_1(ptr); - return HEAP8[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_1u(ptr) { - if (runtimeInitialized) return __asan_c_load_1u(ptr); - return HEAPU8[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_2(ptr) { - if (runtimeInitialized) return __asan_c_load_2(ptr); - return HEAP16[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_2u(ptr) { - if (runtimeInitialized) return __asan_c_load_2u(ptr); - return HEAPU16[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_4(ptr) { - if (runtimeInitialized) return __asan_c_load_4(ptr); - return HEAP32[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_4u(ptr) { - if (runtimeInitialized) return __asan_c_load_4u(ptr) >>> 0; - return HEAPU32[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_8(ptr) { - if (runtimeInitialized) return __asan_c_load_8(ptr); - return HEAP64[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_8u(ptr) { - if (runtimeInitialized) return BigInt.asUintN(64, __asan_c_load_8u(ptr)); - return HEAPU64[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_f(ptr) { - if (runtimeInitialized) return __asan_c_load_f(ptr); - return HEAPF32[ptr]; -} -/** @suppress{duplicate} */ -function _asan_js_load_d(ptr) { - if (runtimeInitialized) return __asan_c_load_d(ptr); - return HEAPF64[ptr]; +function _asan_js_load(arr, index) { + if (runtimeInitialized) { + const elemSize = arr.BYTES_PER_ELEMENT; + ___asan_loadN(index * elemSize, elemSize); + } + return arr[index]; } -/** @suppress{duplicate} */ -function _asan_js_store_1(ptr, val) { - if (runtimeInitialized) return __asan_c_store_1(ptr, val); - return HEAP8[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_1u(ptr, val) { - if (runtimeInitialized) return __asan_c_store_1u(ptr, val); - return HEAPU8[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_2(ptr, val) { - if (runtimeInitialized) return __asan_c_store_2(ptr, val); - return HEAP16[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_2u(ptr, val) { - if (runtimeInitialized) return __asan_c_store_2u(ptr, val); - return HEAPU16[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_4(ptr, val) { - if (runtimeInitialized) return __asan_c_store_4(ptr, val); - return HEAP32[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_4u(ptr, val) { - if (runtimeInitialized) return __asan_c_store_4u(ptr, val) >>> 0; - return HEAPU32[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_8(ptr, val) { - if (runtimeInitialized) return __asan_c_store_8(ptr, val); - return HEAP64[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_8u(ptr, val) { +function _asan_js_store(arr, index, value) { if (runtimeInitialized) { - __asan_c_store_8u(ptr, val); - return val; + const elemSize = arr.BYTES_PER_ELEMENT; + ___asan_storeN(index * elemSize, elemSize); } - return HEAPU64[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_f(ptr, val) { - if (runtimeInitialized) return __asan_c_store_f(ptr, val); - return HEAPF32[ptr] = val; -} -/** @suppress{duplicate} */ -function _asan_js_store_d(ptr, val) { - if (runtimeInitialized) return __asan_c_store_d(ptr, val); - return HEAPF64[ptr] = val; + return arr[index] = value; } diff --git a/system/lib/asan_js.c b/system/lib/asan_js.c deleted file mode 100644 index a349270479ea6..0000000000000 --- a/system/lib/asan_js.c +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2020 The Emscripten Authors. All rights reserved. - * Emscripten is available under two separate licenses, the MIT license and the - * University of Illinois/NCSA Open Source License. Both these licenses can be - * found in the LICENSE file. - */ - -// Helper functions for JavaScript: JS calls these to do memory operations, and -// we get ASan coverage that way (as we can't see direct typed array view access -// in JS). - -#include -#include - -// Note that we receive *shifted* values here. That is, -// -// HEAP32[x >> 2] -// -// is turned into -// -// _asan_c_load_4(x >> 2); -// -// and therefore we must shift to get the actual pointer. Doing it this way -// lets us behave the same as JS would wrt shifts and alignment. - -int32_t _asan_c_load_1(int8_t* ptr) { - return *ptr; -} -uint32_t _asan_c_load_1u(uint8_t* ptr) { - return *ptr; -} -int32_t _asan_c_load_2(uintptr_t shifted) { - int16_t* ptr = (int16_t*)(shifted << 1); - return *ptr; -} -uint32_t _asan_c_load_2u(uintptr_t shifted) { - uint16_t* ptr = (uint16_t*)(shifted << 1); - return *ptr; -} -int32_t _asan_c_load_4(uintptr_t shifted) { - int32_t* ptr = (int32_t*)(shifted << 2); - return *ptr; -} -uint32_t _asan_c_load_4u(uintptr_t shifted) { - uint32_t* ptr = (uint32_t*)(shifted << 2); - return *ptr; -} -int64_t _asan_c_load_8(uintptr_t shifted) { - int64_t* ptr = (int64_t*)(shifted << 3); - return *ptr; -} -uint64_t _asan_c_load_8u(uintptr_t shifted) { - uint64_t* ptr = (uint64_t*)(shifted << 3); - return *ptr; -} -float _asan_c_load_f(uintptr_t shifted) { - float* ptr = (float*)(shifted << 2); - return *ptr; -} -double _asan_c_load_d(uintptr_t shifted) { - double* ptr = (double*)(shifted << 3); - return *ptr; -} - -// Note that the stores return the value, which is what JS does, as you can -// do -// x = HEAP32[..] = val; -int32_t _asan_c_store_1(int8_t* ptr, int8_t val) { - return *ptr = val; -} -uint32_t _asan_c_store_1u(uint8_t* ptr, uint8_t val) { - return *ptr = val; -} -int32_t _asan_c_store_2(uintptr_t shifted, int16_t val) { - int16_t* ptr = (int16_t*)(shifted << 1); - return *ptr = val; -} -uint32_t _asan_c_store_2u(uintptr_t shifted, uint16_t val) { - uint16_t* ptr = (uint16_t*)(shifted << 1); - return *ptr = val; -} -int32_t _asan_c_store_4(uintptr_t shifted, int32_t val) { - int32_t* ptr = (int32_t*)(shifted << 2); - return *ptr = val; -} -uint32_t _asan_c_store_4u(uintptr_t shifted, uint32_t val) { - uint32_t* ptr = (uint32_t*)(shifted << 2); - return *ptr = val; -} -int64_t _asan_c_store_8(uintptr_t shifted, int64_t val) { - int64_t* ptr = (int64_t*)(shifted << 3); - return *ptr = val; -} -uint64_t _asan_c_store_8u(uintptr_t shifted, uint64_t val) { - uint64_t* ptr = (uint64_t*)(shifted << 3); - return *ptr = val; -} -float _asan_c_store_f(uintptr_t shifted, float val) { - float* ptr = (float*)(shifted << 2); - return *ptr = val; -} -double _asan_c_store_d(uintptr_t shifted, double val) { - double* ptr = (double*)(shifted << 3); - return *ptr = val; -} diff --git a/test/js_optimizer/asanify-output.js b/test/js_optimizer/asanify-output.js index 6308bf7e8afc8..2c196180a3c3b 100644 --- a/test/js_optimizer/asanify-output.js +++ b/test/js_optimizer/asanify-output.js @@ -1,57 +1,57 @@ -_asan_js_store_1(x, 1); +_asan_js_store(HEAP8, x, 1); -_asan_js_store_2(x, 2); +_asan_js_store(HEAP16, x, 2); -_asan_js_store_4(x, 3); +_asan_js_store(HEAP32, x, 3); -_asan_js_store_1u(x, 4); +_asan_js_store(HEAPU8, x, 4); -_asan_js_store_2u(x, 5); +_asan_js_store(HEAPU16, x, 5); -_asan_js_store_4u(x, 6); +_asan_js_store(HEAPU32, x, 6); -_asan_js_store_f(x, 7); +_asan_js_store(HEAPF32, x, 7); -_asan_js_store_d(x, 8); +_asan_js_store(HEAPF64, x, 8); -_asan_js_store_8(x, 9n); +_asan_js_store(HEAP64, x, 9n); -_asan_js_store_8u(x, 10n); +_asan_js_store(HEAPU64, x, 10n); -a1 = _asan_js_load_1(x); +a1 = _asan_js_load(HEAP8, x); -a2 = _asan_js_load_2(x); +a2 = _asan_js_load(HEAP16, x); -a3 = _asan_js_load_4(x); +a3 = _asan_js_load(HEAP32, x); -a4 = _asan_js_load_1u(x); +a4 = _asan_js_load(HEAPU8, x); -a5 = _asan_js_load_2u(x); +a5 = _asan_js_load(HEAPU16, x); -a6 = _asan_js_load_4u(x); +a6 = _asan_js_load(HEAPU32, x); -a7 = _asan_js_load_f(x); +a7 = _asan_js_load(HEAPF32, x); -a8 = _asan_js_load_d(x); +a8 = _asan_js_load(HEAPF64, x); -a9 = _asan_js_load_8(x); +a9 = _asan_js_load(HEAP64, x); -a10 = _asan_js_load_8u(x); +a10 = _asan_js_load(HEAPU64, x); -foo = _asan_js_store_1u(1337, 42); +foo = _asan_js_store(HEAPU8, 1337, 42); -_asan_js_load_2(bar(_asan_js_load_d(5))); +_asan_js_load(HEAP16, bar(_asan_js_load(HEAPF64, 5))); -_asan_js_store_f(x, _asan_js_load_4(y)); +_asan_js_store(HEAPF32, x, _asan_js_load(HEAP32, y)); -function _asan_js_load_1(ptr) { +function _asan_js_load(ptr) { return HEAP8[ptr]; } function somethingElse() { - return _asan_js_load_1(ptr); + return _asan_js_load(HEAP8, ptr); } HEAP8.length; -_asan_js_load_1(length); +_asan_js_load(HEAP8, length); diff --git a/test/js_optimizer/asanify.js b/test/js_optimizer/asanify.js index bba03a1d5da90..30e4b3951ad69 100644 --- a/test/js_optimizer/asanify.js +++ b/test/js_optimizer/asanify.js @@ -37,7 +37,7 @@ HEAPF32[x] = HEAP32[y]; // access in these functions, as then we'd get infinite recursion - this is // where we do actually need to still do a HEAP8[..] etc. operation without // any ASan instrumentation. -function _asan_js_load_1(ptr) { +function _asan_js_load(ptr) { return HEAP8[ptr]; } diff --git a/tools/acorn-optimizer.mjs b/tools/acorn-optimizer.mjs index 379412e20349f..47a0cf465f16d 100755 --- a/tools/acorn-optimizer.mjs +++ b/tools/acorn-optimizer.mjs @@ -1474,49 +1474,7 @@ function asanify(ast) { c(value); if (isHEAPAccess(target)) { // Instrument a store. - const ptr = target.property; - switch (target.object.name) { - case 'HEAP8': { - makeCallExpression(node, '_asan_js_store_1', [ptr, value]); - break; - } - case 'HEAPU8': { - makeCallExpression(node, '_asan_js_store_1u', [ptr, value]); - break; - } - case 'HEAP16': { - makeCallExpression(node, '_asan_js_store_2', [ptr, value]); - break; - } - case 'HEAPU16': { - makeCallExpression(node, '_asan_js_store_2u', [ptr, value]); - break; - } - case 'HEAP32': { - makeCallExpression(node, '_asan_js_store_4', [ptr, value]); - break; - } - case 'HEAPU32': { - makeCallExpression(node, '_asan_js_store_4u', [ptr, value]); - break; - } - case 'HEAP64': { - makeCallExpression(node, '_asan_js_store_8', [ptr, value]); - break; - } - case 'HEAPU64': { - makeCallExpression(node, '_asan_js_store_8u', [ptr, value]); - break; - } - case 'HEAPF32': { - makeCallExpression(node, '_asan_js_store_f', [ptr, value]); - break; - } - case 'HEAPF64': { - makeCallExpression(node, '_asan_js_store_d', [ptr, value]); - break; - } - } + makeCallExpression(node, '_asan_js_store', [target.object, target.property, value]); } else { c(target); } @@ -1527,49 +1485,7 @@ function asanify(ast) { c(node.object); } else { // Instrument a load. - const ptr = node.property; - switch (node.object.name) { - case 'HEAP8': { - makeCallExpression(node, '_asan_js_load_1', [ptr]); - break; - } - case 'HEAPU8': { - makeCallExpression(node, '_asan_js_load_1u', [ptr]); - break; - } - case 'HEAP16': { - makeCallExpression(node, '_asan_js_load_2', [ptr]); - break; - } - case 'HEAPU16': { - makeCallExpression(node, '_asan_js_load_2u', [ptr]); - break; - } - case 'HEAP32': { - makeCallExpression(node, '_asan_js_load_4', [ptr]); - break; - } - case 'HEAPU32': { - makeCallExpression(node, '_asan_js_load_4u', [ptr]); - break; - } - case 'HEAP64': { - makeCallExpression(node, '_asan_js_load_8', [ptr]); - break; - } - case 'HEAPU64': { - makeCallExpression(node, '_asan_js_load_8u', [ptr]); - break; - } - case 'HEAPF32': { - makeCallExpression(node, '_asan_js_load_f', [ptr]); - break; - } - case 'HEAPF64': { - makeCallExpression(node, '_asan_js_load_d', [ptr]); - break; - } - } + makeCallExpression(node, '_asan_js_load', [node.object, node.property]); } }, }); diff --git a/tools/emscripten.py b/tools/emscripten.py index eac5c5a446996..77d4d5ffde65b 100644 --- a/tools/emscripten.py +++ b/tools/emscripten.py @@ -40,18 +40,7 @@ # helper functions for JS to call into C to do memory operations. these # let us sanitize memory access from the JS side, by calling into C where # it has been instrumented. -ASAN_C_HELPERS = [ - '_asan_c_load_1', '_asan_c_load_1u', - '_asan_c_load_2', '_asan_c_load_2u', - '_asan_c_load_4', '_asan_c_load_4u', - '_asan_c_load_8', '_asan_c_load_8u', - '_asan_c_load_f', '_asan_c_load_d', - '_asan_c_store_1', '_asan_c_store_1u', - '_asan_c_store_2', '_asan_c_store_2u', - '_asan_c_store_4', '_asan_c_store_4u', - '_asan_c_store_8', '_asan_c_store_8u', - '_asan_c_store_f', '_asan_c_store_d', -] +ASAN_C_HELPERS = ['__asan_loadN', '__asan_storeN'] def maybe_disable_filesystem(imports): @@ -1178,7 +1167,7 @@ def create_pointer_conversion_wrappers(metadata): mapping[sym] = sig for f in ASAN_C_HELPERS: - mapping[f] = '_p' + mapping[f] = '_pp' wrappers = ''' // Argument name here must shadow the `wasmExports` global so diff --git a/tools/link.py b/tools/link.py index 60874b5aa4041..eb6ec23fa79ae 100644 --- a/tools/link.py +++ b/tools/link.py @@ -1608,7 +1608,7 @@ def limit_incoming_module_api(): # do anything (as the user's list won't contain these functions), and if # we did add them, the pass would assert on incompatible lists, hence the # condition in the above if. - settings.ASYNCIFY_REMOVE += emscripten.ASAN_C_HELPERS + settings.ASYNCIFY_REMOVE.append("__asan_*") if settings.ASAN_SHADOW_SIZE != -1: diagnostics.warning('emcc', 'ASAN_SHADOW_SIZE is ignored and will be removed in a future release') diff --git a/tools/system_libs.py b/tools/system_libs.py index c02556f518a02..ded959c84562f 100644 --- a/tools/system_libs.py +++ b/tools/system_libs.py @@ -2149,16 +2149,6 @@ class libasan_rt(SanitizerLibrary): src_dir = 'system/lib/compiler-rt/lib/asan' -class libasan_js(Library): - name = 'libasan_js' - never_force = True - - cflags = ['-fsanitize=address'] - - src_dir = 'system/lib' - src_files = ['asan_js.c'] - - # This library is used when STANDALONE_WASM is set. In that mode, we don't # want to depend on JS, and so this library contains implementations of # things that we'd normally do in JS. That includes some general things @@ -2336,7 +2326,6 @@ def add_sanitizer_libs(): if settings.USE_ASAN: force_include.append('libasan_rt') add_library('libasan_rt') - add_library('libasan_js') elif settings.USE_LSAN: force_include.append('liblsan_rt') add_library('liblsan_rt')