Add C++ code to make use of .pc_list

This commit is contained in:
Théophile Bastian 2018-05-11 13:09:35 +02:00
parent 83b304db95
commit 26d7b2afd5
8 changed files with 119 additions and 5 deletions

View file

@ -2,6 +2,8 @@
#include "gen_context_struct.hpp"
#include "settings.hpp"
#include <algorithm>
using namespace std;
static const char* PRELUDE =
@ -13,8 +15,12 @@ CodeGenerator::CodeGenerator(
const SimpleDwarf& dwarf,
std::ostream& os,
NamingScheme naming_scheme):
dwarf(dwarf), os(os), naming_scheme(naming_scheme)
{}
dwarf(dwarf), os(os), pc_list(nullptr), naming_scheme(naming_scheme)
{
if(!settings::pc_list.empty()) {
pc_list = make_unique<PcListReader>(settings::pc_list);
}
}
void CodeGenerator::generate() {
gen_of_dwarf();
@ -95,8 +101,7 @@ void CodeGenerator::gen_of_row(
const SimpleDwarf::DwRow& row,
uintptr_t row_end)
{
os << "\t\tcase " << std::hex << "0x" << row.ip
<< " ... 0x" << row_end << ":" << std::dec << endl;
gen_case(row.ip, row_end);
os << "\t\t\t" << "out_ctx.rsp = ";
gen_of_reg(row.cfa);
@ -113,6 +118,28 @@ void CodeGenerator::gen_of_row(
os << "\t\t\treturn " << "out_ctx" << ";" << endl;
}
void CodeGenerator::gen_case(uintptr_t low_bound, uintptr_t high_bound) {
if(pc_list == nullptr) {
os << "\t\tcase " << std::hex << "0x" << low_bound
<< " ... 0x" << high_bound << ":" << std::dec << endl;
}
else {
const auto& first_it = lower_bound(
pc_list->get_list().begin(),
pc_list->get_list().end(),
low_bound);
const auto& last_it = upper_bound(
pc_list->get_list().begin(),
pc_list->get_list().end(),
high_bound);
os << std::hex;
for(auto it = first_it; it != last_it; ++it)
os << "\t\tcase 0x" << *it << ":\n";
os << std::dec;
}
}
static const char* ctx_of_dw_name(SimpleDwarf::MachineRegister reg) {
switch(reg) {
case SimpleDwarf::REG_RIP:

View file

@ -4,8 +4,10 @@
#include <ostream>
#include <functional>
#include <memory>
#include "SimpleDwarf.hpp"
#include "PcListReader.hpp"
class CodeGenerator {
public:
@ -38,6 +40,7 @@ class CodeGenerator {
void gen_of_row(
const SimpleDwarf::DwRow& row,
uintptr_t row_end);
void gen_case(uintptr_t low_bound, uintptr_t high_bound);
void gen_of_reg(
const SimpleDwarf::DwRegister& reg);
@ -46,6 +49,7 @@ class CodeGenerator {
private:
SimpleDwarf dwarf;
std::ostream& os;
std::unique_ptr<PcListReader> pc_list;
NamingScheme naming_scheme;
};

View file

@ -4,7 +4,13 @@ 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 settings.o main.o
OBJS=\
DwarfReader.o \
SimpleDwarf.o \
CodeGenerator.o \
PcListReader.o \
settings.o \
main.o
###############################################################################

32
src/PcListReader.cpp Normal file
View file

@ -0,0 +1,32 @@
#include "PcListReader.hpp"
#include <fstream>
using namespace std;
PcListReader::PcListReader(const std::string& path): path(path)
{}
void PcListReader::read() {
ifstream handle(path, ifstream::in | ifstream::binary);
if(!handle.good()) {
throw PcListReader::CannotReadFile();
}
uintptr_t last_pc;
unsigned char buffer[8];
while(!handle.eof()) {
handle.read((char*)buffer, 8);
if(handle.gcount() != 8)
throw PcListReader::BadFormat();
last_pc = 0;
for(int shift = 0; shift < 8; ++shift) {
uintptr_t c_byte = buffer[shift];
c_byte <<= 8*shift;
last_pc |= c_byte;
}
pc_list.push_back(last_pc);
}
}

30
src/PcListReader.hpp Normal file
View file

@ -0,0 +1,30 @@
/** Reads .pc_list files, containing a list of valid program counters for some
* elf file.
*/
#pragma once
#include <vector>
#include <string>
#include <cstdint>
class PcListReader {
public:
/// Thrown when the file is somehow not readable
class CannotReadFile: std::exception {};
/// Thrown when the file contains bad content (probably not aligned 8B)
class BadFormat: std::exception {};
PcListReader(const std::string& path);
/// Actually read and process the file
void read();
/// Access the PC list (filled iff `read` was called before)
std::vector<uintptr_t>& get_list() { return pc_list; }
private:
std::string path;
std::vector<uintptr_t> pc_list;
};

View file

@ -45,6 +45,17 @@ MainOptions options_parse(int argc, char** argv) {
settings::switch_generation_policy =
settings::SGP_GlobalSwitch;
}
else if(option == "--pc-list") {
if(option_pos + 1 == argc) { // missing parameter
exit_status = 1;
print_helptext = true;
}
else {
++option_pos;
settings::pc_list = argv[option_pos];
}
}
}
if(!seen_switch_gen_policy) {

View file

@ -2,4 +2,5 @@
namespace settings {
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
std::string pc_list = "";
}

View file

@ -4,6 +4,8 @@
#pragma once
#include <string>
namespace settings {
/// Controls how the eh_elf switches are generated
enum SwitchGenerationPolicy {
@ -12,4 +14,5 @@ namespace settings {
};
extern SwitchGenerationPolicy switch_generation_policy;
extern std::string pc_list;
}