-
Notifications
You must be signed in to change notification settings - Fork 566
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
i#6417: restore registers before syscall. #6475
base: master
Are you sure you want to change the base?
Changes from all commits
925d9e6
b463ae2
9bba603
c6cf84b
185cd63
d0f8a79
438bca2
94073fe
732be3c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) | ||
Output format: | ||
<--record#-> <--instr#->: <---tid---> <record details> | ||
------------------------------------------------------------ | ||
.* | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function==syscall #222> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x8765> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x7> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x22> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0xffffffffffffffff> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
.* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) | ||
Output format: | ||
<--record#-> <--instr#->: <---tid---> <record details> | ||
------------------------------------------------------------ | ||
.* | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function==syscall #192> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x8765> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x7> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x22> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0xffffffff> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
.* |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
Calling mmap\(0, 0x8765, 0x7, 0x22, -1, 0\) | ||
Output format: | ||
<--record#-> <--instr#->: <---tid---> <record details> | ||
------------------------------------------------------------ | ||
.* | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function==syscall #9> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x8765> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x7> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x22> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0xffffffff> | ||
+[0-9]+ +[0-9]+: +[0-9]+ <marker: function argument 0x0> | ||
.* |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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) || | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks good for pre-syscall. But after the syscall we need to update the spilled values with whatever the kernel wrote: so we need to also check for instr_is_syscall in the loop labeled To test, add an asm sequence to drreg-test (ifdef LINUX I guess) with a single block with a syscall in the middle and a pattern the test client can find (see existing DRREG_TEST_38_ASM e.g.) and the test client for that block can then reserve eax and ecx and clobber both register both before and after the syscall. |
||
/* 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. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But if drreg treated ecx as dead, it wouldn't have preserved the original app value, so it won't have that value to restore. (So why did the tests pass? Did drmemtrace happen to not clobber ecx b/c it picked other scratch regs?). I think we want to keep your original change to not treat a syscall dest reg as dead, and then we'll spill it and it will be available for restores. (And we won't then want this check below for instr_is_syscall). |
||
*/ | ||
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; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 <sys/mman.h> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe this file should be in suite/tests/linux/ as mmap is unix-specific (that's the directory that has the mmap.c test as well). |
||
#include <stdio.h> | ||
|
||
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, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally we include tools.h and use |
||
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; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
Calling mmap(0, 0x8765, 0x7, 0x22, -1, 0) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, this code is restoring the flags. I don't think they are an input to any syscall on any platform (they are an output on Mac).