Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -180,4 +180,4 @@ build/
.html/
.latex/

out/
out/
13 changes: 10 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,12 @@ find_package(libelf REQUIRED)
# Find package dependancies
list(APPEND CMAKE_PREFIX_PATH "${CMAKE_SOURCE_DIR}/build/Debug/generators")

#Linking Libraries
add_executable(${PROJECT_NAME} src/main.cpp src/elf_parser.cpp src/gcc_parse.cpp)
#Creating Executable Target
add_executable(${PROJECT_NAME} src/main.cpp
src/elf_parser.cpp
src/gcc_parse.cpp
src/state_machine.cpp
src/concrete_states.cpp)

#Linking Libraries
target_link_libraries(${PROJECT_NAME} PUBLIC ctre::ctre libelf::libelf)
Expand Down Expand Up @@ -45,7 +49,10 @@ target_compile_options(${PROJECT_NAME} PRIVATE ${COMPILER_BUILD_FLAGS})

libhal_unit_test(SOURCES
tests/main.test.cpp
tests/testing.test.cpp
# tests/testing.test.cpp

src/state_machine.cpp
src/concrete_states.cpp

PACKAGES
tl-function-ref
Expand Down
2 changes: 1 addition & 1 deletion conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ def build_requirements(self):
"""
def layout(self):
cmake_layout(self)

"""
Method to build the project
"""
Expand Down
247 changes: 247 additions & 0 deletions include/concrete_states.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
/**
* @file concrete_states.hpp
* @brief Concrete state implementations for the state machine.
*
* This file defines all concrete states used in the state machine workflow.
* Each state represents a distinct phase in the processing pipeline, from
* user input through validation to output generation.
*
* The states follow a sequential workflow:
* UserInput → ElfParser → Callgraph → AbiParser → Validator → Output
*
* ErrorState can be entered from any state when an error occurs.
*/

#pragma once
#include <memory>
#include <optional>
#include <print>

#include "state.hpp"
#include "state_context.hpp"

/**
* @class UserInputState
* @brief Initial state that handles user input collection and validation.
*
* This is the entry point of the state machine. It processes user input,
* validates parameters, and prepares the context for subsequent states.
*
* @note This is the default initial state of the StateMachine.
*/
class UserInputState : public State
{
public:
/**
* @brief Initialize user input processing.
* @param p_context Shared state context for storing input data.
*/
void enter(StateContext& p_context) override;

/**
* @brief Process and validate user input.
* @param p_context Context to store validated input parameters.
*/
void handle(StateContext& p_context) override;

/**
* @brief Transition to ElfParserState or ErrorState.
* @param p_context Context containing validated input.
* @return Next state (typically ElfParserState) or ErrorState on failure.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class ElfParserState
* @brief Parses ELF (Executable and Linkable Format) binary files.
*
* This state reads and analyzes ELF binaries, extracting relevant information
* such as symbols, sections, and metadata needed for further processing.
*/
class ElfParserState : public State
{
public:
/**
* @brief Initialize ELF parsing resources.
* @param p_context Context containing file paths and configuration.
*/
void enter(StateContext& p_context) override;

/**
* @brief Parse the ELF binary and extract data.
* @param p_context Context to store parsed ELF information.
*/
void handle(StateContext& p_context) override;

/**
* @brief Transition to CallgraphState or ErrorState.
* @param p_context Context containing parsed ELF data.
* @return Next state (typically CallgraphState) or ErrorState on parse
* failure.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class CallgraphState
* @brief Generates and analyzes the call graph from parsed binary data.
*
* This state parses the GCC call graph representing function relationships
* and dependencies within the analyzed binary.
*/
class CallgraphState : public State
{
public:
/**
* @brief Initialize call graph generation.
* @param p_context Context containing parsed binary data.
*/
void enter(StateContext& p_context) override;

/**
* @brief Build the call graph structure.
* @param p_context Context to store the generated call graph.
*/
void handle(StateContext& p_context) override;

/**
* @brief Transition to AbiParserState or ErrorState.
* @param p_context Context containing the call graph.
* @return Next state (typically AbiParserState) or ErrorState on failure.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class AbiParserState
* @brief Parses and analyzes Application Binary Interface (ABI) information.
*
* This state extracts and processes ABI-related data, including function
* signatures, calling conventions, and interface specifications.
*/
class AbiParserState : public State
{
public:
/**
* @brief Initialize ABI parsing.
* @param p_context Context containing call graph and binary data.
*/
void enter(StateContext& p_context) override;

/**
* @brief Parse ABI specifications and interface data.
* @param p_context Context to store parsed ABI information.
*/
void handle(StateContext& p_context) override;

/**
* @brief Transition to ValidatorState or ErrorState.
* @param p_context Context containing ABI data.
* @return Next state (typically ValidatorState) or ErrorState on parse
* failure.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class ValidatorState
* @brief Validates the processed data for correctness and consistency.
*
* This state performs validation checks on the parsed and processed data
* to ensure exceptions meets requirements and is internally consistent before
* output.
*/
class ValidatorState : public State
{
public:
/**
* @brief Initialize validation checks.
* @param p_context Context containing all processed data.
*/
void enter(StateContext& p_context) override;

/**
* @brief Perform validation on processed data.
* @param p_context Context containing data to validate.
*/
void handle(StateContext& p_context) override;

/**
* @brief Transition to OutputState or ErrorState.
* @param p_context Context with validation results.
* @return Next state (OutputState if valid) or ErrorState on validation
* failure.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class OutputState
* @brief Generates and writes the final output.
*
* This is the final state in the normal execution flow. It formats and
* outputs the processed results to the specified destination.
*/
class OutputState : public State
{
public:
/**
* @brief Initialize output generation.
* @param p_context Context containing validated data to output.
*/
void enter(StateContext& p_context) override;

/**
* @brief Generate and write output.
* @param p_context Context containing all processed data.
*/
void handle(StateContext& p_context) override;

/**
* @brief Complete execution and terminate state machine.
* @param p_context Context with output results.
* @return std::nullopt to signal state machine completion.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};

/**
* @class ErrorState
* @brief Handles error conditions and cleanup.
*
* This state is entered when an error occurs in any other state. It handles
* error reporting, logging, and cleanup operations before terminating the
* state machine.
*
* @note This state always returns std::nullopt to terminate execution.
*/
class ErrorState : public State
{
public:
/**
* @brief Initialize error handling.
* @param p_context Context containing error information.
*/
void enter(StateContext& p_context) override;

/**
* @brief Process and report the error.
* @param p_context Context with error details for reporting.
*/
void handle(StateContext& p_context) override;

/**
* @brief Terminate state machine after error handling.
* @param p_context Context after error processing.
* @return std::nullopt to signal state machine termination.
*/
std::optional<std::unique_ptr<State>> exit(
StateContext& p_context) override;
};
78 changes: 78 additions & 0 deletions include/state.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#pragma once
#include <memory>
#include <optional>

#include "state_context.hpp"

/**
* @class State
* @brief Abstract base class for all states in the state machine.
*
* The State class defines the interface that all concrete states must
* implement. Each state has three lifecycle phases: enter (initialization),
* handle (main logic), and exit (cleanup and transition). States use the
* StateContext to access shared data and determine transitions.
*
* Concrete states should inherit from this class and implement all three pure
* virtual methods to define their specific behavior.
*
* @note This is an abstract class and cannot be instantiated directly.
* @see StateMachine
* @see StateContext
* @see state_context.hpp
*/
class State
{
public:
/**
* @brief Called when entering the state.
*
* This method is invoked when the state machine transitions into this
* state. It should perform any initialization or setup required before the
* state's main logic executes.
*
* @param context Reference to the shared state context containing data
* and configuration accessible to all states.
*
* @note This is called before handle() in the state lifecycle.
*/
virtual void enter(StateContext& p_context) = 0;

/**
* @brief Executes the main logic of the state.
*
* This method contains the primary behavior and operations of the state.
* It is called after enter() and before exit() during state execution.
*
* @param context Reference to the shared state context for accessing
* and modifying shared data.
*
* @note This is where the state performs its core functionality.
*/
virtual void handle(StateContext& p_context) = 0;

/**
* @brief Called when exiting the state and determines the next state.
*
* This method is invoked after handle() completes. It should perform any
* cleanup operations and return the next state to transition to. If this
* returns std::nullopt, the state machine will terminate.
*
* @param context Reference to the shared state context for accessing
* data needed to determine the next state.
*
* @return std::optional<std::unique_ptr<State>> The next state to
* transition to, or std::nullopt to terminate the state machine.
*
* @note Returning std::nullopt signals the end of state machine execution.
* @note The returned state's ownership is transferred to the state machine.
*/
virtual std::optional<std::unique_ptr<State>> exit(StateContext& p_context)
= 0;

/**
* @brief Virtual destructor for proper cleanup of derived classes.
*
*/
virtual ~State() = default;
};
23 changes: 23 additions & 0 deletions include/state_context.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#pragma once

/**
* @brief Content in this is temporary. Please change
* them according to what the state desires. All data relating to
* SAFE will be stored here and shared between the states.
*
*/
class StateContext
{
public:
void inc_data()
{
data++;
}
int get_data()
{
return data;
}

private:
int data = 0;
};
Loading