https://github.com/svs-quic updated https://github.com/llvm/llvm-project/pull/207675
>From a921acec8a4e4b577066372ce3f8511d66d18bbe Mon Sep 17 00:00:00 2001 From: Sudharsan Veeravalli <[email protected]> Date: Mon, 6 Jul 2026 12:52:43 +0530 Subject: [PATCH 1/3] [RISCV][LLDB] Add RISC-V Architecture plugin for trap validation --- .../Plugins/Architecture/CMakeLists.txt | 1 + .../Architecture/RISCV/ArchitectureRISCV.cpp | 46 +++++++++++ .../Architecture/RISCV/ArchitectureRISCV.h | 36 +++++++++ .../Plugins/Architecture/RISCV/CMakeLists.txt | 7 ++ lldb/unittests/Architecture/CMakeLists.txt | 1 + .../RISCV/ArchitectureRISCVTest.cpp | 80 +++++++++++++++++++ .../Architecture/RISCV/CMakeLists.txt | 11 +++ lldb/unittests/CMakeLists.txt | 1 + 8 files changed, 183 insertions(+) create mode 100644 lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp create mode 100644 lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h create mode 100644 lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt create mode 100644 lldb/unittests/Architecture/CMakeLists.txt create mode 100644 lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp create mode 100644 lldb/unittests/Architecture/RISCV/CMakeLists.txt diff --git a/lldb/source/Plugins/Architecture/CMakeLists.txt b/lldb/source/Plugins/Architecture/CMakeLists.txt index 0f898ef5116e9..93288ea5841db 100644 --- a/lldb/source/Plugins/Architecture/CMakeLists.txt +++ b/lldb/source/Plugins/Architecture/CMakeLists.txt @@ -4,3 +4,4 @@ add_subdirectory(Arm) add_subdirectory(Mips) add_subdirectory(PPC64) add_subdirectory(AArch64) +add_subdirectory(RISCV) diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp new file mode 100644 index 0000000000000..f56a0712981a9 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp @@ -0,0 +1,46 @@ +//===-- ArchitectureRISCV.cpp ---------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/RISCV/ArchitectureRISCV.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Utility/ArchSpec.h" + +#include <algorithm> + +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ArchitectureRISCV) + +void ArchitectureRISCV::Initialize() { + PluginManager::RegisterPlugin(GetPluginNameStatic(), + "RISC-V-specific algorithms", + &ArchitectureRISCV::Create); +} + +void ArchitectureRISCV::Terminate() { + PluginManager::UnregisterPlugin(&ArchitectureRISCV::Create); +} + +std::unique_ptr<Architecture> ArchitectureRISCV::Create(const ArchSpec &arch) { + auto machine = arch.GetMachine(); + if (machine != llvm::Triple::riscv32 && machine != llvm::Triple::riscv64) + return nullptr; + return std::unique_ptr<Architecture>(new ArchitectureRISCV()); +} + +bool ArchitectureRISCV::IsValidTrapInstruction( + llvm::ArrayRef<uint8_t> reference, llvm::ArrayRef<uint8_t> observed) const { + // RISC-V has only two trap encodings here: 16-bit C.EBREAK or 32-bit EBREAK. + // These instructions don't have any operands so check that the reference and + // exact bytes match. + if ((reference.size() != 2 && reference.size() != 4) || + reference.size() > observed.size()) + return false; + + return std::equal(reference.begin(), reference.end(), observed.begin()); +} diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h new file mode 100644 index 0000000000000..0a97411a25f76 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h @@ -0,0 +1,36 @@ +//===-- ArchitectureRISCV.h -------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H +#define LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H + +#include "lldb/Core/Architecture.h" + +namespace lldb_private { + +class ArchitectureRISCV : public Architecture { +public: + static llvm::StringRef GetPluginNameStatic() { return "riscv"; } + static void Initialize(); + static void Terminate(); + + llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } + + void OverrideStopInfo(Thread &thread) const override {} + + bool IsValidTrapInstruction(llvm::ArrayRef<uint8_t> reference, + llvm::ArrayRef<uint8_t> observed) const override; + +private: + static std::unique_ptr<Architecture> Create(const ArchSpec &arch); + ArchitectureRISCV() = default; +}; + +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_ARCHITECTURE_RISCV_ARCHITECTURERISCV_H diff --git a/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt b/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt new file mode 100644 index 0000000000000..443b948179e63 --- /dev/null +++ b/lldb/source/Plugins/Architecture/RISCV/CMakeLists.txt @@ -0,0 +1,7 @@ +add_lldb_library(lldbPluginArchitectureRISCV PLUGIN + ArchitectureRISCV.cpp + + LINK_LIBS + lldbCore + lldbUtility + ) diff --git a/lldb/unittests/Architecture/CMakeLists.txt b/lldb/unittests/Architecture/CMakeLists.txt new file mode 100644 index 0000000000000..4e66d7aaa260d --- /dev/null +++ b/lldb/unittests/Architecture/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(RISCV) diff --git a/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp b/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp new file mode 100644 index 0000000000000..619bc5696f861 --- /dev/null +++ b/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp @@ -0,0 +1,80 @@ +//===-- ArchitectureRISCVTest.cpp -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Plugins/Architecture/RISCV/ArchitectureRISCV.h" +#include "lldb/Core/Architecture.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Utility/ArchSpec.h" + +#include "gtest/gtest.h" + +using namespace lldb_private; + +class ArchitectureRISCVTest : public testing::Test { +protected: + static void SetUpTestSuite() { ArchitectureRISCV::Initialize(); } + static void TearDownTestSuite() { ArchitectureRISCV::Terminate(); } +}; + +TEST_F(ArchitectureRISCVTest, CreatesPluginForRISCVTargets) { + EXPECT_TRUE(PluginManager::CreateArchitectureInstance( + ArchSpec("riscv32-unknown-unknown-elf"))); + EXPECT_TRUE(PluginManager::CreateArchitectureInstance( + ArchSpec("riscv64-unknown-unknown-elf"))); + EXPECT_FALSE(PluginManager::CreateArchitectureInstance( + ArchSpec("x86_64-unknown-unknown-elf"))); +} + +TEST_F(ArchitectureRISCVTest, ValidatesEBreak) { + std::unique_ptr<Architecture> arch = + PluginManager::CreateArchitectureInstance( + ArchSpec("riscv32-unknown-unknown-elf")); + ASSERT_TRUE(arch); + + const uint8_t ebreak[] = {0x73, 0x00, 0x10, 0x00}; + const uint8_t ebreak_with_extra_bytes[] = {0x73, 0x00, 0x10, + 0x00, 0xff, 0xff}; + const uint8_t wrong_immediate[] = {0x73, 0x00, 0x20, 0x00}; + const uint8_t truncated_ebreak[] = {0x73, 0x00}; + const llvm::ArrayRef<uint8_t> empty_reference; + const uint8_t bad_size_reference[] = {0x73, 0x00, 0x10}; + + EXPECT_TRUE(arch->IsValidTrapInstruction(ebreak, ebreak)); + EXPECT_TRUE(arch->IsValidTrapInstruction(ebreak, ebreak_with_extra_bytes)); + EXPECT_FALSE(arch->IsValidTrapInstruction(ebreak, wrong_immediate)); + EXPECT_FALSE(arch->IsValidTrapInstruction(ebreak, truncated_ebreak)); + EXPECT_FALSE(arch->IsValidTrapInstruction(empty_reference, ebreak)); + EXPECT_FALSE(arch->IsValidTrapInstruction(bad_size_reference, ebreak)); +} + +TEST_F(ArchitectureRISCVTest, ValidatesCompressedEBreak) { + std::unique_ptr<Architecture> arch = + PluginManager::CreateArchitectureInstance( + ArchSpec("riscv64-unknown-unknown-elf")); + ASSERT_TRUE(arch); + + const uint8_t compressed_ebreak[] = {0x02, 0x90}; + const uint8_t compressed_ebreak_with_extra_bytes[] = {0x02, 0x90, 0xff, 0xff}; + const uint8_t compressed_unimp[] = {0x00, 0x00}; + const uint8_t truncated_compressed_ebreak[] = {0x02}; + const llvm::ArrayRef<uint8_t> empty_reference; + const uint8_t bad_size_reference[] = {0x02, 0x90, 0xff}; + + EXPECT_TRUE( + arch->IsValidTrapInstruction(compressed_ebreak, compressed_ebreak)); + EXPECT_TRUE(arch->IsValidTrapInstruction(compressed_ebreak, + compressed_ebreak_with_extra_bytes)); + EXPECT_FALSE( + arch->IsValidTrapInstruction(empty_reference, compressed_ebreak)); + EXPECT_FALSE( + arch->IsValidTrapInstruction(bad_size_reference, compressed_ebreak)); + EXPECT_FALSE( + arch->IsValidTrapInstruction(compressed_ebreak, compressed_unimp)); + EXPECT_FALSE(arch->IsValidTrapInstruction(compressed_ebreak, + truncated_compressed_ebreak)); +} diff --git a/lldb/unittests/Architecture/RISCV/CMakeLists.txt b/lldb/unittests/Architecture/RISCV/CMakeLists.txt new file mode 100644 index 0000000000000..f8e75bd423e13 --- /dev/null +++ b/lldb/unittests/Architecture/RISCV/CMakeLists.txt @@ -0,0 +1,11 @@ +if ("RISCV" IN_LIST LLVM_TARGETS_TO_BUILD) + add_lldb_unittest(ArchitectureRISCVTests + ArchitectureRISCVTest.cpp + + LINK_COMPONENTS + Support + LINK_LIBS + lldbCore + lldbPluginArchitectureRISCV + lldbUtility) +endif() diff --git a/lldb/unittests/CMakeLists.txt b/lldb/unittests/CMakeLists.txt index 6ce3643bc65be..b0b7f68a7dcd6 100644 --- a/lldb/unittests/CMakeLists.txt +++ b/lldb/unittests/CMakeLists.txt @@ -77,6 +77,7 @@ if (NOT CMAKE_SYSTEM_NAME MATCHES "Windows") add_subdirectory(DAP) endif() add_subdirectory(ABI) +add_subdirectory(Architecture) add_subdirectory(Breakpoint) add_subdirectory(Callback) add_subdirectory(Core) >From f6b3aedc3889e75101eecb3f4a19b3a0287ebd94 Mon Sep 17 00:00:00 2001 From: Sudharsan Veeravalli <[email protected]> Date: Mon, 6 Jul 2026 14:50:45 +0530 Subject: [PATCH 2/3] Simplify return and correct comment --- .../source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp index f56a0712981a9..d135e6702d1ad 100644 --- a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp @@ -10,8 +10,6 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Utility/ArchSpec.h" -#include <algorithm> - using namespace lldb_private; LLDB_PLUGIN_DEFINE(ArchitectureRISCV) @@ -37,10 +35,10 @@ bool ArchitectureRISCV::IsValidTrapInstruction( llvm::ArrayRef<uint8_t> reference, llvm::ArrayRef<uint8_t> observed) const { // RISC-V has only two trap encodings here: 16-bit C.EBREAK or 32-bit EBREAK. // These instructions don't have any operands so check that the reference and - // exact bytes match. + // observed bytes match. if ((reference.size() != 2 && reference.size() != 4) || reference.size() > observed.size()) return false; - return std::equal(reference.begin(), reference.end(), observed.begin()); + return reference == observed.take_front(reference.size()); } >From 368d0f0009fa7a0864fa8f1f0eec4c673f011025 Mon Sep 17 00:00:00 2001 From: Sudharsan Veeravalli <[email protected]> Date: Tue, 7 Jul 2026 09:28:31 +0530 Subject: [PATCH 3/3] Address comments --- lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp | 4 ++-- lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h | 2 +- lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp index d135e6702d1ad..b6539abfb588b 100644 --- a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.cpp @@ -1,4 +1,4 @@ -//===-- ArchitectureRISCV.cpp ---------------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -35,7 +35,7 @@ bool ArchitectureRISCV::IsValidTrapInstruction( llvm::ArrayRef<uint8_t> reference, llvm::ArrayRef<uint8_t> observed) const { // RISC-V has only two trap encodings here: 16-bit C.EBREAK or 32-bit EBREAK. // These instructions don't have any operands so check that the reference and - // observed bytes match. + // observed bytes match. if ((reference.size() != 2 && reference.size() != 4) || reference.size() > observed.size()) return false; diff --git a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h index 0a97411a25f76..826ad7952dcd9 100644 --- a/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h +++ b/lldb/source/Plugins/Architecture/RISCV/ArchitectureRISCV.h @@ -1,4 +1,4 @@ -//===-- ArchitectureRISCV.h -------------------------------------*- C++ -*-===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp b/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp index 619bc5696f861..36072004e6d5c 100644 --- a/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp +++ b/lldb/unittests/Architecture/RISCV/ArchitectureRISCVTest.cpp @@ -1,4 +1,4 @@ -//===-- ArchitectureRISCVTest.cpp -----------------------------------------===// +//===----------------------------------------------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
