Skip to content

Commit

Permalink
i#1684 xarch-IR: Support separate host and target arch
Browse files Browse the repository at this point in the history
Adds support for building with different host and target
architectures.  The goal is to support running drdisas, drdecode,
drraw2trace, and drcachesim trace analyzers on one host machine while
targeting recorded bytes or traces from a different type of machine:
e.g., processing aarch64 traces on an x86_64 machine.  The goal is
*not* to turn DR into a cross-ISA binary translator: we only support
standalone mode here, not full DR managed mode.  Long-term it would be
nicer to split out the DR standalone mode interfaces into separate
libraries but that is beyond the scope of the current work.

Adds a top-level CMake option variable "TARGET_ARCH" which defaults to
CMAKE_SYSTEM_PROCESSOR but can be set to a different value.  The
regular arch variables/defines X86, AARCH64, and ARM are set from
TARGET_ARCH, while new values DR_HOST_{X86,AARCH64,ARM} are set for
the host.

The bulk of the code is built targeting the TARGET_ARCH, with only
assembly code and other limited code using the DR_HOST_* arch.  This
limits the scope of the code changes as compared to the opposite
approach.  A new define DR_HOST_NOT_TARGET is used to simply disable
cases where the host and target and intertwined and difficult to
easily separate, such as TLS handling.

The key code changed to use DR_HOST_* includes:
+ *.asm files
+ arch_exports.h inline asm for atomics and other key utilities
+ system call defines (we don't want to have our raw syscall wrappers running
  incorrect syscall numbers: we'll end up with fork bombs or other madness)

Code using built-in __*__ arch defines is changed to use our defines:
+ sigcontext.h, which is also augmented for some missing AArch64 types
+ x86_code_test.c

Code reading ELF headers is relaxed to allow *any* arch, since we need
the host for standalone init code but the target for raw2trace module
mapping.

Nearly all tests are disabled not just from running but also from
building for simplicity, to reduce code changes here.

TODO: Add new runsuite build
TODO: Add new drcachesim xarch tests
TODO: A couple of NOCHECK's in the diff

Issue: #1684, #4318
  • Loading branch information
derekbruening committed Jun 18, 2020
1 parent 4471c9b commit 37c9204
Show file tree
Hide file tree
Showing 27 changed files with 302 additions and 129 deletions.
35 changes: 33 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,16 @@ endif ()

# The target architecture.
# For cross-compilation this should still work as you're supposed to set this var.
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(TARGET_ARCH "${CMAKE_SYSTEM_PROCESSOR}" CACHE STRING "Target architecture")
if (TARGET_ARCH MATCHES "^arm")
set(ARM 1) # This means AArch32.
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
message(STATUS "Building for ARM")
elseif (TARGET_ARCH MATCHES "^aarch64")
set(AARCH64 1)
message(STATUS "Building for AArch64")
else ()
set(X86 1) # This means IA-32 or AMD64
message(STATUS "Building for x86")
endif ()

if (X86)
Expand All @@ -233,6 +237,33 @@ else ()
set(ARCH_NAME_SHARED ${ARCH_NAME})
endif ()

# The execution architecture, which might differ from the target for building
# an AArch64 decoder to execute on x86 machines (i#1684).
if (NOT "${TARGET_ARCH}" STREQUAL "${CMAKE_SYSTEM_PROCESSOR}")
set(DR_HOST_NOT_TARGET 1)
endif ()
if (CMAKE_SYSTEM_PROCESSOR MATCHES "^arm")
set(DR_HOST_ARM 1) # This means AArch32.
set(DR_HOST_ARCH_NAME "arm")
set(DR_HOST_AARCHXX 1)
set(DR_HOST_ARCH_NAME_SHARED aarchxx)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64")
set(DR_HOST_AARCH64 1)
set(DR_HOST_ARCH_NAME "aarch64")
set(DR_HOST_AARCHXX 1)
set(DR_HOST_ARCH_NAME_SHARED aarchxx)
set(DR_HOST_X64 1)
elseif (CMAKE_SYSTEM_PROCESSOR MATCHES "^x86_32")
set(DR_HOST_X86 1)
set(DR_HOST_ARCH_NAME "x86")
set(DR_HOST_ARCH_NAME_SHARED ${DR_HOST_ARCH_NAME})
else ()
set(DR_HOST_X86 1)
set(DR_HOST_ARCH_NAME "x86")
set(DR_HOST_ARCH_NAME_SHARED ${DR_HOST_ARCH_NAME})
set(DR_HOST_X64 1)
endif ()

# The plan is to use X64 to mean 64-bit generically, whether AMD64 or AARCH64.
# Whether 64-bit is expected to be selected by user setting up compiler
# prior to invoking CMake: it has to be that way for Windows, and for
Expand Down
16 changes: 8 additions & 8 deletions core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ endif ()
set(asm_deps
"${PROJECT_SOURCE_DIR}/core/arch/asm_defines.asm"
"${PROJECT_BINARY_DIR}/configure.h")
add_asm_target(arch/${ARCH_NAME}/${ARCH_NAME}.asm arch_core_asm_src arch_core_asm_tgt
"_core" "" "${asm_deps}")
if (NOT "${ARCH_NAME}" STREQUAL "${ARCH_NAME_SHARED}")
add_asm_target(arch/${ARCH_NAME_SHARED}/${ARCH_NAME_SHARED}.asm
add_asm_target(arch/${DR_HOST_ARCH_NAME}/${DR_HOST_ARCH_NAME}.asm
arch_core_asm_src arch_core_asm_tgt "_core" "" "${asm_deps}")
if (NOT "${DR_HOST_ARCH_NAME}" STREQUAL "${DR_HOST_ARCH_NAME_SHARED}")
add_asm_target(arch/${DR_HOST_ARCH_NAME_SHARED}/${DR_HOST_ARCH_NAME_SHARED}.asm
archshared_core_asm_src archshared_core_asm_tgt
"_core" "" "${asm_deps}")
endif ()
Expand All @@ -86,7 +86,7 @@ if (UNIX)
# our auxiliary tools (i#1504), but we do *not* want our own memcpy and
# memset for static-lib DR core. Thus we separate them out. The i#1504
# glibc versioning is only an issue on x86.
add_asm_target(arch/${ARCH_NAME}/memfuncs.asm memfuncs_asm_src memfuncs_asm_tgt
add_asm_target(arch/${DR_HOST_ARCH_NAME}/memfuncs.asm memfuncs_asm_src memfuncs_asm_tgt
"_memfuncs" "" "${asm_deps}")
add_library(drmemfuncs STATIC ${memfuncs_asm_src} lib/memmove.c)
add_gen_events_deps(drmemfuncs)
Expand All @@ -98,7 +98,7 @@ endif ()
# i#1409: to share core libc-ish code with non-core, we use the "drlibc" library.
add_asm_target(drlibc/drlibc_xarch.asm drlibc_xarch_asm_src drlibc_xarch_asm_tgt
"_core" "" "${asm_deps}")
add_asm_target(drlibc/drlibc_${ARCH_NAME}.asm drlibc_arch_asm_src
add_asm_target(drlibc/drlibc_${DR_HOST_ARCH_NAME}.asm drlibc_arch_asm_src
drlibc_arch_asm_tgt
"" "" "${asm_deps}")
set(DRLIBC_SRCS
Expand Down Expand Up @@ -1050,7 +1050,7 @@ endif ()
###########################################################################
# Unit tests

if (BUILD_TESTS)
if (BUILD_TESTS AND NOT DR_HOST_NOT_TARGET)
add_executable(unit_tests unit_tests.c
# These unit tests have been moved from the x86_code module into a new x86_code
# test module that gets its own clang/gcc options for testing (-mno-vzeroupper).
Expand Down Expand Up @@ -1124,7 +1124,7 @@ if (BUILD_TESTS)
set_tests_properties(unit_tests PROPERTIES LABELS OSX)
endif ()
copy_target_to_device(unit_tests "${location_suffix}")
endif (BUILD_TESTS)
endif ()

###########################################################################

Expand Down
4 changes: 4 additions & 0 deletions core/arch/aarchxx/mangle.c
Original file line number Diff line number Diff line change
Expand Up @@ -2853,8 +2853,10 @@ mangle_icache_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
opnd_create_base_disp(dr_reg_stolen, DR_REG_NULL, 0, 16, OPSZ_16),
opnd_create_reg(xt == dr_reg_stolen ? DR_REG_X0 : xt),
opnd_create_reg(DR_REG_X30)));
# ifndef DR_HOST_NOT_TARGET
insert_mov_immed_arch(dcontext, NULL, NULL, (ptr_int_t)icache_op_ic_ivau_asm,
opnd_create_reg(DR_REG_X30), ilist, instr, NULL, NULL);
# endif
PRE(ilist, instr, /* mov x0, x28 */
XINST_CREATE_move(dcontext, opnd_create_reg(DR_REG_X0),
opnd_create_reg(dr_reg_stolen)));
Expand Down Expand Up @@ -2887,8 +2889,10 @@ mangle_icache_op(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr,
dcontext,
opnd_create_base_disp(dr_reg_stolen, DR_REG_NULL, 0, 8, OPSZ_16),
opnd_create_reg(DR_REG_X1), opnd_create_reg(DR_REG_X2)));
# ifndef DR_HOST_NOT_TARGET
insert_mov_immed_arch(dcontext, NULL, NULL, (ptr_int_t)icache_op_isb_asm,
opnd_create_reg(DR_REG_X2), ilist, instr, NULL, NULL);
# endif
insert_mov_immed_arch(dcontext, NULL, NULL, (ptr_int_t)pc,
opnd_create_reg(DR_REG_X1), ilist, instr, NULL, NULL);
PRE(ilist, instr, /* mov x0, x28 */
Expand Down
8 changes: 4 additions & 4 deletions core/arch/arch_exports.h
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ atomic_add_exchange_int64(volatile int64 *var, int64 value)
# define atomic_add_exchange atomic_add_exchange_int

#else /* UNIX */
# ifdef X86
# ifdef DR_HOST_X86
/* IA-32 vol 3 7.1.4: processor will internally suppress the bus lock
* if target is within cache line.
*/
Expand Down Expand Up @@ -632,7 +632,7 @@ atomic_add_exchange_int64(volatile int64 *var, int64 value)
# define SET_IF_NOT_ZERO(flag) SET_FLAG(nz, flag)
# define SET_IF_NOT_LESS(flag) SET_FLAG(nl, flag)

# elif defined(AARCH64)
# elif defined(DR_HOST_AARCH64)

# define ATOMIC_1BYTE_WRITE(target, value, hot_patch) \
do { \
Expand Down Expand Up @@ -817,7 +817,7 @@ atomic_dec_becomes_zero(volatile int *var)
return atomic_add_exchange_int(var, -1) == 0;
}

# elif defined(ARM)
# elif defined(DR_HOST_ARM)

# define ATOMIC_1BYTE_WRITE(target, value, hot_patch) \
do { \
Expand Down Expand Up @@ -979,7 +979,7 @@ proc_get_timestamp(void);
# define ATOMIC_COMPARE_EXCHANGE_PTR ATOMIC_COMPARE_EXCHANGE
# endif

# ifndef AARCH64
# ifndef DR_HOST_AARCH64
/* Atomically increments *var by 1
* Returns true if the resulting value is zero, otherwise returns false
*/
Expand Down
5 changes: 5 additions & 0 deletions core/arch/asm_defines.asm
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,11 @@
# define AARCHXX
#endif

//NOCHECK
#define X86
#undef AARCH64
#undef AARCHXX

#if (defined(ARM) && defined(X64)) || (defined(AARCH64) && !defined(X64))
# error ARM is only 32-bit; AARCH64 is 64-bit
#endif
Expand Down
6 changes: 3 additions & 3 deletions core/arch/x86_code_test.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2013-2019 Google, Inc. All rights reserved.
* Copyright (c) 2013-2020 Google, Inc. All rights reserved.
* Copyright (c) 2001-2010 VMware, Inc. All rights reserved.
* **********************************************************/

Expand Down Expand Up @@ -105,7 +105,7 @@ test_cpuid()
# endif
}

# ifdef __AVX__
# if !defined(DR_HOST_NOT_TARGET) && defined(__AVX__)

static void
unit_test_get_ymm_caller_saved()
Expand Down Expand Up @@ -393,7 +393,7 @@ unit_test_asm(dcontext_t *dc)
print_file(STDERR, "testing asm\n");
test_call_switch_stack(dc);
test_cpuid();
# ifdef UNIX
# if defined(UNIX) && !defined(DR_HOST_NOT_TARGET)
# ifdef __AVX__
unit_test_get_ymm_caller_saved();
# endif
Expand Down
6 changes: 5 additions & 1 deletion core/drlibc/drlibc.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* **********************************************************
* Copyright (c) 2015-2019 Google, Inc. All rights reserved.
* Copyright (c) 2015-2020 Google, Inc. All rights reserved.
* **********************************************************/

/*
Expand Down Expand Up @@ -117,6 +117,9 @@ kernel_is_64bit(void)
void
clear_icache(void *beg, void *end)
{
# ifdef DR_HOST_NOT_TARGET
ASSERT_NOT_REACHED();
# else
static size_t cache_info = 0;
size_t dcache_line_size;
size_t icache_line_size;
Expand Down Expand Up @@ -159,6 +162,7 @@ clear_icache(void *beg, void *end)

/* Instruction Synchronization Barrier */
__asm__ __volatile__("isb" : : : "memory");
# endif
}
#endif

Expand Down
15 changes: 11 additions & 4 deletions core/drlibc/drlibc_module_elf.c
Original file line number Diff line number Diff line change
Expand Up @@ -108,9 +108,14 @@ is_elf_so_header_common(app_pc base, size_t size, bool memory)
if ((elf_header.e_version != 1) ||
(memory && elf_header.e_ehsize != sizeof(ELF_HEADER_TYPE)) ||
(memory &&
# ifdef DR_HOST_NOT_TARGET
false
# else
elf_header.e_machine !=
IF_X86_ELSE(IF_X64_ELSE(EM_X86_64, EM_386),
IF_X64_ELSE(EM_AARCH64, EM_ARM))))
IF_HOST_X86_ELSE(IF_HOST_X64_ELSE(EM_X86_64, EM_386),
IF_HOST_X64_ELSE(EM_AARCH64, EM_ARM))
# endif
))
return false;
#endif
/* FIXME - should we add any of these to the check? For real
Expand All @@ -119,10 +124,12 @@ is_elf_so_header_common(app_pc base, size_t size, bool memory)
ASSERT_CURIOSITY(!memory || elf_header.e_ehsize == sizeof(ELF_HEADER_TYPE));
ASSERT_CURIOSITY(elf_header.e_ident[EI_OSABI] == ELFOSABI_SYSV ||
elf_header.e_ident[EI_OSABI] == ELFOSABI_LINUX);
#ifndef DR_HOST_NOT_TARGET
ASSERT_CURIOSITY(!memory ||
elf_header.e_machine ==
IF_X86_ELSE(IF_X64_ELSE(EM_X86_64, EM_386),
IF_X64_ELSE(EM_AARCH64, EM_ARM)));
IF_HOST_X86_ELSE(IF_HOST_X64_ELSE(EM_X86_64, EM_386),
IF_HOST_X64_ELSE(EM_AARCH64, EM_ARM)));
#endif
return true;
}
return false;
Expand Down
11 changes: 11 additions & 0 deletions core/lib/globals_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -796,6 +796,17 @@ typedef struct _instr_t instr_t;
#endif
/* DR_API EXPORT END */

#ifdef DR_HOST_X86
# define IF_HOST_X86_ELSE(x, y) x
#else
# define IF_HOST_X86_ELSE(x, y) y
#endif
#ifdef DR_HOST_X64
# define IF_HOST_X64_ELSE(x, y) x
#else
# define IF_HOST_X64_ELSE(x, y) y
#endif

typedef enum {
SYSLOG_INFORMATION = 0x1,
SYSLOG_WARNING = 0x2,
Expand Down
38 changes: 29 additions & 9 deletions core/unix/include/sigcontext.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ typedef struct _kernel_fpx_sw_bytes_t {
__u32 padding[7]; /* for future use. */
} kernel_fpx_sw_bytes_t;

#ifdef __i386__
#ifdef X86_32
/*
* As documented in the iBCS2 standard..
*
Expand Down Expand Up @@ -161,7 +161,7 @@ typedef struct _kernel_sigcontext_t {
unsigned long cr2;
} kernel_sigcontext_t;

#elif defined(__amd64__)
#elif defined(X86_64)

/* FXSAVE frame */
/* Note: reserved1/2 may someday contain valuable data. Always save/restore
Expand Down Expand Up @@ -220,9 +220,9 @@ typedef struct _kernel_sigcontext_t {
unsigned long reserved1[8];
} kernel_sigcontext_t;

#endif /* !__i386__ */
#endif

#if defined(__i386__) || defined(__amd64__)
#if defined(X86_32) || defined(X86_64)
typedef struct _kernel_xsave_hdr_t {
__u64 xstate_bv;
__u64 reserved1[2];
Expand All @@ -246,9 +246,9 @@ typedef struct _kernel_xstate_t {
kernel_ymmh_state_t ymmh;
/* new processor state extensions go here */
} kernel_xstate_t;
#endif /* __i386__ || __amd64__ */
#endif

#ifdef __arm__
#ifdef ARM
/*
* Signal context structure - contains all info to do with the state
* before the signal handler was invoked. Note: only add new entries
Expand Down Expand Up @@ -314,9 +314,9 @@ typedef struct _kernel_iwmmxt_sigframe_t {
/* Dummy padding block: a block with this magic should be skipped. */
# define DUMMY_MAGIC 0xb0d9ed01

#endif /* __arm__ */
#endif

#ifdef __aarch64__
#ifdef AARCH64

typedef struct _kernel_sigcontext_t {
unsigned long long fault_address;
Expand All @@ -328,6 +328,26 @@ typedef struct _kernel_sigcontext_t {
unsigned char __reserved[4096] __attribute__((__aligned__(16)));
} kernel_sigcontext_t;

#endif /* __aarch64__ */
/*
* Header to be used at the beginning of structures extending the user
* context. Such structures must be placed after the rt_sigframe on the stack
* and be 16-byte aligned. The last structure must be a dummy one with the
* magic and size set to 0.
*/
struct _aarch64_ctx {
__u32 magic;
__u32 size;
};

# define FPSIMD_MAGIC 0x46508001

struct fpsimd_context {
struct _aarch64_ctx head;
__u32 fpsr;
__u32 fpcr;
__uint128_t vregs[32];
};

#endif

#endif /* _SIGCONTEXT_H_ */
8 changes: 5 additions & 3 deletions core/unix/include/syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
# error Only use this file on Linux
#endif

#ifdef X86
#ifdef DR_HOST_X86
# include "syscall_linux_x86.h"
#elif defined(ARM)
#elif defined(DR_HOST_ARM)
# include "syscall_linux_arm.h"
#elif defined(AARCH64)
#elif defined(DR_HOST_AARCH64)
# include "syscall_linux_uapi.h"
#else
# error Unknown platform.
#endif

#endif /* _SYSCALL_H_ */
Loading

0 comments on commit 37c9204

Please sign in to comment.