eh_elf generator: now also producing global switch
This commit is contained in:
parent
601fb2fcd0
commit
4b327c7c56
|
@ -1,5 +1,6 @@
|
|||
#include "CodeGenerator.hpp"
|
||||
#include "gen_context_struct.hpp"
|
||||
#include "settings.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
@ -23,42 +24,71 @@ void CodeGenerator::gen_of_dwarf() {
|
|||
os << CONTEXT_STRUCT_STR << '\n'
|
||||
<< PRELUDE << '\n' << endl;
|
||||
|
||||
vector<LookupEntry> lookup_entries;
|
||||
switch(settings::switch_generation_policy) {
|
||||
case settings::SGP_SwitchPerFunc:
|
||||
{
|
||||
vector<LookupEntry> lookup_entries;
|
||||
|
||||
// A function per FDE
|
||||
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);
|
||||
// A function per FDE
|
||||
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);
|
||||
os << endl;
|
||||
gen_function_of_fde(fde);
|
||||
os << endl;
|
||||
}
|
||||
|
||||
gen_lookup(lookup_entries);
|
||||
break;
|
||||
}
|
||||
case settings::SGP_GlobalSwitch:
|
||||
{
|
||||
gen_unwind_func_header("_eh_elf");
|
||||
for(const auto& fde: dwarf.fde_list) {
|
||||
gen_switchpart_of_fde(fde);
|
||||
}
|
||||
gen_unwind_func_footer();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
gen_lookup(lookup_entries);
|
||||
}
|
||||
|
||||
void CodeGenerator::gen_of_fde(const SimpleDwarf::Fde& fde) {
|
||||
void CodeGenerator::gen_unwind_func_header(const std::string& name) {
|
||||
os << "unwind_context_t "
|
||||
<< naming_scheme(fde)
|
||||
<< name
|
||||
<< "(unwind_context_t ctx, uintptr_t pc) {\n"
|
||||
<< "\tunwind_context_t out_ctx;\n"
|
||||
<< "\tswitch(pc) {" << endl;
|
||||
}
|
||||
|
||||
void CodeGenerator::gen_unwind_func_footer() {
|
||||
os << "\t\tdefault: assert(0);\n"
|
||||
<< "\t}\n"
|
||||
<< "}" << endl;
|
||||
}
|
||||
|
||||
void CodeGenerator::gen_function_of_fde(const SimpleDwarf::Fde& fde) {
|
||||
gen_unwind_func_header(naming_scheme(fde));
|
||||
|
||||
gen_switchpart_of_fde(fde);
|
||||
|
||||
gen_unwind_func_footer();
|
||||
}
|
||||
|
||||
void CodeGenerator::gen_switchpart_of_fde(const SimpleDwarf::Fde& fde) {
|
||||
os << "\t\t/********** FDE: 0x" << std::hex << fde.fde_offset
|
||||
<< ", PC = 0x" << fde.beg_ip << std::dec << " */" << std::endl;
|
||||
for(size_t fde_row_id=0; fde_row_id < fde.rows.size(); ++fde_row_id)
|
||||
{
|
||||
uintptr_t up_bound = fde.end_ip;
|
||||
uintptr_t up_bound = fde.end_ip - 1;
|
||||
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(
|
||||
|
|
|
@ -31,7 +31,10 @@ class CodeGenerator {
|
|||
};
|
||||
|
||||
void gen_of_dwarf();
|
||||
void gen_of_fde(const SimpleDwarf::Fde& fde);
|
||||
void gen_unwind_func_header(const std::string& name);
|
||||
void gen_unwind_func_footer();
|
||||
void gen_function_of_fde(const SimpleDwarf::Fde& fde);
|
||||
void gen_switchpart_of_fde(const SimpleDwarf::Fde& fde);
|
||||
void gen_of_row(
|
||||
const SimpleDwarf::DwRow& row,
|
||||
uintptr_t row_end);
|
||||
|
|
|
@ -28,6 +28,7 @@ SimpleDwarf DwarfReader::read() const {
|
|||
|
||||
SimpleDwarf::Fde DwarfReader::read_fde(const core::Fde& fde) const {
|
||||
SimpleDwarf::Fde output;
|
||||
output.fde_offset = fde.get_fde_offset();
|
||||
output.beg_ip = fde.get_low_pc();
|
||||
output.end_ip = fde.get_low_pc() + fde.get_func_length();
|
||||
|
||||
|
|
|
@ -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 CodeGenerator.o main.o
|
||||
OBJS=DwarfReader.o SimpleDwarf.o CodeGenerator.o settings.o main.o
|
||||
|
||||
###############################################################################
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@ struct SimpleDwarf {
|
|||
};
|
||||
|
||||
struct Fde {
|
||||
uintptr_t fde_offset; ///< This FDE's offset in the original DWARF
|
||||
uintptr_t beg_ip, ///< This FDE's start instruction pointer
|
||||
end_ip; ///< This FDE's end instruction pointer
|
||||
std::vector<DwRow> rows; ///< Dwarf rows for this FDE
|
||||
|
|
67
src/main.cpp
67
src/main.cpp
|
@ -8,17 +8,72 @@
|
|||
#include "DwarfReader.hpp"
|
||||
#include "CodeGenerator.hpp"
|
||||
|
||||
#include "settings.hpp"
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct MainOptions {
|
||||
std::string elf_path;
|
||||
};
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if(argc < 2) {
|
||||
cerr << "Error: missing input file. Usage:" << endl
|
||||
<< argv[0] << " path/to/binary.elf" << endl;
|
||||
exit(1);
|
||||
MainOptions options_parse(int argc, char** argv) {
|
||||
MainOptions out;
|
||||
|
||||
bool seen_switch_gen_policy = false;
|
||||
bool print_helptext = false;
|
||||
int exit_status = -1;
|
||||
|
||||
for(int option_pos = 1; option_pos < argc; ++option_pos) {
|
||||
std::string option(argv[option_pos]);
|
||||
|
||||
if(option.find("-") != 0) { // This is not an option argument
|
||||
out.elf_path = option;
|
||||
}
|
||||
|
||||
else if(option == "--help") {
|
||||
print_helptext = true;
|
||||
exit_status = 0;
|
||||
}
|
||||
|
||||
else if(option == "--switch-per-func") {
|
||||
seen_switch_gen_policy = true;
|
||||
settings::switch_generation_policy =
|
||||
settings::SGP_SwitchPerFunc;
|
||||
}
|
||||
else if(option == "--global-switch") {
|
||||
seen_switch_gen_policy = true;
|
||||
settings::switch_generation_policy =
|
||||
settings::SGP_GlobalSwitch;
|
||||
}
|
||||
}
|
||||
|
||||
SimpleDwarf parsed_dwarf = DwarfReader(argv[1]).read();
|
||||
if(!seen_switch_gen_policy) {
|
||||
cerr << "Error: please use either --switch-per-func or "
|
||||
<< "--global-switch." << endl;
|
||||
print_helptext = true;
|
||||
exit_status = 1;
|
||||
}
|
||||
if(out.elf_path.empty()) {
|
||||
cerr << "Error: missing input file." << endl;
|
||||
print_helptext = true;
|
||||
exit_status = 1;
|
||||
}
|
||||
|
||||
if(print_helptext) {
|
||||
cerr << "Usage: "
|
||||
<< argv[0]
|
||||
<< " [--switch-per-func | --global-switch] elf_path"
|
||||
<< endl;
|
||||
}
|
||||
if(exit_status >= 0)
|
||||
exit(exit_status);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
MainOptions opts = options_parse(argc, argv);
|
||||
SimpleDwarf parsed_dwarf = DwarfReader(opts.elf_path).read();
|
||||
|
||||
CodeGenerator code_gen(
|
||||
parsed_dwarf,
|
||||
|
|
5
src/settings.cpp
Normal file
5
src/settings.cpp
Normal file
|
@ -0,0 +1,5 @@
|
|||
#include "settings.hpp"
|
||||
|
||||
namespace settings {
|
||||
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
|
||||
}
|
15
src/settings.hpp
Normal file
15
src/settings.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
/** This compile unit holds a few global variables controlling the code
|
||||
* generator's settings. These variables are used program-wide.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace settings {
|
||||
/// Controls how the eh_elf switches are generated
|
||||
enum SwitchGenerationPolicy {
|
||||
SGP_SwitchPerFunc, ///< One switch per function, plus a lookup function
|
||||
SGP_GlobalSwitch ///< One big switch per ELF file
|
||||
};
|
||||
|
||||
extern SwitchGenerationPolicy switch_generation_policy;
|
||||
}
|
Loading…
Reference in a new issue