Skip to content

Commit

Permalink
Created backend server
Browse files Browse the repository at this point in the history
  • Loading branch information
Anivice committed Jan 16, 2025
1 parent 74f3bfe commit 3f383dc
Show file tree
Hide file tree
Showing 59 changed files with 15,528 additions and 55 deletions.
21 changes: 14 additions & 7 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -319,19 +319,26 @@ if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
add_custom_target(
COPY_HDA_FILE ALL
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/tests/hda.img ${CMAKE_CURRENT_BINARY_DIR}/
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/tests/example.sysasm ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS tests/hda.img tests/example.sysasm
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/tests/example.asm ${CMAKE_CURRENT_BINARY_DIR}/
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/tests/example2.asm ${CMAKE_CURRENT_BINARY_DIR}/
DEPENDS tests/hda.img tests/example.asm
COMMENT "Copy disk image sample with ASCII texts in it."
)
endif ()

# Console Executable:
find_package(nlohmann_json REQUIRED)

add_executable(sysdarft-system
src/SysdarftMain.cpp
src/SysdarftConsole/SysdarftMain.cpp
src/include/SysdarftConsole.h
src/include/SysdarftMain.h
src/MainArgProcessor.cpp
src/MainCompile.cpp
src/SysdarftConsole/MainArgProcessor.cpp
src/SysdarftConsole/MainCompile.cpp
src/SysdarftConsole/RemoteDebugServer.cpp
src/SysdarftConsole/ConditionalExpression.cpp
src/SysdarftConsole/ShowContext.cpp
src/SysdarftConsole/DebugAction.cpp
)
target_include_directories(sysdarft-system PUBLIC src/include)
target_link_libraries(sysdarft-system PUBLIC Sysdarft)
target_include_directories(sysdarft-system PUBLIC src/include src/include/crow)
target_link_libraries(sysdarft-system PUBLIC Sysdarft nlohmann_json::nlohmann_json)
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sysdarft
![Lines of Code](https://img.shields.io/badge/ProjectLines-11576-cyan)
![Size of Code](https://img.shields.io/badge/ProjectSize-696%20K-yellow)
![Lines of Code](https://img.shields.io/badge/ProjectLines-27080-cyan)
![Size of Code](https://img.shields.io/badge/ProjectSize-1324%20K-yellow)
[![Automated CMake Test Workflow](https://github.com/Anivice/Sysdarft/actions/workflows/CMake_GitHub_Action.yml/badge.svg)](https://github.com/Anivice/Sysdarft/actions/workflows/CMake_GitHub_Action.yml)

Sysdarft is a hypothetical binary 64bit architecture.
Expand Down
15 changes: 15 additions & 0 deletions src/SysdarftConsole/ConditionalExpression.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include <SysdarftMain.h>

std::vector < uint8_t >
RemoteDebugServer::
compile_conditional_expression_to_byte_code(const std::string & conditional_expression)
{
return {};
}

bool
RemoteDebugServer::
is_condition_met(std::vector < uint8_t > condition_expression_byte_code)
{
return false;
}
31 changes: 31 additions & 0 deletions src/SysdarftConsole/DebugAction.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include <SysdarftMain.h>

void RemoteDebugServer::at_breakpoint(__uint128_t, const uint8_t opcode, const SysdarftCPU::WidthAndOperandsType & args)
{
while (true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
{
std::lock_guard lock(action_access_mutex);
std::lock_guard lock2(action_result_access_mutex);

if (debug_action_request.empty()) {
continue;
}

switch (debug_action_request.at(0))
{
// NOTE: debug_action_result must be non-empty when return to avoid dead lock
case CONTINUE:
debug_action_result = "Continue";
return;
case SHOW_CONTEXT:
debug_action_result = show_context(CPUInstance, opcode, args);
break;
default: /* ignore any abnormal behavior */ break;
}

debug_action_request.clear();
}
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
189 changes: 189 additions & 0 deletions src/SysdarftConsole/RemoteDebugServer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
#include <nlohmann/json.hpp>
#include <chrono>
#include <fstream>
#include <thread>
#include <mutex>
#include <vector>
#include <memory>
#include <SysdarftMain.h>

using namespace std::literals;
using json = nlohmann::json;

RemoteDebugServer::RemoteDebugServer(
const std::string & ip,
uint16_t port,
SysdarftCPU & _CPUInstance,
const std::string & crow_log_file)
: CPUInstance(_CPUInstance), SysdarftLogHandlerInstance(crow_log, !crow_log_file.empty())
{
// Setup Crow log handler
try {
if (!crow_log_file.empty()) {
crow_log.open(crow_log_file);
}

crow::logger::setHandler(&SysdarftLogHandlerInstance);
crow::logger::setLogLevel(crow::LogLevel::Debug);
} catch (const std::exception & e) {
std::cerr << "Error occurred while setting up log stream: " << e.what() << std::endl;
throw;
}

// Install handler
CPUInstance.bindIsBreakHere(this, &RemoteDebugServer::if_breakpoint);
CPUInstance.bindBreakpointHandler(this, &RemoteDebugServer::at_breakpoint);

// Install backend handler
CROW_ROUTE(JSONBackend, "/IsAPIAvailable")([]()
{
// Create a JSON object using nlohmann/json
json response;
response["Version"] = SYSDARFT_VERSION;
response["Result"] = SYSDARFT_INFORMATION;

const auto timeNow = std::chrono::system_clock::now();
response["UNIXTimestamp"] = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
timeNow.time_since_epoch()).count());

// Return the JSON as a Crow response with the correct MIME type
return crow::response{response.dump()};
});

CROW_ROUTE(JSONBackend, "/SetBreakpoint").methods(crow::HTTPMethod::POST)
([this](const crow::request& req)
{
// Create a JSON object using nlohmann/json
json response;
response["Version"] = SYSDARFT_VERSION;
const auto timeNow = std::chrono::system_clock::now();
response["UNIXTimestamp"] = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
timeNow.time_since_epoch()).count());

std::string bodyString = req.body;
json clientJson;
try {
clientJson = json::parse(bodyString);
} catch (const std::exception&) {
response["Result"] = "Invalid Argument";
return crow::response(400, response.dump());
}

if ( !clientJson.contains("CB")
|| !clientJson.contains("IP")
|| !clientJson.contains("Condition"))
{
response["Result"] = "Invalid Argument (Missing CB, IP, and/or Condition)";
return crow::response(400, response.dump());
}

std::vector < uint8_t > expression_byte_code;
try {
expression_byte_code =
compile_conditional_expression_to_byte_code(clientJson["Condition"]);
} catch (const std::exception & e) {
response["Result"] = "Conditional Expression Error: " + std::string(e.what());
return crow::response(400, response.dump());
}

std::string CB_literal = clientJson["CB"];
std::string IP_literal = clientJson["IP"];

process_base16(CB_literal);
process_base16(IP_literal);

CB_literal = execute_bc(CB_literal);
IP_literal = execute_bc(IP_literal);

const auto CB = std::strtoull(CB_literal.c_str(), nullptr, 10);
const auto IP = std::strtoull(IP_literal.c_str(), nullptr, 10);

bool have_i_processed = false;
for (auto it = breakpoint_list.begin(); it != breakpoint_list.end(); ++it)
{
if ((it->first.first + it->first.second) == (IP + CB)) {
it->second = expression_byte_code;
have_i_processed = true;
break;
}
}

// if not found, add
if (!have_i_processed) {
breakpoint_list.emplace(std::pair(CB, IP), expression_byte_code);
}

response["Result"] = "Success";
response["Linear"] = std::to_string(CB + IP);
// Return the JSON as a Crow response with the correct MIME type
return crow::response{response.dump()};
});

CROW_ROUTE(JSONBackend, "/ShowContext").methods(crow::HTTPMethod::GET)([this]()
{
json response;
response["Version"] = SYSDARFT_VERSION;
const auto timeNow = std::chrono::system_clock::now();
response["UNIXTimestamp"] = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
timeNow.time_since_epoch()).count());
response["Result"] = "Success";

response["Context"] = invoke_action(SHOW_CONTEXT);

return crow::response{response.dump()};
});

CROW_ROUTE(JSONBackend, "/Continue").methods(crow::HTTPMethod::POST)([this]()
{
json response;
response["Version"] = SYSDARFT_VERSION;
const auto timeNow = std::chrono::system_clock::now();
response["UNIXTimestamp"] = std::to_string(std::chrono::duration_cast<std::chrono::seconds>(
timeNow.time_since_epoch()).count());
response["Result"] = "Success";

invoke_action(CONTINUE);

return crow::response{response.dump()};
});

server_thread = std::thread ([this](
// DO NOT capture the current context, since it will cause `stack-use-after-return`
const std::string & IP_,
const uint16_t port_)
{
debug::set_thread_name("Crow Backend");
JSONBackend.bindaddr(IP_).port(port_).multithreaded().run();
}, ip, port);
}

RemoteDebugServer::~RemoteDebugServer()
{
JSONBackend.stop();

// Join the server thread to clean up
if (server_thread.joinable()) {
server_thread.join();
}
}

bool RemoteDebugServer::if_breakpoint(__uint128_t)
{
const auto CB = CPUInstance.load<CodeBaseType>();
const auto IP = CPUInstance.load<InstructionPointerType>();

// halt system at startup, which is exactly where the start of BIOS is located
if (!skip_bios_ip_check) {
skip_bios_ip_check = true; // skip next IP+CB == BIOS scenario
return true;
}

for (auto & [breakpoint, condition] : breakpoint_list)
{
if ((CB + IP) == (breakpoint.first + breakpoint.second)) {
return is_condition_met(condition);
}
}

return false;
}
Loading

0 comments on commit 3f383dc

Please sign in to comment.