225 changes: 225 additions & 0 deletions lldb/source/Host/openbsd/Host.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
//===-- source/Host/openbsd/Host.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

// C Includes
#include <sys/types.h>

#include <sys/signal.h>
#include <sys/exec.h>
#include <sys/proc.h>
#include <sys/ptrace.h>
#include <sys/sysctl.h>
#include <sys/user.h>

#include <stdio.h>

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Module.h"
#include "lldb/Core/StreamFile.h"
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/NameMatches.h"

#include "llvm/Support/Host.h"

extern "C" {
extern char **environ;
}

using namespace lldb;
using namespace lldb_private;

size_t Host::GetEnvironment(StringList &env) {
char *v;
char **var = environ;
for (; var != NULL && *var != NULL; ++var) {
v = strchr(*var, (int)'-');
if (v == NULL)
continue;
env.AppendString(v);
}
return env.GetSize();
}

static bool
GetOpenBSDProcessArgs(const ProcessInstanceInfoMatch *match_info_ptr,
ProcessInstanceInfo &process_info) {
if (process_info.ProcessIDIsValid()) {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_ARGS,
(int)process_info.GetProcessID()};

char arg_data[8192];
size_t arg_data_size = sizeof(arg_data);
if (::sysctl(mib, 4, arg_data, &arg_data_size, NULL, 0) == 0) {
DataExtractor data(arg_data, arg_data_size, endian::InlHostByteOrder(),
sizeof(void *));
lldb::offset_t offset = 0;
const char *cstr;

cstr = data.GetCStr(&offset);
if (cstr) {
process_info.GetExecutableFile().SetFile(cstr, false);

if (!(match_info_ptr == NULL ||
NameMatches(
process_info.GetExecutableFile().GetFilename().GetCString(),
match_info_ptr->GetNameMatchType(),
match_info_ptr->GetProcessInfo().GetName())))
return false;

Args &proc_args = process_info.GetArguments();
while (1) {
const uint8_t *p = data.PeekData(offset, 1);
while ((p != NULL) && (*p == '\0') && offset < arg_data_size) {
++offset;
p = data.PeekData(offset, 1);
}
if (p == NULL || offset >= arg_data_size)
return true;

cstr = data.GetCStr(&offset);
if (cstr)
proc_args.AppendArgument(llvm::StringRef(cstr));
else
return true;
}
}
}
}
return false;
}

static bool GetOpenBSDProcessCPUType(ProcessInstanceInfo &process_info) {
if (process_info.ProcessIDIsValid()) {
process_info.GetArchitecture() =
HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
return true;
}
process_info.GetArchitecture().Clear();
return false;
}

static bool GetOpenBSDProcessUserAndGroup(ProcessInstanceInfo &process_info) {
struct kinfo_proc proc_kinfo;
size_t proc_kinfo_size;

if (process_info.ProcessIDIsValid()) {
int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID,
(int)process_info.GetProcessID()};
proc_kinfo_size = sizeof(struct kinfo_proc);

if (::sysctl(mib, 4, &proc_kinfo, &proc_kinfo_size, NULL, 0) == 0) {
if (proc_kinfo_size > 0) {
process_info.SetParentProcessID(proc_kinfo.p_ppid);
process_info.SetUserID(proc_kinfo.p_ruid);
process_info.SetGroupID(proc_kinfo.p_rgid);
process_info.SetEffectiveUserID(proc_kinfo.p_uid);
process_info.SetEffectiveGroupID(proc_kinfo.p_gid);
return true;
}
}
}
process_info.SetParentProcessID(LLDB_INVALID_PROCESS_ID);
process_info.SetUserID(UINT32_MAX);
process_info.SetGroupID(UINT32_MAX);
process_info.SetEffectiveUserID(UINT32_MAX);
process_info.SetEffectiveGroupID(UINT32_MAX);
return false;
}

uint32_t Host::FindProcesses(const ProcessInstanceInfoMatch &match_info,
ProcessInstanceInfoList &process_infos) {
std::vector<struct kinfo_proc> kinfos;

int mib[3] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};

size_t pid_data_size = 0;
if (::sysctl(mib, 3, NULL, &pid_data_size, NULL, 0) != 0)
return 0;

// Add a few extra in case a few more show up
const size_t estimated_pid_count =
(pid_data_size / sizeof(struct kinfo_proc)) + 10;

kinfos.resize(estimated_pid_count);
pid_data_size = kinfos.size() * sizeof(struct kinfo_proc);

if (::sysctl(mib, 3, &kinfos[0], &pid_data_size, NULL, 0) != 0)
return 0;

const size_t actual_pid_count = (pid_data_size / sizeof(struct kinfo_proc));

bool all_users = match_info.GetMatchAllUsers();
const ::pid_t our_pid = getpid();
const uid_t our_uid = getuid();
for (size_t i = 0; i < actual_pid_count; i++) {
const struct kinfo_proc &kinfo = kinfos[i];
const bool kinfo_user_matches = (all_users || (kinfo.p_ruid == our_uid) ||
// Special case, if lldb is being run as
// root we can attach to anything.
(our_uid == 0));

if (kinfo_user_matches == false || // Make sure the user is acceptable
kinfo.p_pid == our_pid || // Skip this process
kinfo.p_pid == 0 || // Skip kernel (kernel pid is zero)
kinfo.p_stat == SZOMB || // Zombies are bad, they like brains...
kinfo.p_psflags & PS_TRACED || // Being debugged?
kinfo.p_flag & P_WEXIT) // Working on exiting
continue;

ProcessInstanceInfo process_info;
process_info.SetProcessID(kinfo.p_pid);
process_info.SetParentProcessID(kinfo.p_ppid);
process_info.SetUserID(kinfo.p_ruid);
process_info.SetGroupID(kinfo.p_rgid);
process_info.SetEffectiveUserID(kinfo.p_svuid);
process_info.SetEffectiveGroupID(kinfo.p_svgid);

// Make sure our info matches before we go fetch the name and cpu type
if (match_info.Matches(process_info) &&
GetOpenBSDProcessArgs(&match_info, process_info)) {
GetOpenBSDProcessCPUType(process_info);
if (match_info.Matches(process_info))
process_infos.Append(process_info);
}
}

return process_infos.GetSize();
}

bool Host::GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info) {
process_info.SetProcessID(pid);

if (GetOpenBSDProcessArgs(NULL, process_info)) {
// should use libprocstat instead of going right into sysctl?
GetOpenBSDProcessCPUType(process_info);
GetOpenBSDProcessUserAndGroup(process_info);
return true;
}

process_info.Clear();
return false;
}

Error Host::ShellExpandArguments(ProcessLaunchInfo &launch_info) {
return Error("unimplemented");
}
65 changes: 65 additions & 0 deletions lldb/source/Host/openbsd/HostInfoOpenBSD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
//===-- HostInfoOpenBSD.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "lldb/Host/openbsd/HostInfoOpenBSD.h"

#include <stdio.h>
#include <string.h>
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/utsname.h>

using namespace lldb_private;

bool HostInfoOpenBSD::GetOSVersion(uint32_t &major, uint32_t &minor,
uint32_t &update) {
struct utsname un;

::memset(&un, 0, sizeof(utsname));
if (uname(&un) < 0)
return false;

int status = sscanf(un.release, "%u.%u", &major, &minor);
return status == 2;
}

bool HostInfoOpenBSD::GetOSBuildString(std::string &s) {
int mib[2] = {CTL_KERN, KERN_OSREV};
char osrev_str[12];
uint32_t osrev = 0;
size_t osrev_len = sizeof(osrev);

if (::sysctl(mib, 2, &osrev, &osrev_len, NULL, 0) == 0) {
::snprintf(osrev_str, sizeof(osrev_str), "%-8.8u", osrev);
s.assign(osrev_str);
return true;
}

s.clear();
return false;
}

bool HostInfoOpenBSD::GetOSKernelDescription(std::string &s) {
struct utsname un;

::memset(&un, 0, sizeof(utsname));
s.clear();

if (uname(&un) < 0)
return false;

s.assign(un.version);

return true;
}

FileSpec HostInfoOpenBSD::GetProgramFileSpec() {
static FileSpec g_program_filespec;
return g_program_filespec;
}
11 changes: 9 additions & 2 deletions lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ namespace {
const char *const LLDB_NT_OWNER_FREEBSD = "FreeBSD";
const char *const LLDB_NT_OWNER_GNU = "GNU";
const char *const LLDB_NT_OWNER_NETBSD = "NetBSD";
const char *const LLDB_NT_OWNER_OPENBSD = "OpenBSD";
const char *const LLDB_NT_OWNER_CSR = "csr";
const char *const LLDB_NT_OWNER_ANDROID = "Android";
const char *const LLDB_NT_OWNER_CORE = "CORE";
Expand Down Expand Up @@ -832,7 +833,7 @@ bool ObjectFileELF::SetLoadAddress(Target &target, lldb::addr_t value,
if (section_list) {
if (!value_is_offset) {
bool found_offset = false;
for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) {
for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
if (header == nullptr)
continue;
Expand Down Expand Up @@ -1369,6 +1370,12 @@ ObjectFileELF::RefineModuleDetailsFromNote(lldb_private::DataExtractor &data,
"ObjectFileELF::%s detected NetBSD, min version constant %" PRIu32,
__FUNCTION__, version_info);
}
// Process OpenBSD ELF notes.
else if (note.n_name == LLDB_NT_OWNER_OPENBSD) {
// Set the elf OS version to OpenBSD. Also clear the vendor.
arch_spec.GetTriple().setOS(llvm::Triple::OSType::OpenBSD);
arch_spec.GetTriple().setVendor(llvm::Triple::VendorType::UnknownVendor);
}
// Process CSR kalimba notes
else if ((note.n_type == LLDB_NT_GNU_ABI_TAG) &&
(note.n_name == LLDB_NT_OWNER_CSR)) {
Expand Down Expand Up @@ -3349,7 +3356,7 @@ bool ObjectFileELF::GetArchitecture(ArchSpec &arch) {
// headers
// that might shed more light on the architecture
if (ParseProgramHeaders()) {
for (size_t i = 0, count = GetProgramHeaderCount(); i < count; ++i) {
for (size_t i = 1, count = GetProgramHeaderCount(); i <= count; ++i) {
const elf::ELFProgramHeader *header = GetProgramHeaderByIndex(i);
if (header && header->p_type == PT_NOTE && header->p_offset != 0 &&
header->p_filesz > 0) {
Expand Down
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Platform/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
add_subdirectory(FreeBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "NetBSD")
add_subdirectory(NetBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
add_subdirectory(OpenBSD)
#elseif (CMAKE_SYSTEM_NAME MATCHES "Darwin")
add_subdirectory(MacOSX)
#elseif (CMAKE_SYSTEM_NAME MATCHES "Windows")
Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ PlatformSP PlatformFreeBSD::CreateInstance(bool force, const ArchSpec *arch) {
create = true;
break;

#if defined(__FreeBSD__) || defined(__OpenBSD__)
#if defined(__FreeBSD__)
// Only accept "unknown" for the OS if the host is BSD and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
Expand Down
9 changes: 9 additions & 0 deletions lldb/source/Plugins/Platform/OpenBSD/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
add_lldb_library(lldbPluginPlatformOpenBSD PLUGIN
PlatformOpenBSD.cpp

LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbTarget
)
223 changes: 223 additions & 0 deletions lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,223 @@
//===-- PlatformOpenBSD.cpp -------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "PlatformOpenBSD.h"
#include "lldb/Host/Config.h"

// C Includes
#include <stdio.h>
#ifndef LLDB_DISABLE_POSIX
#include <sys/utsname.h>
#endif

// C++ Includes
// Other libraries and framework includes
// Project includes
#include "lldb/Core/Debugger.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/State.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
#include "lldb/Utility/Error.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/StreamString.h"

// Define these constants from OpenBSD mman.h for use when targeting
// remote openbsd systems even when host has different values.
#define MAP_PRIVATE 0x0002
#define MAP_ANON 0x1000

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::platform_openbsd;

static uint32_t g_initialize_count = 0;

//------------------------------------------------------------------

PlatformSP PlatformOpenBSD::CreateInstance(bool force, const ArchSpec *arch) {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PLATFORM));
LLDB_LOG(log, "force = {0}, arch=({1}, {2})", force,
arch ? arch->GetArchitectureName() : "<null>",
arch ? arch->GetTriple().getTriple() : "<null>");

bool create = force;
if (create == false && arch && arch->IsValid()) {
const llvm::Triple &triple = arch->GetTriple();
switch (triple.getOS()) {
case llvm::Triple::OpenBSD:
create = true;
break;

#if defined(__OpenBSD__)
// Only accept "unknown" for the OS if the host is BSD and
// it "unknown" wasn't specified (it was just returned because it
// was NOT specified)
case llvm::Triple::OSType::UnknownOS:
create = !arch->TripleOSWasSpecified();
break;
#endif
default:
break;
}
}
LLDB_LOG(log, "create = {0}", create);
if (create) {
return PlatformSP(new PlatformOpenBSD(false));
}
return PlatformSP();
}

ConstString PlatformOpenBSD::GetPluginNameStatic(bool is_host) {
if (is_host) {
static ConstString g_host_name(Platform::GetHostPlatformName());
return g_host_name;
} else {
static ConstString g_remote_name("remote-openbsd");
return g_remote_name;
}
}

const char *PlatformOpenBSD::GetPluginDescriptionStatic(bool is_host) {
if (is_host)
return "Local OpenBSD user platform plug-in.";
else
return "Remote OpenBSD user platform plug-in.";
}

ConstString PlatformOpenBSD::GetPluginName() {
return GetPluginNameStatic(IsHost());
}

void PlatformOpenBSD::Initialize() {
Platform::Initialize();

if (g_initialize_count++ == 0) {
#if defined(__OpenBSD__)
PlatformSP default_platform_sp(new PlatformOpenBSD(true));
default_platform_sp->SetSystemArchitecture(HostInfo::GetArchitecture());
Platform::SetHostPlatform(default_platform_sp);
#endif
PluginManager::RegisterPlugin(
PlatformOpenBSD::GetPluginNameStatic(false),
PlatformOpenBSD::GetPluginDescriptionStatic(false),
PlatformOpenBSD::CreateInstance, nullptr);
}
}

void PlatformOpenBSD::Terminate() {
if (g_initialize_count > 0) {
if (--g_initialize_count == 0) {
PluginManager::UnregisterPlugin(PlatformOpenBSD::CreateInstance);
}
}

PlatformPOSIX::Terminate();
}

//------------------------------------------------------------------
/// Default Constructor
//------------------------------------------------------------------
PlatformOpenBSD::PlatformOpenBSD(bool is_host)
: PlatformPOSIX(is_host) // This is the local host platform
{}

PlatformOpenBSD::~PlatformOpenBSD() = default;

bool PlatformOpenBSD::GetSupportedArchitectureAtIndex(uint32_t idx,
ArchSpec &arch) {
if (IsHost()) {
ArchSpec hostArch = HostInfo::GetArchitecture(HostInfo::eArchKindDefault);
if (hostArch.GetTriple().isOSOpenBSD()) {
if (idx == 0) {
arch = hostArch;
return arch.IsValid();
}
}
} else {
if (m_remote_platform_sp)
return m_remote_platform_sp->GetSupportedArchitectureAtIndex(idx, arch);

llvm::Triple triple;
// Set the OS to OpenBSD
triple.setOS(llvm::Triple::OpenBSD);
// Set the architecture
switch (idx) {
case 0:
triple.setArchName("x86_64");
break;
case 1:
triple.setArchName("i386");
break;
case 2:
triple.setArchName("aarch64");
break;
case 3:
triple.setArchName("arm");
break;
default:
return false;
}
// Leave the vendor as "llvm::Triple:UnknownVendor" and don't specify the
// vendor by
// calling triple.SetVendorName("unknown") so that it is a "unspecified
// unknown".
// This means when someone calls triple.GetVendorName() it will return an
// empty string
// which indicates that the vendor can be set when two architectures are
// merged

// Now set the triple into "arch" and return true
arch.SetTriple(triple);
return true;
}
return false;
}

void PlatformOpenBSD::GetStatus(Stream &strm) {
Platform::GetStatus(strm);

#ifndef LLDB_DISABLE_POSIX
// Display local kernel information only when we are running in host mode.
// Otherwise, we would end up printing non-OpenBSD information (when running
// on Mac OS for example).
if (IsHost()) {
struct utsname un;

if (uname(&un))
return;

strm.Printf(" Kernel: %s\n", un.sysname);
strm.Printf(" Release: %s\n", un.release);
strm.Printf(" Version: %s\n", un.version);
}
#endif
}

// OpenBSD processes cannot yet be launched by spawning and attaching.
bool PlatformOpenBSD::CanDebugProcess() {
return false;
}

void PlatformOpenBSD::CalculateTrapHandlerSymbolNames() {
m_trap_handlers.push_back(ConstString("_sigtramp"));
}

uint64_t PlatformOpenBSD::ConvertMmapFlagsToPlatform(const ArchSpec &arch,
unsigned flags) {
uint64_t flags_platform = 0;

if (flags & eMmapFlagsPrivate)
flags_platform |= MAP_PRIVATE;
if (flags & eMmapFlagsAnon)
flags_platform |= MAP_ANON;
return flags_platform;
}
66 changes: 66 additions & 0 deletions lldb/source/Plugins/Platform/OpenBSD/PlatformOpenBSD.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
//===-- PlatformOpenBSD.h ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_PlatformOpenBSD_h_
#define liblldb_PlatformOpenBSD_h_

#include "Plugins/Platform/POSIX/PlatformPOSIX.h"

namespace lldb_private {
namespace platform_openbsd {

class PlatformOpenBSD : public PlatformPOSIX {
public:
PlatformOpenBSD(bool is_host);

~PlatformOpenBSD() override;

static void Initialize();

static void Terminate();

//------------------------------------------------------------
// lldb_private::PluginInterface functions
//------------------------------------------------------------
static lldb::PlatformSP CreateInstance(bool force, const ArchSpec *arch);

static ConstString GetPluginNameStatic(bool is_host);

static const char *GetPluginDescriptionStatic(bool is_host);

ConstString GetPluginName() override;

uint32_t GetPluginVersion() override { return 1; }

//------------------------------------------------------------
// lldb_private::Platform functions
//------------------------------------------------------------
const char *GetDescription() override {
return GetPluginDescriptionStatic(IsHost());
}

void GetStatus(Stream &strm) override;

bool GetSupportedArchitectureAtIndex(uint32_t idx, ArchSpec &arch) override;

bool CanDebugProcess() override;

void CalculateTrapHandlerSymbolNames() override;

uint64_t ConvertMmapFlagsToPlatform(const ArchSpec &arch,
unsigned flags) override;

private:
DISALLOW_COPY_AND_ASSIGN(PlatformOpenBSD);
};

} // namespace platform_openbsd
} // namespace lldb_private

#endif // liblldb_PlatformOpenBSD_h_
2 changes: 2 additions & 0 deletions lldb/source/Plugins/Process/Utility/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ add_lldb_library(lldbPluginProcessUtility PLUGIN
RegisterContextMach_x86_64.cpp
RegisterContextMemory.cpp
RegisterContextNetBSD_x86_64.cpp
RegisterContextOpenBSD_i386.cpp
RegisterContextOpenBSD_x86_64.cpp
RegisterContextPOSIX_arm.cpp
RegisterContextPOSIX_arm64.cpp
RegisterContextPOSIX_mips64.cpp
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===-- RegisterContextOpenBSD_i386.cpp ------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include "RegisterContextOpenBSD_i386.h"
#include "RegisterContextPOSIX_x86.h"

using namespace lldb_private;
using namespace lldb;

// /usr/include/machine/reg.h
struct GPR {
uint32_t eax;
uint32_t ecx;
uint32_t edx;
uint32_t ebx;
uint32_t esp;
uint32_t ebp;
uint32_t esi;
uint32_t edi;
uint32_t eip;
uint32_t eflags;
uint32_t cs;
uint32_t ss;
uint32_t ds;
uint32_t es;
uint32_t fs;
uint32_t gs;
};

struct dbreg {
uint32_t dr[8]; /* debug registers */
/* Index 0-3: debug address registers */
/* Index 4-5: reserved */
/* Index 6: debug status */
/* Index 7: debug control */
};

using FPR_i386 = FXSAVE;

struct UserArea {
GPR gpr;
FPR_i386 i387;
};

#define DR_SIZE sizeof(uint32_t)
#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(dbreg, dr[reg_index]))

//---------------------------------------------------------------------------
// Include RegisterInfos_i386 to declare our g_register_infos_i386 structure.
//---------------------------------------------------------------------------
#define DECLARE_REGISTER_INFOS_I386_STRUCT
#include "RegisterInfos_i386.h"
#undef DECLARE_REGISTER_INFOS_I386_STRUCT

RegisterContextOpenBSD_i386::RegisterContextOpenBSD_i386(
const ArchSpec &target_arch)
: RegisterInfoInterface(target_arch) {}

size_t RegisterContextOpenBSD_i386::GetGPRSize() const { return sizeof(GPR); }

const RegisterInfo *RegisterContextOpenBSD_i386::GetRegisterInfo() const {
switch (m_target_arch.GetMachine()) {
case llvm::Triple::x86:
return g_register_infos_i386;
default:
assert(false && "Unhandled target architecture.");
return NULL;
}
}

uint32_t RegisterContextOpenBSD_i386::GetRegisterCount() const {
return static_cast<uint32_t>(sizeof(g_register_infos_i386) /
sizeof(g_register_infos_i386[0]));
}
26 changes: 26 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_i386.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
//===-- RegisterContextOpenBSD_i386.h ---------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_RegisterContextOpenBSD_i386_H_
#define liblldb_RegisterContextOpenBSD_i386_H_

#include "RegisterInfoInterface.h"

class RegisterContextOpenBSD_i386 : public lldb_private::RegisterInfoInterface {
public:
RegisterContextOpenBSD_i386(const lldb_private::ArchSpec &target_arch);

size_t GetGPRSize() const override;

const lldb_private::RegisterInfo *GetRegisterInfo() const override;

uint32_t GetRegisterCount() const override;
};

#endif
112 changes: 112 additions & 0 deletions lldb/source/Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
//===-- RegisterContextOpenBSD_x86_64.cpp ----------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//

#include "RegisterContextOpenBSD_x86_64.h"
#include "RegisterContextPOSIX_x86.h"
#include <vector>

using namespace lldb_private;
using namespace lldb;

// /usr/include/machine/reg.h
typedef struct _GPR {
uint64_t rdi;
uint64_t rsi;
uint64_t rdx;
uint64_t rcx;
uint64_t r8;
uint64_t r9;
uint64_t r10;
uint64_t r11;
uint64_t r12;
uint64_t r13;
uint64_t r14;
uint64_t r15;
uint64_t rbp;
uint64_t rbx;
uint64_t rax;
uint64_t rsp;
uint64_t rip;
uint64_t rflags;
uint64_t cs;
uint64_t ss;
uint64_t ds;
uint64_t es;
uint64_t fs;
uint64_t gs;
} GPR;

struct DBG {
uint64_t dr[16]; /* debug registers */
/* Index 0-3: debug address registers */
/* Index 4-5: reserved */
/* Index 6: debug status */
/* Index 7: debug control */
/* Index 8-15: reserved */
};

struct UserArea {
GPR gpr;
FPR fpr;
DBG dbg;
};

#define DR_OFFSET(reg_index) (LLVM_EXTENSION offsetof(DBG, dr[reg_index]))

//---------------------------------------------------------------------------
// Include RegisterInfos_x86_64 to declare our g_register_infos_x86_64
// structure.
//---------------------------------------------------------------------------
#define DECLARE_REGISTER_INFOS_X86_64_STRUCT
#include "RegisterInfos_x86_64.h"
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT

static std::vector<lldb_private::RegisterInfo> &GetSharedRegisterInfoVector() {
static std::vector<lldb_private::RegisterInfo> register_infos;
return register_infos;
}

static const RegisterInfo *
PrivateGetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
case llvm::Triple::x86_64:
return g_register_infos_x86_64;
default:
assert(false && "Unhandled target architecture.");
return nullptr;
}
}

static uint32_t
PrivateGetRegisterCount(const lldb_private::ArchSpec &target_arch) {
switch (target_arch.GetMachine()) {
case llvm::Triple::x86_64:
return static_cast<uint32_t>(sizeof(g_register_infos_x86_64) /
sizeof(g_register_infos_x86_64[0]));
default:
assert(false && "Unhandled target architecture.");
return 0;
}
}

RegisterContextOpenBSD_x86_64::RegisterContextOpenBSD_x86_64(
const ArchSpec &target_arch)
: lldb_private::RegisterInfoInterface(target_arch),
m_register_info_p(PrivateGetRegisterInfoPtr(target_arch)),
m_register_count(PrivateGetRegisterCount(target_arch)) {}

size_t RegisterContextOpenBSD_x86_64::GetGPRSize() const { return sizeof(GPR); }

const RegisterInfo *RegisterContextOpenBSD_x86_64::GetRegisterInfo() const {
return m_register_info_p;
}

uint32_t RegisterContextOpenBSD_x86_64::GetRegisterCount() const {
return m_register_count;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
//===-- RegisterContextOpenBSD_x86_64.h -------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_RegisterContextOpenBSD_x86_64_H_
#define liblldb_RegisterContextOpenBSD_x86_64_H_

#include "RegisterInfoInterface.h"

class RegisterContextOpenBSD_x86_64
: public lldb_private::RegisterInfoInterface {
public:
RegisterContextOpenBSD_x86_64(const lldb_private::ArchSpec &target_arch);

size_t GetGPRSize() const override;

const lldb_private::RegisterInfo *GetRegisterInfo() const override;

uint32_t GetRegisterCount() const override;

private:
const lldb_private::RegisterInfo *m_register_info_p;
const uint32_t m_register_count;
};

#endif
34 changes: 34 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,10 @@ enum {
NT_FILE = 0x46494c45,
NT_PRXFPREG = 0x46e62b7f,
NT_SIGINFO = 0x53494749,
NT_OPENBSD_PROCINFO = 10,
NT_OPENBSD_AUXV = 11,
NT_OPENBSD_REGS = 20,
NT_OPENBSD_FPREGS = 21,
};

namespace FREEBSD {
Expand Down Expand Up @@ -481,6 +485,18 @@ static void ParseFreeBSDThrMisc(ThreadData &thread_data, DataExtractor &data) {
thread_data.name = data.GetCStr(&offset, 20);
}

static void ParseOpenBSDProcInfo(ThreadData &thread_data, DataExtractor &data)
{
lldb::offset_t offset = 0;

int version = data.GetU32(&offset);
if (version != 1)
return;

offset += 4;
thread_data.signo = data.GetU32(&offset);
}

/// Parse Thread context from PT_NOTE segment and store it in the thread list
/// Notes:
/// 1) A PT_NOTE segment is composed of one or more NOTE entries.
Expand Down Expand Up @@ -569,6 +585,24 @@ Error ProcessElfCore::ParseThreadContextsFromNoteSegment(
default:
break;
}
} else if (note.n_name.substr(0, 7) == "OpenBSD") {
// OpenBSD per-thread information is stored in notes named
// "OpenBSD@nnn" so match on the initial part of the string.
m_os = llvm::Triple::OpenBSD;
switch (note.n_type) {
case NT_OPENBSD_PROCINFO:
ParseOpenBSDProcInfo(*thread_data, note_data);
break;
case NT_OPENBSD_AUXV:
m_auxv = DataExtractor(note_data);
break;
case NT_OPENBSD_REGS:
thread_data->gpregset = note_data;
break;
case NT_OPENBSD_FPREGS:
thread_data->fpregset = note_data;
break;
}
} else if (note.n_name == "CORE") {
switch (note.n_type) {
case NT_PRSTATUS:
Expand Down
22 changes: 22 additions & 0 deletions lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
#include "Plugins/Process/Utility/RegisterContextLinux_s390x.h"
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_i386.h"
#include "Plugins/Process/Utility/RegisterContextOpenBSD_x86_64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
#include "ProcessElfCore.h"
Expand Down Expand Up @@ -133,6 +135,26 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
break;
}

case llvm::Triple::OpenBSD: {
switch (arch.GetMachine()) {
case llvm::Triple::aarch64:
reg_interface = new RegisterInfoPOSIX_arm64(arch);
break;
case llvm::Triple::arm:
reg_interface = new RegisterInfoPOSIX_arm(arch);
break;
case llvm::Triple::x86:
reg_interface = new RegisterContextOpenBSD_i386(arch);
break;
case llvm::Triple::x86_64:
reg_interface = new RegisterContextOpenBSD_x86_64(arch);
break;
default:
break;
}
break;
}

default:
break;
}
Expand Down