#include "commit_request.hpp" #include #include #include #include #include #include #include struct ArenaDebugger { const CommitRequest &commit_request; const ArenaAllocator &arena; std::unordered_set referenced_addresses; explicit ArenaDebugger(const CommitRequest &cr) : commit_request(cr), arena(cr.arena()) {} void analyze_references() { // Track all string_view data pointers from the parsed commit request if (commit_request.request_id().has_value()) { add_reference(commit_request.request_id()->data(), commit_request.request_id()->size()); } add_reference(commit_request.leader_id().data(), commit_request.leader_id().size()); for (const auto &precond : commit_request.preconditions()) { add_reference(precond.begin.data(), precond.begin.size()); add_reference(precond.end.data(), precond.end.size()); } for (const auto &op : commit_request.operations()) { add_reference(op.param1.data(), op.param1.size()); add_reference(op.param2.data(), op.param2.size()); } } void add_reference(const char *ptr, size_t size) { if (ptr && size > 0) { referenced_addresses.insert(ptr); // Also add end pointer to mark the range referenced_addresses.insert(ptr + size - 1); } } void visualize_arena() { std::cout << "=== Arena Visualization Debug Tool ===" << std::endl; std::cout << "Analyzing commit request and arena memory layout" << std::endl; std::cout << std::endl; // First, analyze what's referenced analyze_references(); // Print basic arena statistics std::cout << "Arena Statistics:" << std::endl; std::cout << "- Total allocated: " << arena.total_allocated() << " bytes" << std::endl; std::cout << "- Currently used: " << arena.used_bytes() << " bytes" << std::endl; std::cout << "- Number of blocks: " << arena.num_blocks() << " blocks" << std::endl; std::cout << "- Referenced addresses: " << referenced_addresses.size() << std::endl; std::cout << std::endl; // Use the arena's debug_dump with content visualization std::cout << "Raw Arena Memory Layout:" << std::endl; arena.debug_dump(std::cout, true, true, 1024); std::cout << std::endl; std::cout << "=== Pointer Analysis ===" << std::endl; // Scan for potential pointers in arena memory using the arena's built-in // method scan_arena_pointers(); std::cout << std::endl; std::cout << "=== Referenced Memory Regions ===" << std::endl; visualize_referenced_data(); } private: void scan_arena_pointers() { std::cout << "Scanning all used arena memory for 64-bit aligned pointers..." << std::endl; // Use the arena's comprehensive pointer scanning method auto pointers = arena.find_intra_arena_pointers(); std::cout << "Arena memory scan complete:" << std::endl; std::cout << "- Total scanned: " << arena.used_bytes() << " bytes across " << arena.num_blocks() << " blocks" << std::endl; std::cout << "- Intra-arena pointers found: " << pointers.size() << std::endl; if (pointers.empty()) { std::cout << "No intra-arena pointers detected." << std::endl; return; } std::cout << std::endl; std::cout << "Detected pointers:" << std::endl; for (size_t i = 0; i < pointers.size(); ++i) { const auto &ptr_info = pointers[i]; std::cout << "Pointer #" << (i + 1) << ":" << std::endl; std::cout << " Source: " << ptr_info.source_addr << " (Block #" << ptr_info.source_block_number << ", offset +0x" << std::hex << ptr_info.source_offset << std::dec << ")" << std::endl; std::cout << " Target: " << ptr_info.target_addr << " (Block #" << ptr_info.target_block_number << ", offset +0x" << std::hex << ptr_info.target_offset << std::dec << ")" << std::endl; // Try to identify what this pointer might be pointing to identify_pointer_target(ptr_info.target_addr); std::cout << std::endl; } } void identify_pointer_target(const void *target_addr) { // Check if this target address matches any of our known string data std::cout << " Points to: "; bool found_match = false; // Check request_id if (commit_request.request_id().has_value()) { const auto &req_id = *commit_request.request_id(); if (target_addr >= req_id.data() && target_addr < req_id.data() + req_id.size()) { std::cout << "request_id string"; found_match = true; } } // Check leader_id if (!found_match) { const auto &leader_id = commit_request.leader_id(); if (target_addr >= leader_id.data() && target_addr < leader_id.data() + leader_id.size()) { std::cout << "leader_id string"; found_match = true; } } // Check preconditions if (!found_match) { for (size_t i = 0; i < commit_request.preconditions().size(); ++i) { const auto &precond = commit_request.preconditions()[i]; if (!precond.begin.empty() && target_addr >= precond.begin.data() && target_addr < precond.begin.data() + precond.begin.size()) { std::cout << "precondition[" << i << "].begin string"; found_match = true; break; } if (!precond.end.empty() && target_addr >= precond.end.data() && target_addr < precond.end.data() + precond.end.size()) { std::cout << "precondition[" << i << "].end string"; found_match = true; break; } } } // Check operations if (!found_match) { for (size_t i = 0; i < commit_request.operations().size(); ++i) { const auto &op = commit_request.operations()[i]; if (!op.param1.empty() && target_addr >= op.param1.data() && target_addr < op.param1.data() + op.param1.size()) { std::cout << "operation[" << i << "].param1 string"; found_match = true; break; } if (!op.param2.empty() && target_addr >= op.param2.data() && target_addr < op.param2.data() + op.param2.size()) { std::cout << "operation[" << i << "].param2 string"; found_match = true; break; } } } if (!found_match) { std::cout << "unknown arena data"; } std::cout << std::endl; } std::string_view find_string_view_for_data(const char *data) { if (commit_request.request_id().has_value() && commit_request.request_id()->data() == data) { return *commit_request.request_id(); } if (commit_request.leader_id().data() == data) { return commit_request.leader_id(); } for (const auto &precond : commit_request.preconditions()) { if (precond.begin.data() == data) return precond.begin; if (precond.end.data() == data) return precond.end; } for (const auto &op : commit_request.operations()) { if (op.param1.data() == data) return op.param1; if (op.param2.data() == data) return op.param2; } return {}; } void visualize_referenced_data() { std::cout << "Visualizing parsed commit request data references:" << std::endl; std::cout << std::endl; // Show request_id if (commit_request.request_id().has_value()) { std::cout << "request_id: "; visualize_string_data(*commit_request.request_id()); } // Show leader_id std::cout << "leader_id: "; visualize_string_data(commit_request.leader_id()); // Show read_version std::cout << "read_version: " << commit_request.read_version() << std::endl; // Show preconditions std::cout << "preconditions (" << commit_request.preconditions().size() << "):" << std::endl; for (size_t i = 0; i < commit_request.preconditions().size(); ++i) { const auto &precond = commit_request.preconditions()[i]; std::cout << " [" << i << "] type: " << precondition_type_to_string(precond.type) << ", version: " << precond.version << std::endl; std::cout << " begin: "; visualize_string_data(precond.begin, " "); std::cout << " end: "; visualize_string_data(precond.end, " "); } // Show operations std::cout << "operations (" << commit_request.operations().size() << "):" << std::endl; for (size_t i = 0; i < commit_request.operations().size(); ++i) { const auto &op = commit_request.operations()[i]; std::cout << " [" << i << "] type: " << operation_type_to_string(op.type) << std::endl; std::cout << " param1: "; visualize_string_data(op.param1, " "); std::cout << " param2: "; visualize_string_data(op.param2, " "); } } void visualize_string_data(std::string_view sv, const std::string &indent = "") { if (sv.empty()) { std::cout << "(empty)" << std::endl; return; } const char *data = sv.data(); size_t size = sv.size(); std::cout << "\"" << sv << "\" @ " << static_cast(data) << " [" << size << " bytes]"; if (referenced_addresses.count(data)) { std::cout << " (REFERENCED)"; } std::cout << std::endl; // Show hex dump of the string data if (size > 0 && size <= 64) { // Only show hex for reasonable sizes std::cout << indent << "Hex: "; for (size_t i = 0; i < size; ++i) { unsigned char byte = static_cast(data[i]); std::cout << std::hex << std::setfill('0') << std::setw(2) << static_cast(byte) << std::dec; if ((i + 1) % 4 == 0 && i < size - 1) std::cout << " "; } std::cout << std::endl; } } const char *precondition_type_to_string(Precondition::Type type) { switch (type) { case Precondition::Type::PointRead: return "point_read"; case Precondition::Type::RangeRead: return "range_read"; default: return "unknown"; } } const char *operation_type_to_string(Operation::Type type) { switch (type) { case Operation::Type::Write: return "write"; case Operation::Type::Delete: return "delete"; case Operation::Type::RangeDelete: return "range_delete"; default: return "unknown"; } } }; int main(int argc, char *argv[]) { if (argc != 2) { std::cerr << "Usage: " << argv[0] << " " << std::endl; std::cerr << "Debug tool to visualize arena memory layout from commit " "request JSON" << std::endl; return 1; } const char *filename = argv[1]; // Read JSON file std::ifstream file(filename); if (!file.is_open()) { std::cerr << "Error: Could not open file '" << filename << "'" << std::endl; return 1; } std::ostringstream ss; ss << file.rdbuf(); std::string json_content = ss.str(); file.close(); if (json_content.empty()) { std::cerr << "Error: File is empty or could not be read" << std::endl; return 1; } std::cout << "Reading commit request from: " << filename << std::endl; std::cout << "JSON size: " << json_content.size() << " bytes" << std::endl; std::cout << std::endl; // Parse the commit request CommitRequest commit_request; // Make a mutable copy for parsing (weaseljson requires mutable data) std::vector mutable_json(json_content.begin(), json_content.end()); mutable_json.push_back('\0'); // Null terminate for safety bool parse_success = commit_request.parse_json(mutable_json.data(), mutable_json.size() - 1); if (!parse_success || !commit_request.is_parse_complete()) { std::cerr << "Error: Failed to parse JSON" << std::endl; if (commit_request.has_parse_error()) { std::cerr << "Parse error: " << commit_request.get_parse_error() << std::endl; } return 1; } std::cout << "Successfully parsed commit request!" << std::endl; std::cout << std::endl; // Create debugger and visualize ArenaDebugger debugger(commit_request); debugger.visualize_arena(); return 0; }