Skip to content

Commit

Permalink
i#38 attach: Enable attach on AArch64
Browse files Browse the repository at this point in the history
Implements missing functionality for ptrace attach on AArch64 and
AArch32: generated code sequences were previously x86-only;
-skip_syscall handling only supported x86; and AArch64 does not
support PTRACE_POKEUSER or PTRACE_PEEKUSER.

For AArch32, Thumb vs Arm mode require multiple steps: clearing LSB to
point at the path used as data via a call; switching to Arm mode for
DR's _start; setting the LSB of the initial app PC.

For AArch32, additionally fixes an encoder error where the opcode is
queried before copying a needs-no-encoding instruction.  This is
required for the instruction used to hold data for injection.

Tweaks the disassembler to leave a level 0 instr alone, again to
better handle the data-only insruction used for injection.

Enables the client.attach test on AArch64 and AArch32.  For AArch32,
it needs -skip_syscall.  Long-term we want that on by default
everywhere but we want explicit tests that hit it on all platforms
first.

Issue: #38
  • Loading branch information
derekbruening committed Apr 12, 2022
1 parent de027cf commit 0232d80
Show file tree
Hide file tree
Showing 9 changed files with 251 additions and 86 deletions.
2 changes: 1 addition & 1 deletion api/docs/release.dox
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ changes:
- Nothing yet (placeholder).

Further non-compatibility-affecting changes include:
- Added AArchXX support for attaching to a running process.
- Added new fields analyze_case_ex and instrument_instr_ex to #drbbdup_options_t.
- Added drbbdup support to drwrap via #DRWRAP_INVERT_CONTROL, drwrap_invoke_insert(),
and drwrap_invoke_insert_cleanup_only().
Expand Down Expand Up @@ -1983,7 +1984,6 @@ We hope to include the following major features in future releases:
parent process, injection is very early (before kernel32.dll is loaded),
but we plan to provide injection at the very first user-mode instruction
in the future.
- Linux externally-triggered attaching.
- Persistent and process-shared code caches.
- Full control over trace building.

Expand Down
4 changes: 3 additions & 1 deletion core/arch/aarchxx/aarchxx.asm
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2014-2016 Google, Inc. All rights reserved.
* Copyright (c) 2014-2022 Google, Inc. All rights reserved.
* Copyright (c) 2016 ARM Limited. All rights reserved.
* **********************************************************/

Expand Down Expand Up @@ -42,6 +42,8 @@ START_FILE
# if !defined(STANDALONE_UNIT_TEST) && !defined(STATIC_LIBRARY)
DECLARE_FUNC(_start)
GLOBAL_LABEL(_start:)
/* i#38: Attaching in middle of blocking syscall requires padded null bytes. */
nop
mov FP, #0 /* clear frame ptr for stack trace bottom */
/* i#1676, i#1708: relocate dynamorio if it is not loaded to preferred address.
* We call this here to ensure it's safe to access globals once in C code
Expand Down
8 changes: 6 additions & 2 deletions core/ir/arm/encode.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2014-2021 Google, Inc. All rights reserved.
* Copyright (c) 2014-2022 Google, Inc. All rights reserved.
* **********************************************************/

/*
Expand Down Expand Up @@ -3033,7 +3033,6 @@ instr_encode_arch(dcontext_t *dcontext, instr_t *instr, byte *copy_pc, byte *fin
}

decode_info_init_for_instr(&di, instr);
di.opcode = instr_get_opcode(instr);
di.check_reachable = check_reachable;
di.start_pc = copy_pc;
di.final_pc = final_pc;
Expand Down Expand Up @@ -3061,6 +3060,11 @@ instr_encode_arch(dcontext_t *dcontext, instr_t *instr, byte *copy_pc, byte *fin
}
CLIENT_ASSERT(instr_operands_valid(instr), "instr_encode error: operands invalid");

/* We delay this until after handling raw instrs to avoid trying to get the opcode
* of a data-only instr.
*/
di.opcode = instr_get_opcode(instr);

info = instr_get_instr_info(instr);
if (info == NULL) {
if (has_instr_opnds != NULL)
Expand Down
22 changes: 14 additions & 8 deletions core/ir/disassemble_shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -1522,10 +1522,10 @@ instrlist_disassemble(void *drcontext, app_pc tag, instrlist_t *ilist, file_t ou
level = 4;
/* encode instr and then output as BINARY */
nxt_pc = instr_encode_ignore_reachability(dcontext, instr, bytes);
ASSERT(nxt_pc != NULL);
CLIENT_ASSERT(nxt_pc != NULL, "failed to encode instr");
len = (int)(nxt_pc - bytes);
addr = bytes;
CLIENT_ASSERT(len < 64, "instrlist_disassemble: too-long instr");
CLIENT_ASSERT(len < sizeof(bytes), "instrlist_disassemble: too-long instr");
} else {
addr = instr_get_raw_bits(instr);
len = instr_length(dcontext, instr);
Expand Down Expand Up @@ -1565,12 +1565,18 @@ instrlist_disassemble(void *drcontext, app_pc tag, instrlist_t *ilist, file_t ou
while (len) {
print_file(outfile, " +%-4d %c%d " IF_X64_ELSE("%20s", "%12s"), offs,
instr_is_app(instr) ? 'L' : 'm', level, " ");
next_addr = internal_disassemble_to_file(
dcontext, addr, addr, outfile, false, true,
IF_X64_ELSE(" ",
" "));
if (next_addr == NULL)
break;
/* Leave level 0 alone as it may not be code. */
if (level == 0) {
print_file(outfile, " <...%d bytes...>\n", instr->length);
next_addr = addr + instr->length;
} else {
next_addr = internal_disassemble_to_file(
dcontext, addr, addr, outfile, false, true,
IF_X64_ELSE(" ",
" "));
if (next_addr == NULL)
break;
}
sz = (int)(next_addr - addr);
CLIENT_ASSERT(sz <= len, "instrlist_disassemble: invalid length");
len -= sz;
Expand Down
5 changes: 4 additions & 1 deletion core/ir/opnd.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2011-2021 Google, Inc. All rights reserved.
* Copyright (c) 2011-2022 Google, Inc. All rights reserved.
* Copyright (c) 2000-2010 VMware, Inc. All rights reserved.
* **********************************************************/

Expand Down Expand Up @@ -222,6 +222,7 @@ opnd_create_sized_tls_slot(int offs, opnd_size_t size);
/* This should be kept in sync w/ the defines in x86/x86.asm */
enum {
#ifdef X86
DR_SYSNUM_REG = DR_REG_EAX,
# ifdef X64
# ifdef UNIX
/* SysV ABI calling convention */
Expand Down Expand Up @@ -266,12 +267,14 @@ enum {
REGPARM_2 = DR_REG_R2,
REGPARM_3 = DR_REG_R3,
# ifdef X64
DR_SYSNUM_REG = DR_REG_R8,
REGPARM_4 = DR_REG_R4,
REGPARM_5 = DR_REG_R5,
REGPARM_6 = DR_REG_R6,
REGPARM_7 = DR_REG_R7,
NUM_REGPARM = 8,
# else
DR_SYSNUM_REG = DR_REG_R7,
NUM_REGPARM = 4,
# endif /* 64/32 */
REDZONE_SIZE = 0,
Expand Down
Loading

0 comments on commit 0232d80

Please sign in to comment.