Skip to content

Commit

Permalink
no transform on check.cpp. reorganize check.cpp
Browse files Browse the repository at this point in the history
No reachability notes on assume-assert

Signed-off-by: Elazar Gershuni <[email protected]>
  • Loading branch information
elazarg committed Nov 15, 2024
1 parent 37be029 commit 71c3f8d
Show file tree
Hide file tree
Showing 25 changed files with 443 additions and 706 deletions.
8 changes: 4 additions & 4 deletions src/asm_cfg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ static void add_cfg_nodes(cfg_t& cfg, const label_t& caller_label, const label_t
macro_labels.erase(macro_label);

if (stack_frame_prefix == macro_label.stack_frame_prefix) {
throw std::runtime_error{stack_frame_prefix + ": illegal recursion"};
throw crab::InvalidControlFlow{stack_frame_prefix + ": illegal recursion"};
}

// Clone the macro block into a new block with the new stack frame prefix.
Expand Down Expand Up @@ -143,7 +143,7 @@ static void add_cfg_nodes(cfg_t& cfg, const label_t& caller_label, const label_t
const label_t label(macro_label.from, macro_label.to, caller_label_str);
if (const auto pins = std::get_if<CallLocal>(&cfg.at(label).cmd)) {
if (stack_frame_depth >= MAX_CALL_STACK_FRAMES) {
throw std::runtime_error{"too many call stack frames"};
throw crab::InvalidControlFlow{"too many call stack frames"};
}
add_cfg_nodes(cfg, label, pins->target);
}
Expand All @@ -163,7 +163,7 @@ static cfg_t instruction_seq_to_cfg(const InstructionSeq& insts, const bool must
}

if (insts.size() == 0) {
throw std::invalid_argument{"empty instruction sequence"};
throw crab::InvalidControlFlow{"empty instruction sequence"};
} else {
const auto& [label, inst, _0] = insts[0];
cfg.get_node(cfg.entry_label()) >> cfg.get_node(label);
Expand All @@ -183,7 +183,7 @@ static cfg_t instruction_seq_to_cfg(const InstructionSeq& insts, const bool must
fallthrough = std::get<0>(insts[i + 1]);
} else {
if (has_fall(inst) && must_have_exit) {
throw std::invalid_argument{"fallthrough in last instruction"};
throw crab::InvalidControlFlow{"fallthrough in last instruction"};
}
}
if (const auto jmp = std::get_if<Jmp>(&inst)) {
Expand Down
64 changes: 32 additions & 32 deletions src/asm_files.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ template <typename T>
requires std::is_trivially_copyable_v<T>
static vector<T> vector_of(const char* data, const ELFIO::Elf_Xword size) {
if (size % sizeof(T) != 0 || size > std::numeric_limits<uint32_t>::max() || !data) {
throw std::runtime_error("Invalid argument to vector_of");
throw UnmarshalError("Invalid argument to vector_of");
}
return {reinterpret_cast<const T*>(data), reinterpret_cast<const T*>(data + size)};
}
Expand Down Expand Up @@ -111,10 +111,10 @@ static size_t parse_map_sections(const ebpf_verifier_options_t& options, const e
if (map_count > 0) {
map_record_size = s->get_size() / map_count;
if (s->get_data() == nullptr || map_record_size == 0) {
throw std::runtime_error("bad maps section");
throw UnmarshalError("bad maps section");
}
if (s->get_size() % map_record_size != 0) {
throw std::runtime_error("bad maps section size");
throw UnmarshalError("bad maps section size");
}
platform->parse_maps_section(map_descriptors, s->get_data(), map_record_size, map_count, platform, options);
}
Expand All @@ -131,9 +131,9 @@ vector<raw_program> read_elf(const string& path, const string& desired_section,
}
struct stat st;
if (stat(path.c_str(), &st)) {
throw std::runtime_error(string(strerror(errno)) + " opening " + path);
throw UnmarshalError(string(strerror(errno)) + " opening " + path);
}
throw std::runtime_error("Can't process ELF file " + path);
throw UnmarshalError("Can't process ELF file " + path);
}

static std::tuple<string, ELFIO::Elf_Xword>
Expand Down Expand Up @@ -168,8 +168,8 @@ void relocate_map(ebpf_inst& inst, const std::string& symbol_name,
const ELFIO::const_symbol_section_accessor& symbols) {
// Only permit loading the address of the map.
if ((inst.opcode & INST_CLS_MASK) != INST_CLS_LD) {
throw std::runtime_error("Illegal operation on symbol " + symbol_name + " at location " +
std::to_string(offset / sizeof(ebpf_inst)));
throw UnmarshalError("Illegal operation on symbol " + symbol_name + " at location " +
std::to_string(offset / sizeof(ebpf_inst)));
}
inst.src = 1; // magic number for LoadFd

Expand All @@ -190,8 +190,8 @@ void relocate_map(ebpf_inst& inst, const std::string& symbol_name,
}
}
if (reloc_value >= info.map_descriptors.size()) {
throw std::runtime_error("Bad reloc value (" + std::to_string(reloc_value) + "). " +
"Make sure to compile with -O2.");
throw UnmarshalError("Bad reloc value (" + std::to_string(reloc_value) + "). " +
"Make sure to compile with -O2.");
}
inst.imm = info.map_descriptors.at(reloc_value).original_fd;
}
Expand All @@ -213,17 +213,17 @@ static vector<ebpf_inst> read_subprogram(const ELFIO::section& subprogram_sectio
auto [subprogram_name, subprogram_size] =
get_program_name_and_size(subprogram_section, subprogram_offset, symbols);
if (subprogram_size == 0) {
throw std::runtime_error("Zero-size subprogram '" + subprogram_name + "' in section '" +
subprogram_section.get_name() + "'");
throw UnmarshalError("Zero-size subprogram '" + subprogram_name + "' in section '" +
subprogram_section.get_name() + "'");
}
if (subprogram_name == symbol_name) {
// Append subprogram instructions to the main program.
return vector_of<ebpf_inst>(subprogram_section.get_data() + subprogram_offset, subprogram_size);
}
subprogram_offset += subprogram_size;
}
throw std::runtime_error("Subprogram '" + symbol_name + "' not found in section '" + subprogram_section.get_name() +
"'");
throw UnmarshalError("Subprogram '" + symbol_name + "' not found in section '" + subprogram_section.get_name() +
"'");
}

static void append_subprograms(raw_program& prog, const vector<raw_program>& programs,
Expand Down Expand Up @@ -254,8 +254,8 @@ static void append_subprograms(raw_program& prog, const vector<raw_program>& pro
const int64_t target_offset = gsl::narrow_cast<int64_t>(subprogram_offsets[reloc.target_function_name]);
const auto offset_diff = target_offset - gsl::narrow<int64_t>(reloc.source_offset) - 1;
if (offset_diff < std::numeric_limits<int32_t>::min() || offset_diff > std::numeric_limits<int32_t>::max()) {
throw std::runtime_error("Offset difference out of int32_t range for instruction at source offset " +
std::to_string(reloc.source_offset));
throw UnmarshalError("Offset difference out of int32_t range for instruction at source offset " +
std::to_string(reloc.source_offset));
}
prog.prog[reloc.source_offset].imm = gsl::narrow_cast<int32_t>(offset_diff);
}
Expand All @@ -282,20 +282,20 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
const ebpf_verifier_options_t& options, const ebpf_platform_t* platform) {
ELFIO::elfio reader;
if (!reader.load(input_stream)) {
throw std::runtime_error("Can't process ELF file " + path);
throw UnmarshalError("Can't process ELF file " + path);
}

auto symbol_section = reader.sections[".symtab"];
if (!symbol_section) {
throw std::runtime_error("No symbol section found in ELF file " + path);
throw UnmarshalError("No symbol section found in ELF file " + path);
}

// Make sure the ELFIO library will be able to parse the symbol section correctly.
auto expected_entry_size =
reader.get_class() == ELFIO::ELFCLASS32 ? sizeof(ELFIO::Elf32_Sym) : sizeof(ELFIO::Elf64_Sym);

if (symbol_section->get_entry_size() != expected_entry_size) {
throw std::runtime_error("Invalid symbol section found in ELF file " + path);
throw UnmarshalError("Invalid symbol section found in ELF file " + path);
}

program_info info{platform};
Expand Down Expand Up @@ -324,7 +324,7 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
parse_map_sections(options, platform, reader, info.map_descriptors, map_section_indices, symbols);
} else {
if (!btf_data.has_value()) {
throw std::runtime_error("No BTF section found in ELF file " + path);
throw UnmarshalError("No BTF section found in ELF file " + path);
}
map_record_size_or_map_offsets = parse_map_section(*btf_data, info.map_descriptors);
// Prevail requires:
Expand Down Expand Up @@ -390,7 +390,7 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path

if (prelocs) {
if (!prelocs->get_data()) {
throw std::runtime_error("Malformed relocation data");
throw UnmarshalError("Malformed relocation data");
}
ELFIO::const_relocation_section_accessor reloc{reader, prelocs};

Expand All @@ -410,7 +410,7 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
}
offset -= program_offset;
if (offset / sizeof(ebpf_inst) >= prog.prog.size()) {
throw std::runtime_error("Invalid relocation data");
throw UnmarshalError("Invalid relocation data");
}
ebpf_inst& inst = prog.prog[offset / sizeof(ebpf_inst)];

Expand All @@ -437,7 +437,6 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
unresolved_symbols_errors.push_back(unresolved_symbol);
}
}
prog.line_info.resize(prog.prog.size());
res.push_back(prog);
program_offset += program_size;
}
Expand All @@ -457,8 +456,8 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
for (const auto& unresolved_symbol : unresolved_symbols_errors) {
std::cerr << unresolved_symbol << std::endl;
}
throw std::runtime_error("There are relocations in section but no maps sections in file " + path +
"\nMake sure to inline all function calls.");
throw UnmarshalError("There are relocations in section but no maps sections in file " + path +
"\nMake sure to inline all function calls.");
}

auto btf_ext = reader.sections[".BTF.ext"];
Expand All @@ -469,10 +468,11 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path
if (program.section_name == section && instruction_offset >= program.insn_off &&
instruction_offset < program.insn_off + program.prog.size() * sizeof(ebpf_inst)) {
const size_t inst_index = (instruction_offset - program.insn_off) / sizeof(ebpf_inst);
if (inst_index >= program.line_info.size()) {
throw std::runtime_error("Invalid BTF data");
if (inst_index >= program.prog.size()) {
throw UnmarshalError("Invalid BTF data");
}
program.line_info[inst_index] = {file_name, source, line_number, column_number};
program.info.line_info.insert_or_assign(
inst_index, btf_line_info_t{file_name, source, line_number, column_number});
return;
}
}
Expand All @@ -482,20 +482,20 @@ vector<raw_program> read_elf(std::istream& input_stream, const std::string& path

// BTF doesn't include line info for every instruction, only on the first instruction per source line.
for (auto& program : res) {
for (size_t i = 1; i < program.line_info.size(); i++) {
for (size_t i = 1; i < program.info.line_info.size(); i++) {
// If the previous PC has line info, copy it.
if (program.line_info[i].line_number == 0 && program.line_info[i - 1].line_number != 0) {
program.line_info[i] = program.line_info[i - 1];
if (program.info.line_info[i].line_number == 0 && program.info.line_info[i - 1].line_number != 0) {
program.info.line_info[i] = program.info.line_info[i - 1];
}
}
}
}

if (res.empty()) {
if (desired_section.empty()) {
throw std::runtime_error("Can't find any non-empty TEXT sections in file " + path);
throw UnmarshalError("Can't find any non-empty TEXT sections in file " + path);
}
throw std::runtime_error("Can't find section " + desired_section + " in file " + path);
throw UnmarshalError("Can't find section " + desired_section + " in file " + path);
}
return res;
}
5 changes: 5 additions & 0 deletions src/asm_files.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
#include "asm_syntax.hpp"
#include "platform.hpp"

class UnmarshalError final : public std::runtime_error {
public:
explicit UnmarshalError(const std::string& what) : std::runtime_error(what) {}
};

std::vector<raw_program> read_raw(std::string path, program_info info);
std::vector<raw_program> read_elf(const std::string& path, const std::string& desired_section,
const ebpf_verifier_options_t& options, const ebpf_platform_t* platform);
Expand Down
8 changes: 4 additions & 4 deletions src/asm_unmarshal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -696,7 +696,7 @@ struct Unmarshaller {
}
}

vector<LabeledInstruction> unmarshal(vector<ebpf_inst> const& insts, vector<btf_line_info_t> const& line_info) {
vector<LabeledInstruction> unmarshal(vector<ebpf_inst> const& insts) {
vector<LabeledInstruction> prog;
int exit_count = 0;
if (insts.empty()) {
Expand Down Expand Up @@ -773,8 +773,8 @@ struct Unmarshaller {

std::optional<btf_line_info_t> current_line_info = {};

if (pc < line_info.size()) {
current_line_info = line_info[pc];
if (pc < info.line_info.size()) {
current_line_info = info.line_info.at(pc);
}

prog.emplace_back(label_t(gsl::narrow<int>(pc)), new_ins, current_line_info);
Expand All @@ -796,7 +796,7 @@ struct Unmarshaller {
std::variant<InstructionSeq, std::string> unmarshal(const raw_program& raw_prog, vector<vector<string>>& notes) {
global_program_info = raw_prog.info;
try {
return Unmarshaller{notes, raw_prog.info}.unmarshal(raw_prog.prog, raw_prog.line_info);
return Unmarshaller{notes, raw_prog.info}.unmarshal(raw_prog.prog);
} catch (InvalidInstruction& arg) {
std::ostringstream ss;
ss << arg.pc << ": " << arg.what() << "\n";
Expand Down
5 changes: 2 additions & 3 deletions src/config.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,9 +43,8 @@ struct ebpf_verifier_options_t {
};

struct ebpf_verifier_stats_t {
int total_unreachable;
int total_warnings;
int max_loop_count;
int total_warnings{};
int max_loop_count{};
};

extern thread_local ebpf_verifier_options_t thread_local_options;
21 changes: 6 additions & 15 deletions src/crab/cfg.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@

namespace crab {

class InvalidControlFlow final : public std::runtime_error {
public:
explicit InvalidControlFlow(const std::string& what) : std::runtime_error(what) {}
};

class cfg_t;

// Node type for the CFG
Expand Down Expand Up @@ -322,7 +327,7 @@ class cfg_t final {
[[nodiscard]]
std::vector<label_t> sorted_labels() const {
std::vector<label_t> labels = this->labels();
std::sort(labels.begin(), labels.end());
std::ranges::sort(labels);
return labels;
}

Expand Down Expand Up @@ -351,20 +356,6 @@ class cfg_t final {
const auto rng = prev_nodes(b);
return std::distance(rng.begin(), rng.end()) == 1;
}

// mark reachable blocks from curId
template <class AnyCfg>
void mark_alive_blocks(label_t curId, AnyCfg& cfg_t, visited_t& visited) {
if (visited.contains(curId)) {
return;
}
visited.insert(curId);
for (const auto& child : cfg_t.next_nodes(curId)) {
mark_alive_blocks(child, cfg_t, visited);
}
}

void remove_unreachable_blocks();
};

class basic_block_t final {
Expand Down
Loading

0 comments on commit 71c3f8d

Please sign in to comment.