Add generation of a lookup function

This commit is contained in:
Théophile Bastian 2018-04-24 17:44:09 +02:00
parent 44543d85d3
commit c07b0623e4
3 changed files with 58 additions and 6 deletions

View file

@ -8,10 +8,16 @@ static const char* PRELUDE =
"\n" "\n"
"typedef struct {\n" "typedef struct {\n"
" uintptr_t rip, rsp, rbp;\n" " uintptr_t rip, rsp, rbp;\n"
"} unwind_context_t;\n"; "} unwind_context_t;\n"
"\n"
"typedef unwind_context_t (*_fde_func_t)(unwind_context_t, uintptr_t);\n"
;
CodeGenerator::CodeGenerator(const SimpleDwarf& dwarf, std::ostream& os): CodeGenerator::CodeGenerator(
dwarf(dwarf), os(os) const SimpleDwarf& dwarf,
std::ostream& os,
NamingScheme naming_scheme):
dwarf(dwarf), os(os), naming_scheme(naming_scheme)
{} {}
void CodeGenerator::generate() { void CodeGenerator::generate() {
@ -21,15 +27,26 @@ void CodeGenerator::generate() {
void CodeGenerator::gen_of_dwarf() { void CodeGenerator::gen_of_dwarf() {
os << PRELUDE << '\n' << endl; os << PRELUDE << '\n' << endl;
vector<LookupEntry> lookup_entries;
// A function per FDE // A function per FDE
for(const auto& fde: dwarf.fde_list) { for(const auto& fde: dwarf.fde_list) {
LookupEntry cur_entry;
cur_entry.name = naming_scheme(fde);
cur_entry.beg = fde.beg_ip;
cur_entry.end = fde.end_ip;
lookup_entries.push_back(cur_entry);
gen_of_fde(fde); gen_of_fde(fde);
os << endl; os << endl;
} }
gen_lookup(lookup_entries);
} }
void CodeGenerator::gen_of_fde(const SimpleDwarf::Fde& fde) { void CodeGenerator::gen_of_fde(const SimpleDwarf::Fde& fde) {
os << "unwind_context_t _fde_" << fde.beg_ip os << "unwind_context_t "
<< naming_scheme(fde)
<< "(unwind_context_t ctx, uintptr_t pc) {\n" << "(unwind_context_t ctx, uintptr_t pc) {\n"
<< "\tunwind_context_t out_ctx;\n" << "\tunwind_context_t out_ctx;\n"
<< "\tswitch(pc) {" << endl; << "\tswitch(pc) {" << endl;
@ -104,3 +121,15 @@ void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
break; break;
} }
} }
void CodeGenerator::gen_lookup(const std::vector<LookupEntry>& entries) {
os << "_fde_func_t _fde_lookup(uintptr_t pc) {\n"
<< "\tswitch(pc) {" << endl;
for(const auto& entry: entries) {
os << "\t\tcase " << entry.beg << " ... " << entry.end - 1 << ":\n"
<< "\t\t\treturn &" << entry.name << ";" << endl;
}
os << "\t\tdefault: assert(0);\n"
<< "\t}\n"
<< "}" << endl;
}

View file

@ -3,22 +3,33 @@
#pragma once #pragma once
#include <ostream> #include <ostream>
#include <functional>
#include "SimpleDwarf.hpp" #include "SimpleDwarf.hpp"
class CodeGenerator { class CodeGenerator {
public: public:
/// A function deriving a generated function name from a FDE
typedef std::function<std::string(const SimpleDwarf::Fde&)>
NamingScheme;
/// Unimplemented case /// Unimplemented case
class NotImplementedCase: public std::exception {}; class NotImplementedCase: public std::exception {};
/** Create a CodeGenerator to generate code for the given dwarf, on the /** Create a CodeGenerator to generate code for the given dwarf, on the
* given std::ostream object (eg. cout). */ * given std::ostream object (eg. cout). */
CodeGenerator(const SimpleDwarf& dwarf, std::ostream& os); CodeGenerator(const SimpleDwarf& dwarf, std::ostream& os,
NamingScheme naming_scheme);
/// Actually generate the code on the given stream /// Actually generate the code on the given stream
void generate(); void generate();
private: //meth private: //meth
struct LookupEntry {
std::string name;
uintptr_t beg, end;
};
void gen_of_dwarf(); void gen_of_dwarf();
void gen_of_fde(const SimpleDwarf::Fde& fde); void gen_of_fde(const SimpleDwarf::Fde& fde);
void gen_of_row( void gen_of_row(
@ -27,7 +38,11 @@ class CodeGenerator {
void gen_of_reg( void gen_of_reg(
const SimpleDwarf::DwRegister& reg); const SimpleDwarf::DwRegister& reg);
void gen_lookup(const std::vector<LookupEntry>& entries);
private: private:
SimpleDwarf dwarf; SimpleDwarf dwarf;
std::ostream& os; std::ostream& os;
NamingScheme naming_scheme;
}; };

View file

@ -1,6 +1,7 @@
/** Entry point */ /** Entry point */
#include <iostream> #include <iostream>
#include <sstream>
#include <cstdlib> #include <cstdlib>
#include "SimpleDwarf.hpp" #include "SimpleDwarf.hpp"
@ -23,7 +24,14 @@ int main(int argc, char** argv) {
cerr << "=====================" << endl << endl; cerr << "=====================" << endl << endl;
CodeGenerator code_gen(parsed_dwarf, cout); CodeGenerator code_gen(
parsed_dwarf,
cout,
[](const SimpleDwarf::Fde& fde) {
std::ostringstream ss;
ss << "_fde_" << fde.beg_ip;
return ss.str();
});
code_gen.generate(); code_gen.generate();
return 0; return 0;