Compare commits

...

20 commits
v0.1 ... master

Author SHA1 Message Date
DataHoarder 875f6588d9 Implement proper Init OutputContext
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-05 16:29:07 +02:00
DataHoarder 3868034b6b Update rrcc mappings for new set
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-03 22:21:34 +02:00
DataHoarder 812d1d632f hide NOP bytes by default
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-03 01:36:25 +02:00
DataHoarder 926b1d6a82 Decode new rrcc extended symbols with comments
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-03 01:12:49 +02:00
DataHoarder 83a1b7d280 Fixed rrcc register naming
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-03 00:26:32 +02:00
DataHoarder b019ab7684 Fixed Write command max length 2021-08-03 00:25:51 +02:00
DataHoarder 6a5d9696e7 Added more rrc-as register annotations
Some checks failed
continuous-integration/drone/push Build is failing
2021-08-02 21:05:34 +02:00
DataHoarder 6d3760c96e fixed several clang-tidy warnings
All checks were successful
continuous-integration/drone/push Build is passing
2021-08-01 20:18:57 +02:00
DataHoarder 2324a561f3 Added know NOP instructions to properly handle rrc-as symbols 2021-08-01 20:11:04 +02:00
DataHoarder bf7c3cefe5 Add virtual destructor to abstract Instruction class 2021-08-01 20:10:33 +02:00
DataHoarder 9b2ad65c3a Added more known addresses from reverse engineering
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone/tag Build is passing
2021-03-28 12:55:11 +02:00
DataHoarder 0caa10273e Added interrupt handler known jump and parsing when found
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-11 13:18:17 +01:00
DataHoarder f5ce6a92ce Added decoding of rrc-as debug annotations
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-04 17:43:33 +01:00
DataHoarder aa883d3f87 doWrite -> doRead for PCIe SBus request
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-03 08:02:33 +01:00
DataHoarder cda150ef51 Fix typo in Poll old toString
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-03 04:11:27 +01:00
DataHoarder 1ed3d43abe Added default values for some registers
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-02 04:29:31 +01:00
DataHoarder c3bcf99d6a use AddressWithOffset on WRITE
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-01 08:25:35 +01:00
DataHoarder 1fbb828944 Fix bug on COPY: do address + m[offset] instead of address + offset
All checks were successful
continuous-integration/drone/push Build is passing
2021-01-01 03:52:38 +01:00
DataHoarder 15690f54fd Move speculative count check to report more accurate numbers 2021-01-01 03:52:33 +01:00
DataHoarder 81b89b8d11 Force drone to build on linux-amd64
All checks were successful
continuous-integration/drone/push Build is passing
2020-12-31 01:22:14 +01:00
24 changed files with 380 additions and 99 deletions

View file

@ -3,6 +3,10 @@ kind: pipeline
type: docker
name: default
platform:
os: linux
arch: amd64
steps:
- name: build
image: ubuntu:20.04

View file

@ -47,3 +47,42 @@ void AnalysisState::setRegister(const Instruction::AddressWithOffset &address, u
uint32_t AnalysisState::getAddressWithOffset(const Instruction::AddressWithOffset &address) const {
return address.address + getAddressOffset(address.offset);
}
uint32_t AnalysisState::getDefaultRegisterValue(uint32_t addr) {
if(addr == (uint32_t)KnownRegisters::SOFT_RESET){
return 0b0000000001111111110111;
}else if(addr == (uint32_t)KnownRegisters::DEVICE_CFG){
return 0b01111111110000000;
}else if(addr == (uint32_t)KnownRegisters::RESET_CFG){
return (0x40 << 8) | 0x10;
}else if(addr == (uint32_t)KnownRegisters::VITAL_PRODUCT_DATA){
return 0xAE21;
}else if(addr == (uint32_t)KnownRegisters::SRAM_ERR_IM_0){
return 0xFFFFFFFF;
}else if(addr == (uint32_t)KnownRegisters::SRAM_ERR_IM_1){
return 0x0000FFFF;
}else if(addr == (uint32_t)KnownRegisters::SW_IM){
return 0xFFFFFFFF;
}else if(addr == (uint32_t)KnownRegisters::CHIP_VERSION){
return 0x1;
}else if(addr == (uint32_t)KnownRegisters::REI_CTRL){
return 0b1;
}else if(addr == (uint32_t)KnownRegisters::GPIO_IM){
return 0xFFFFFFFF;
}else if(addr == (uint32_t)KnownRegisters::PLL_PCIE_CTRL){
return (0xA << 18) | (0x19 << 10) | (0x1 << 3) | 0b1;
}else if(addr == (uint32_t)KnownRegisters::SBUS_PCIE_CFG){
return 0b1;
}else if(addr == (uint32_t)KnownRegisters::SBUS_PCIE_IM){
return 0xFFFFFFFF;
}
return 0;
}
void AnalysisState::setRegister(uint32_t addr, uint32_t value) {
if(addr == (uint32_t)KnownRegisters::BSM_ARGS){
addKnownJump(value & 0xFFFFFF, current, JumpKind::Interrupt);
}
memory[addr] = value;
}

View file

@ -40,7 +40,8 @@ enum class JumpKind {
Speculative,
Branch,
Loop,
Return
Return,
Interrupt
};
typedef std::unordered_map<uint32_t, std::vector<std::pair<uint32_t, JumpKind>>> AnalysisJumpTable;
@ -84,15 +85,14 @@ public:
void setRegister(const Instruction::AddressWithOffset &address, uint32_t value);
void setRegister(uint32_t addr, uint32_t value) {
memory[addr] = value;
}
void setRegister(uint32_t addr, uint32_t value);
uint32_t getRegister(const Instruction::AddressWithOffset &address) const;
uint32_t getRegister(uint32_t addr) const {
return memory.find(addr) == memory.end() ? 0 : memory.at(addr);
return memory.find(addr) == memory.end() ? getDefaultRegisterValue(addr) : memory.at(addr);
}
static uint32_t getDefaultRegisterValue(uint32_t addr);
uint32_t getAddressWithOffset(const Instruction::AddressWithOffset &address) const;

View file

@ -232,23 +232,31 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
break;
}
state.setRegister((uint32_t)KnownRegisters::BSM_CTRL, (state.getRegister((uint32_t)KnownRegisters::BSM_CTRL) & 0xFF) | ((instruction->getEndAddress()) << 8)); // Set EepromAddr as next address
auto possibleBranches = instruction->execute(state);
if ((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) &&
jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()) {
jumpsUsed[instruction->getEndAddress()] = false; //TODO: remove this or make it opt-in by default
}
if (jumpsUsed.find(state.current) != jumpsUsed.end() && !jumpsUsed[state.current]) {
jumpsUsed.erase(state.current); //Clear to recognize a non-speculative jump
}
if ((instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP ||
instruction->getCommand() == Instruction::Instruction::CommandOp::RETURN) &&
jumpsUsed.find(instruction->getEndAddress()) == jumpsUsed.end()) {
jumpsUsed[instruction->getEndAddress()] = false;
}
if (state.current == 0) {
//std::cout << "EXIT DUE TO END " << std::hex << state.previous << " -> " << std::hex << state.current << "\n";
break;
}
//Handle interrupts
uint32_t addr = state.getRegister((uint32_t) KnownRegisters::BSM_ARGS) & 0xFFFFFF;
if(addr != 0 && jumpsUsed.find(addr) == jumpsUsed.end()){
jumpsUsed[addr] = false;
}
if (instruction->getCommand() == Instruction::Instruction::CommandOp::JUMP) {
uint32_t nextAddress = instruction->getAddress() - 1;
while (true) {
@ -258,9 +266,9 @@ void ImageFormat::decodeAnalyzeInstructionsAt(uint32_t offset) {
const auto &writeInstruction = reinterpret_cast<const std::unique_ptr<Instruction::Write> &>(previousInstruction);
if (
(
writeInstruction->address == (uint32_t) KnownRegisters::MGMT_SCRATCH_1
|| (writeInstruction->address >= (uint32_t) KnownRegisters::BSM_SCRATCH_START &&
writeInstruction->address < (uint32_t) KnownRegisters::BSM_SCRATCH_END)
writeInstruction->address.address == (uint32_t) KnownRegisters::MGMT_SCRATCH_1
|| (writeInstruction->address.address >= (uint32_t) KnownRegisters::BSM_SCRATCH_START &&
writeInstruction->address.address < (uint32_t) KnownRegisters::BSM_SCRATCH_END)
)
&& writeInstruction->data.size() == 1
) { //This is commonly used before jumps to mark return values or switch statements

View file

@ -52,6 +52,10 @@ std::string OutputContext::getComment(uint32_t location) const {
return "";
}
bool OutputContext::isNop(uint32_t location) const {
return nop.find(location) != nop.end();
}
std::string OutputContext::getDataHeader(uint32_t location) const {
std::stringstream s;
@ -115,6 +119,9 @@ void OutputContext::analyze() {
case JumpKind::Return:
from << "Return";
break;
case JumpKind::Interrupt:
from << "Interrupt";
break;
}
from << "), ";
} else {
@ -147,7 +154,7 @@ void OutputContext::analyze() {
if (writeInstruction.data.size() == 1 &&
writeInstruction.data[0] == e.first) { //Return value!
//TODO: mark join?
addComment(writeInstruction.getAddress() + 4, locText);
addComment(writeInstruction.getAddress() + 4, locText, true);
foundReturn = true;
break;
}
@ -169,7 +176,7 @@ void OutputContext::analyze() {
}
if (e.second.size() > 1 || (!hasContinue && !e.second.empty())) {
addComment(e.first, "<" + getLabel(e.first, true) + "> " + from.str());
addComment(e.first, "<" + getLabel(e.first, true) + "> " + from.str(), true);
}
}
@ -181,19 +188,29 @@ void OutputContext::addMapping(uint32_t location, const std::string &name, bool
}
}
void OutputContext::addComment(uint32_t location, const std::string &comment) {
void OutputContext::addComment(uint32_t location, const std::string &comment, bool force) {
if (comments.find(location) != comments.end()) {
comments[location] = comment + " --- " + comments[location];
comments[location] = force ? comment + " :: " + comments[location] : comments[location] + " :: " + comment;
} else {
comments[location] = comment;
}
}
void OutputContext::setNop(uint32_t location) {
nop[location] = true;
}
std::string OutputContext::getAddressRegisterName(uint32_t addr, uint8_t offset) const {
if (offset || registers.find(addr) == registers.end()) {
uint64_t k = (uint64_t)addr | ((uint64_t)offset << 32);
if (registers.find(k) == registers.end()) {
return ::getAddressRegisterName(addr, offset);
} else {
return registers.at(addr);
return registers.at(k);
}
}
void OutputContext::addRegister(const Instruction::AddressWithOffset &address, const std::string &name) {
registers[(uint64_t)address.address | ((uint64_t)address.offset << 32)] = name;
}

View file

@ -41,21 +41,22 @@ private:
const ImageFormat &image;
std::unordered_map<uint32_t, std::string> mappings;
std::unordered_map<uint32_t, std::string> comments;
std::unordered_map<uint32_t, std::string> registers;
std::unordered_map<uint64_t, std::string> registers;
std::unordered_map<uint32_t, bool> nop;
public:
OutputContext(const ImageFormat &image) : image(image) {
explicit OutputContext(const ImageFormat &image) : image(image) {
}
void addMapping(uint32_t location, const std::string &name, bool force = false);
void addComment(uint32_t location, const std::string &comment);
void addComment(uint32_t location, const std::string &comment, bool force = false);
void addRegister(uint32_t addr, const std::string &name) {
registers[addr] = name;
}
void setNop(uint32_t location);
void addRegister(const Instruction::AddressWithOffset& address, const std::string &name);
std::string getAddressRegisterName(uint32_t addr, uint8_t offset) const;
@ -69,6 +70,8 @@ public:
std::string getDataHeader(uint32_t location) const;
bool isNop(uint32_t location) const;
std::string getDataEntry(uint32_t location, const std::string &representation = "") const;
std::string getInstructionString(const Instruction::Instruction &instruction) const;

View file

@ -64,6 +64,8 @@ std::string getRegisterName(KnownRegisters addr) {
return "INTERRUPT_MASK_BSM";
case KnownRegisters::CHIP_VERSION:
return "CHIP_VERSION";
case KnownRegisters::BSM_CTRL:
return "BSM_CTRL";
case KnownRegisters::BSM_ARGS:
return "BSM_ARGS";
case KnownRegisters::BSM_ADDR_OFFSET_0:

View file

@ -52,11 +52,17 @@ enum class KnownRegisters : uint32_t {
INTERRUPT_MASK_BSM = 0x442,
SRAM_ERR_IM_0 = 0x448,
SRAM_ERR_IM_1 = 0x449,
SW_IM = 0x44E,
CHIP_VERSION = 0x452,
BSM_SCRATCH_START = 0x800,
BSM_SCRATCH_END = BSM_SCRATCH_START + 0x400 - 1,
BSM_CTRL = 0x000C00,
BSM_ARGS = 0x000C01,
BSM_ADDR_OFFSET_0 = 0x000C04,

View file

@ -180,7 +180,7 @@ Instruction::Calc::execute(AnalysisState &state) const {
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Calc::toBytes() const {

View file

@ -179,7 +179,7 @@ Instruction::CalcImm::execute(AnalysisState &state) const {
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::CalcImm::toBytes() const {

View file

@ -83,15 +83,15 @@ std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Copy::execute(AnalysisState &state) const {
for (uint32_t i = 0; i < count; ++i) {
state.setRegister(addressBB.offset + addressBB.address + i,
state.getRegister(addressAA.offset + addressAA.address + i));
state.setRegister(state.getAddressOffset(addressBB.offset) + addressBB.address + i,
state.getRegister(state.getAddressOffset(addressAA.offset) + addressAA.address + i));
}
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}

View file

@ -52,14 +52,14 @@ std::vector<Instruction::OutputFormat> Instruction::End::toOutputFormat(const Ou
}
std::vector<uint32_t> Instruction::End::getPossibleBranches() const {
return std::vector<uint32_t>();
return {};
}
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::End::execute(AnalysisState &state) const {
state.current = 0;
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::End::toBytes() const {

View file

@ -29,6 +29,7 @@
#include "../Registers.h"
#include <iostream>
#include <iomanip>
#include "../OutputContext.h"
void Instruction::Init::fromBytes(uint32_t offset, const std::vector<uint8_t> &bytes) {
_address = offset;
@ -69,18 +70,35 @@ std::string Instruction::Init::toString() const {
if (count > 1 && increment) {
op << " UNTIL " << getAddressRegisterName(address + count - 1, addressOffset);
}
op << " COUNT " << std::hex << std::setw(6) << std::setfill('0') << count;
op << " INCREMENT " << std::dec << (uint32_t) increment;
op << " COUNT " << std::hex << std::setw(6) << std::setfill('0') << count;
op << " DATA 0x" << std::hex << std::setw(8) << std::setfill('0') << data;
op << " INC 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add;
op << " ADD 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add;
return op.str();
}
std::vector<Instruction::OutputFormat> Instruction::Init::toOutputFormat(const OutputContext &context) const {
return std::vector<OutputFormat>{
//TODO
std::vector<OutputFormat> f{
OutputFormat{getAddress() + 0 * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "INIT" << " "
<< context.getAddressRegisterName(
address, addressOffset)
<< ", INC " << std::dec
<< (uint32_t) increment).str()}
};
f.emplace_back(OutputFormat{getAddress() + 1 * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " COUNT " << std::dec
<< count).str()});
f.emplace_back(OutputFormat{getAddress() + 2 * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " DATA 0x" << std::hex << std::setw(8) << std::setfill('0') << data).str()});
f.emplace_back(OutputFormat{getAddress() + 3 * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " ADD 0x" << std::hex << std::setw(8) << std::setfill('0') << data_add).str()});
return f;
}
std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
@ -90,14 +108,14 @@ std::vector<uint32_t> Instruction::Init::getPossibleBranches() const {
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Init::execute(AnalysisState &state) const {
for (uint32_t i = 0; i < count; ++i) {
state.setRegister(address + (increment ? i : 0), data + data_add * i);
state.setRegister(address + increment, data + data_add * i);
}
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Init::toBytes() const {

View file

@ -54,11 +54,11 @@ namespace Instruction {
execute(AnalysisState &state) const override;
uint8_t addressOffset;
uint8_t increment;
uint32_t address;
uint32_t count;
uint32_t data;
uint32_t data_add;
uint8_t addressOffset{};
uint8_t increment{};
uint32_t address{};
uint32_t count{};
uint32_t data{};
uint32_t data_add{};
};
}

View file

@ -48,6 +48,8 @@ namespace Instruction {
uint32_t _endAddress{};
public:
virtual ~Instruction()= default;
enum class CommandOp : uint8_t {
WRITE = 0b00000000,
COPY = 0b01000000,

View file

@ -70,7 +70,7 @@ Instruction::Jump::execute(AnalysisState &state) const {
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Absolute);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Jump::toBytes() const {

View file

@ -182,7 +182,7 @@ std::vector<Instruction::OutputFormat> Instruction::Load::toOutputFormat(const O
dynamic_cast<std::stringstream &>(std::stringstream("") << " "
<< context.getAddressRegisterName(
address +
offset - 2,
(increment ? offset - 2 : 0),
addressOffset)
<< " = 0x" << std::hex
<< std::setw(8)
@ -220,7 +220,7 @@ Instruction::Load::execute(AnalysisState &state) const {
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Load::toBytes() const {

View file

@ -74,9 +74,9 @@ std::string Instruction::Poll::toString() const {
op << "POLL IF (" << getAddressRegisterName(address) << " & 0x" << std::hex << std::setw(8)
<< std::setfill('0') << mask << ")";
if (equality) {
op << " != ";
} else {
op << " == ";
} else {
op << " != ";
}
op << "0x" << std::hex << std::setw(8) << std::setfill('0') << value << " WAIT " << std::dec << retryInterval
<< " MAX " << std::dec << maxRetry << " EXCEED JUMP 0x" << std::hex << std::setw(6) << std::setfill('0')

View file

@ -63,7 +63,7 @@ std::vector<Instruction::OutputFormat> Instruction::Return::toOutputFormat(const
}
std::vector<uint32_t> Instruction::Return::getPossibleBranches() const {
return std::vector<uint32_t>();
return {};
}
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
@ -73,7 +73,7 @@ Instruction::Return::execute(AnalysisState &state) const {
state.addKnownJump(jumpAddress, getAddress(), JumpKind::Return);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}

View file

@ -92,7 +92,7 @@ Instruction::Set::execute(AnalysisState &state) const {
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Set::toBytes() const {

View file

@ -70,7 +70,7 @@ Instruction::Wait::execute(AnalysisState &state) const {
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Wait::toBytes() const {

View file

@ -36,12 +36,12 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
uint32_t command = bytes[offset++];
uint8_t count = (1 + (command >> 2) & 0b1111);
addressOffset = command & 0b11;
uint8_t count = (1 + ((command >> 2) & 0b1111));
address.offset = command & 0b11;
address = bytes[offset++] << 16;
address |= bytes[offset++] << 8;
address |= bytes[offset++];
address.address = bytes[offset++] << 16;
address.address |= bytes[offset++] << 8;
address.address |= bytes[offset++];
for (uint32_t i = 0; i < count; ++i) {
uint32_t entry = bytes[offset++] << 24;
@ -57,7 +57,7 @@ void Instruction::Write::fromBytes(uint32_t offset, const std::vector<uint8_t> &
std::string Instruction::Write::toString() const {
std::stringstream op;
op << "WRITE " << getAddressRegisterName(address, addressOffset) << " = 0x";
op << "WRITE " << getAddressRegisterName(address) << " = 0x";
for (auto d : data) {
op << std::hex << std::setw(8) << std::setfill('0') << d;
@ -71,8 +71,7 @@ std::vector<Instruction::OutputFormat> Instruction::Write::toOutputFormat(const
std::vector<OutputFormat> f{
OutputFormat{getAddress() + offset++ * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << "WRITE" << " "
<< context.getAddressRegisterName(
address, addressOffset) << ", "
<< context.getAddressRegisterName(address) << ", "
<< std::dec
<< (uint32_t) data.size()).str()}
};
@ -81,8 +80,7 @@ std::vector<Instruction::OutputFormat> Instruction::Write::toOutputFormat(const
f.emplace_back(OutputFormat{getAddress() + offset * 4,
dynamic_cast<std::stringstream &>(std::stringstream("") << " "
<< context.getAddressRegisterName(
address + offset -
1, addressOffset)
address.address + offset - 1, address.offset)
<< " = 0x" << std::hex
<< std::setw(8)
<< std::setfill('0')
@ -100,29 +98,27 @@ std::vector<uint32_t> Instruction::Write::getPossibleBranches() const {
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
Instruction::Write::execute(AnalysisState &state) const {
auto memoryOffset = state.getAddressOffset(addressOffset);
auto memoryOffset = state.getAddressOffset(address.offset);
for (uint32_t i = 0; i < data.size(); ++i) {
state.setRegister(memoryOffset + address + i, data[i]);
state.setRegister(memoryOffset + address.address + i, data[i]);
}
state.current = _endAddress;
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
state.addKnownJump(getEndAddress(), getAddress(), JumpKind::Continue);
return std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>();
return {};
}
std::vector<uint8_t> Instruction::Write::toBytes() const {
std::vector<uint8_t> bytes;
bytes.emplace_back((uint8_t) getCommand() | ((data.size() - 1) << 2) | addressOffset);
bytes.emplace_back((uint8_t) getCommand() | ((data.size() - 1) << 2) | address.offset);
bytes.emplace_back((address >> 16) & 0xFF);
bytes.emplace_back((address >> 8) & 0xFF);
bytes.emplace_back(address & 0xFF);
bytes.emplace_back((address.address >> 16) & 0xFF);
bytes.emplace_back((address.address >> 8) & 0xFF);
bytes.emplace_back(address.address & 0xFF);
for (auto d : data) {
bytes.emplace_back((d >> 24) & 0xFF);

View file

@ -55,9 +55,7 @@ namespace Instruction {
std::vector<std::pair<uint32_t, std::unordered_map<uint32_t, uint32_t>>>
execute(AnalysisState &state) const override;
uint8_t addressOffset;
uint32_t address;
AddressWithOffset address;
std::vector<uint32_t> data;
};
}

View file

@ -34,6 +34,24 @@
#include "Registers.h"
#include "instructions/Load.h"
#include "OutputContext.h"
#include "instructions/End.h"
std::string ltrim(const std::string &s)
{
size_t start = s.find_first_not_of(" \n\r\t\f\v");
return (start == std::string::npos) ? "" : s.substr(start);
}
std::string rtrim(const std::string &s)
{
size_t end = s.find_last_not_of(" \n\r\t\f\v");
return (end == std::string::npos) ? "" : s.substr(0, end + 1);
}
std::string trim(const std::string &s) {
return rtrim(ltrim(s));
}
void decodeImage(const std::string &fileName) {
@ -46,7 +64,7 @@ void decodeImage(const std::string &fileName) {
auto imageObject = ImageFormat::fromBytes(bytes);
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", imageObject.getHeader().speed, imageObject.getHeader().mode,
printf("SPEED: 0x%02x MODE: 0x%02x BOOT: 0x%08x\n", static_cast<uint32_t>(imageObject.getHeader().speed), static_cast<uint32_t>(imageObject.getHeader().mode),
imageObject.getHeader().baseAddress);
std::cout << "SIGNATURE: " << imageObject.imageSignature << "\n";
@ -193,27 +211,61 @@ void decodeImage(const std::string &fileName) {
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 10, "api_PEP_MAC_BASE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 100, "api_CUSTOM_MAC_BASE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x0d9, "platform_FUNCTION_PCIeReset_enable"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x0da, "platform_FUNCTION_PCIeReset_disable"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x0db, "platform_FUNCTION_SERDES_InterruptCode_1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x0dc, "platform_FUNCTION_SERDES_InterruptCode_0"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12e, "param_SBUS_PCIE_REQUEST_-_SBUS_PCIE_RESPONSE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12f, "param_SBUS_PCIE_COMMAND_doRead"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x130, "param_SBUS_PCIE_COMMAND.DeviceAddress"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x131, "param_SBUS_PCIE_COMMAND.Register"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x132, "custom_param_RETURN_TO_SUCCESS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x133, "custom_param_RETURN_TO_FAILURE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x139, "custom_PEP_ADDR_OFFSET"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x13a, "custom_PEP_offset_PCIE_PORTLOGIC"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x13c, "custom_PEP_CONFIG_numberOfLanes"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x141, "custom_PEP_CONFIG_serial0"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x142, "custom_PEP_CONFIG_serial1"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x143, "custom_PEP_CONFIG_mgmtPep"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x144, "custom_PEP_CONFIG_vendor_device"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x145, "custom_PEP_CONFIG_subVendor_subDevice"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x145, "custom_PEP_CONFIG_gen"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x13c, "custom_PEP_CONFIG_numberOfLanes"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x17f, "custom_PEP_CONFIG_ASPMEnable"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x139, "custom_PEP_ADDR_OFFSET"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x154, "custom_PEP_NUMBER"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12e, "param_SBUS_PCIE_REQUEST_-_SBUS_PCIE_RESPONSE"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x12f, "param_SBUS_PCIE_COMMAND_doWrite"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x130, "param_SBUS_PCIE_COMMAND.DeviceAddress"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x131, "param_SBUS_PCIE_COMMAND.Register"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15a, "platform_PEP_skip_SRIOV_config"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15b, "platform_PEP0_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15c, "platform_PEP1_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15d, "platform_PEP2_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15e, "platform_PEP3_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x15f, "platform_PEP4_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x150, "platform_PEP5_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x151, "platform_PEP6_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x152, "platform_PEP7_PCIE_CLK_CTRL"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x164, "custom_PEP_CONFIG_gen"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x16b, "platform_PEP0_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x16c, "platform_PEP1_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x16d, "platform_PEP2_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x16e, "platform_PEP3_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x16f, "platform_PEP4_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x160, "platform_PEP5_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x161, "platform_PEP6_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x162, "platform_PEP7_something_counter"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x17f, "custom_PEP_CONFIG_ASPMEnable"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x132, "custom_param_RETURN_TO_SUCCESS"},
{(uint32_t) KnownRegisters::BSM_SCRATCH_START + 0x133, "custom_param_RETURN_TO_FAILURE"},
/**
* api_BSM_STATUS: Step[0-7]
@ -264,14 +316,6 @@ void decodeImage(const std::string &fileName) {
};
for (auto &e : knownNames) {
ctx.addMapping(e.first, e.second);
}
for (auto &c : comments) {
ctx.addComment(c.first, c.second);
}
for(uint32_t i = 10; i < 200; ++i){
if(registerRename.find((uint32_t) KnownRegisters::BSM_SCRATCH_START + i) == registerRename.end()){
std::stringstream s;
@ -305,7 +349,145 @@ void decodeImage(const std::string &fileName) {
}
for (auto &r : registerRename) {
ctx.addRegister(r.first, r.second);
ctx.addRegister(Instruction::AddressWithOffset{r.first, 0}, r.second);
}
bool isKnownAssembler = false;
if (imageObject.imageSignature.find("rrc-as") != std::string::npos) {
//Known assembler
isKnownAssembler = true;
comments.clear();
knownNames.clear();
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_ADDR_OFFSET_3), 0}, "rrcc_STACK_POINTER");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_ADDR_OFFSET_2), 0}, "rrcc_FRAME_POINTER");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::MGMT_SCRATCH_0), 0}, "rrcc_SCRATCH_0");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::MGMT_SCRATCH_1), 0}, "rrcc_SCRATCH_1");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E0, 0}, "rrcc_RETURN_VALUE");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E1, 0}, "rrcc_RETURN_VALUE_EXTRA");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E2, 0}, "rrcc_P0");
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1E3, 0}, "rrcc_P1");
for(uint32_t i = 0; i < 16; ++i){
ctx.addRegister(Instruction::AddressWithOffset{i, 3}, "rrcc_STACK_POINTER+" +
std::to_string(i));
}
for(uint32_t i = 0; i < 16; ++i){
ctx.addRegister(Instruction::AddressWithOffset{i, 2}, "rrcc_FRAME_POINTER+" +
std::to_string(i));
}
for(uint32_t i = 0; i < 16; ++i){
ctx.addRegister(Instruction::AddressWithOffset{static_cast<uint32_t>(KnownRegisters::BSM_SCRATCH_START) + 0x1F0 + i, 0}, "rrcc_R" +
std::to_string(i));
}
for (auto& i : imageObject.getInstructions()){
std::unique_ptr<Instruction::Instruction> decodedInstruction = nullptr;
std::unique_ptr<Instruction::Instruction> decodedInstruction2 = nullptr;
const Instruction::End* endPointer = nullptr;
if(i.second->getCommand() == Instruction::Instruction::CommandOp::END){
endPointer = reinterpret_cast<const Instruction::End*>(i.second.get());
if(endPointer->reserved == 0 || endPointer->reserved == 0xFFFFFF){
endPointer = nullptr;
}
}
if(endPointer == nullptr && imageObject.findConstInstructionByAddress(i.second->getEndAddress(), false) == nullptr){
decodedInstruction = Instruction::Instruction::decodeInstructionFromBytes(i.second->getEndAddress(), imageObject.getBaseImage());
if(decodedInstruction != nullptr && decodedInstruction->getCommand() == Instruction::Instruction::CommandOp::END){
endPointer = reinterpret_cast<const Instruction::End*>(decodedInstruction.get());
if(endPointer->reserved != endPointer->getAddress()){
endPointer = nullptr;
}
}
}
if(endPointer != nullptr){ //Found backwards pointer
bool hasMore = true;
ctx.setNop(endPointer->getAddress());
uint32_t functionEnd = endPointer->reserved - 4;
uint32_t nextAddress = endPointer->getEndAddress();
do{
decodedInstruction2 = Instruction::Instruction::decodeInstructionFromBytes(nextAddress, imageObject.getBaseImage());
if(decodedInstruction2 != nullptr && decodedInstruction2->getCommand() == Instruction::Instruction::CommandOp::LOAD){
auto loadPointer = reinterpret_cast<const Instruction::Load&>(*decodedInstruction2);
for(auto nopAddr = loadPointer.getAddress(); nopAddr < loadPointer.getEndAddress(); nopAddr += 4){
ctx.setNop(nopAddr);
}
uint32_t targetAddress = loadPointer.address;
std::string stringData;
for(auto& d : loadPointer.data){
uint8_t c = ((d >> 24) & 0xFF);
if(c == 0){
break;
}
stringData.push_back(c);
c = ((d >> 16) & 0xFF);
if(c == 0){
break;
}
stringData.push_back(c);
c = ((d >> 8) & 0xFF);
if(c == 0){
break;
}
stringData.push_back(c);
c = (d & 0xFF);
if(c == 0){
break;
}
stringData.push_back(c);
}
switch (loadPointer.addressOffset) {
case 0: //FunctionName
knownNames[targetAddress] = stringData;
break;
case 1: //Comment
std::string s = stringData;
size_t pos = 0;
std::string token;
while ((pos = s.find('\n')) != std::string::npos) {
token = s.substr(0, pos);
auto trimmed = trim(token);
if(!trimmed.empty()){
ctx.addComment(targetAddress, trimmed);
}
s.erase(0, pos + 1);
}
auto trimmed = trim(s);
if(!trimmed.empty()){
ctx.addComment(targetAddress, trimmed);
}
break;
}
nextAddress = loadPointer.getEndAddress();
hasMore = loadPointer.increment == 1;
}else{
break;
}
} while (hasMore);
}
}
}
for (auto &e : knownNames) {
ctx.addMapping(e.first, e.second);
}
for (auto &c : comments) {
ctx.addComment(c.first, c.second);
}
ctx.analyze();
@ -313,7 +495,9 @@ void decodeImage(const std::string &fileName) {
uint32_t prevAddress = 0;
for (const auto &entry : imageObject.getInstructions()) {
const auto &instruction = entry.second;
if (instruction->getAddress() < prevAddress) {
if(ctx.isNop(instruction->getAddress())){
continue;
}else if (instruction->getAddress() < prevAddress) {
std::cout << "========== DECODE ERROR? ========== " << std::hex << std::setw(8) << std::setfill('0')
<< prevAddress << " - " << std::hex << std::setw(8) << std::setfill('0')
<< instruction->getAddress() << "\n";
@ -321,6 +505,10 @@ void decodeImage(const std::string &fileName) {
(instruction->getAddress() - prevAddress) < 1024) {
std::cout << "\n\n";
for (uint32_t addr = prevAddress; addr < instruction->getAddress(); addr += 4) {
if(ctx.isNop(addr)){
continue;
}
std::stringstream op;
std::string printable;
op << std::hex << std::setw(6) << std::setfill('0') << addr << " ";