ebpf-for-windows/tools/elfhelper/ElfHelper.cpp

118 строки
3.1 KiB
C++

// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#include "framework.h"
#include <cassert>
#include <iostream>
#include <string>
#include <vector>
#include "CLI11.hpp"
#include "elfio/elfio.hpp"
#include "win_ebpf.hpp"
using std::string;
using std::vector;
// Section name MUST indicate the program type.
static BpfProgType
section_to_progtype(const std::string& section)
{
if (section.find("xdp") != std::string::npos)
return BpfProgType::XDP;
return BpfProgType::UNSPEC;
}
// template <typename T>
static vector<char>
vector_of(ELFIO::section* sec)
{
if (!sec)
return {};
auto data = sec->get_data();
auto size = sec->get_size();
// assert(size % sizeof(T) == 0);
return {(char*)data, (char*)(data + size)};
}
vector<raw_program>
read_elf(const std::string& path, const std::string& desired_section)
{
ELFIO::elfio reader;
if (!reader.load(path)) {
throw std::runtime_error(string("Can't find or process ELF file ") + path);
}
vector<raw_program> res;
program_info info;
// Go through the sections to find the required secion.
// Extract the instructions to be passed to the jitter.
for (const auto section : reader.sections) {
const string name = section->get_name();
std::cout << "section " << name << endl;
if (!desired_section.empty() && name != desired_section)
continue;
if (name == "license" || name == "version" || name == "maps")
continue;
if (name != ".text" && name.find('.') == 0) {
continue;
}
info.program_type = section_to_progtype(name);
if (section->get_size() == 0)
continue;
raw_program prog{path, name, vector_of(section), info};
res.push_back(prog);
}
if (res.empty()) {
throw std::runtime_error(string("Can't find section ") + desired_section + " in file " + path);
}
return res;
}
int __cdecl main(int argc, char** argv)
{
CLI::App app{"Elf Reader"};
std::string filename;
app.add_option("path", filename, "Path to elf file")->required()->type_name("FILE");
std::string desired_section;
app.add_option("section", desired_section, "Section name")->type_name("SECTION");
bool list = false;
app.add_flag("-l", list, "List sections");
CLI11_PARSE(app, argc, argv);
// load elf file
vector<raw_program> raw_progs = read_elf(filename, desired_section);
// Print out the sections
if (list || raw_progs.size() != 1) {
// sections
for (const raw_program& raw_prog : raw_progs) {
std::cout << raw_prog.section << " ";
// raw instructions
if (raw_prog.section == ".text") {
int count = 0;
std::cout << endl;
for (char inst : raw_prog.prog) {
std::cout << " 0x" << std::hex << (int)inst;
// new line after 8 bytes
if (count++ == 7) {
std::cout << endl;
count = 0;
}
}
}
}
std::cout << endl;
}
return 0;
}