Skip to content

Commit

Permalink
Revert "Preserve fs/gs_base when tracing 32 bit programs on 64 bit ke…
Browse files Browse the repository at this point in the history
…rnels."

This reverts commit c3292c7.
  • Loading branch information
khuey committed Aug 25, 2020
1 parent 29e1ff7 commit 2600795
Show file tree
Hide file tree
Showing 10 changed files with 14 additions and 172 deletions.
79 changes: 13 additions & 66 deletions src/Registers.cc
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,6 @@ void Registers::write_register_by_user_offset(uintptr_t offset,
// well sign-extend %eax in all cases.

typedef void (*NarrowConversion)(int32_t& r32, uint64_t& r64);
typedef void (*CopyConversion)(uint64_t& r32_base, uint64_t& r64_base);
template <NarrowConversion narrow, NarrowConversion narrow_signed>
void convert_x86(X86Arch::user_regs_struct& x86,
X64Arch::user_regs_struct& x64) {
Expand All @@ -537,35 +536,10 @@ void convert_x86(X86Arch::user_regs_struct& x86,
narrow(x86.xgs, x64.gs);
narrow(x86.xss, x64.ss);
}
template <NarrowConversion narrow, NarrowConversion narrow_signed, CopyConversion copy>
void convert_x86_with_fsgsbase(X64Arch::x86_user_regs_struct& x86,
X64Arch::user_regs_struct& x64) {
narrow_signed(x86.eax, x64.rax);
narrow(x86.ebx, x64.rbx);
narrow(x86.ecx, x64.rcx);
narrow(x86.edx, x64.rdx);
narrow(x86.esi, x64.rsi);
narrow(x86.edi, x64.rdi);
narrow(x86.esp, x64.rsp);
narrow(x86.ebp, x64.rbp);
narrow(x86.eip, x64.rip);
narrow(x86.orig_eax, x64.orig_rax);
narrow(x86.eflags, x64.eflags);
narrow(x86.xcs, x64.cs);
narrow(x86.xds, x64.ds);
narrow(x86.xes, x64.es);
narrow(x86.xfs, x64.fs);
narrow(x86.xgs, x64.gs);
narrow(x86.xss, x64.ss);
copy(x86.fs_base, x64.fs_base);
copy(x86.gs_base, x64.gs_base);
}

void to_x86_narrow(int32_t& r32, uint64_t& r64) { r32 = r64; }
void to_x86_copy(uint64_t& r32_base, uint64_t& r64_base) { r32_base = r64_base; }
void from_x86_narrow(int32_t& r32, uint64_t& r64) { r64 = (uint32_t)r32; }
void from_x86_narrow_signed(int32_t& r32, uint64_t& r64) { r64 = (int64_t)r32; }
void from_x86_copy(uint64_t& r32_base, uint64_t& r64_base) { r64_base = r32_base; }

void Registers::set_from_ptrace(const NativeArch::user_regs_struct& ptrace_regs) {
if (arch() == NativeArch::arch()) {
Expand All @@ -574,17 +548,10 @@ void Registers::set_from_ptrace(const NativeArch::user_regs_struct& ptrace_regs)
}

DEBUG_ASSERT(arch() == x86 && NativeArch::arch() == x86_64);
if (rdgsbase_works()) {
convert_x86_with_fsgsbase<to_x86_narrow, to_x86_narrow, to_x86_copy>(
u.x86on64regs,
*const_cast<X64Arch::user_regs_struct*>(
reinterpret_cast<const X64Arch::user_regs_struct*>(&ptrace_regs)));
} else {
convert_x86<to_x86_narrow, to_x86_narrow>(
u.x86regs,
*const_cast<X64Arch::user_regs_struct*>(
reinterpret_cast<const X64Arch::user_regs_struct*>(&ptrace_regs)));
}
convert_x86<to_x86_narrow, to_x86_narrow>(
u.x86regs,
*const_cast<X64Arch::user_regs_struct*>(
reinterpret_cast<const X64Arch::user_regs_struct*>(&ptrace_regs)));
}

/**
Expand All @@ -605,13 +572,8 @@ NativeArch::user_regs_struct Registers::get_ptrace() const {

DEBUG_ASSERT(arch() == x86 && NativeArch::arch() == x86_64);
memset(&result, 0, sizeof(result));
if (rdgsbase_works()) {
convert_x86_with_fsgsbase<from_x86_narrow, from_x86_narrow_signed, from_x86_copy>(
const_cast<Registers*>(this)->u.x86on64regs, result.x64arch_api);
} else {
convert_x86<from_x86_narrow, from_x86_narrow_signed>(
const_cast<Registers*>(this)->u.x86regs, result.x64arch_api);
}
convert_x86<from_x86_narrow, from_x86_narrow_signed>(
const_cast<Registers*>(this)->u.x86regs, result.x64arch_api);
return result.linux_api;
}

Expand All @@ -635,13 +597,8 @@ Registers::InternalData Registers::get_ptrace_for_self_arch() const {
Registers::InternalData Registers::get_regs_for_trace() const {
switch (arch_) {
case x86:
if (x86 == NativeArch::arch() || !rdgsbase_works()) {
return { reinterpret_cast<const uint8_t*>(&u.x86regs),
sizeof(u.x86regs) };
} else {
return { reinterpret_cast<const uint8_t*>(&u.x86on64regs),
sizeof(u.x86on64regs) };
}
return { reinterpret_cast<const uint8_t*>(&u.x86regs),
sizeof(u.x86regs) };
case x86_64:
return { reinterpret_cast<const uint8_t*>(&u.x64regs),
sizeof(u.x64regs) };
Expand Down Expand Up @@ -682,23 +639,13 @@ void Registers::set_from_ptrace_for_arch(SupportedArch a, const void* data,

void Registers::set_from_trace(SupportedArch a, const void* data,
size_t size) {
if (a == NativeArch::arch()) {
DEBUG_ASSERT(size == sizeof(NativeArch::user_regs_struct));
set_from_ptrace(*static_cast<const NativeArch::user_regs_struct*>(data));
return;
if (is_x86ish(a)) {
return set_from_ptrace_for_arch(a, data, size);
}

DEBUG_ASSERT(a == x86 && NativeArch::arch() == x86_64);
// We don't support a 32-bit tracee trying to set registers of a 64-bit tracee
DEBUG_ASSERT(arch() == x86);
// It was asserted that rdgsbase_works matches the registers size earlier.
if (rdgsbase_works()) {
DEBUG_ASSERT(size == sizeof(u.x86on64regs));
memcpy(&u.x86on64regs, data, sizeof(u.x86on64regs));
} else {
DEBUG_ASSERT(size == sizeof(u.x86regs) || size == sizeof(u.x86on64regs));
memcpy(&u.x86regs, data, sizeof(u.x86regs));
}
DEBUG_ASSERT(a == aarch64);
DEBUG_ASSERT(size == sizeof(u.arm64regs));
memcpy(&u.arm64regs, data, sizeof(u.arm64regs));
}

uintptr_t Registers::flags() const {
Expand Down
1 change: 0 additions & 1 deletion src/Registers.h
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,6 @@ class Registers {
SupportedArch arch_;
union {
rr::X86Arch::user_regs_struct x86regs;
rr::X64Arch::x86_user_regs_struct x86on64regs;
rr::X64Arch::user_regs_struct x64regs;
struct {
// This is the NT_PRSTATUS regset
Expand Down
2 changes: 1 addition & 1 deletion src/ReplaySession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ static void check_xsave_compatibility(const TraceReader& trace_in) {
// to XSAVE instructions executed on our CPU, or examines XCR0 directly,
// This will cause divergence. The dynamic linker examines XCR0 so this
// is nearly guaranteed.
cerr << "rr: Trace XCR0 value " << HEX(tracee_xcr0) << " != our XCR0 "
cerr << "Trace XCR0 value " << HEX(tracee_xcr0) << " != our XCR0 "
<< "value " << HEX(our_xcr0) << "; Replay will probably fail "
<< "because glibc dynamic loader examines XCR0\n\n";
}
Expand Down
3 changes: 0 additions & 3 deletions src/TraceInfoCommand.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,6 @@ static int dump_trace_info(const string& trace_dir, FILE* out) {
}
fputs("\n ],\n", out);

fprintf(out, " \"hasFsGsBaseValuesFor32Bit\":\"%s\",\n",
trace.has_fsgsbase_values_for_32_bit() ? "true" : "false");

ReplaySession::Flags flags;
flags.redirect_stdio = false;
flags.share_private_mappings = false;
Expand Down
11 changes: 0 additions & 11 deletions src/TraceStream.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
#include "AddressSpace.h"
#include "AutoRemoteSyscalls.h"
#include "Event.h"
#include "Flags.h"
#include "RecordSession.h"
#include "RecordTask.h"
#include "TaskishUid.h"
Expand Down Expand Up @@ -1324,7 +1323,6 @@ void TraceWriter::close(CloseStatus status, const TraceUuid* uuid) {
Data::Reader(reinterpret_cast<const uint8_t*>(cpuid_records.data()),
cpuid_records.size() * sizeof(CPUIDRecord)));
x86data.setXcr0(xcr0());
x86data.setHasFsGsBaseValuesFor32Bit(rdgsbase_works());
}

// Add a random UUID to the trace metadata. This lets tools identify a trace
Expand Down Expand Up @@ -1478,13 +1476,6 @@ TraceReader::TraceReader(const string& dir)
arch_ = from_trace_arch(header.getNativeArch());
if (is_x86ish(arch_)) {
auto x86data = header.getX86();
if (arch_ == x86_64 && !x86data.getHasFsGsBaseValuesFor32Bit() && rdgsbase_works()) {
if (!Flags::get().suppress_environment_warnings) {
cerr << "rr: Traces with 32 bit processes made on 64 bit kernels before 5.9 cannot be "
"replayed on kernel 5.9 or later. For forward compatibility, boot your 64 bit "
"5.9+ kernel with the 'nofsgsbase' parameter.\n\n";
}
}
trace_uses_cpuid_faulting = x86data.getHasCpuidFaulting();
Data::Reader cpuid_records_bytes = x86data.getCpuidRecords();
size_t len = cpuid_records_bytes.size() / sizeof(CPUIDRecord);
Expand All @@ -1495,7 +1486,6 @@ TraceReader::TraceReader(const string& dir)
memcpy(cpuid_records_.data(), cpuid_records_bytes.begin(),
len * sizeof(CPUIDRecord));
xcr0_ = x86data.getXcr0();
has_fsgsbase_values_for_32_bit_ = x86data.getHasFsGsBaseValuesFor32Bit();;
}

// Set the global time at 0, so that when we tick it for the first
Expand Down Expand Up @@ -1523,7 +1513,6 @@ TraceReader::TraceReader(const TraceReader& other)
preload_thread_locals_recorded_ = other.preload_thread_locals_recorded_;
rrcall_base_ = other.rrcall_base_;
arch_ = other.arch_;
has_fsgsbase_values_for_32_bit_ = other.has_fsgsbase_values_for_32_bit_;
}

TraceReader::~TraceReader() {}
Expand Down
3 changes: 0 additions & 3 deletions src/TraceStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,8 +420,6 @@ class TraceReader : public TraceStream {

SupportedArch arch() const { return arch_; }

bool has_fsgsbase_values_for_32_bit() const { return has_fsgsbase_values_for_32_bit_; }

private:
CompressedReader& reader(Substream s) { return *readers[s]; }
const CompressedReader& reader(Substream s) const { return *readers[s]; }
Expand All @@ -436,7 +434,6 @@ class TraceReader : public TraceStream {
bool trace_uses_cpuid_faulting;
bool preload_thread_locals_recorded_;
int rrcall_base_;
bool has_fsgsbase_values_for_32_bit_;
SupportedArch arch_;
};

Expand Down
24 changes: 0 additions & 24 deletions src/kernel_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -1737,30 +1737,6 @@ struct X64Arch : public BaseArch<SupportedArch::x86_64, WordSize64Defs> {
RR_VERIFY_TYPE_ARCH(SupportedArch::x86_64, ::user_regs_struct,
user_regs_struct);

// When running on a 64 bit kernel we must track fs_base/gs_base for
// a 32 bit program.
struct x86_user_regs_struct {
int32_t ebx;
int32_t ecx;
int32_t edx;
int32_t esi;
int32_t edi;
int32_t ebp;
int32_t eax;
int32_t xds;
int32_t xes;
int32_t xfs;
int32_t xgs;
int32_t orig_eax;
int32_t eip;
int32_t xcs;
int32_t eflags;
int32_t esp;
int32_t xss;
uint64_t fs_base;
uint64_t gs_base;
};

struct sigcontext {
uint64_t r8;
uint64_t r9;
Expand Down
2 changes: 0 additions & 2 deletions src/rr_trace.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -76,8 +76,6 @@ struct Header {
# Captured XCR0 value defining XSAVE features enabled by OS.
# 0 means "unknown"; default to everything supported by CPUID EAX=0xd ECX=0
xcr0 @5 :UInt64;
# 32 bit frames have fs/gsbase values.
hasFsGsBaseValuesFor32Bit @11 :Bool;
}
}

Expand Down
57 changes: 0 additions & 57 deletions src/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -811,63 +811,6 @@ uint64_t xcr0() {
#endif
}

#define SEGV_HANDLER_MAGIC 0x98765432

static void rdgsbase_segv_handler(__attribute__((unused)) int sig,
__attribute__((unused)) siginfo_t* si,
void* user) {
#if defined(__x86_64__)
ucontext_t* ctx = (ucontext_t*)user;
ctx->uc_mcontext.gregs[REG_RIP] += 5;
ctx->uc_mcontext.gregs[REG_RAX] = SEGV_HANDLER_MAGIC;
#else
(void)user;
FATAL_X86_ONLY();
#endif
}


bool rdgsbase_works() {
#if defined(__x86_64__)
static bool did_check_rdgsbase = false;
static bool rdgsbase_ok = false;

if (did_check_rdgsbase) {
return rdgsbase_ok;
}
did_check_rdgsbase = true;

struct sigaction sa;
struct sigaction old_sa;
sa.sa_sigaction = rdgsbase_segv_handler;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_SIGINFO;
if (sigaction(SIGILL, &sa, &old_sa) < 0) {
FATAL() << "Can't set sighandler";
}

uint64_t rax;
asm volatile("rdgsbase %%rax"
: "=a"(rax) :);
if (rax == SEGV_HANDLER_MAGIC) {
LOG(debug) << "rdgsbase not available";
} else {
LOG(debug) << "rdgsbase works";
rdgsbase_ok = true;
}

if (sigaction(SIGILL, &old_sa, NULL) < 0) {
FATAL() << "Can't restore sighandler";
}
return rdgsbase_ok;
#elif defined(__i386__)
return false;
#else
FATAL_X86_ONLY();
return false;
#endif
}

#if defined(__i386__) || defined(__x86_64__)
CPUIDData cpuid(uint32_t code, uint32_t subrequest) {
CPUIDData result;
Expand Down
4 changes: 0 additions & 4 deletions src/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,6 @@ bool xsave_enabled();
* Fetch current XCR0 value using XGETBV instruction.
*/
uint64_t xcr0();
/**
* Does the rdgsbase instruction work?
*/
bool rdgsbase_works();

/**
* Return all CPUID values supported by this CPU.
Expand Down

0 comments on commit 2600795

Please sign in to comment.