compiler: generate rows for CIE

This commit is contained in:
Théophile Bastian 2019-06-09 03:32:54 +02:00
parent 8d66dd9a2b
commit a0f58b592d
6 changed files with 176 additions and 48 deletions

View file

@ -9,9 +9,6 @@
using namespace std; using namespace std;
using namespace dwarf; using namespace dwarf;
typedef std::set<std::pair<int, core::FrameSection::register_def> >
dwarfpp_row_t;
DwarfReader::DwarfReader(const string& path): DwarfReader::DwarfReader(const string& path):
root(fileno(ifstream(path))) root(fileno(ifstream(path)))
{} {}
@ -30,7 +27,7 @@ static void dump_expr(const core::FrameSection::register_def& reg) {
fprintf(stderr, "\n"); fprintf(stderr, "\n");
} }
SimpleDwarf DwarfReader::read() const { SimpleDwarf DwarfReader::read() {
const core::FrameSection& fs = root.get_frame_section(); const core::FrameSection& fs = root.get_frame_section();
SimpleDwarf output; SimpleDwarf output;
@ -42,57 +39,119 @@ SimpleDwarf DwarfReader::read() const {
return output; return output;
} }
SimpleDwarf::Fde DwarfReader::read_fde(const core::Fde& fde) const { void DwarfReader::add_cell_to_row(
const dwarf::core::FrameSection::register_def& reg,
int reg_id,
int ra_reg,
SimpleDwarf::DwRow& cur_row)
{
if(reg_id == DW_FRAME_CFA_COL3) {
cur_row.cfa = read_register(reg);
}
else {
try {
SimpleDwarf::MachineRegister reg_type =
from_dwarfpp_reg(reg_id, ra_reg);
switch(reg_type) {
case SimpleDwarf::REG_RBP:
cur_row.rbp = read_register(reg);
break;
case SimpleDwarf::REG_RBX:
cur_row.rbx = read_register(reg);
break;
case SimpleDwarf::REG_RA:
cur_row.ra = read_register(reg);
break;
default:
break;
}
}
catch(const UnsupportedRegister&) {} // Just ignore it.
}
}
void DwarfReader::append_row_to_fde(
const dwarfpp_row_t& row,
uintptr_t row_addr,
int ra_reg,
SimpleDwarf::Fde& output)
{
SimpleDwarf::DwRow cur_row;
cur_row.ip = row_addr;
for(const auto& cell: row) {
add_cell_to_row(cell.second, cell.first, ra_reg, cur_row);
}
if(cur_row.cfa.type == SimpleDwarf::DwRegister::REG_UNDEFINED)
{
// Not set
throw InvalidDwarf();
}
output.rows.push_back(cur_row);
}
template<typename Key, typename Value>
static std::set<std::pair<Key, Value> > map_to_setpair(
const std::map<Key, Value>& src_map)
{
std::set<std::pair<Key, Value> > out;
for(const auto map_it: src_map) {
out.insert(map_it);
}
return out;
}
void DwarfReader::append_results_to_fde(
const dwarf::core::FrameSection::instrs_results& results,
int ra_reg,
SimpleDwarf::Fde& output)
{
for(const auto row_pair: results.rows) {
append_row_to_fde(
row_pair.second,
row_pair.first.lower(),
ra_reg,
output);
}
if(results.unfinished_row.size() > 0) {
try {
append_row_to_fde(
map_to_setpair(results.unfinished_row),
results.unfinished_row_addr,
ra_reg,
output);
} catch(const InvalidDwarf&) {
// Ignore: the unfinished_row can be undefined
}
}
}
SimpleDwarf::Fde DwarfReader::read_fde(const core::Fde& fde) {
SimpleDwarf::Fde output; SimpleDwarf::Fde output;
output.fde_offset = fde.get_fde_offset(); output.fde_offset = fde.get_fde_offset();
output.beg_ip = fde.get_low_pc(); output.beg_ip = fde.get_low_pc();
output.end_ip = fde.get_low_pc() + fde.get_func_length(); output.end_ip = fde.get_low_pc() + fde.get_func_length();
auto rows = fde.decode().rows;
const core::Cie& cie = *fde.find_cie(); const core::Cie& cie = *fde.find_cie();
int ra_reg = cie.get_return_address_register_rule(); int ra_reg = cie.get_return_address_register_rule();
for(const auto row_pair: rows) { // CIE rows
SimpleDwarf::DwRow cur_row; core::FrameSection cie_fs(root.get_dbg(), true);
auto cie_rows = cie_fs.interpret_instructions(
cie,
fde.get_low_pc(),
cie.get_initial_instructions(),
cie.get_initial_instructions_length());
cur_row.ip = row_pair.first.lower(); // FDE rows
auto fde_rows = fde.decode();
const dwarfpp_row_t& row = row_pair.second; // instrs
append_results_to_fde(cie_rows, ra_reg, output);
for(const auto& cell: row) { append_results_to_fde(fde_rows, ra_reg, output);
if(cell.first == DW_FRAME_CFA_COL3) {
cur_row.cfa = read_register(cell.second);
}
else {
try {
SimpleDwarf::MachineRegister reg_type =
from_dwarfpp_reg(cell.first, ra_reg);
switch(reg_type) {
case SimpleDwarf::REG_RBP:
cur_row.rbp = read_register(cell.second);
break;
case SimpleDwarf::REG_RBX:
cur_row.rbx = read_register(cell.second);
break;
case SimpleDwarf::REG_RA:
cur_row.ra = read_register(cell.second);
break;
default:
break;
}
}
catch(const UnsupportedRegister&) {} // Just ignore it.
}
}
if(cur_row.cfa.type == SimpleDwarf::DwRegister::REG_UNDEFINED)
{
// Not set
throw InvalidDwarf();
}
output.rows.push_back(cur_row);
}
return output; return output;
} }

View file

@ -13,6 +13,9 @@
#include "SimpleDwarf.hpp" #include "SimpleDwarf.hpp"
typedef std::set<std::pair<int, dwarf::core::FrameSection::register_def> >
dwarfpp_row_t;
class DwarfReader { class DwarfReader {
public: public:
class InvalidDwarf: public std::exception {}; class InvalidDwarf: public std::exception {};
@ -21,14 +24,31 @@ class DwarfReader {
DwarfReader(const std::string& path); DwarfReader(const std::string& path);
/** Actually read the ELF file, generating a `SimpleDwarf` output. */ /** Actually read the ELF file, generating a `SimpleDwarf` output. */
SimpleDwarf read() const; SimpleDwarf read();
private: //meth private: //meth
SimpleDwarf::Fde read_fde(const dwarf::core::Fde& fde) const; SimpleDwarf::Fde read_fde(const dwarf::core::Fde& fde);
void append_results_to_fde(
const dwarf::core::FrameSection::instrs_results& results,
int ra_reg,
SimpleDwarf::Fde& output);
SimpleDwarf::DwRegister read_register( SimpleDwarf::DwRegister read_register(
const dwarf::core::FrameSection::register_def& reg) const; const dwarf::core::FrameSection::register_def& reg) const;
void add_cell_to_row(
const dwarf::core::FrameSection::register_def& reg,
int reg_id,
int ra_reg,
SimpleDwarf::DwRow& cur_row);
void append_row_to_fde(
const dwarfpp_row_t& row,
uintptr_t row_addr,
int ra_reg,
SimpleDwarf::Fde& output);
SimpleDwarf::MachineRegister from_dwarfpp_reg( SimpleDwarf::MachineRegister from_dwarfpp_reg(
int reg_id, int reg_id,
int ra_reg=-1 int ra_reg=-1

View file

@ -14,6 +14,7 @@ OBJS=\
PcHoleFiller.o \ PcHoleFiller.o \
EmptyFdeDeleter.o \ EmptyFdeDeleter.o \
ConseqEquivFilter.o \ ConseqEquivFilter.o \
OverriddenRowFilter.o \
SwitchStatement.o \ SwitchStatement.o \
NativeSwitchCompiler.o \ NativeSwitchCompiler.o \
FactoredSwitchCompiler.o \ FactoredSwitchCompiler.o \

View file

@ -0,0 +1,31 @@
#include "OverriddenRowFilter.hpp"
OverriddenRowFilter::OverriddenRowFilter(bool enable)
: SimpleDwarfFilter(enable)
{}
SimpleDwarf OverriddenRowFilter::do_apply(const SimpleDwarf& dw) const {
SimpleDwarf out;
for(const auto& fde: dw.fde_list) {
out.fde_list.push_back(SimpleDwarf::Fde());
SimpleDwarf::Fde& cur_fde = out.fde_list.back();
cur_fde.fde_offset = fde.fde_offset;
cur_fde.beg_ip = fde.beg_ip;
cur_fde.end_ip = fde.end_ip;
if(fde.rows.empty())
continue;
for(size_t pos=0; pos < fde.rows.size(); ++pos) {
const auto& row = fde.rows[pos];
if(pos == fde.rows.size() - 1
|| row.ip != fde.rows[pos+1].ip)
{
cur_fde.rows.push_back(row);
}
}
}
return out;
}

View file

@ -0,0 +1,15 @@
/** SimpleDwarfFilter to remove the first `n-1` rows of a block of `n`
* contiguous rows that have the exact same address. */
#pragma once
#include "SimpleDwarf.hpp"
#include "SimpleDwarfFilter.hpp"
class OverriddenRowFilter: public SimpleDwarfFilter {
public:
OverriddenRowFilter(bool enable=true);
private:
SimpleDwarf do_apply(const SimpleDwarf& dw) const;
};

View file

@ -13,6 +13,7 @@
#include "PcHoleFiller.hpp" #include "PcHoleFiller.hpp"
#include "EmptyFdeDeleter.hpp" #include "EmptyFdeDeleter.hpp"
#include "ConseqEquivFilter.hpp" #include "ConseqEquivFilter.hpp"
#include "OverriddenRowFilter.hpp"
#include "settings.hpp" #include "settings.hpp"
@ -106,8 +107,9 @@ int main(int argc, char** argv) {
SimpleDwarf filtered_dwarf = SimpleDwarf filtered_dwarf =
PcHoleFiller(!settings::keep_holes)( PcHoleFiller(!settings::keep_holes)(
EmptyFdeDeleter()( EmptyFdeDeleter()(
OverriddenRowFilter()(
ConseqEquivFilter()( ConseqEquivFilter()(
parsed_dwarf))); parsed_dwarf))));
FactoredSwitchCompiler* sw_compiler = new FactoredSwitchCompiler(1); FactoredSwitchCompiler* sw_compiler = new FactoredSwitchCompiler(1);
CodeGenerator code_gen( CodeGenerator code_gen(