Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
04fbc31
force brew llvm on osx
f1ammable Jan 11, 2026
a43e714
add example subcommand
f1ammable Jan 11, 2026
328a159
check binary type against current platform (WIP)
f1ammable Jan 16, 2026
649b1af
update `core` and `cmd` libs to be in include path
f1ammable Jan 22, 2026
303b8b7
start target and wait for it to finish
f1ammable Jan 27, 2026
3c1b0aa
split `Error` into component-specific error type
f1ammable Feb 11, 2026
299a1a7
refactor `Target`
f1ammable Feb 11, 2026
affb947
move `Macho` into own library
f1ammable Feb 11, 2026
cabd816
build: enforce stricter brew llvm checks
f1ammable Feb 13, 2026
9c3fde7
feat: trace process via mach exceptions
f1ammable Feb 13, 2026
c0dcce5
chore: update vcpkg
f1ammable Feb 13, 2026
c51a53a
refactor(core/macho): remove global variable usage
f1ammable Feb 13, 2026
be7e211
refactor(macho): handle unix signals refiring
f1ammable Feb 14, 2026
4c8a799
feat(macho): show exception reason and unix signal
f1ammable Feb 14, 2026
d76b7c7
feat(macho): implement `resume` command
f1ammable Feb 14, 2026
abedf4e
feat(macho): start process suspended
f1ammable Feb 14, 2026
807d874
feat(macho): show exit code when target exits
f1ammable Feb 15, 2026
2fbb1e2
style: allow non-private members in classes
f1ammable Feb 15, 2026
6ee7f9f
feat(macho): arm64 set breakpoints
f1ammable Feb 17, 2026
caab317
feat(macho): resume execution after breakpoints
f1ammable Feb 17, 2026
2fa48d0
build: link core library for tests
f1ammable Feb 19, 2026
2adf8bd
test(cmd): don't treat variables as function calls
f1ammable Feb 19, 2026
261abff
style: exclude mig-generated headers
f1ammable Feb 19, 2026
baebb3b
fix(cmd): return early in `checkNumberOperand`
f1ammable Feb 19, 2026
d3c4ea0
test(cmd): improve test coverage for interpreter
f1ammable Feb 19, 2026
69be254
test(cmd): add tests for `Expr` and lint file
f1ammable Feb 19, 2026
e73aa67
test(cmd): add tests for subcommands
f1ammable Feb 19, 2026
3e5b7ab
test(cmd): add tests for built-in functions
f1ammable Feb 19, 2026
4a39780
feat(core/cmd): disable and toggle breakpoints
f1ammable Feb 19, 2026
45ec152
fix(core/macho): use map reference instead of copy
f1ammable Feb 19, 2026
33423ef
refactor(core/macho): make `m_target` static
f1ammable Feb 19, 2026
3c6b24c
refactor(cmd/mach): consolidate removing and toggling breakpoints
f1ammable Feb 20, 2026
e314c7c
refactor(core): use `Expected` for casting address
f1ammable Feb 20, 2026
241036b
perf: re-arrange member variables to reduce padding
f1ammable Feb 20, 2026
88856ad
fix(mach): decode exit status
f1ammable Feb 20, 2026
e76ac6a
fix(core/mach): use typedefs + wait for event loop to finish
f1ammable Feb 20, 2026
72aed90
docs: update readme
f1ammable Feb 22, 2026
b73360f
fix: remove unused includes and files
f1ammable Feb 22, 2026
fff94fc
fix: include mach headers only if on osx
f1ammable Feb 22, 2026
162bdee
fix: remove even more apple includes
f1ammable Feb 22, 2026
2464bb8
fix: add header guards for osx includes
f1ammable Feb 23, 2026
41f6cf4
fix: add `format` include
f1ammable Feb 23, 2026
42ee492
style: run formatter
f1ammable Feb 23, 2026
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
5 changes: 3 additions & 2 deletions .clang-tidy
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ Checks: >
-readability-else-after-return,
-readability-braces-around-statements,
-google-readability-braces-around-statements,
-misc-include-cleaner
-misc-include-cleaner,
-cppcoreguidelines-non-private-member-variables-in-classes

WarningsAsErrors: ''

Expand Down Expand Up @@ -86,7 +87,7 @@ CheckOptions:
value: true

# Exclude third-party code and build artifacts
HeaderFilterRegex: '^.*/(src|test)/.*\.(h|hpp)$'
HeaderFilterRegex: '^.*/(src|test)/(?!.*mach_exc).*\.(h|hpp)$'

# Suppress warnings from system headers
SystemHeaders: false
50 changes: 49 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,44 @@ set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

# OPTIONAL: Use ccache if present
find_program(CCACHE_PROGRAM ccache)
if(CCACHE_PROGRAM)
set(CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
set(CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}")
message(STATUS "ccache found: ${CCACHE_PROGRAM}")
else()
message(WARNING "ccache not found - builds will be slower. Install with: brew install ccache")
endif()

# Only brew LLVM is supported on OSX at the moment
if(CMAKE_HOST_SYSTEM_NAME MATCHES "Darwin")
# Find brew
find_program(BREW_PROGRAM brew)
if(NOT BREW_PROGRAM)
message(FATAL_ERROR "Homebrew not found! Install from https://brew.sh")
endif()

# Find LLVM
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE BREW_LLVM_RESULT ERROR_QUIET)
if(NOT BREW_LLVM_RESULT EQUAL 0)
message(FATAL_ERROR "Brew LLVM not found! Install with: brew install llvm")
endif()

# Use brew LLVM clang
set(CMAKE_C_COMPILER "${LLVM_PREFIX}/bin/clang")
set(CMAKE_CXX_COMPILER "${LLVM_PREFIX}/bin/clang++")

# Link with brew LLVM libc++
execute_process(COMMAND brew --prefix llvm OUTPUT_VARIABLE LLVM_PREFIX OUTPUT_STRIP_TRAILING_WHITESPACE)
add_compile_options(-stdlib=libc++)
add_link_options(-stdlib=libc++ -L${LLVM_PREFIX}/lib/c++ -Wl,-rpath,${LLVM_PREFIX}/lib/c++)

# Set OSX SDK
execute_process(COMMAND xcrun --sdk macosx --show-sdk-path OUTPUT_VARIABLE OSX_SYSROOT OUTPUT_STRIP_TRAILING_WHITESPACE)
set(CMAKE_OSX_SYSROOT "${OSX_SYSROOT}")
endif()

project(caesar VERSION 0.1.0)

# Optional: Enable code coverage
Expand Down Expand Up @@ -33,9 +71,13 @@ if(ENABLE_COVERAGE)
message(STATUS "Code coverage enabled")
endif()

add_executable(caesar src/main.cpp)
add_executable(caesar src/main.cpp src/error.cpp src/error.hpp src/formatter.hpp)
target_link_libraries(caesar PRIVATE caesar_cmd caesar_core)

if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_libraries(caesar PRIVATE caesar_macho)
endif()

# Optional: Build tests
if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR OR CAESAR_BUILD_TESTS)
option(CAESAR_BUILD_TESTS "Build tests" ON)
Expand All @@ -52,10 +94,16 @@ if(CAESAR_BUILD_TESTS)
test/cmd/test_object.cpp
test/cmd/test_parser.cpp
test/cmd/test_scanner.cpp
test/cmd/test_stdlib.cpp
src/error.cpp
)

target_link_libraries(caesar_test PRIVATE caesar_cmd caesar_core Catch2::Catch2WithMain)

if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_link_libraries(caesar_test PRIVATE caesar_macho)
endif()

# Apply coverage flags to test executable if coverage is enabled
if(ENABLE_COVERAGE)
target_compile_options(caesar_test PUBLIC ${COVERAGE_COMPILE_FLAGS})
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ A modern C++20 cross-platform debugger.

The debugger is built with a modular architecture:

- **Core Engine** (`src/core/`): Core debugger engine functionality
- **Core Engine** (`src/core/`): Core debugger engine functionality. Split into separate libraries per platform
- **Command System** (`src/cmd/`): Expression parser, interpreter, and AST components

## Building
Expand All @@ -28,7 +28,7 @@ The debugger is built with a modular architecture:
```bash
mkdir build
cd build
cmake ..
cmake .. --preset (debug|release)
make
```

Expand All @@ -42,6 +42,13 @@ Run the debugger without arguments to enter interactive mode:

This starts a REPL where you can enter expressions and commands.

Alternatively, run with a file to automatically set a target upon startup:

```bash
./caesar (file)
```


### Development Environment

The project includes a development setup script:
Expand All @@ -50,15 +57,21 @@ The project includes a development setup script:
./start.sh
```

This creates a tmux session with editor, compiler, and miscellaneous panes for efficient development. This is my preffered environment, feel free to use or adapt it to your own needs.
This creates a tmux session with editor, compiler, and miscellaneous panes for efficient development. This is my preferred environment, feel free to use or adapt it to your own needs.

## Components

### Expression Engine
- **Scanner**: Tokenizes input expressions
- **Parser**: Builds abstract syntax trees from tokens
- **Interpreter**: Evaluates expressions with support for literals, grouping, unary and binary operations
- **AST Printer**: Debug utility for visualizing abstract syntax trees
- **Built-in Functions**: Native commands for debugging (breakpoint, run, resume, etc.)

### Core Debugging Engine
- **Target**: Process control, breakpoint management, and binary inspection
- **Macho**: Mach-O parser supporting 64-bit architectures and byte swapping
- **Exception Ports**: Mach-based exception handling for traps and signals
- **ASLR**: Automatic slide detection for address resolution

## Project Status

Expand Down
8 changes: 8 additions & 0 deletions src/Entitlements.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.debugger</key>
<true/>
</dict>
</plist>
5 changes: 1 addition & 4 deletions src/cmd/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
add_library(caesar_cmd STATIC
error.cpp
error.hpp
scanner.cpp
scanner.hpp
token.hpp
Expand All @@ -17,9 +15,8 @@ add_library(caesar_cmd STATIC
callable.hpp
stdlib.hpp
object.hpp
formatter.hpp
)

target_include_directories(caesar_cmd PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/..
)
5 changes: 5 additions & 0 deletions src/cmd/callable.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@
#include <format>
#include <vector>

#include "core/context.hpp"
#include "core/target.hpp"
#include "object.hpp"

class Interpreter;

class Callable {
protected:
std::unique_ptr<Target>& m_target = Context::getTarget();

public:
virtual ~Callable() = default;
virtual Object call(std::vector<Object> args) = 0;
Expand Down
25 changes: 14 additions & 11 deletions src/cmd/environment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
void Environment::define(const std::string& name, Object value) {
if (m_values.contains(name))
if (auto* ptr = std::get_if<std::shared_ptr<Callable>>(&m_values[name])) {
Error::error(TokenType::IDENTIFIER,
std::format("Cannot assign to {} as it is a function", name),
ErrorType::RUNTIME_ERROR);
CmdError::error(
TokenType::IDENTIFIER,
std::format("Cannot assign to {} as it is a function", name),
CmdErrorType::RUNTIME_ERROR);
return;
}

Expand All @@ -22,9 +23,9 @@ void Environment::define(const std::string& name, Object value) {

Object Environment::get(const Token& name) {
if (m_values.contains(name.m_lexeme)) return m_values[name.m_lexeme];
Error::error(name.m_type,
std::format("Undefined variable '{}'.", name.m_lexeme),
ErrorType::RUNTIME_ERROR);
CmdError::error(name.m_type,
std::format("Undefined variable '{}'.", name.m_lexeme),
CmdErrorType::RUNTIME_ERROR);
return std::monostate{};
}

Expand All @@ -33,22 +34,24 @@ void Environment::assign(const Token& name, Object value) {
if (auto* val =
std::get_if<std::shared_ptr<Callable>>(&m_values[name.m_lexeme]);
val != nullptr) {
Error::error(
CmdError::error(
name.m_type,
std::format("Cannot reassign {} as it is a function", name.m_lexeme),
ErrorType::RUNTIME_ERROR);
CmdErrorType::RUNTIME_ERROR);
return;
}
m_values[name.m_lexeme] = std::move(value);
return;
}

Error::error(name.m_type,
std::format("Undefined variable '{}'", name.m_lexeme),
ErrorType::RUNTIME_ERROR);
CmdError::error(name.m_type,
std::format("Undefined variable '{}'", name.m_lexeme),
CmdErrorType::RUNTIME_ERROR);
}

Environment& Environment::getInstance() {
static Environment instance;
return instance;
}

std::map<std::string, Object> Environment::getAll() { return m_values; }
4 changes: 4 additions & 0 deletions src/cmd/environment.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@ class Environment {
Environment() : m_values({}) {
this->define("print", std::make_shared<PrintFn>(PrintFn()));
this->define("len", std::make_shared<LenFn>(LenFn()));
this->define("breakpoint", std::make_shared<BreakpointFn>(BreakpointFn()));
this->define("run", std::make_shared<RunFn>(RunFn()));
this->define("resume", std::make_shared<ContinueFn>(ContinueFn()));
}

public:
void define(const std::string& name, Object value);
Object get(const Token& name);
std::map<std::string, Object> getAll();
void assign(const Token& name, Object value);

Environment(Environment& other) = delete;
Expand Down
22 changes: 0 additions & 22 deletions src/cmd/error.cpp

This file was deleted.

48 changes: 0 additions & 48 deletions src/cmd/error.hpp

This file was deleted.

Loading
Loading