Add C++ code to make use of .pc_list
This commit is contained in:
parent
83b304db95
commit
26d7b2afd5
8 changed files with 119 additions and 5 deletions
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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
32
src/PcListReader.cpp
Normal 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
30
src/PcListReader.hpp
Normal 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;
|
||||
};
|
11
src/main.cpp
11
src/main.cpp
|
@ -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) {
|
||||
|
|
|
@ -2,4 +2,5 @@
|
|||
|
||||
namespace settings {
|
||||
SwitchGenerationPolicy switch_generation_policy = SGP_SwitchPerFunc;
|
||||
std::string pc_list = "";
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue