2022-03-24 19:06:09 +00:00
|
|
|
#include "TargetDescriptor.hpp"
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-03-25 00:19:32 +00:00
|
|
|
#include <numeric>
|
|
|
|
|
|
2021-08-07 17:22:59 +01:00
|
|
|
#include "src/Exceptions/Exception.hpp"
|
2022-03-24 19:06:09 +00:00
|
|
|
#include "src/Logger/Logger.hpp"
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-03-31 16:05:39 +01:00
|
|
|
namespace Bloom::DebugServer::Gdb::AvrGdb
|
2022-02-05 15:32:08 +00:00
|
|
|
{
|
|
|
|
|
using Bloom::Targets::TargetRegisterDescriptor;
|
|
|
|
|
using Bloom::Targets::TargetRegisterType;
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-03-24 19:06:09 +00:00
|
|
|
using Bloom::Exceptions::Exception;
|
|
|
|
|
|
|
|
|
|
TargetDescriptor::TargetDescriptor(const Bloom::Targets::TargetDescriptor& targetDescriptor)
|
2022-08-30 02:04:35 +01:00
|
|
|
: DebugServer::Gdb::TargetDescriptor(
|
|
|
|
|
targetDescriptor,
|
|
|
|
|
{
|
|
|
|
|
{Targets::TargetMemoryType::FLASH, 0},
|
|
|
|
|
{Targets::TargetMemoryType::RAM, 0x00800000U},
|
2022-12-08 21:18:04 +00:00
|
|
|
{Targets::TargetMemoryType::EEPROM, 0x00810000U},
|
2022-08-30 02:04:35 +01:00
|
|
|
}
|
|
|
|
|
)
|
2022-03-24 19:06:09 +00:00
|
|
|
{
|
2022-02-05 15:32:08 +00:00
|
|
|
this->loadRegisterMappings();
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
2022-10-01 21:01:37 +01:00
|
|
|
std::optional<GdbRegisterNumber> TargetDescriptor::getRegisterNumberFromTargetRegisterDescriptor(
|
2022-03-24 19:06:09 +00:00
|
|
|
const Targets::TargetRegisterDescriptor& registerDescriptor
|
2022-03-25 00:12:16 +00:00
|
|
|
) const {
|
2022-03-24 19:06:09 +00:00
|
|
|
return this->targetRegisterDescriptorsByGdbNumber.valueAt(registerDescriptor);
|
|
|
|
|
}
|
|
|
|
|
|
2022-10-01 21:01:37 +01:00
|
|
|
const RegisterDescriptor& TargetDescriptor::getRegisterDescriptorFromNumber(GdbRegisterNumber number) const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto registerDescriptorIt = this->registerDescriptorsByGdbNumber.find(number);
|
|
|
|
|
if (registerDescriptorIt.has_value()) {
|
|
|
|
|
return (*registerDescriptorIt)->second;
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
throw Exception(
|
|
|
|
|
"Unknown register from GDB - register number (" + std::to_string(number)
|
|
|
|
|
+ ") not mapped to any GDB register descriptor."
|
|
|
|
|
);
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|
2021-12-28 01:16:21 +00:00
|
|
|
|
2022-03-25 00:12:16 +00:00
|
|
|
const TargetRegisterDescriptor& TargetDescriptor::getTargetRegisterDescriptorFromNumber(
|
2022-10-01 21:01:37 +01:00
|
|
|
GdbRegisterNumber number
|
2022-03-25 00:12:16 +00:00
|
|
|
) const {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto targetRegisterDescriptorIt = this->targetRegisterDescriptorsByGdbNumber.find(number);
|
|
|
|
|
if (targetRegisterDescriptorIt.has_value()) {
|
|
|
|
|
return (*targetRegisterDescriptorIt)->second;
|
2022-03-24 19:06:09 +00:00
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
throw Exception(
|
|
|
|
|
"Unknown register from GDB - register number (" + std::to_string(number)
|
|
|
|
|
+ ") not mapped to any target register descriptor."
|
|
|
|
|
);
|
2021-08-07 17:22:59 +01:00
|
|
|
}
|
|
|
|
|
|
2022-10-01 21:01:37 +01:00
|
|
|
const std::vector<GdbRegisterNumber>& TargetDescriptor::getRegisterNumbers() const {
|
2022-03-25 00:14:32 +00:00
|
|
|
return this->registerNumbers;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-24 19:06:09 +00:00
|
|
|
void TargetDescriptor::loadRegisterMappings() {
|
2022-12-03 22:16:21 +00:00
|
|
|
const auto& registerDescriptorsByType = this->targetDescriptor.registerDescriptorsByType;
|
2022-02-05 15:32:08 +00:00
|
|
|
if (!registerDescriptorsByType.contains(TargetRegisterType::STATUS_REGISTER)) {
|
|
|
|
|
throw Exception("Missing status register descriptor");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!registerDescriptorsByType.contains(TargetRegisterType::STACK_POINTER)) {
|
|
|
|
|
throw Exception("Missing stack pointer register descriptor");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!registerDescriptorsByType.contains(TargetRegisterType::PROGRAM_COUNTER)) {
|
|
|
|
|
throw Exception("Missing program counter register descriptor");
|
|
|
|
|
}
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
if (
|
|
|
|
|
!registerDescriptorsByType.contains(TargetRegisterType::GENERAL_PURPOSE_REGISTER)
|
2022-02-05 15:32:08 +00:00
|
|
|
|| registerDescriptorsByType.at(TargetRegisterType::GENERAL_PURPOSE_REGISTER).size() != 32
|
|
|
|
|
) {
|
|
|
|
|
throw Exception("Unexpected general purpose register count");
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-25 00:14:32 +00:00
|
|
|
/*
|
|
|
|
|
* For AVR targets, avr-gdb defines 35 registers in total:
|
|
|
|
|
*
|
|
|
|
|
* Register number 0 through 31 are general purpose registers
|
|
|
|
|
* Register number 32 is the status register (SREG)
|
|
|
|
|
* Register number 33 is the stack pointer register
|
|
|
|
|
* Register number 34 is the program counter register
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
// Generate 35 register numbers (0 -> 34)
|
|
|
|
|
std::iota(this->registerNumbers.begin(), this->registerNumbers.end(), 0);
|
|
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
/*
|
|
|
|
|
* Worth noting that gpRegisterDescriptors will always be sorted in the correct order, from register 0 to 31.
|
|
|
|
|
*
|
2022-03-25 00:19:32 +00:00
|
|
|
* Hmm, but the sorting is based on the start address (see TargetRegisterDescriptor::<() for more). So
|
|
|
|
|
* effectively, we're assuming that the registers will be laid out in the correct order, in memory. I think
|
|
|
|
|
* this assumption is fair.
|
2022-02-05 15:32:08 +00:00
|
|
|
*/
|
|
|
|
|
const auto& gpRegisterDescriptors = registerDescriptorsByType.at(
|
|
|
|
|
TargetRegisterType::GENERAL_PURPOSE_REGISTER
|
|
|
|
|
);
|
|
|
|
|
|
2022-03-25 00:19:32 +00:00
|
|
|
// General purpose registers
|
2022-10-01 21:01:37 +01:00
|
|
|
GdbRegisterNumber regNumber = 0;
|
2022-02-05 15:32:08 +00:00
|
|
|
for (const auto& descriptor : gpRegisterDescriptors) {
|
|
|
|
|
this->registerDescriptorsByGdbNumber.insert(std::pair(
|
|
|
|
|
regNumber,
|
|
|
|
|
RegisterDescriptor(
|
|
|
|
|
regNumber,
|
|
|
|
|
1,
|
|
|
|
|
"General Purpose Register " + std::to_string(regNumber)
|
|
|
|
|
)
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
this->targetRegisterDescriptorsByGdbNumber.insert(std::pair(
|
|
|
|
|
regNumber,
|
|
|
|
|
descriptor
|
|
|
|
|
));
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
regNumber++;
|
|
|
|
|
}
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-03-25 00:19:32 +00:00
|
|
|
// Status, stack pointer and program counter registers
|
2022-02-05 15:32:08 +00:00
|
|
|
const auto statusDescriptor = RegisterDescriptor(
|
|
|
|
|
32,
|
|
|
|
|
1,
|
|
|
|
|
"Status Register"
|
|
|
|
|
);
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
this->registerDescriptorsByGdbNumber.insert(std::pair(statusDescriptor.number, statusDescriptor));
|
|
|
|
|
this->targetRegisterDescriptorsByGdbNumber.insert(std::pair(
|
|
|
|
|
statusDescriptor.number,
|
|
|
|
|
*(registerDescriptorsByType.at(TargetRegisterType::STATUS_REGISTER).begin())
|
2021-12-28 01:16:21 +00:00
|
|
|
));
|
2021-08-07 18:09:12 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
const auto stackPointerDescriptor = RegisterDescriptor(
|
|
|
|
|
33,
|
|
|
|
|
2,
|
|
|
|
|
"Stack Pointer Register"
|
|
|
|
|
);
|
|
|
|
|
|
2022-12-03 22:16:21 +00:00
|
|
|
this->registerDescriptorsByGdbNumber.insert(std::pair(stackPointerDescriptor.number, stackPointerDescriptor));
|
2021-12-28 01:16:21 +00:00
|
|
|
this->targetRegisterDescriptorsByGdbNumber.insert(std::pair(
|
2022-02-05 15:32:08 +00:00
|
|
|
stackPointerDescriptor.number,
|
|
|
|
|
*(registerDescriptorsByType.at(TargetRegisterType::STACK_POINTER).begin())
|
2021-08-07 17:22:59 +01:00
|
|
|
));
|
2021-08-30 22:23:27 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
const auto programCounterDescriptor = RegisterDescriptor(
|
|
|
|
|
34,
|
|
|
|
|
4,
|
|
|
|
|
"Program Counter"
|
|
|
|
|
);
|
2021-08-07 17:22:59 +01:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
this->registerDescriptorsByGdbNumber.insert(std::pair(
|
|
|
|
|
programCounterDescriptor.number,
|
|
|
|
|
programCounterDescriptor
|
|
|
|
|
));
|
|
|
|
|
this->targetRegisterDescriptorsByGdbNumber.insert(std::pair(
|
|
|
|
|
programCounterDescriptor.number,
|
|
|
|
|
*(registerDescriptorsByType.at(TargetRegisterType::PROGRAM_COUNTER).begin())
|
|
|
|
|
));
|
|
|
|
|
|
|
|
|
|
if (registerDescriptorsByType.at(TargetRegisterType::STATUS_REGISTER).size() > statusDescriptor.size) {
|
|
|
|
|
throw Exception("AVR8 status target register size exceeds the GDB register size.");
|
|
|
|
|
}
|
2021-12-28 01:16:21 +00:00
|
|
|
|
2022-02-05 15:32:08 +00:00
|
|
|
if (registerDescriptorsByType.at(TargetRegisterType::STACK_POINTER).size() > stackPointerDescriptor.size) {
|
|
|
|
|
throw Exception("AVR8 stack pointer target register size exceeds the GDB register size.");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (
|
|
|
|
|
registerDescriptorsByType.at(TargetRegisterType::PROGRAM_COUNTER).size() > programCounterDescriptor.size
|
|
|
|
|
) {
|
|
|
|
|
throw Exception("AVR8 program counter size exceeds the GDB register size.");
|
|
|
|
|
}
|
2021-12-28 01:16:21 +00:00
|
|
|
}
|
2021-08-07 17:22:59 +01:00
|
|
|
}
|