Skip to content

Commit

Permalink
Added dynamic TargetDescription
Browse files Browse the repository at this point in the history
TargetDescription dynamically generates the "master" target description
contents (target.xml), so that we only have to manage the individual
concrete CPU features (like foo-sse.xml, for instance). TargetDescription
will generate the xml contents that includes the used features.

Removed combinatorial target.xml files

These are now handled by `TargetDescription` instead.

This unblocks the rr-debugger#3776 PR (AVX512 support) from getting pulled in,
though that PR will need to take this PR into account.
  • Loading branch information
theIDinside committed Jul 11, 2024
1 parent 1628175 commit c276f0e
Show file tree
Hide file tree
Showing 12 changed files with 170 additions and 149 deletions.
7 changes: 1 addition & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,7 @@ set(RR_SOURCES
src/SourcesCommand.cc
src/StdioMonitor.cc
src/SysCpuMonitor.cc
src/TargetDescription.cc
src/Task.cc
src/ThreadGroup.cc
src/TraceeAttentionSet.cc
Expand Down Expand Up @@ -768,12 +769,6 @@ set(RR_GDB_RESOURCES
64bit-seg.xml
64bit-sse.xml
64bit-pkeys.xml
amd64-pkeys-linux.xml
amd64-avx-linux.xml
amd64-linux.xml
i386-pkeys-linux.xml
i386-avx-linux.xml
i386-linux.xml
aarch64-core.xml
aarch64-fpu.xml
aarch64-pauth.xml
Expand Down
1 change: 1 addition & 0 deletions src/GdbServer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,7 @@ void GdbServer::dispatch_regs_request(const Registers& regs,
return;
}
vector<GdbServerRegisterValue> rs;
rs.reserve(end);
for (GdbServerRegister r = GdbServerRegister(0); r <= end; r = GdbServerRegister(r + 1)) {
rs.push_back(get_reg(regs, extra_regs, r));
}
Expand Down
42 changes: 13 additions & 29 deletions src/GdbServerConnection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
#include "DebuggerExtensionCommandHandler.h"
#include "ReplaySession.h"
#include "ScopedFd.h"
#include "TargetDescription.h"
#include "core.h"
#include "log.h"

Expand Down Expand Up @@ -111,7 +112,8 @@ unique_ptr<GdbServerConnection> GdbServerConnection::await_connection(
Task* t, ScopedFd& listen_fd, const GdbServerConnection::Features& features) {
auto dbg = unique_ptr<GdbServerConnection>(
new GdbServerConnection(t->thread_group()->tguid(), features));
dbg->set_cpu_features(get_cpu_features(t->arch()));
const auto arch = t->arch();
dbg->set_cpu_features(arch, get_cpu_features(arch));
dbg->await_debugger(listen_fd);
return dbg;
}
Expand Down Expand Up @@ -503,29 +505,6 @@ static string read_target_desc(const char* file_name) {
return ss.str();
}

static const char* target_description_name(uint32_t cpu_features) {
// This doesn't scale, but it's what gdb does...
switch (cpu_features) {
case 0:
return "i386-linux.xml";
case GdbServerConnection::CPU_X86_64:
return "amd64-linux.xml";
case GdbServerConnection::CPU_AVX:
return "i386-avx-linux.xml";
case GdbServerConnection::CPU_X86_64 | GdbServerConnection::CPU_AVX:
return "amd64-avx-linux.xml";
case GdbServerConnection::CPU_PKU | GdbServerConnection::CPU_AVX:
return "i386-pkeys-linux.xml";
case GdbServerConnection::CPU_X86_64 | GdbServerConnection::CPU_PKU | GdbServerConnection::CPU_AVX:
return "amd64-pkeys-linux.xml";
case GdbServerConnection::CPU_AARCH64:
return "aarch64-core.xml";
default:
FATAL() << "Unknown features";
return nullptr;
}
}

bool GdbServerConnection::xfer(const char* name, char* args) {
const char* mode = args;
args = strchr(args, ':');
Expand Down Expand Up @@ -609,11 +588,8 @@ bool GdbServerConnection::xfer(const char* name, char* args) {
return false;
}

string target_desc =
read_target_desc((strcmp(annex, "") && strcmp(annex, "target.xml"))
? annex
: target_description_name(cpu_features_));
write_xfer_response(target_desc.c_str(), target_desc.size(), offset, len);
const auto desc = (strcmp(annex, "") && strcmp(annex, "target.xml") ? read_target_desc(annex) : target_decription->to_xml());
write_xfer_response(desc.c_str(), desc.size(), offset, len);
return false;
}

Expand Down Expand Up @@ -2341,4 +2317,12 @@ bool GdbServerConnection::is_connection_alive() { return connection_alive_; }

bool GdbServerConnection::is_pass_signal(int sig) { return pass_signals.find(to_gdb_signum(sig)) != pass_signals.end(); }

void GdbServerConnection::set_cpu_features(SupportedArch arch,
uint32_t features) {
cpu_features_ = features;
DEBUG_ASSERT(target_decription == nullptr &&
"Target description already created");
target_decription = std::make_unique<TargetDescription>(arch, cpu_features_);
}

} // namespace rr
5 changes: 4 additions & 1 deletion src/GdbServerConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "ReplaySession.h"
#include "ReplayTimeline.h"
#include "ScopedFd.h"
#include "TargetDescription.h"
#include "TaskishUid.h"
#include "core.h"

Expand Down Expand Up @@ -750,7 +751,8 @@ class GdbServerConnection {
CPU_AARCH64 = 0x4,
CPU_PKU = 0x8
};
void set_cpu_features(uint32_t features) { cpu_features_ = features; }

void set_cpu_features(SupportedArch arch, uint32_t features);
uint32_t cpu_features() const { return cpu_features_; }

GdbServerConnection(ThreadGroupUid tguid, const Features& features);
Expand Down Expand Up @@ -877,6 +879,7 @@ class GdbServerConnection {
bool hwbreak_supported_; // client supports hwbreak extension
bool swbreak_supported_; // client supports swbreak extension
bool list_threads_in_stop_reply_; // client requested threads: and thread-pcs: in stop replies
std::unique_ptr<TargetDescription> target_decription{nullptr};
};

} // namespace rr
Expand Down
124 changes: 124 additions & 0 deletions src/TargetDescription.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
#include "TargetDescription.h"
#include "GdbServerConnection.h"
#include "kernel_abi.h"
#include <sstream>
namespace rr {

class FeatureStream {
std::stringstream stream{};
const char* arch_prefix{nullptr};

public:
std::string result() noexcept { return stream.str(); }

template <typename Any>
friend FeatureStream& operator<<(FeatureStream& stream, Any any) noexcept;
};

template <typename Any>
FeatureStream& operator<<(FeatureStream& stream, Any any) noexcept {
stream.stream << any;
return stream;
}

template <>
FeatureStream& operator<<(FeatureStream& stream,
rr::SupportedArch arch) noexcept {
stream << "<architecture>";
switch (arch) {
case rr::x86:
stream << "i386";
stream.arch_prefix = "32bit-";
break;
case rr::x86_64:
stream << "i386:x86-64";
stream.arch_prefix = "64bit-";
break;
case rr::aarch64:
stream << "aarch64";
stream.arch_prefix = "aarch64-";
break;
}
stream << "</architecture>\n";
return stream;
}

template <>
FeatureStream& operator<<(FeatureStream& stream,
TargetFeature feature) noexcept {
DEBUG_ASSERT(stream.arch_prefix != nullptr &&
"No architecture has been provided to description");
stream << R"( <xi:include href=")" << stream.arch_prefix;
switch (feature) {
case TargetFeature::Core:
stream << "core.xml";
break;
case TargetFeature::Linux:
stream << "linux.xml";
break;
case TargetFeature::SSE:
stream << "sse.xml";
break;
case TargetFeature::AVX:
stream << "avx.xml";
break;
case TargetFeature::PKeys:
stream << "pkeys.xml";
break;
case TargetFeature::Segment:
stream << "seg.xml";
break;
}
stream << R"("/>)" << '\n';
return stream;
}

TargetDescription::TargetDescription(rr::SupportedArch arch,
u32 cpu_features) noexcept
: arch(arch), target_features() {

// default-assumed registers per arch
switch (arch) {
case rr::x86:
target_features.push_back(TargetFeature::Core);
target_features.push_back(TargetFeature::SSE);
target_features.push_back(TargetFeature::Linux);
break;
case rr::x86_64:
target_features.push_back(TargetFeature::Core);
target_features.push_back(TargetFeature::SSE);
target_features.push_back(TargetFeature::Linux);
target_features.push_back(TargetFeature::Segment);
break;
case rr::aarch64:
target_features.push_back(TargetFeature::Core);
break;
}

if (cpu_features & rr::GdbServerConnection::CPU_AVX) {
DEBUG_ASSERT((arch == rr::x86 || arch == rr::x86_64) && "unexpected arch");
target_features.push_back(TargetFeature::AVX);
}

if (cpu_features & rr::GdbServerConnection::CPU_PKU) {
DEBUG_ASSERT((arch == rr::x86 || arch == rr::x86_64) && "unexpected arch");
target_features.push_back(TargetFeature::PKeys);
}
}

static constexpr auto Header = R"(<?xml version="1.0"?>
<!DOCTYPE target SYSTEM "gdb-target.dtd">
<target>
)";

std::string TargetDescription::to_xml() const noexcept {
FeatureStream fs{};
fs << Header << arch << "<osabi>GNU/Linux</osabi>\n";
for (const auto feature : target_features) {
fs << feature;
}
fs << "</target>";

return fs.result();
}
} // namespace rr
27 changes: 27 additions & 0 deletions src/TargetDescription.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#pragma once
#include "kernel_abi.h"
#include <cstdint>

namespace rr {

struct GdbServerRegisterValue;

using u32 = std::uint32_t;

enum class TargetFeature : u32 {
Core = 0,
SSE,
Linux,
Segment,
AVX,
PKeys
};

class TargetDescription {
SupportedArch arch;
std::vector<TargetFeature> target_features;
public:
explicit TargetDescription(rr::SupportedArch arch, u32 cpu_features) noexcept;
std::string to_xml() const noexcept;
};
}
19 changes: 0 additions & 19 deletions third-party/gdb/amd64-avx-linux.xml

This file was deleted.

19 changes: 0 additions & 19 deletions third-party/gdb/amd64-linux.xml

This file was deleted.

20 changes: 0 additions & 20 deletions third-party/gdb/amd64-pkeys-linux.xml

This file was deleted.

18 changes: 0 additions & 18 deletions third-party/gdb/i386-avx-linux.xml

This file was deleted.

18 changes: 0 additions & 18 deletions third-party/gdb/i386-linux.xml

This file was deleted.

Loading

0 comments on commit c276f0e

Please sign in to comment.