mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 19:44:38 +08:00
Patch from Andrew Kaylor for linux:
The attached patch adds support for debugging 32-bit processes when running a 64-bit lldb on an x86_64 Linux system. Making this work required two basic changes: 1) Getting lldb to report that it could debug 32-bit processes 2) Changing an assumption about how ptrace works when debugging cross-platform For the first change, I took a conservative approach and only enabled this for x86_64 Linux platforms. It may be that the change I made in Host.cpp could be extended to other 64-bit Linux platforms, but I'm not familiar enough with the other platforms to know for sure. For the second change, the Linux ProcessMonitor class was assuming that ptrace(PTRACE_[PEEK|POKE]DATA...) would read/write a "word" based on the child process word size. However, the ptrace documentation says that the "word" size read or written is "determined by the OS variant." I verified experimentally that when ptracing a 32-bit child from a 64-bit parent a 64-bit word is read or written. llvm-svn: 163398
This commit is contained in:
@@ -339,6 +339,12 @@ Host::GetArchitecture (SystemDefaultArchitecture arch_kind)
|
||||
break;
|
||||
|
||||
case llvm::Triple::x86_64:
|
||||
g_host_arch_64.SetTriple(triple);
|
||||
g_supports_64 = true;
|
||||
g_host_arch_32.SetTriple(triple.get32BitArchVariant());
|
||||
g_supports_32 = true;
|
||||
break;
|
||||
|
||||
case llvm::Triple::sparcv9:
|
||||
case llvm::Triple::ppc64:
|
||||
case llvm::Triple::cellspu:
|
||||
|
||||
@@ -312,6 +312,17 @@ PlatformLinux::GetSupportedArchitectureAtIndex (uint32_t idx, ArchSpec &arch)
|
||||
arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture);
|
||||
return arch.IsValid();
|
||||
}
|
||||
else if (idx == 1)
|
||||
{
|
||||
// If the default host architecture is 64-bit, look for a 32-bit variant
|
||||
ArchSpec hostArch
|
||||
= Host::GetArchitecture(Host::eSystemDefaultArchitecture);
|
||||
if (hostArch.IsValid() && hostArch.GetTriple().isArch64Bit())
|
||||
{
|
||||
arch = Host::GetArchitecture (Host::eSystemDefaultArchitecture32);
|
||||
return arch.IsValid();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -77,19 +77,19 @@ static void PtraceDisplayBytes(__ptrace_request &req, void *data)
|
||||
verbose_log->Printf("PTRACE_POKETEXT %s", buf.GetData());
|
||||
break;
|
||||
}
|
||||
case PTRACE_POKEDATA:
|
||||
case PTRACE_POKEDATA:
|
||||
{
|
||||
DisplayBytes(buf, &data, 8);
|
||||
verbose_log->Printf("PTRACE_POKEDATA %s", buf.GetData());
|
||||
break;
|
||||
}
|
||||
case PTRACE_POKEUSER:
|
||||
case PTRACE_POKEUSER:
|
||||
{
|
||||
DisplayBytes(buf, &data, 8);
|
||||
verbose_log->Printf("PTRACE_POKEUSER %s", buf.GetData());
|
||||
break;
|
||||
}
|
||||
case PTRACE_SETREGS:
|
||||
case PTRACE_SETREGS:
|
||||
{
|
||||
DisplayBytes(buf, data, sizeof(user_regs_struct));
|
||||
verbose_log->Printf("PTRACE_SETREGS %s", buf.GetData());
|
||||
@@ -101,7 +101,7 @@ static void PtraceDisplayBytes(__ptrace_request &req, void *data)
|
||||
verbose_log->Printf("PTRACE_SETFPREGS %s", buf.GetData());
|
||||
break;
|
||||
}
|
||||
case PTRACE_SETSIGINFO:
|
||||
case PTRACE_SETSIGINFO:
|
||||
{
|
||||
DisplayBytes(buf, data, sizeof(siginfo_t));
|
||||
verbose_log->Printf("PTRACE_SETSIGINFO %s", buf.GetData());
|
||||
@@ -126,7 +126,7 @@ PtraceWrapper(__ptrace_request req, pid_t pid, void *addr, void *data,
|
||||
if (log)
|
||||
log->Printf("ptrace(%s, %u, %p, %p) called from file %s line %d",
|
||||
reqName, pid, addr, data, file, line);
|
||||
|
||||
|
||||
PtraceDisplayBytes(req, data);
|
||||
|
||||
errno = 0;
|
||||
@@ -163,9 +163,11 @@ PtraceWrapper(__ptrace_request req, pid_t pid, void *addr, void *data,
|
||||
// functions without needed to go thru the thread funnel.
|
||||
|
||||
static size_t
|
||||
DoReadMemory(lldb::pid_t pid, unsigned word_size,
|
||||
DoReadMemory(lldb::pid_t pid,
|
||||
lldb::addr_t vm_addr, void *buf, size_t size, Error &error)
|
||||
{
|
||||
// ptrace word size is determined by the host, not the child
|
||||
static const unsigned word_size = sizeof(void*);
|
||||
unsigned char *dst = static_cast<unsigned char*>(buf);
|
||||
size_t bytes_read;
|
||||
size_t remainder;
|
||||
@@ -179,7 +181,6 @@ DoReadMemory(lldb::pid_t pid, unsigned word_size,
|
||||
pid, word_size, (void*)vm_addr, buf, size);
|
||||
|
||||
assert(sizeof(data) >= word_size);
|
||||
assert(sizeof(void*) == word_size);
|
||||
for (bytes_read = 0; bytes_read < size; bytes_read += remainder)
|
||||
{
|
||||
errno = 0;
|
||||
@@ -218,9 +219,11 @@ DoReadMemory(lldb::pid_t pid, unsigned word_size,
|
||||
}
|
||||
|
||||
static size_t
|
||||
DoWriteMemory(lldb::pid_t pid, unsigned word_size,
|
||||
DoWriteMemory(lldb::pid_t pid,
|
||||
lldb::addr_t vm_addr, const void *buf, size_t size, Error &error)
|
||||
{
|
||||
// ptrace word size is determined by the host, not the child
|
||||
static const unsigned word_size = sizeof(void*);
|
||||
const unsigned char *src = static_cast<const unsigned char*>(buf);
|
||||
size_t bytes_written = 0;
|
||||
size_t remainder;
|
||||
@@ -232,7 +235,6 @@ DoWriteMemory(lldb::pid_t pid, unsigned word_size,
|
||||
log->Printf ("ProcessMonitor::%s(%d, %d, %p, %p, %d, _)", __FUNCTION__,
|
||||
pid, word_size, (void*)vm_addr, buf, size);
|
||||
|
||||
assert(sizeof(void*) == word_size);
|
||||
for (bytes_written = 0; bytes_written < size; bytes_written += remainder)
|
||||
{
|
||||
remainder = size - bytes_written;
|
||||
@@ -263,7 +265,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned word_size,
|
||||
else
|
||||
{
|
||||
unsigned char buff[8];
|
||||
if (DoReadMemory(pid, word_size, vm_addr,
|
||||
if (DoReadMemory(pid, vm_addr,
|
||||
buff, word_size, error) != word_size)
|
||||
{
|
||||
if (log)
|
||||
@@ -273,7 +275,7 @@ DoWriteMemory(lldb::pid_t pid, unsigned word_size,
|
||||
|
||||
memcpy(buff, src, remainder);
|
||||
|
||||
if (DoWriteMemory(pid, word_size, vm_addr,
|
||||
if (DoWriteMemory(pid, vm_addr,
|
||||
buff, word_size, error) != word_size)
|
||||
{
|
||||
if (log)
|
||||
@@ -361,10 +363,9 @@ private:
|
||||
void
|
||||
ReadOperation::Execute(ProcessMonitor *monitor)
|
||||
{
|
||||
const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
|
||||
lldb::pid_t pid = monitor->GetPID();
|
||||
|
||||
m_result = DoReadMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
|
||||
m_result = DoReadMemory(pid, m_addr, m_buff, m_size, m_error);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -392,10 +393,9 @@ private:
|
||||
void
|
||||
WriteOperation::Execute(ProcessMonitor *monitor)
|
||||
{
|
||||
const unsigned word_size = monitor->GetProcess().GetAddressByteSize();
|
||||
lldb::pid_t pid = monitor->GetPID();
|
||||
|
||||
m_result = DoWriteMemory(pid, word_size, m_addr, m_buff, m_size, m_error);
|
||||
m_result = DoWriteMemory(pid, m_addr, m_buff, m_size, m_error);
|
||||
}
|
||||
|
||||
|
||||
@@ -744,7 +744,7 @@ DetachOperation::Execute(ProcessMonitor *monitor)
|
||||
|
||||
if (ptrace(PT_DETACH, pid, NULL, 0) < 0)
|
||||
m_error.SetErrorToErrno();
|
||||
|
||||
|
||||
}
|
||||
|
||||
ProcessMonitor::OperationArgs::OperationArgs(ProcessMonitor *monitor)
|
||||
@@ -1060,22 +1060,22 @@ ProcessMonitor::Launch(LaunchArgs *args)
|
||||
args->m_error.SetErrorToGenericError();
|
||||
switch (WEXITSTATUS(status))
|
||||
{
|
||||
case ePtraceFailed:
|
||||
case ePtraceFailed:
|
||||
args->m_error.SetErrorString("Child ptrace failed.");
|
||||
break;
|
||||
case eDupStdinFailed:
|
||||
case eDupStdinFailed:
|
||||
args->m_error.SetErrorString("Child open stdin failed.");
|
||||
break;
|
||||
case eDupStdoutFailed:
|
||||
case eDupStdoutFailed:
|
||||
args->m_error.SetErrorString("Child open stdout failed.");
|
||||
break;
|
||||
case eDupStderrFailed:
|
||||
case eDupStderrFailed:
|
||||
args->m_error.SetErrorString("Child open stderr failed.");
|
||||
break;
|
||||
case eExecFailed:
|
||||
case eExecFailed:
|
||||
args->m_error.SetErrorString("Child exec failed.");
|
||||
break;
|
||||
default:
|
||||
default:
|
||||
args->m_error.SetErrorString("Child returned unknown exit status.");
|
||||
break;
|
||||
}
|
||||
@@ -1228,7 +1228,7 @@ ProcessMonitor::MonitorCallback(void *callback_baton,
|
||||
case SIGTRAP:
|
||||
message = MonitorSIGTRAP(monitor, &info, pid);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
message = MonitorSignal(monitor, &info, pid);
|
||||
break;
|
||||
@@ -1342,7 +1342,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
|
||||
|
||||
reason = ProcessMessage::eInvalidCrashReason;
|
||||
|
||||
switch (info->si_code)
|
||||
switch (info->si_code)
|
||||
{
|
||||
default:
|
||||
assert(false && "unexpected si_code for SIGSEGV");
|
||||
@@ -1354,7 +1354,7 @@ ProcessMonitor::GetCrashReasonForSIGSEGV(const siginfo_t *info)
|
||||
reason = ProcessMessage::ePrivilegedAddress;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return reason;
|
||||
}
|
||||
|
||||
@@ -1675,7 +1675,7 @@ ProcessMonitor::Detach()
|
||||
DoOperation(&op);
|
||||
StopMonitor();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
ProcessMonitor::DupDescriptor(const char *path, int fd, int flags)
|
||||
|
||||
Reference in New Issue
Block a user