Generate compilable C code, untested
This commit is contained in:
parent
d13b625cc5
commit
44543d85d3
4 changed files with 147 additions and 2 deletions
106
src/CodeGenerator.cpp
Normal file
106
src/CodeGenerator.cpp
Normal 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
33
src/CodeGenerator.hpp
Normal 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;
|
||||
};
|
|
@ -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
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue