From 12e749f542072c0a94422d6df87056372e5e8cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Th=C3=A9ophile=20Bastian?= Date: Fri, 22 Jun 2018 09:14:56 +0200 Subject: [PATCH] Handle rbx --- shared/context_struct.h | 3 ++- src/CodeGenerator.cpp | 14 ++++++++++++-- src/ConseqEquivFilter.cpp | 1 + src/DwarfReader.cpp | 5 +++++ src/SimpleDwarf.cpp | 15 +++++++++++++++ src/SimpleDwarf.hpp | 7 +++++-- 6 files changed, 40 insertions(+), 5 deletions(-) diff --git a/shared/context_struct.h b/shared/context_struct.h index 692b911..585cbb7 100644 --- a/shared/context_struct.h +++ b/shared/context_struct.h @@ -4,13 +4,14 @@ typedef enum { UNWF_RIP=0, UNWF_RSP=1, UNWF_RBP=2, + UNWF_RBX=3, UNWF_ERROR=7 } unwind_flags_t; typedef struct { uint8_t flags; - uintptr_t rip, rsp, rbp; + uintptr_t rip, rsp, rbp, rbx; } unwind_context_t; typedef uintptr_t (*deref_func_t)(uintptr_t); diff --git a/src/CodeGenerator.cpp b/src/CodeGenerator.cpp index a55a4c0..a2d567f 100644 --- a/src/CodeGenerator.cpp +++ b/src/CodeGenerator.cpp @@ -83,9 +83,9 @@ void CodeGenerator::gen_unwind_func_header(const std::string& name) { struct UnwFlags { UnwFlags(): - error(false), rip(false), rsp(false), rbp(false) {} + error(false), rip(false), rsp(false), rbp(false), rbx(false) {} - bool error, rip, rsp, rbp; + bool error, rip, rsp, rbp, rbx; uint8_t to_uint8() const { uint8_t out = 0; @@ -95,6 +95,8 @@ struct UnwFlags { out |= (1 << UNWF_RSP); if(rbp) out |= (1 << UNWF_RBP); + if(rbx) + out |= (1 << UNWF_RBX); if(error) out |= (1 << UNWF_ERROR); @@ -174,6 +176,12 @@ void CodeGenerator::gen_of_row( os << ';' << endl; } + if(check_reg_defined(row.rbx)) { + flags.rbx = true; + os << "\t\t\t" << "out_ctx.rbx = "; + gen_of_reg(row.rbx); + os << ';' << endl; + } } catch(const UnhandledRegister& exn) { // This should not happen, since we check_reg_*, but heh. flags.error = true; @@ -219,6 +227,8 @@ static const char* ctx_of_dw_name(SimpleDwarf::MachineRegister reg) { return "ctx.rsp"; case SimpleDwarf::REG_RBP: return "ctx.rbp"; + case SimpleDwarf::REG_RBX: + return "ctx.rbx"; case SimpleDwarf::REG_RA: throw CodeGenerator::NotImplementedCase(); } diff --git a/src/ConseqEquivFilter.cpp b/src/ConseqEquivFilter.cpp index 6724298..e3d871a 100644 --- a/src/ConseqEquivFilter.cpp +++ b/src/ConseqEquivFilter.cpp @@ -20,6 +20,7 @@ static bool equiv_row( return r1.ip == r2.ip && equiv_reg(r1.cfa, r2.cfa) && equiv_reg(r1.rbp, r2.rbp) + && equiv_reg(r1.rbx, r2.rbx) && equiv_reg(r1.ra, r2.ra); } diff --git a/src/DwarfReader.cpp b/src/DwarfReader.cpp index ec25ac8..76cde53 100644 --- a/src/DwarfReader.cpp +++ b/src/DwarfReader.cpp @@ -55,6 +55,9 @@ SimpleDwarf::Fde DwarfReader::read_fde(const core::Fde& fde) const { case SimpleDwarf::REG_RBP: cur_row.rbp = read_register(cell.second); break; + case SimpleDwarf::REG_RBX: + cur_row.rbx = read_register(cell.second); + break; case SimpleDwarf::REG_RA: cur_row.ra = read_register(cell.second); break; @@ -130,6 +133,8 @@ SimpleDwarf::MachineRegister DwarfReader::from_dwarfpp_reg( return SimpleDwarf::REG_RSP; case lib::DWARF_X86_64_RBP: return SimpleDwarf::REG_RBP; + case lib::DWARF_X86_64_RBX: + return SimpleDwarf::REG_RBX; default: throw UnsupportedRegister(); } diff --git a/src/SimpleDwarf.cpp b/src/SimpleDwarf.cpp index c556734..59a14a9 100644 --- a/src/SimpleDwarf.cpp +++ b/src/SimpleDwarf.cpp @@ -1,4 +1,15 @@ #include "SimpleDwarf.hpp" +#include "../shared/context_struct.h" + +uint8_t SimpleDwarf::to_shared_flag(SimpleDwarf::MachineRegister mreg) { + switch(mreg) { + case REG_RIP: return (1 << UNWF_RIP); + case REG_RSP: return (1 << UNWF_RSP); + case REG_RBP: return (1 << UNWF_RBP); + case REG_RBX: return (1 << UNWF_RBX); + default: return 0; + } +} static std::ostream& operator<<( std::ostream& out, @@ -14,6 +25,9 @@ static std::ostream& operator<<( case SimpleDwarf::REG_RBP: out << "rbp"; break; + case SimpleDwarf::REG_RBX: + out << "rbx"; + break; case SimpleDwarf::REG_RA: out << "RA"; break; @@ -49,6 +63,7 @@ std::ostream& operator<<(std::ostream& out, const SimpleDwarf::DwRow& row) { out << std::hex << row.ip << std::dec << '\t' << row.cfa << '\t' << row.rbp + << '\t' << row.rbx << '\t' << row.ra; out << std::endl; return out; diff --git a/src/SimpleDwarf.hpp b/src/SimpleDwarf.hpp index d5dbfc3..8d69c12 100644 --- a/src/SimpleDwarf.hpp +++ b/src/SimpleDwarf.hpp @@ -13,12 +13,14 @@ struct SimpleDwarf { /** A machine register (eg. %rip) among the supported ones (x86_64 only * for now) */ - static const std::size_t HANDLED_REGISTERS_COUNT = 4; + static const std::size_t HANDLED_REGISTERS_COUNT = 5; enum MachineRegister { - REG_RIP, REG_RSP, REG_RBP, + REG_RIP, REG_RSP, REG_RBP, REG_RBX, REG_RA ///< A bit of cheating: not a machine register }; + static uint8_t to_shared_flag(MachineRegister mreg); + struct DwRegister { /** Holds a single Dwarf register value */ @@ -44,6 +46,7 @@ struct SimpleDwarf { uintptr_t ip; ///< Instruction pointer DwRegister cfa; ///< Canonical Frame Address DwRegister rbp; ///< Base pointer register + DwRegister rbx; ///< RBX, sometimes used for unwinding DwRegister ra; ///< Return address friend std::ostream& operator<<(std::ostream &, const DwRow&);