diff --git a/README.md b/README.md index 5d52a22..1541496 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,81 @@ # SAFE: Static Analyzer For Exceptions + Exceptions binary analysis tool (for Itanum ARM ABI) + +## Code Repository + +https://github.com/libhal/exception-insights + +## Code Structure + +exception-insight +├── CMakeLists.txt +├── CMakeUserPresets.json +├── LICENSE +├── README.md +├── build +│ ├── Debug +│ │ ├── CMakeCache.txt +│ │ ├── CMakeFiles +│ │ ├── Makefile +│ │ ├── cmake_install.cmake +│ │ ├── compile_commands.json +│ │ ├── generators +│ │ ├── metadata +│ │ ├── safe +│ │ └── unit_test +│ └── logs +│ ├── RTTI_typeinfo.txt +│ └── function_binary.txt +├── compile_commands.json +├── conanfile.py +├── docs +│ ├── Doxyfile +│ ├── html +│ │ └── search +│ └── latex +│ └── Makefile +├── include +│ ├── abi_parse.hpp +│ ├── elf_parser.hpp +│ ├── gcc_parse.hpp +│ └── validator.hpp +├── src +│ ├── abi_parse.cpp +│ ├── elf_parser.cpp +│ ├── gcc_parse.cpp +│ ├── main.cpp +│ ├── throw.cpp +│ └── validator.cpp +├── testing_programs +│ ├── build +│ │ ├── demo_class +│ │ ├── elf_test +│ │ ├── multi_tu.whole-program +│ │ └── simple +│ ├── demo.cpp +│ ├── demo_class.cpp +│ ├── demo_two.cpp +│ ├── demo_two.h +│ ├── elf_test.cpp +│ ├── gcc_parse.py +│ ├── generate_and_build.ps1 +│ ├── generate_and_build.sh +│ ├── shell.nix +│ ├── simple.cpp +│ ├── single_tu.cpp +│ └── test.c +└── tests +├── abi_parser.test.cpp +├── elf_parser.test.cpp +├── gcc_callgraph.test.cpp +├── main.test.cpp +├── testing.test.cpp +├── validator.test.cpp +└── validator_catch.test.cpp + +# Build instructions + +1. Build Command: `rm -r build && conan build . ` +2. Run Command: `./build/Debug/safe ` + - Run with test file command: `./build/Debug/safe testing_programs/build/simple ` diff --git a/include/validator.hpp b/include/validator.hpp index 9099772..f801d60 100644 --- a/include/validator.hpp +++ b/include/validator.hpp @@ -22,6 +22,16 @@ #include "gelf.h" namespace safe { + + enum class CorrelateError + { + NoTypeinfoForFunction, // Validator has no typeinfo for this function + NoThrownTypes, // Function exists, but no throws recorded + NoCatchRecords, // No LSDA catch records matched any thrown type + TypeResolveFailed, // LSDA::resolve_type() failed for some index + NoLsdaLoaded, // load_lsda() never called + }; + struct CatchRecord { std::string scope_id; // example: "scope[0]" @@ -58,15 +68,6 @@ class Validator bool check_thrown_functions(std::string_view func_name); std::vector find_thrown_functions(); - enum class CorrelateError - { - NoTypeinfoForFunction, // Validator has no typeinfo for this function - NoThrownTypes, // Function exists, but no throws recorded - NoCatchRecords, // No LSDA catch records matched any thrown type - TypeResolveFailed, // LSDA::resolve_type() failed for some index - NoLsdaLoaded, // load_lsda() never called - }; - using Result = std::expected, CorrelateError>; void load_lsda(const LsdaParser& lsda); diff --git a/src/abi_parse.cpp b/src/abi_parse.cpp index 50ab1e0..ffb92ee 100644 --- a/src/abi_parse.cpp +++ b/src/abi_parse.cpp @@ -425,10 +425,11 @@ void LsdaParser::parse_actions_tail(size_t table_start, size_t limit_end) // truncate chain when target is outside known entries // techdebt: handle cross LSDA/shared-tail action chains when we // parse full .gcc_except_table sections instead of single LSDAs. - std::cerr << "[AbiParser] warning: next_offset from entry_offset=" - << a.entry_offset - << " points to unknown target_offset=" << target_offset - << " – truncating action chain\n"; + // temporary comment out for demo! + // std::cerr << "[AbiParser] warning: next_offset from entry_offset=" + // << a.entry_offset + // << " points to unknown target_offset=" << target_offset + // << " – truncating action chain\n"; a.next_index = -1; continue; } diff --git a/src/main.cpp b/src/main.cpp index e578515..027a2d6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -10,15 +10,14 @@ */ #include #include +#include #include #include #include #include #include -#include #include -#include -#include +#include #include "abi_parse.hpp" #include "elf_parser.hpp" @@ -122,24 +121,42 @@ int main(int argc, char* argv[]) // Load LSDA catch table into Validator val.load_lsda(lsda); - auto res = val.analyze_exceptions("_Z3fooi"); - if (!res.has_value()) { - std::print("analyze_exceptions failed\n"); - return EXIT_FAILURE; - } - - for (const auto& f : val.find_thrown_functions()) { - std::println("throws: {}", - val.demangle(f.name.c_str()).value_or(f.name)); + std::println("======================================="); + std::println("Function that can throw: "); + std::println("======================================="); + std::vector callsite_function = val.find_thrown_functions(); + for (const auto& func : callsite_function) { + std::println(" {}", + val.demangle(func.name.c_str()).value_or(func.name)); } + std::println("======================================="); + std::println("Catch Sites: "); + std::println("======================================="); // we print it but we canremove this - for (const auto& m : res.value()) { - auto dn = val.demangle(m.thrown.name.c_str()).value_or(m.thrown.name); - std::print("Thrown: {}\n", dn); - for (auto* h : m.handlers) { - std::print(" caught by {} type_index={}\n", h->scope_id, h->type_index); + for (const auto& func : callsite_function) { + std::println("Function: {}", func.name); + + auto caught_throws = val.analyze_exceptions(func.name); + if (!caught_throws.has_value()) { + std::print("analyze_exceptions failed\n"); + return EXIT_FAILURE; + } + + for (auto& caught_throw : caught_throws.value()) { + symbol_s caught_throw_obj = caught_throw.thrown; + std::string caught_throw_name + = val.demangle(caught_throw_obj.name.c_str()) + .value_or(caught_throw_obj.name); + std::println("\tThrows: {}", caught_throw_name); + auto callsite_handlers = caught_throw.handlers; + for (auto& handler : callsite_handlers) { + std::print("\t\t* caught by {}\n\t\t* type_index={}\n", + handler->scope_id, + handler->type_index); + } } + std::println("---------------------------------------"); } return 0; diff --git a/testing_programs/simple.cpp b/testing_programs/simple.cpp index 3f56ce1..217aebe 100644 --- a/testing_programs/simple.cpp +++ b/testing_programs/simple.cpp @@ -5,12 +5,10 @@ void foo(int i) { throw std::invalid_argument("arg error"); } else if(i == 1){ throw 67; - } else if(i == 0){ - throw std::runtime_error("error"); } else if(i == 2){ throw "error"; } else if (i == 3){ - throw 6.7; + throw 6; } } @@ -23,7 +21,11 @@ void baa() { int main(){ try{ baa(); - } catch (...) { + } catch (int& i) { - }; + } catch (std::string& s) { + + } catch (std::invalid_argument& e) { + + } } \ No newline at end of file