Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
!.vscode/extensions.json
*.code-workspace


## Logs ##
logs/

Expand Down
6 changes: 6 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ repos:
args: [--style=google]
- id: cpplint
args: [--filter=-build/include_order]
exclude: |
(?x)^(
subprojects/.*/include/.*\.skel\.h|
subprojects/.*/src/vmlinux\.h|
include/third-party/.*
)$
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.1.0
hooks:
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ On Ubuntu 24.04:

```bash
# ProcPS
apt install libcapstone-dev
apt install libcapstone-dev
# Linux Perf
apt install linux-tools-common linux-tools-generic
# SQLite
Expand Down
80 changes: 80 additions & 0 deletions examples/benchmark.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I recommend to move this to another folder, like examples.

Also, keep the comment and naming style

* @file benchmark.c
* @author Diego Avila <diego.avila@uned.cr>
* Anthony Montero <anthonymr2010@estudiantec.cr>
* @brief Benchmark program for CPU consumption testing
*
* @copyright Copyright (c) 2026. See License for Licensing
*/

#define _POSIX_C_SOURCE 200809L

#include <cblas.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static double now_sec(void) {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec + ts.tv_nsec * 1e-9;
}

int main(int argc, char **argv) {
if (argc < 4) {
fprintf(stderr, "Usage: %s <N> <reps> <warmup>\n", argv[0]);
return 1;
}
int N = atoi(argv[1]); /* matrix size: N x N */
int reps = atoi(argv[2]); /* number of repetitions to average */
int warmup = atoi(argv[3]); /* warmup runs before measured reps */

/* allocate matrices (row-major for cblas, but using column-major calls
* consistent with BLAS)
*/
size_t elems = (size_t)N * (size_t)N;
double *A = aligned_alloc(64, elems * sizeof(double));
double *B = aligned_alloc(64, elems * sizeof(double));
double *C = aligned_alloc(64, elems * sizeof(double));
if (!A || !B || !C) {
fprintf(stderr, "Allocation failed\n");
return 1;
}

/* init with random values (deterministic seed) */
srand(42);
for (size_t i = 0; i < elems; ++i) {
A[i] = ((double)rand() / RAND_MAX);
B[i] = ((double)rand() / RAND_MAX);
C[i] = 0.0;
}

/* Warmup runs (not measured) */
for (int w = 0; w < warmup; ++w) {
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, N, N, N, 1.0, A, N,
B, N, 0.0, C, N);
}

/* Measured reps */
double t0 = now_sec();
for (int r = 0; r < reps; ++r) {
cblas_dgemm(CblasRowMajor, CblasNoTrans, CblasNoTrans, N, N, N, 1.0, A, N,
B, N, 0.0, C, N);
}
double t1 = now_sec();

double elapsed = (t1 - t0); /* average time per multiplication (seconds) */

/* FLOPs for one matrix multiply (approx): 2 * N^3 */
double flops = 2.0 * (double)N * (double)N * (double)N;
double gflops = (flops / elapsed) / 1e9;

/* Print a succinct output */
printf("N=%d reps=%d warmup=%d time_s=%.9f gflops=%.6f\n", N, reps, warmup,
elapsed, gflops);

free(A);
free(B);
free(C);
return 0;
}
4 changes: 2 additions & 2 deletions examples/csv-testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <efimon/logger/csv.hpp>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <efimon/logger/csv.hpp>

using namespace efimon; // NOLINT

int main(int /*argc*/, char** /*argv*/) {
Expand Down
4 changes: 2 additions & 2 deletions examples/frequency-query.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <efimon/proc/cpuinfo.hpp>

#include <unistd.h>

#include <efimon/proc/cpuinfo.hpp>
#include <iostream>
#include <utility>
#include <vector>

int main(int, char **) {
efimon::CPUInfo info{};
Expand Down
12 changes: 12 additions & 0 deletions examples/meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,15 @@ if enable_ptrace_capstone
install : false,
)
endif

if enable_sampling_by_pid
executable('sampling-by-pid-testing',
[
files('sampling-by-pid-testing.cpp')
],
cpp_args : cpp_args,
include_directories : [project_inc],
dependencies: [project_deps, libefimon_dep],
install : false,
)
endif
5 changes: 2 additions & 3 deletions examples/process-manager-threaded.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <efimon/arg-parser.hpp>
#include <efimon/process-manager.hpp>

#include <algorithm>
#include <chrono> // NOLINT
#include <condition_variable> // NOLINT
#include <efimon/arg-parser.hpp>
#include <efimon/process-manager.hpp>
#include <iostream>
#include <mutex> // NOLINT
#include <string>
Expand Down
3 changes: 1 addition & 2 deletions examples/process-manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,9 @@
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <algorithm>
#include <efimon/arg-parser.hpp>
#include <efimon/process-manager.hpp>

#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
Expand Down
3 changes: 1 addition & 2 deletions examples/process-tracking.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
#include <unistd.h>

#include <algorithm>
#include <efimon/proc/list.hpp>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

#include <efimon/proc/list.hpp>

int main(int argc, char **argv) {
std::vector<std::string> users;

Expand Down
1 change: 1 addition & 0 deletions examples/process-tree.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#include <efimon/arg-parser.hpp>
#include <efimon/logger/macros.hpp>
#include <efimon/proc/process-tree.hpp>
#include <iostream>
#include <string>
#include <unordered_map>
#include <vector>
Expand Down
66 changes: 66 additions & 0 deletions examples/sampling-by-pid-testing.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/**
* @file sampling-by-pid-testing.cpp
* @author Diego Avila (diego.avila@uned.cr)
* @brief Example of eBPF Sampling-by-PID observer testing
*
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <unistd.h>

#include <cstdlib>
#include <efimon/ebpf-modules/cpu-assembly-sampler/sampling-by-pid.hpp>
#include <iostream>
#include <string>

using namespace efimon; // NOLINT

int main(int argc, char **argv) {
if (argc <= 1) {
std::cerr << "No PID specified" << std::endl;
return -1;
}

uint u_pid = std::atoi(argv[1]);
std::cout << "PID: " << u_pid << std::endl;

SamplingByPIDObserver ob_sampling{u_pid};
ob_sampling.SetInterval(2000);

std::cout << "Sampling for 2 seconds..." << std::endl;
auto st_ret = ob_sampling.Trigger();
if (st_ret.code != Status::OK) {
std::cerr << "ERROR: " << st_ret.msg << std::endl;
return -1;
}

std::cout << "Raw eBPF samples collected: "
<< ob_sampling.GetCollectedSamplesCount() << std::endl;
std::cout << "Decoded userspace samples: "
<< ob_sampling.GetDecodedSamplesCount() << std::endl;

auto *p_readings_ann =
dynamic_cast<InstructionReadings *>(ob_sampling.GetReadings()[0]);

std::cout << "Histogram:" << std::endl;
for (const auto &kv_histogram : p_readings_ann->histogram) {
std::cout << "\t" << std::get<0>(kv_histogram) << ": "
<< std::get<1>(kv_histogram) << std::endl;
}

std::cout << "Classification:" << std::endl;
for (const auto &kv_type : p_readings_ann->classification) {
std::cout << "\t" << AsmClassifier::TypeString(kv_type.first) << ": "
<< std::endl;
for (const auto &kv_family : kv_type.second) {
std::cout << "\t\t" << AsmClassifier::FamilyString(kv_family.first)
<< ": " << std::endl;
for (const auto &kv_origin : kv_family.second) {
std::cout << "\t\t\t" << AsmClassifier::OriginString(kv_origin.first)
<< ": " << kv_origin.second << std::endl;
}
}
}

return 0;
}
4 changes: 2 additions & 2 deletions examples/sqlite-testing.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* @copyright Copyright (c) 2024. See License for Licensing
*/

#include <efimon/logger/sqlite.hpp>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <efimon/logger/sqlite.hpp>

using namespace efimon; // NOLINT

int main(int /*argc*/, char** /*argv*/) {
Expand Down
14 changes: 7 additions & 7 deletions include/efimon/asm-classifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,8 +92,9 @@ enum class DataOrigin {
* The first type determines the instruction type, the second the family or
* group and the third the data origin
*/
using InstructionPair =
std::tuple<assembly::InstructionType, assembly::InstructionFamily, uint8_t>;
using InstructionPair = std::tuple<assembly::InstructionType,
assembly::InstructionFamily, // NOLINT
uint8_t>; // NOLINT

/**
* Interface to classify the instructions into families and types
Expand All @@ -108,18 +109,17 @@ class AsmClassifier {
* @param operands operands types
* @return InstructionPair
*/
virtual InstructionPair Classify(const std::string &inst,
const std::string &operands) const
noexcept = 0;
virtual InstructionPair Classify(
const std::string &inst, const std::string &operands) const noexcept = 0;

/**
* Determines if the operands belong to memory, immediate or register values
*
* @param operands as it comes from objdump
* @return string with r, i or m symbolising the type of operands
*/
virtual const std::string OperandTypes(const std::string &operands) const
noexcept = 0;
virtual const std::string OperandTypes(
const std::string &operands) const noexcept = 0;

/**
* Default destructor for inheritance (implementation)
Expand Down
4 changes: 2 additions & 2 deletions include/efimon/asm-classifier/x86-classifier.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ class x86Classifier : public AsmClassifier {
* @param operands as it comes from objdump
* @return string with r, i or m symbolising the type of operands
*/
const std::string OperandTypes(const std::string &operands) const
noexcept override;
const std::string OperandTypes(
const std::string &operands) const noexcept override;

/**
* Default destructor for inheritance (implementation)
Expand Down
13 changes: 13 additions & 0 deletions include/efimon/ebpf-modules/cpu-assembly-sampler/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#
# See LICENSE for more information about licensing
# Copyright 2026
#
# Author: Diego Avila <diego.avila@uned.cr>
#

lib_sampling_by_pid_headers = []
if enable_sampling_by_pid
lib_sampling_by_pid_headers += [
files('sampling-by-pid.hpp'),
]
Comment thread
dierpg marked this conversation as resolved.
endif
Loading