Generate compilable C code, untested

This commit is contained in:
Théophile Bastian 2018-04-23 18:58:05 +02:00
parent d13b625cc5
commit 44543d85d3
4 changed files with 147 additions and 2 deletions

106
src/CodeGenerator.cpp Normal file
View file

@ -0,0 +1,106 @@
#include "CodeGenerator.hpp"
using namespace std;
static const char* PRELUDE =
"#include <stdint.h>\n"
"#include <assert.h>\n"
"\n"
"typedef struct {\n"
" uintptr_t rip, rsp, rbp;\n"
"} unwind_context_t;\n";
CodeGenerator::CodeGenerator(const SimpleDwarf& dwarf, std::ostream& os):
dwarf(dwarf), os(os)
{}
void CodeGenerator::generate() {
gen_of_dwarf();
}
void CodeGenerator::gen_of_dwarf() {
os << PRELUDE << '\n' << endl;
// A function per FDE
for(const auto& fde: dwarf.fde_list) {
gen_of_fde(fde);
os << endl;
}
}
void CodeGenerator::gen_of_fde(const SimpleDwarf::Fde& fde) {
os << "unwind_context_t _fde_" << fde.beg_ip
<< "(unwind_context_t ctx, uintptr_t pc) {\n"
<< "\tunwind_context_t out_ctx;\n"
<< "\tswitch(pc) {" << endl;
for(size_t fde_row_id=0; fde_row_id < fde.rows.size(); ++fde_row_id)
{
uintptr_t up_bound = fde.end_ip;
if(fde_row_id != fde.rows.size() - 1)
up_bound = fde.rows[fde_row_id + 1].ip - 1;
gen_of_row(fde.rows[fde_row_id], up_bound);
}
os << "\t\tdefault: assert(0);\n"
<< "\t}\n"
<< "}" << endl;
}
void CodeGenerator::gen_of_row(
const SimpleDwarf::DwRow& row,
uintptr_t row_end)
{
os << "\t\tcase " << row.ip
<< " ... " << row_end << ":" << endl;
os << "\t\t\t" << "out_ctx.rsp = ";
gen_of_reg(row.cfa);
os << ';' << endl;
os << "\t\t\t" << "out_ctx.rbp = ";
gen_of_reg(row.rbp);
os << ';' << endl;
os << "\t\t\t" << "out_ctx.rip = ";
gen_of_reg(row.ra);
os << ';' << endl;
os << "\t\t\treturn " << "out_ctx" << ";" << endl;
}
static const char* ctx_of_dw_name(SimpleDwarf::MachineRegister reg) {
switch(reg) {
case SimpleDwarf::REG_RIP:
throw CodeGenerator::NotImplementedCase();
case SimpleDwarf::REG_RSP:
return "ctx.rsp";
case SimpleDwarf::REG_RBP:
return "ctx.rbp";
case SimpleDwarf::REG_RA:
throw CodeGenerator::NotImplementedCase();
}
return "";
}
void CodeGenerator::gen_of_reg(const SimpleDwarf::DwRegister& reg) {
switch(reg.type) {
case SimpleDwarf::DwRegister::REG_UNDEFINED:
os << "0"; // FIXME do better?
break;
case SimpleDwarf::DwRegister::REG_REGISTER:
os << "*((uintptr_t*)("
<< ctx_of_dw_name(reg.reg)
<< " + ("
<< reg.offset
<< ")))";
break;
case SimpleDwarf::DwRegister::REG_CFA_OFFSET:
os << "out_ctx.rip + (" << reg.offset << ")";
break;
case SimpleDwarf::DwRegister::REG_NOT_IMPLEMENTED:
os << "0; assert(0)";
break;
}
}

33
src/CodeGenerator.hpp Normal file
View file

@ -0,0 +1,33 @@
/** Generates C code from SimpleDwarf */
#pragma once
#include <ostream>
#include "SimpleDwarf.hpp"
class CodeGenerator {
public:
/// Unimplemented case
class NotImplementedCase: public std::exception {};
/** Create a CodeGenerator to generate code for the given dwarf, on the
* given std::ostream object (eg. cout). */
CodeGenerator(const SimpleDwarf& dwarf, std::ostream& os);
/// Actually generate the code on the given stream
void generate();
private: //meth
void gen_of_dwarf();
void gen_of_fde(const SimpleDwarf::Fde& fde);
void gen_of_row(
const SimpleDwarf::DwRow& row,
uintptr_t row_end);
void gen_of_reg(
const SimpleDwarf::DwRegister& reg);
private:
SimpleDwarf dwarf;
std::ostream& os;
};

View file

@ -4,7 +4,7 @@ CXXFLAGS=$(CXXLOCS) -Wall -Wextra -std=c++14 -O2 -g
CXXLIBS=-lelf -ldwarf -ldwarfpp -lsrk31c++ -lc++fileno
TARGET=dwarf-assembly
OBJS=DwarfReader.o SimpleDwarf.o main.o
OBJS=DwarfReader.o SimpleDwarf.o CodeGenerator.o main.o
###############################################################################

View file

@ -5,6 +5,7 @@
#include "SimpleDwarf.hpp"
#include "DwarfReader.hpp"
#include "CodeGenerator.hpp"
using namespace std;
@ -18,7 +19,12 @@ int main(int argc, char** argv) {
SimpleDwarf parsed_dwarf = DwarfReader(argv[1]).read();
cout << parsed_dwarf;
cerr << parsed_dwarf;
cerr << "=====================" << endl << endl;
CodeGenerator code_gen(parsed_dwarf, cout);
code_gen.generate();
return 0;
}