diff --git a/clients/drcachesim/tests/offline-syscall-mmap-aarch64.templatex b/clients/drcachesim/tests/offline-syscall-mmap-aarch64.templatex new file mode 100644 index 00000000000..1bdd4965302 --- /dev/null +++ b/clients/drcachesim/tests/offline-syscall-mmap-aarch64.templatex @@ -0,0 +1,13 @@ +Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) +Output format: +<--record#-> <--instr#->: <---tid---> +------------------------------------------------------------ +.* + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ +.* diff --git a/clients/drcachesim/tests/offline-syscall-mmap-x86-32.templatex b/clients/drcachesim/tests/offline-syscall-mmap-x86-32.templatex new file mode 100644 index 00000000000..8b8386e5f9e --- /dev/null +++ b/clients/drcachesim/tests/offline-syscall-mmap-x86-32.templatex @@ -0,0 +1,13 @@ +Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) +Output format: +<--record#-> <--instr#->: <---tid---> +------------------------------------------------------------ +.* + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ +.* diff --git a/clients/drcachesim/tests/offline-syscall-mmap-x86-64.templatex b/clients/drcachesim/tests/offline-syscall-mmap-x86-64.templatex new file mode 100644 index 00000000000..29228f89c8c --- /dev/null +++ b/clients/drcachesim/tests/offline-syscall-mmap-x86-64.templatex @@ -0,0 +1,13 @@ +Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) +Output format: +<--record#-> <--instr#->: <---tid---> +------------------------------------------------------------ +.* + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ + +[0-9]+ +[0-9]+: +[0-9]+ +.* diff --git a/ext/drreg/drreg.c b/ext/drreg/drreg.c index f8ff39e0840..8f532fbca00 100644 --- a/ext/drreg/drreg.c +++ b/ext/drreg/drreg.c @@ -486,6 +486,11 @@ drreg_insert_restore_all(void *drcontext, instrlist_t *bb, instr_t *inst, (instr_is_label(inst) && ((ptr_uint_t)instr_get_note(inst) == DR_NOTE_ANNOTATION || (ptr_uint_t)instr_get_note(inst) == DR_NOTE_REG_BARRIER)) || + /* i#6417: in case of a syscall, restore the values of registers since + * they may be used as input parameters for the kernel. For example, + * ECX is used to store the length for mmap2. + */ + instr_is_syscall(inst) || /* DR slots are not guaranteed across app instrs */ (pt->aflags.slot != MAX_SPILLS && pt->aflags.slot >= (int)ops.num_spill_slots))) { @@ -531,6 +536,11 @@ drreg_insert_restore_all(void *drcontext, instrlist_t *bb, instr_t *inst, (instr_is_label(inst) && ((ptr_uint_t)instr_get_note(inst) == DR_NOTE_ANNOTATION || (ptr_uint_t)instr_get_note(inst) == DR_NOTE_REG_BARRIER)) || + /* i#6417: in case of a syscall, restore the values of registers since + * they may be used as input parameters for the kernel. For example, + * ECX is used to store the length for mmap2. + */ + instr_is_syscall(inst) || /* Treat a partial write as a read, to restore rest of reg */ (instr_writes_to_reg(inst, reg, DR_QUERY_INCLUDE_ALL) && !instr_writes_to_exact_reg(inst, reg, DR_QUERY_INCLUDE_ALL)) || @@ -1346,7 +1356,13 @@ static drreg_status_t drreg_restore_reg_now(void *drcontext, instrlist_t *ilist, instr_t *inst, per_thread_t *pt, reg_id_t reg) { - if (pt->reg[GPR_IDX(reg)].ever_spilled) { + /* i#6417: in case of a syscall, restore the values of registers since + * they may be used as input parameters for the kernel. For example, + * ECX is used to store the length for mmap2. Register used to store the + * output of the syscall is marked as not spilled, so we need to check for + * syscall as well. + */ + if (pt->reg[GPR_IDX(reg)].ever_spilled || instr_is_syscall(inst)) { if (pt->reg[GPR_IDX(reg)].xchg != DR_REG_NULL) { /* XXX i#511: NYI */ return DRREG_ERROR_FEATURE_NOT_AVAILABLE; diff --git a/suite/tests/CMakeLists.txt b/suite/tests/CMakeLists.txt index 9fd8690e105..78009e761ce 100644 --- a/suite/tests/CMakeLists.txt +++ b/suite/tests/CMakeLists.txt @@ -2171,6 +2171,10 @@ if (X86) # FIXME i#1551, i#1569: port asm to ARM and AArch64 endif (X86) tobuild(common.getretaddr common/getretaddr.c) +if (UNIX) + tobuild(common.syscall-mmap common/syscall-mmap.c) +endif () + if (X86) # FIXME i#1551, i#1569: port asm to ARM and AArch64 # XXX i#1287: implement for MacOS # We do not support -no_early_inject on Android (i#1873). @@ -4885,6 +4889,21 @@ if (BUILD_CLIENTS) "@-tool@invariant_checker" "") endif () + if (UNIX) + if (X86) + if (X64) + torunonly_drcacheoff(syscall-mmap-x86-64 common.syscall-mmap + "-record_syscall 9|6" "@-simulator_type@view" "") + else () + torunonly_drcacheoff(syscall-mmap-x86-32 common.syscall-mmap + "-record_syscall 192|6" "@-simulator_type@view" "") + endif () + elseif (AARCH64) + torunonly_drcacheoff(syscall-mmap-aarch64 common.syscall-mmap + "-record_syscall 222|6" "@-simulator_type@view" "") + endif () + endif () + ########################################################################### # drcpusim tests diff --git a/suite/tests/common/syscall-mmap.c b/suite/tests/common/syscall-mmap.c new file mode 100644 index 00000000000..e78f4d033ee --- /dev/null +++ b/suite/tests/common/syscall-mmap.c @@ -0,0 +1,49 @@ +/* ********************************************************** + * Copyright (c) 2023 Google, Inc. All rights reserved. + * **********************************************************/ + +/* + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * * Neither the name of VMware, Inc. nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + */ + +#include +#include + +int +main() +{ + void *p; + const size_t size = 0x00008765; + printf("Calling mmap(0, 0x%x, 0x%x, 0x%x, -1, 0)\n", (unsigned int)size, + PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE); + p = mmap(0, size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE, -1, 0); + if (p == MAP_FAILED) { + printf("mmap ERROR 0x%p\n", p); + return 1; + } + return 0; +} diff --git a/suite/tests/common/syscall-mmap.expect b/suite/tests/common/syscall-mmap.expect new file mode 100644 index 00000000000..86fe565ac58 --- /dev/null +++ b/suite/tests/common/syscall-mmap.expect @@ -0,0 +1 @@ +Calling mmap(0, 0x8765, 0x7, 0x22, -1, 0)