2021-06-10 22:02:00 +03:00
|
|
|
// Copyright (c) Microsoft Corporation
|
|
|
|
// SPDX-License-Identifier: MIT
|
2021-03-10 05:38:31 +03:00
|
|
|
|
2021-01-16 05:39:40 +03:00
|
|
|
#define WIN32_LEAN_AND_MEAN
|
2021-03-10 03:25:24 +03:00
|
|
|
#include <windows.h>
|
2021-03-10 01:54:03 +03:00
|
|
|
#include <iomanip>
|
|
|
|
#include <locale>
|
|
|
|
#include <netsh.h>
|
2021-03-10 03:25:24 +03:00
|
|
|
#include "elf.h"
|
|
|
|
#include "tokens.h"
|
2022-03-10 03:15:58 +03:00
|
|
|
#include "utilities.h"
|
2021-03-02 21:45:34 +03:00
|
|
|
|
2021-01-16 05:39:40 +03:00
|
|
|
TOKEN_VALUE g_LevelEnum[2] = {
|
2021-03-10 01:54:03 +03:00
|
|
|
{L"normal", VL_NORMAL},
|
|
|
|
{L"verbose", VL_VERBOSE},
|
2021-01-16 05:39:40 +03:00
|
|
|
};
|
|
|
|
|
2021-03-10 05:38:31 +03:00
|
|
|
DWORD
|
|
|
|
handle_ebpf_show_disassembly(
|
|
|
|
LPCWSTR machine, LPWSTR* argv, DWORD current_index, DWORD argc, DWORD flags, LPCVOID data, BOOL* done)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(machine);
|
|
|
|
UNREFERENCED_PARAMETER(flags);
|
|
|
|
UNREFERENCED_PARAMETER(data);
|
|
|
|
UNREFERENCED_PARAMETER(done);
|
|
|
|
|
|
|
|
TAG_TYPE tags[] = {
|
|
|
|
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
|
|
|
|
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
|
|
|
|
};
|
|
|
|
ULONG tag_type[_countof(tags)] = {0};
|
|
|
|
|
|
|
|
ULONG status =
|
|
|
|
PreprocessCommand(nullptr, argv, current_index, argc, tags, _countof(tags), 0, _countof(tags), tag_type);
|
|
|
|
|
|
|
|
std::string filename;
|
|
|
|
std::string section = ""; // Use the first code section by default.
|
|
|
|
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
|
|
|
|
switch (tag_type[i]) {
|
|
|
|
case 0: // FILENAME
|
|
|
|
{
|
|
|
|
filename = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: // SECTION
|
|
|
|
{
|
|
|
|
section = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
default:
|
|
|
|
status = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
|
|
}
|
2021-02-27 02:36:50 +03:00
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
2021-03-10 01:54:03 +03:00
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
|
|
|
|
const char* disassembly = nullptr;
|
|
|
|
const char* error_message = nullptr;
|
|
|
|
if (ebpf_api_elf_disassemble_section(filename.c_str(), section.c_str(), &disassembly, &error_message) != 0) {
|
|
|
|
std::cerr << error_message << std::endl;
|
2021-06-23 06:42:18 +03:00
|
|
|
ebpf_free_string(error_message);
|
2021-03-10 05:38:31 +03:00
|
|
|
return ERROR_SUPPRESS_OUTPUT;
|
|
|
|
} else {
|
|
|
|
std::cout << disassembly << std::endl;
|
2021-06-23 06:42:18 +03:00
|
|
|
ebpf_free_string(disassembly);
|
2021-03-10 05:38:31 +03:00
|
|
|
return NO_ERROR;
|
2021-01-16 05:39:40 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-03-10 05:38:31 +03:00
|
|
|
DWORD
|
|
|
|
handle_ebpf_show_sections(
|
|
|
|
LPCWSTR machine, LPWSTR* argv, DWORD current_index, DWORD argc, DWORD flags, LPCVOID data, BOOL* done)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(machine);
|
|
|
|
UNREFERENCED_PARAMETER(flags);
|
|
|
|
UNREFERENCED_PARAMETER(data);
|
|
|
|
UNREFERENCED_PARAMETER(done);
|
|
|
|
|
|
|
|
TAG_TYPE tags[] = {
|
|
|
|
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
|
|
|
|
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
|
|
|
|
{TOKEN_LEVEL, NS_REQ_ZERO, FALSE},
|
|
|
|
};
|
|
|
|
ULONG tag_type[_countof(tags)] = {0};
|
|
|
|
|
|
|
|
ULONG status =
|
|
|
|
PreprocessCommand(nullptr, argv, current_index, argc, tags, _countof(tags), 0, _countof(tags), tag_type);
|
|
|
|
|
|
|
|
VERBOSITY_LEVEL level = VL_NORMAL;
|
|
|
|
std::string filename;
|
|
|
|
std::string section;
|
|
|
|
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
|
|
|
|
switch (tag_type[i]) {
|
|
|
|
case 0: // FILENAME
|
|
|
|
{
|
|
|
|
filename = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: // SECTION
|
|
|
|
{
|
|
|
|
section = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 2: // LEVEL
|
|
|
|
status = MatchEnumTag(NULL, argv[current_index + i], _countof(g_LevelEnum), g_LevelEnum, (PULONG)&level);
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
status = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
|
|
}
|
2021-01-16 05:39:40 +03:00
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
2021-01-16 05:39:40 +03:00
|
|
|
}
|
|
|
|
|
2021-03-10 05:38:31 +03:00
|
|
|
// If the user specified a section and no level, default to verbose.
|
|
|
|
if (tags[1].bPresent && !tags[2].bPresent) {
|
|
|
|
level = VL_VERBOSE;
|
|
|
|
}
|
2021-03-05 21:49:25 +03:00
|
|
|
|
2022-05-12 00:06:49 +03:00
|
|
|
ebpf_section_info_t* section_data = nullptr;
|
2021-03-10 01:54:03 +03:00
|
|
|
|
2021-03-10 05:38:31 +03:00
|
|
|
const char* error_message = nullptr;
|
2022-05-12 00:06:49 +03:00
|
|
|
if (ebpf_enumerate_sections(filename.c_str(), level == VL_VERBOSE, §ion_data, &error_message) != 0) {
|
2021-03-10 05:38:31 +03:00
|
|
|
std::cerr << error_message << std::endl;
|
2021-06-23 06:42:18 +03:00
|
|
|
ebpf_free_string(error_message);
|
2022-05-12 00:06:49 +03:00
|
|
|
ebpf_free_sections(section_data);
|
2021-03-10 05:38:31 +03:00
|
|
|
return ERROR_SUPPRESS_OUTPUT;
|
|
|
|
}
|
2021-02-27 02:36:50 +03:00
|
|
|
|
2021-03-06 01:47:18 +03:00
|
|
|
if (level == VL_NORMAL) {
|
2021-03-10 05:38:31 +03:00
|
|
|
std::cout << "\n";
|
2021-05-26 08:05:03 +03:00
|
|
|
std::cout << " Section Type # Maps Size\n";
|
|
|
|
std::cout << "==================== ========= ====== ======\n";
|
2021-03-10 05:38:31 +03:00
|
|
|
}
|
2022-05-12 00:06:49 +03:00
|
|
|
for (auto current_section = section_data; current_section != nullptr; current_section = current_section->next) {
|
|
|
|
if (!section.empty() && strcmp(current_section->section_name, section.c_str()) != 0) {
|
|
|
|
continue;
|
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
if (level == VL_NORMAL) {
|
2022-05-12 00:06:49 +03:00
|
|
|
std::cout << std::setw(20) << std::right << current_section->section_name << " " << std::setw(9)
|
|
|
|
<< current_section->program_type_name << " " << std::setw(6) << current_section->map_count
|
|
|
|
<< " " << std::setw(6) << current_section->raw_data_size << "\n";
|
2021-03-10 05:38:31 +03:00
|
|
|
} else {
|
|
|
|
std::cout << "\n";
|
2022-05-12 00:06:49 +03:00
|
|
|
std::cout << "Section : " << current_section->section_name << "\n";
|
|
|
|
std::cout << "Program Type : " << current_section->program_type_name << "\n";
|
|
|
|
std::cout << "# Maps : " << current_section->map_count << "\n";
|
|
|
|
std::cout << "Size : " << current_section->raw_data_size << " bytes\n";
|
|
|
|
for (auto stat = current_section->stats; stat != nullptr; stat = stat->next) {
|
|
|
|
std::cout << std::setw(13) << std::left << stat->key << ": " << stat->value << "\n";
|
2021-03-10 05:38:31 +03:00
|
|
|
}
|
|
|
|
}
|
2021-01-16 05:39:40 +03:00
|
|
|
}
|
2021-03-06 01:47:18 +03:00
|
|
|
|
2022-05-12 00:06:49 +03:00
|
|
|
ebpf_free_sections(section_data);
|
|
|
|
ebpf_free_string(error_message);
|
2021-03-10 05:38:31 +03:00
|
|
|
return NO_ERROR;
|
2021-01-16 05:39:40 +03:00
|
|
|
}
|
|
|
|
|
2021-03-10 05:38:31 +03:00
|
|
|
DWORD
|
|
|
|
handle_ebpf_show_verification(
|
|
|
|
LPCWSTR machine, LPWSTR* argv, DWORD current_index, DWORD argc, DWORD flags, LPCVOID data, BOOL* done)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(machine);
|
|
|
|
UNREFERENCED_PARAMETER(flags);
|
|
|
|
UNREFERENCED_PARAMETER(data);
|
|
|
|
UNREFERENCED_PARAMETER(done);
|
|
|
|
|
|
|
|
TAG_TYPE tags[] = {
|
|
|
|
{TOKEN_FILENAME, NS_REQ_PRESENT, FALSE},
|
|
|
|
{TOKEN_SECTION, NS_REQ_ZERO, FALSE},
|
2021-04-17 23:09:43 +03:00
|
|
|
{TOKEN_LEVEL, NS_REQ_ZERO, FALSE},
|
2021-03-10 05:38:31 +03:00
|
|
|
};
|
|
|
|
ULONG tag_type[_countof(tags)] = {0};
|
|
|
|
|
|
|
|
ULONG status =
|
|
|
|
PreprocessCommand(nullptr, argv, current_index, argc, tags, _countof(tags), 0, _countof(tags), tag_type);
|
|
|
|
|
2021-04-17 23:09:43 +03:00
|
|
|
VERBOSITY_LEVEL level = VL_NORMAL;
|
2021-03-10 05:38:31 +03:00
|
|
|
std::string filename;
|
|
|
|
std::string section = ""; // Use the first code section by default.
|
|
|
|
for (int i = 0; (status == NO_ERROR) && ((i + current_index) < argc); i++) {
|
|
|
|
switch (tag_type[i]) {
|
|
|
|
case 0: // FILENAME
|
|
|
|
{
|
|
|
|
filename = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case 1: // SECTION
|
|
|
|
{
|
|
|
|
section = down_cast_from_wstring(std::wstring(argv[current_index + i]));
|
|
|
|
break;
|
|
|
|
}
|
2021-04-17 23:09:43 +03:00
|
|
|
case 2: // LEVEL
|
|
|
|
{
|
|
|
|
status = MatchEnumTag(NULL, argv[current_index + i], _countof(g_LevelEnum), g_LevelEnum, (PULONG)&level);
|
|
|
|
if (status != NO_ERROR) {
|
|
|
|
status = ERROR_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
default:
|
|
|
|
status = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
|
|
}
|
2021-01-16 06:47:58 +03:00
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
if (status != NO_ERROR) {
|
|
|
|
return status;
|
2021-01-16 06:47:58 +03:00
|
|
|
}
|
2021-03-10 05:38:31 +03:00
|
|
|
|
|
|
|
const char* report;
|
|
|
|
const char* error_message;
|
2021-06-02 21:22:06 +03:00
|
|
|
ebpf_api_verifier_stats_t stats;
|
2021-03-10 05:38:31 +03:00
|
|
|
|
2022-04-18 21:52:55 +03:00
|
|
|
status = ebpf_api_elf_verify_section_from_file(
|
2021-06-02 21:22:06 +03:00
|
|
|
filename.c_str(), section.c_str(), level == VL_VERBOSE, &report, &error_message, &stats);
|
2021-03-10 05:38:31 +03:00
|
|
|
if (status == ERROR_SUCCESS) {
|
2021-04-17 23:09:43 +03:00
|
|
|
std::cout << report;
|
2021-06-02 21:22:06 +03:00
|
|
|
std::cout << "\nProgram terminates within " << stats.max_instruction_count << " instructions\n";
|
2021-03-10 05:38:31 +03:00
|
|
|
return NO_ERROR;
|
|
|
|
} else {
|
|
|
|
if (error_message) {
|
2021-06-24 04:12:20 +03:00
|
|
|
std::cerr << error_message << std::endl;
|
2021-03-10 05:38:31 +03:00
|
|
|
}
|
|
|
|
if (report) {
|
2021-11-07 21:47:47 +03:00
|
|
|
std::cerr << "\nVerification report:\n" << report;
|
|
|
|
std::cerr << stats.total_warnings << " errors\n\n";
|
2021-03-10 05:38:31 +03:00
|
|
|
}
|
2021-06-23 06:42:18 +03:00
|
|
|
ebpf_free_string(error_message);
|
|
|
|
ebpf_free_string(report);
|
2021-03-10 05:38:31 +03:00
|
|
|
return ERROR_SUPPRESS_OUTPUT;
|
2021-01-16 06:47:58 +03:00
|
|
|
}
|
2021-01-19 21:33:27 +03:00
|
|
|
}
|