Applied debug-interface-specific access restrictions for memory and registers

This commit is contained in:
Nav
2024-12-07 16:43:16 +00:00
parent 289919f330
commit cbfbd9f4b8
11 changed files with 78 additions and 25 deletions

View File

@@ -270,8 +270,8 @@ namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr
} }
} }
Targets::TargetRegisterAccess EdbgAvr8Interface::getRegisterAccess( void EdbgAvr8Interface::applyAccessRestrictions(
const TargetRegisterDescriptor& registerDescriptor, TargetRegisterDescriptor& registerDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor const TargetAddressSpaceDescriptor& addressSpaceDescriptor
) { ) {
/* /*
@@ -281,10 +281,10 @@ namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr
* There are some other memory types we can use to access some other registers during a debug session, but * There are some other memory types we can use to access some other registers during a debug session, but
* these are yet to be implemented. * these are yet to be implemented.
*/ */
const auto access = addressSpaceDescriptor.key == this->session.dataAddressSpace.key const auto accessible = addressSpaceDescriptor.key == this->session.dataAddressSpace.key
|| addressSpaceDescriptor.key == this->session.registerFileAddressSpace.key; || addressSpaceDescriptor.key == this->session.registerFileAddressSpace.key;
registerDescriptor.access.readable = accessible && registerDescriptor.access.readable;
return {access, access}; registerDescriptor.access.writable = accessible && registerDescriptor.access.writable;
} }
TargetMemoryAddress EdbgAvr8Interface::getProgramCounter() { TargetMemoryAddress EdbgAvr8Interface::getProgramCounter() {

View File

@@ -138,8 +138,8 @@ namespace DebugToolDrivers::Microchip::Protocols::Edbg::Avr
*/ */
void deactivate() override; void deactivate() override;
Targets::TargetRegisterAccess getRegisterAccess( void applyAccessRestrictions(
const Targets::TargetRegisterDescriptor& registerDescriptor, Targets::TargetRegisterDescriptor& registerDescriptor,
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor
) override; ) override;

View File

@@ -70,8 +70,7 @@ namespace DebugToolDrivers::TargetInterfaces::Microchip::Avr8
* registers can only be accessed during a programming session. This restriction is specific to the EDBG debug * registers can only be accessed during a programming session. This restriction is specific to the EDBG debug
* interface. * interface.
* *
* This function should communicate any access restrictions for the given register, which apply during a debug * This function should apply any additional access restrictions for the given register.
* session. It does not need to account for any access restrictions that only apply outside of a debug session.
* *
* @param registerDescriptor * @param registerDescriptor
* The descriptor of the register. * The descriptor of the register.
@@ -81,8 +80,8 @@ namespace DebugToolDrivers::TargetInterfaces::Microchip::Avr8
* *
* @return * @return
*/ */
virtual Targets::TargetRegisterAccess getRegisterAccess( virtual void applyAccessRestrictions(
const Targets::TargetRegisterDescriptor& registerDescriptor, Targets::TargetRegisterDescriptor& registerDescriptor,
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor
) = 0; ) = 0;

View File

@@ -59,5 +59,15 @@ namespace DebugToolDrivers::TargetInterfaces::RiscV
virtual void enableProgrammingMode() = 0; virtual void enableProgrammingMode() = 0;
virtual void disableProgrammingMode() = 0; virtual void disableProgrammingMode() = 0;
/**
* The debug interface may have its own access restrictions for memory segments and registers. These member
* functions should adjust the access members of the given segment/register descriptor, to apply any additional
* access restrictions.
*
* The member functions are called as part of the construction of the RISC-V target descriptor.
*/
virtual void applyAccessRestrictions(Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor) = 0;
virtual void applyAccessRestrictions(Targets::TargetRegisterDescriptor& registerDescriptor) = 0;
}; };
} }

View File

@@ -357,6 +357,20 @@ namespace DebugToolDrivers::Wch
this->softwareBreakpointRegistry.clear(); this->softwareBreakpointRegistry.clear();
} }
void WchLinkDebugInterface::applyAccessRestrictions(TargetMemorySegmentDescriptor& memorySegmentDescriptor) {
if (memorySegmentDescriptor.type == TargetMemorySegmentType::FLASH) {
/*
* Actually, we *can* write to flash memory whilst in debug mode (via a partial page write), but we don't
* need to, so I'm just going to block it, for now.
*/
memorySegmentDescriptor.debugModeAccess.writeable = false;
}
}
void WchLinkDebugInterface::applyAccessRestrictions(Targets::TargetRegisterDescriptor& registerDescriptor) {
// I don't believe any further access restrictions are required for registers. TODO: Review after v2.0.0.
}
void WchLinkDebugInterface::setSoftwareBreakpoint(const TargetProgramBreakpoint& breakpoint) { void WchLinkDebugInterface::setSoftwareBreakpoint(const TargetProgramBreakpoint& breakpoint) {
if (breakpoint.size != 2 && breakpoint.size != 4) { if (breakpoint.size != 2 && breakpoint.size != 4) {
throw Exception{"Invalid software breakpoint size (" + std::to_string(breakpoint.size) + ")"}; throw Exception{"Invalid software breakpoint size (" + std::to_string(breakpoint.size) + ")"};

View File

@@ -78,6 +78,9 @@ namespace DebugToolDrivers::Wch
void enableProgrammingMode() override; void enableProgrammingMode() override;
void disableProgrammingMode() override; void disableProgrammingMode() override;
void applyAccessRestrictions(Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor) override;
void applyAccessRestrictions(Targets::TargetRegisterDescriptor& registerDescriptor) override;
private: private:
const WchLinkToolConfig& toolConfig; const WchLinkToolConfig& toolConfig;
const Targets::RiscV::RiscVTargetConfig& targetConfig; const Targets::RiscV::RiscVTargetConfig& targetConfig;

View File

@@ -328,7 +328,7 @@ namespace Targets::Microchip::Avr8
// The debug interface may have its own access restrictions for registers. // The debug interface may have its own access restrictions for registers.
for (auto& [peripheralKey, peripheral] : descriptor.peripheralDescriptorsByKey) { for (auto& [peripheralKey, peripheral] : descriptor.peripheralDescriptorsByKey) {
for (auto& [groupKey, registerGroup] : peripheral.registerGroupDescriptorsByKey) { for (auto& [groupKey, registerGroup] : peripheral.registerGroupDescriptorsByKey) {
this->applyDebugInterfaceRegisterAccessRestrictions( this->applyDebugInterfaceAccessRestrictions(
registerGroup, registerGroup,
descriptor.getAddressSpaceDescriptor(registerGroup.addressSpaceKey) descriptor.getAddressSpaceDescriptor(registerGroup.addressSpaceKey)
); );
@@ -781,23 +781,16 @@ namespace Targets::Microchip::Avr8
this->writeRegisters({{descriptor, value}}); this->writeRegisters({{descriptor, value}});
} }
void Avr8::applyDebugInterfaceRegisterAccessRestrictions( void Avr8::applyDebugInterfaceAccessRestrictions(
TargetRegisterGroupDescriptor& groupDescriptor, TargetRegisterGroupDescriptor& groupDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor const TargetAddressSpaceDescriptor& addressSpaceDescriptor
) { ) {
for (auto& [subgroupKey, subgroupDescriptor] : groupDescriptor.subgroupDescriptorsByKey) {
this->applyDebugInterfaceRegisterAccessRestrictions(subgroupDescriptor, addressSpaceDescriptor);
}
for (auto& [registerKey, registerDescriptor] : groupDescriptor.registerDescriptorsByKey) { for (auto& [registerKey, registerDescriptor] : groupDescriptor.registerDescriptorsByKey) {
if (!registerDescriptor.access.readable && !registerDescriptor.access.writable) { this->avr8DebugInterface->applyAccessRestrictions(registerDescriptor, addressSpaceDescriptor);
// This register is already inaccessible - no need to check for further restrictions
continue;
} }
const auto access = this->avr8DebugInterface->getRegisterAccess(registerDescriptor, addressSpaceDescriptor); for (auto& [subgroupKey, subgroupDescriptor] : groupDescriptor.subgroupDescriptorsByKey) {
registerDescriptor.access.readable = registerDescriptor.access.readable && access.readable; this->applyDebugInterfaceAccessRestrictions(subgroupDescriptor, addressSpaceDescriptor);
registerDescriptor.access.writable = registerDescriptor.access.writable && access.writable;
} }
} }

View File

@@ -169,7 +169,7 @@ namespace Targets::Microchip::Avr8
TargetMemoryBuffer readRegister(const TargetRegisterDescriptor& descriptor); TargetMemoryBuffer readRegister(const TargetRegisterDescriptor& descriptor);
void writeRegister(const TargetRegisterDescriptor& descriptor, const TargetMemoryBuffer& value) ; void writeRegister(const TargetRegisterDescriptor& descriptor, const TargetMemoryBuffer& value) ;
void applyDebugInterfaceRegisterAccessRestrictions( void applyDebugInterfaceAccessRestrictions(
TargetRegisterGroupDescriptor& groupDescriptor, TargetRegisterGroupDescriptor& groupDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor const TargetAddressSpaceDescriptor& addressSpaceDescriptor
); );

View File

@@ -307,6 +307,22 @@ namespace Targets::RiscV
return this->programmingMode; return this->programmingMode;
} }
void RiscV::applyDebugInterfaceAccessRestrictions(TargetAddressSpaceDescriptor& addressSpaceDescriptor) {
for (auto& [segmentKey, segmentDescriptor] : addressSpaceDescriptor.segmentDescriptorsByKey) {
this->riscVDebugInterface->applyAccessRestrictions(segmentDescriptor);
}
}
void RiscV::applyDebugInterfaceAccessRestrictions(TargetRegisterGroupDescriptor& registerGroupDescriptor) {
for (auto& [registerKey, registerDescriptor] : registerGroupDescriptor.registerDescriptorsByKey) {
this->riscVDebugInterface->applyAccessRestrictions(registerDescriptor);
}
for (auto& [subgroupKey, subgroupDescriptor] : registerGroupDescriptor.subgroupDescriptorsByKey) {
this->applyDebugInterfaceAccessRestrictions(subgroupDescriptor);
}
}
const TargetMemorySegmentDescriptor& RiscV::resolveRegisterMemorySegmentDescriptor( const TargetMemorySegmentDescriptor& RiscV::resolveRegisterMemorySegmentDescriptor(
const TargetRegisterDescriptor& regDescriptor, const TargetRegisterDescriptor& regDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor const TargetAddressSpaceDescriptor& addressSpaceDescriptor
@@ -355,6 +371,7 @@ namespace Targets::RiscV
false, false,
{true, true}, {true, true},
{false, false}, {false, false},
false,
std::nullopt std::nullopt
} }
); );
@@ -371,6 +388,7 @@ namespace Targets::RiscV
false, false,
{true, true}, {true, true},
{false, false}, {false, false},
false,
std::nullopt std::nullopt
} }
); );

View File

@@ -11,6 +11,9 @@
#include "TargetDescriptionFile.hpp" #include "TargetDescriptionFile.hpp"
#include "IsaDescriptor.hpp" #include "IsaDescriptor.hpp"
#include "src/Targets/TargetAddressSpaceDescriptor.hpp"
#include "src/Targets/TargetRegisterGroupDescriptor.hpp"
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp" #include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
namespace Targets::RiscV namespace Targets::RiscV
@@ -119,6 +122,9 @@ namespace Targets::RiscV
bool programmingMode = false; bool programmingMode = false;
void applyDebugInterfaceAccessRestrictions(TargetAddressSpaceDescriptor& addressSpaceDescriptor);
void applyDebugInterfaceAccessRestrictions(TargetRegisterGroupDescriptor& registerGroupDescriptor);
const TargetMemorySegmentDescriptor& resolveRegisterMemorySegmentDescriptor( const TargetMemorySegmentDescriptor& resolveRegisterMemorySegmentDescriptor(
const TargetRegisterDescriptor& regDescriptor, const TargetRegisterDescriptor& regDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor const TargetAddressSpaceDescriptor& addressSpaceDescriptor

View File

@@ -78,6 +78,16 @@ namespace Targets::RiscV::Wch
this->cpuPeripheralDescriptor.clone() this->cpuPeripheralDescriptor.clone()
); );
for (auto& [addressSpaceKey, addressSpaceDescriptor] : descriptor.addressSpaceDescriptorsByKey) {
this->applyDebugInterfaceAccessRestrictions(addressSpaceDescriptor);
}
for (auto& [peripheralKey, peripheralDescriptor] : descriptor.peripheralDescriptorsByKey) {
for (auto& [groupKey, groupDescriptor] : peripheralDescriptor.registerGroupDescriptorsByKey) {
this->applyDebugInterfaceAccessRestrictions(groupDescriptor);
}
}
auto& sysAddressSpaceDescriptor = descriptor.getAddressSpaceDescriptor("system"); auto& sysAddressSpaceDescriptor = descriptor.getAddressSpaceDescriptor("system");
sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_program_memory").inspectionEnabled = true; sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_program_memory").inspectionEnabled = true;
sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_ram").inspectionEnabled = true; sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_ram").inspectionEnabled = true;