Skip to content
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#2350 rseq: Use a local copy for native execution #3826

Merged
merged 4 commits into from
Sep 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions api/docs/bt.dox
Original file line number Diff line number Diff line change
Expand Up @@ -1306,22 +1306,23 @@ commit.

This run-twice approach is subject to the following limitations:

- Only x86 is supported for now (no arm or aarch64 support yet).
- The application must store an rseq_cs struct for each rseq region in a
section of its binary named "__rseq_cs", optionally with an "__rseq_cs_ptr_array"
section of pointers into the __rseq_cs section, per established conventions.
These sections must be located in loaded segments.
- The application must use static thread-local storage for its struct rseq registrations.
- The application must use the same signature for every rseq system call.
- Each rseq region's code must never be also executed as a non-restartable sequence.
- Each rseq region must handle being directly restarted without its
abort handler being called (with the machine state restored).
- Each memory store instruction inside an rseq region must have no other side
effects: it must only write to memory and not to any registers.
For example, a push instruction which both writes to memory and the
stack pointer register is not supported.
- Each rseq region must end with a return instruction, and each abort handler
plus rseq code must combine into a callee following normal call-return
semantics.
- Each rseq region's code must end with a fall-through (non-control-flow)
instruction.
- Indirect branches that do not exit the rseq region are not allowed.
- Each rseq region must be entered only from the top, with no branches from outside
the region targeting a point inside the region.
- No system calls are allowed inside rseq regions.
Expand Down
7 changes: 7 additions & 0 deletions core/arch/aarchxx/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -1411,6 +1411,13 @@ insert_mov_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_esti
#endif
}

void
patch_mov_immed_arch(dcontext_t *dcontext, ptr_int_t val, byte *pc, instr_t *first,
instr_t *last)
{
ASSERT_NOT_IMPLEMENTED(false); /* FIXME i#1551, i#1569 */
}

void
insert_push_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_estimate,
ptr_int_t val, instrlist_t *ilist, instr_t *instr,
Expand Down
6 changes: 6 additions & 0 deletions core/arch/arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -504,6 +504,9 @@ insert_mov_immed_ptrsz(dcontext_t *dcontext, ptr_int_t val, opnd_t dst,
instrlist_t *ilist, instr_t *instr, OUT instr_t **first,
OUT instr_t **last);
void
patch_mov_immed_ptrsz(dcontext_t *dcontext, ptr_int_t val, byte *pc, instr_t *first,
instr_t *last);
void
insert_push_immed_ptrsz(dcontext_t *dcontext, ptr_int_t val, instrlist_t *ilist,
instr_t *instr, OUT instr_t **first, OUT instr_t **last);
void
Expand Down Expand Up @@ -535,6 +538,9 @@ insert_mov_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_esti
ptr_int_t val, opnd_t dst, instrlist_t *ilist, instr_t *instr,
OUT instr_t **first, OUT instr_t **last);
void
patch_mov_immed_arch(dcontext_t *dcontext, ptr_int_t val, byte *pc, instr_t *first,
instr_t *last);
void
insert_push_immed_arch(dcontext_t *dcontext, instr_t *src_inst, byte *encode_estimate,
ptr_int_t val, instrlist_t *ilist, instr_t *instr,
OUT instr_t **first, OUT instr_t **last);
Expand Down
25 changes: 24 additions & 1 deletion core/arch/arch_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ atomic_add_exchange_int64(volatile int64 *var, int64 value)

# elif defined(AARCH64)

# define ATOMIC_1BYTE_WRITE(target, value, hot_patch) \
do { \
ASSERT(sizeof(value) == 1); \
/* Not currently used to write code */ \
ASSERT_CURIOSITY(!hot_patch); \
__asm__ __volatile__("strb %w0, [%1]" \
: \
: "r"(value), "r"(target) \
: "memory"); \
} while (0)
# define ATOMIC_4BYTE_WRITE(target, value, hot_patch) \
do { \
ASSERT(sizeof(value) == 4); \
Expand Down Expand Up @@ -726,6 +736,14 @@ atomic_dec_becomes_zero(volatile int *var)

# elif defined(ARM)

# define ATOMIC_1BYTE_WRITE(target, value, hot_patch) \
do { \
ASSERT(sizeof(value) == 1); \
__asm__ __volatile__("strb %0, [%1]" \
: \
: "r"(value), "r"(target) \
: "memory"); \
} while (0)
# define ATOMIC_4BYTE_WRITE(target, value, hot_patch) \
do { \
ASSERT(sizeof(value) == 4); \
Expand Down Expand Up @@ -1645,7 +1663,9 @@ d_r_decode_init(void);
# define STUB_COARSE_DIRECT_SIZE(flags) \
(FRAG_IS_32(flags) ? STUB_COARSE_DIRECT_SIZE32 : STUB_COARSE_DIRECT_SIZE64)

/* writes nops into the address range */
/* Writes nops into the address range.
* XXX i#3828: Better to use the newer multi-byte nops.
*/
# define SET_TO_NOPS(isa_mode, addr, size) memset(addr, 0x90, size)
/* writes debugbreaks into the address range */
# define SET_TO_DEBUG(addr, size) memset(addr, 0xcc, size)
Expand Down Expand Up @@ -2255,6 +2275,9 @@ instr_supports_simple_mangling_epilogue(dcontext_t *dcontext, instr_t *inst);
void
float_pc_update(dcontext_t *dcontext);

void
mangle_finalize(dcontext_t *dcontext, instrlist_t *ilist, fragment_t *f);

/* in retcheck.c */
#ifdef CHECK_RETURNS_SSE2
void
Expand Down
8 changes: 8 additions & 0 deletions core/arch/instr.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,14 @@ enum {
# ifdef WINDOWS
/* used to indicate that a syscall should be executed via shared syscall */
INSTR_SHARED_SYSCALL = 0x01000000,
# else
/* Indicates an instruction that's part of the rseq endpoint. We use this in
* instrlist_t.flags (sort of the same namespace: INSTR_OUR_MANGLING is used there,
* but also EDI_VAL_*) and as a version of DR_NOTE_RSEQ that survives encoding
* (seems like we could store notes for labels in another field so they do
* in fact survive: a union with instr_t.translation?).
*/
INSTR_RSEQ_ENDPOINT = 0x01000000,
# endif

# ifdef CLIENT_INTERFACE
Expand Down
Loading