Use flags in context structures
This commit is contained in:
parent
b6ae4b2115
commit
cd9ecafb4f
3 changed files with 92 additions and 28 deletions
|
@ -1,6 +1,15 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
UNWF_RIP=0,
|
||||||
|
UNWF_RSP=1,
|
||||||
|
UNWF_RBP=2,
|
||||||
|
|
||||||
|
UNWF_ERROR=7
|
||||||
|
} unwind_flags_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint8_t flags;
|
||||||
uintptr_t rip, rsp, rbp;
|
uintptr_t rip, rsp, rbp;
|
||||||
} unwind_context_t;
|
} unwind_context_t;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
#include "CodeGenerator.hpp"
|
#include "CodeGenerator.hpp"
|
||||||
#include "gen_context_struct.hpp"
|
#include "gen_context_struct.hpp"
|
||||||
#include "settings.hpp"
|
#include "settings.hpp"
|
||||||
|
#include "../shared/context_struct.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
@ -28,16 +29,6 @@ CodeGenerator::CodeGenerator(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string undefined_register() {
|
|
||||||
static std::string val = "";
|
|
||||||
if(val.empty()) {
|
|
||||||
std::ostringstream oss;
|
|
||||||
oss << std::numeric_limits<uintptr_t>::max() << "ull";
|
|
||||||
val = oss.str();
|
|
||||||
}
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CodeGenerator::generate() {
|
void CodeGenerator::generate() {
|
||||||
gen_of_dwarf();
|
gen_of_dwarf();
|
||||||
}
|
}
|
||||||
|
@ -90,12 +81,33 @@ void CodeGenerator::gen_unwind_func_header(const std::string& name) {
|
||||||
<< "\tswitch(pc) {" << endl;
|
<< "\tswitch(pc) {" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct UnwFlags {
|
||||||
|
UnwFlags():
|
||||||
|
error(false), rip(false), rsp(false), rbp(false) {}
|
||||||
|
|
||||||
|
bool error, rip, rsp, rbp;
|
||||||
|
|
||||||
|
uint8_t to_uint8() const {
|
||||||
|
uint8_t out = 0;
|
||||||
|
if(rip)
|
||||||
|
out |= (1 << UNWF_RIP);
|
||||||
|
if(rsp)
|
||||||
|
out |= (1 << UNWF_RSP);
|
||||||
|
if(rbp)
|
||||||
|
out |= (1 << UNWF_RBP);
|
||||||
|
if(error)
|
||||||
|
out |= (1 << UNWF_ERROR);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void CodeGenerator::gen_unwind_func_footer() {
|
void CodeGenerator::gen_unwind_func_footer() {
|
||||||
|
UnwFlags flags;
|
||||||
|
flags.error = true;
|
||||||
os << "\t\tdefault:\n"
|
os << "\t\tdefault:\n"
|
||||||
<< "\t\t\tout_ctx.rsp = " << undefined_register() << ";\n"
|
<< "\t\t\tout_ctx.flags = " << (int) flags.to_uint8() << "u;\n"
|
||||||
<< "\t\t\tout_ctx.rbp = " << undefined_register() << ";\n"
|
<< "\t\t\treturn out_ctx;\n"
|
||||||
<< "\t\t\tout_ctx.rip = " << undefined_register() << ";\n"
|
|
||||||
<< "\t\t\treturn out_ctx;"
|
|
||||||
<< "\t}\n"
|
<< "\t}\n"
|
||||||
<< "}" << endl;
|
<< "}" << endl;
|
||||||
}
|
}
|
||||||
|
@ -126,26 +138,51 @@ void CodeGenerator::gen_of_row(
|
||||||
uintptr_t row_end)
|
uintptr_t row_end)
|
||||||
{
|
{
|
||||||
gen_case(row.ip, row_end);
|
gen_case(row.ip, row_end);
|
||||||
|
UnwFlags flags;
|
||||||
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
os << "\t\t\t" << "out_ctx.rsp = ";
|
if(!check_reg_valid(row.ra)) {
|
||||||
gen_of_reg(row.cfa);
|
// RA might be undefined (last frame), but if it is defined and we
|
||||||
os << ';' << endl;
|
// don't implement it (eg. EXPR), it is an error
|
||||||
|
flags.error = true;
|
||||||
|
goto write_flags;
|
||||||
|
}
|
||||||
|
|
||||||
os << "\t\t\t" << "out_ctx.rbp = ";
|
if(check_reg_valid(row.cfa)) {
|
||||||
gen_of_reg(row.rbp);
|
flags.rsp = true;
|
||||||
os << ';' << endl;
|
os << "\t\t\t" << "out_ctx.rsp = ";
|
||||||
|
gen_of_reg(row.cfa);
|
||||||
|
os << ';' << endl;
|
||||||
|
}
|
||||||
|
else { // rsp is required (CFA)
|
||||||
|
flags.error = true;
|
||||||
|
goto write_flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_reg_defined(row.rbp)) {
|
||||||
|
flags.rbp = true;
|
||||||
|
os << "\t\t\t" << "out_ctx.rbp = ";
|
||||||
|
gen_of_reg(row.rbp);
|
||||||
|
os << ';' << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(check_reg_defined(row.ra)) {
|
||||||
|
flags.rip = true;
|
||||||
|
os << "\t\t\t" << "out_ctx.rip = ";
|
||||||
|
gen_of_reg(row.ra);
|
||||||
|
os << ';' << endl;
|
||||||
|
}
|
||||||
|
|
||||||
os << "\t\t\t" << "out_ctx.rip = ";
|
|
||||||
gen_of_reg(row.ra);
|
|
||||||
os << ';' << endl;
|
|
||||||
} catch(const UnhandledRegister& exn) {
|
} catch(const UnhandledRegister& exn) {
|
||||||
os << ";\n"
|
// This should not happen, since we check_reg_*, but heh.
|
||||||
<< "\t\t\tout_ctx.rip = " << undefined_register() << ";\n"
|
flags.error = true;
|
||||||
<< "\t\t\tout_ctx.rsp = " << undefined_register() << ";\n"
|
os << ";\n";
|
||||||
<< "\t\t\tout_ctx.rbp = " << undefined_register() << ";\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
write_flags:
|
||||||
|
os << "\t\t\tout_ctx.flags = " << (int)flags.to_uint8() << "u;" << endl;
|
||||||
|
|
||||||
os << "\t\t\treturn " << "out_ctx" << ";" << endl;
|
os << "\t\t\treturn " << "out_ctx" << ";" << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -188,10 +225,25 @@ static const char* ctx_of_dw_name(SimpleDwarf::MachineRegister reg) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CodeGenerator::check_reg_defined(const SimpleDwarf::DwRegister& reg) {
|
||||||
|
switch(reg.type) {
|
||||||
|
case SimpleDwarf::DwRegister::REG_UNDEFINED:
|
||||||
|
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool CodeGenerator::check_reg_valid(const SimpleDwarf::DwRegister& reg) {
|
||||||
|
return reg.type != SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED;
|
||||||
|
}
|
||||||
|
|
||||||
void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
|
void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
|
||||||
switch(reg.type) {
|
switch(reg.type) {
|
||||||
case SimpleDwarf::DwRegister::REG_UNDEFINED:
|
case SimpleDwarf::DwRegister::REG_UNDEFINED:
|
||||||
os << undefined_register();
|
// This function is not supposed to be called on an undefined
|
||||||
|
// register
|
||||||
|
throw UnhandledRegister();
|
||||||
break;
|
break;
|
||||||
case SimpleDwarf::DwRegister::REG_REGISTER:
|
case SimpleDwarf::DwRegister::REG_REGISTER:
|
||||||
os << ctx_of_dw_name(reg.reg)
|
os << ctx_of_dw_name(reg.reg)
|
||||||
|
|
|
@ -48,6 +48,9 @@ class CodeGenerator {
|
||||||
|
|
||||||
void gen_lookup(const std::vector<LookupEntry>& entries);
|
void gen_lookup(const std::vector<LookupEntry>& entries);
|
||||||
|
|
||||||
|
bool check_reg_defined(const SimpleDwarf::DwRegister& reg);
|
||||||
|
bool check_reg_valid(const SimpleDwarf::DwRegister& reg);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SimpleDwarf dwarf;
|
SimpleDwarf dwarf;
|
||||||
std::ostream& os;
|
std::ostream& os;
|
||||||
|
|
Loading…
Reference in a new issue