From 3990b2c6ee18a1ec08e63a1f2d6b1eb694c4c84c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Wed, 8 Aug 2018 14:33:20 +0200 Subject: [PATCH] dwarf-assembly: support common exprs DW_OP_breg --- src/DwarfReader.cpp | 60 ++++++++++++++++++++++++++++++++++++++++++++- src/DwarfReader.hpp | 5 ++++ 2 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/DwarfReader.cpp b/src/DwarfReader.cpp index eef4809..8d53378 100644 --- a/src/DwarfReader.cpp +++ b/src/DwarfReader.cpp @@ -16,6 +16,20 @@ DwarfReader::DwarfReader(const string& path): root(fileno(ifstream(path))) {} +// Debug function -- dumps an expression +static void dump_expr(const core::FrameSection::register_def& reg) { + assert(reg.k == core::FrameSection::register_def::SAVED_AT_EXPR + || reg.k == core::FrameSection::register_def::VAL_OF_EXPR); + + const encap::loc_expr& expr = reg.saved_at_expr_r(); + + for(const auto& elt: expr) { + fprintf(stderr, "(%02x, %02llx, %02llx, %02llx) :: ", + elt.lr_atom, elt.lr_number, elt.lr_number2, elt.lr_offset); + } + fprintf(stderr, "\n"); +} + SimpleDwarf DwarfReader::read() const { const core::FrameSection& fs = root.get_frame_section(); SimpleDwarf output; @@ -112,7 +126,7 @@ SimpleDwarf::DwRegister DwarfReader::read_register( case core::FrameSection::register_def::SAVED_AT_EXPR: if(is_plt_expr(reg)) output.type = SimpleDwarf::DwRegister::REG_PLT_EXPR; - else + else if(!interpret_simple_expr(reg, output)) output.type = SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED; break; @@ -171,3 +185,47 @@ bool DwarfReader::is_plt_expr( bool res = compare_dw_expr(expr, REFERENCE_PLT_EXPR); return res; } + +bool DwarfReader::interpret_simple_expr( + const dwarf::core::FrameSection::register_def& reg, + SimpleDwarf::DwRegister& output + ) const +{ + bool deref = false; + if(reg.k == core::FrameSection::register_def::SAVED_AT_EXPR) + deref = true; + else if(reg.k == core::FrameSection::register_def::VAL_OF_EXPR) + deref = false; + else + return false; + + const encap::loc_expr& expr = reg.saved_at_expr_r(); + if(expr.size() > 2 || expr.empty()) + return false; + + const auto& exp_reg = expr[0]; + if(0x70 <= exp_reg.lr_atom && exp_reg.lr_atom <= 0x8f) { // DW_OP_breg + int reg_id = exp_reg.lr_atom - 0x70; + try { + output.reg = from_dwarfpp_reg(reg_id, -1); // Cannot be CFA anyway + output.offset = exp_reg.lr_number; + } catch(const UnsupportedRegister& /* exn */) { + return false; // Unsupported register + } + } + + if(expr.size() == 2) { // OK if deref + if(expr[1].lr_atom == 0x06) { // deref + if(deref) + return false; + deref = true; + } + else + return false; + } + + if(deref) + return false; // TODO try stats? Mabye it's worth implementing + output.type = SimpleDwarf::DwRegister::REG_REGISTER; + return true; +} diff --git a/src/DwarfReader.hpp b/src/DwarfReader.hpp index 2d0f5ee..1c94f42 100644 --- a/src/DwarfReader.hpp +++ b/src/DwarfReader.hpp @@ -37,6 +37,11 @@ class DwarfReader { bool is_plt_expr( const dwarf::core::FrameSection::register_def& reg) const; + bool interpret_simple_expr( + const dwarf::core::FrameSection::register_def& reg, + SimpleDwarf::DwRegister& output + ) const; + class UnsupportedRegister: public std::exception {}; private: