LLmp hooks (#2280)
* llmp hooks * separate llmp broker from inner state to allow doing more stuff
This commit is contained in:
parent
399fbccea2
commit
af12b4ba24
@ -8,7 +8,9 @@
|
|||||||
// 4. The "main broker", the gathers the stats from the fuzzer clients and broadcast the newly found testcases from the main evaluator.
|
// 4. The "main broker", the gathers the stats from the fuzzer clients and broadcast the newly found testcases from the main evaluator.
|
||||||
|
|
||||||
use alloc::{boxed::Box, string::String, vec::Vec};
|
use alloc::{boxed::Box, string::String, vec::Vec};
|
||||||
use core::{marker::PhantomData, num::NonZeroUsize, time::Duration};
|
use core::fmt::Debug;
|
||||||
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
|
use core::time::Duration;
|
||||||
|
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
use libafl_bolts::tuples::{Handle, Handled};
|
use libafl_bolts::tuples::{Handle, Handled};
|
||||||
@ -18,7 +20,7 @@ use libafl_bolts::{
|
|||||||
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
|
llmp::{LLMP_FLAG_COMPRESSED, LLMP_FLAG_INITIALIZED},
|
||||||
};
|
};
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{self, LlmpBroker, LlmpClient, LlmpClientDescription, Tag},
|
llmp::{LlmpClient, LlmpClientDescription, Tag},
|
||||||
shmem::{NopShMemProvider, ShMemProvider},
|
shmem::{NopShMemProvider, ShMemProvider},
|
||||||
ClientId,
|
ClientId,
|
||||||
};
|
};
|
||||||
@ -33,9 +35,9 @@ use crate::observers::TimeObserver;
|
|||||||
use crate::state::HasScalabilityMonitor;
|
use crate::state::HasScalabilityMonitor;
|
||||||
use crate::{
|
use crate::{
|
||||||
events::{
|
events::{
|
||||||
AdaptiveSerializer, BrokerEventResult, CustomBufEventResult, Event, EventConfig,
|
AdaptiveSerializer, CustomBufEventResult, Event, EventConfig, EventFirer, EventManager,
|
||||||
EventFirer, EventManager, EventManagerId, EventProcessor, EventRestarter,
|
EventManagerId, EventProcessor, EventRestarter, HasCustomBufHandlers, HasEventManagerId,
|
||||||
HasCustomBufHandlers, HasEventManagerId, LogSeverity, ProgressReporter,
|
LogSeverity, ProgressReporter,
|
||||||
},
|
},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
fuzzer::{EvaluatorObservers, ExecutionProcessor},
|
||||||
@ -45,174 +47,7 @@ use crate::{
|
|||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
|
pub(crate) const _LLMP_TAG_TO_MAIN: Tag = Tag(0x3453453);
|
||||||
|
|
||||||
/// An LLMP-backed event manager for scalable multi-processed fuzzing
|
|
||||||
pub struct CentralizedLlmpEventBroker<I, SP>
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
SP: ShMemProvider + 'static,
|
|
||||||
//CE: CustomEvent<I>,
|
|
||||||
{
|
|
||||||
llmp: LlmpBroker<SP>,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
compressor: GzipCompressor,
|
|
||||||
phantom: PhantomData<I>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, SP> core::fmt::Debug for CentralizedLlmpEventBroker<I, SP>
|
|
||||||
where
|
|
||||||
SP: ShMemProvider + 'static,
|
|
||||||
I: Input,
|
|
||||||
{
|
|
||||||
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
|
||||||
let mut debug_struct = f.debug_struct("CentralizedLlmpEventBroker");
|
|
||||||
let debug = debug_struct.field("llmp", &self.llmp);
|
|
||||||
//.field("custom_buf_handlers", &self.custom_buf_handlers)
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let debug = debug.field("compressor", &self.compressor);
|
|
||||||
debug
|
|
||||||
.field("phantom", &self.phantom)
|
|
||||||
.finish_non_exhaustive()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I, SP> CentralizedLlmpEventBroker<I, SP>
|
|
||||||
where
|
|
||||||
I: Input,
|
|
||||||
SP: ShMemProvider + 'static,
|
|
||||||
{
|
|
||||||
/// Create an event broker from a raw broker.
|
|
||||||
pub fn new(llmp: LlmpBroker<SP>) -> Result<Self, Error> {
|
|
||||||
Ok(Self {
|
|
||||||
llmp,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create an LLMP broker on a port.
|
|
||||||
///
|
|
||||||
/// The port must not be bound yet to have a broker.
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn on_port(shmem_provider: SP, port: u16) -> Result<Self, Error> {
|
|
||||||
Ok(Self {
|
|
||||||
// TODO switch to false after solving the bug
|
|
||||||
llmp: LlmpBroker::with_keep_pages_attach_to_tcp(shmem_provider, port, true)?,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exit the broker process cleanly after at least `n` clients attached and all of them disconnected again
|
|
||||||
pub fn set_exit_cleanly_after(&mut self, n_clients: NonZeroUsize) {
|
|
||||||
self.llmp.set_exit_cleanly_after(n_clients);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run forever in the broker
|
|
||||||
#[cfg(not(feature = "llmp_broker_timeouts"))]
|
|
||||||
pub fn broker_loop(&mut self) -> Result<(), Error> {
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressor = &self.compressor;
|
|
||||||
self.llmp.loop_forever(
|
|
||||||
&mut |client_id, tag, _flags, msg| {
|
|
||||||
if tag == _LLMP_TAG_TO_MAIN {
|
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
|
||||||
let event_bytes = msg;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressed;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let event_bytes = if _flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
|
||||||
compressed = compressor.decompress(msg)?;
|
|
||||||
&compressed
|
|
||||||
} else {
|
|
||||||
msg
|
|
||||||
};
|
|
||||||
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
|
||||||
match Self::handle_in_broker(client_id, &event)? {
|
|
||||||
BrokerEventResult::Forward => Ok(llmp::LlmpMsgHookResult::ForwardToClients),
|
|
||||||
BrokerEventResult::Handled => Ok(llmp::LlmpMsgHookResult::Handled),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(Duration::from_millis(5)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "llmp_debug"))]
|
|
||||||
println!("The last client quit. Exiting.");
|
|
||||||
|
|
||||||
Err(Error::shutting_down())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run in the broker until all clients exit
|
|
||||||
#[cfg(feature = "llmp_broker_timeouts")]
|
|
||||||
pub fn broker_loop(&mut self) -> Result<(), Error> {
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressor = &self.compressor;
|
|
||||||
self.llmp.loop_with_timeouts(
|
|
||||||
&mut |msg_or_timeout| {
|
|
||||||
if let Some((client_id, tag, _flags, msg)) = msg_or_timeout {
|
|
||||||
if tag == _LLMP_TAG_TO_MAIN {
|
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
|
||||||
let event_bytes = msg;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressed;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let event_bytes = if _flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
|
||||||
compressed = compressor.decompress(msg)?;
|
|
||||||
&compressed
|
|
||||||
} else {
|
|
||||||
msg
|
|
||||||
};
|
|
||||||
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
|
||||||
match Self::handle_in_broker(client_id, &event)? {
|
|
||||||
BrokerEventResult::Forward => {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
BrokerEventResult::Handled => Ok(llmp::LlmpMsgHookResult::Handled),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::Handled)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Duration::from_secs(30),
|
|
||||||
Some(Duration::from_millis(5)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "llmp_debug")]
|
|
||||||
println!("The last client quit. Exiting.");
|
|
||||||
|
|
||||||
Err(Error::shutting_down())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle arriving events in the broker
|
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
|
||||||
fn handle_in_broker(
|
|
||||||
_client_id: ClientId,
|
|
||||||
event: &Event<I>,
|
|
||||||
) -> Result<BrokerEventResult, Error> {
|
|
||||||
match &event {
|
|
||||||
Event::NewTestcase {
|
|
||||||
input: _,
|
|
||||||
client_config: _,
|
|
||||||
exit_kind: _,
|
|
||||||
corpus_size: _,
|
|
||||||
observers_buf: _,
|
|
||||||
time: _,
|
|
||||||
executions: _,
|
|
||||||
forward_id: _,
|
|
||||||
} => Ok(BrokerEventResult::Forward),
|
|
||||||
_ => Ok(BrokerEventResult::Handled),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// A wrapper manager to implement a main-secondary architecture with another broker
|
/// A wrapper manager to implement a main-secondary architecture with another broker
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -28,6 +28,8 @@ use std::process::Stdio;
|
|||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use std::{fs::File, os::unix::io::AsRawFd};
|
use std::{fs::File, os::unix::io::AsRawFd};
|
||||||
|
|
||||||
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
|
use libafl_bolts::llmp::LlmpBroker;
|
||||||
#[cfg(all(unix, feature = "std"))]
|
#[cfg(all(unix, feature = "std"))]
|
||||||
use libafl_bolts::os::dup2;
|
use libafl_bolts::os::dup2;
|
||||||
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
#[cfg(all(feature = "std", any(windows, not(feature = "fork"))))]
|
||||||
@ -52,7 +54,7 @@ use super::hooks::EventManagerHooksTuple;
|
|||||||
use crate::observers::TimeObserver;
|
use crate::observers::TimeObserver;
|
||||||
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
#[cfg(all(unix, feature = "std", feature = "fork"))]
|
||||||
use crate::{
|
use crate::{
|
||||||
events::centralized::{CentralizedEventManager, CentralizedLlmpEventBroker},
|
events::{centralized::CentralizedEventManager, llmp::centralized::CentralizedLlmpHook},
|
||||||
state::UsesState,
|
state::UsesState,
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -167,8 +169,8 @@ where
|
|||||||
impl<'a, CF, MT, S, SP> Launcher<'a, CF, (), MT, S, SP>
|
impl<'a, CF, MT, S, SP> Launcher<'a, CF, (), MT, S, SP>
|
||||||
where
|
where
|
||||||
CF: FnOnce(Option<S>, LlmpRestartingEventManager<(), S, SP>, CoreId) -> Result<(), Error>,
|
CF: FnOnce(Option<S>, LlmpRestartingEventManager<(), S, SP>, CoreId) -> Result<(), Error>,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Launch the broker and the clients and fuzz
|
/// Launch the broker and the clients and fuzz
|
||||||
@ -190,8 +192,8 @@ impl<'a, CF, EMH, MT, S, SP> Launcher<'a, CF, EMH, MT, S, SP>
|
|||||||
where
|
where
|
||||||
CF: FnOnce(Option<S>, LlmpRestartingEventManager<EMH, S, SP>, CoreId) -> Result<(), Error>,
|
CF: FnOnce(Option<S>, LlmpRestartingEventManager<EMH, S, SP>, CoreId) -> Result<(), Error>,
|
||||||
EMH: EventManagerHooksTuple<S> + Clone + Copy,
|
EMH: EventManagerHooksTuple<S> + Clone + Copy,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Launch the broker and the clients and fuzz with a user-supplied hook
|
/// Launch the broker and the clients and fuzz with a user-supplied hook
|
||||||
@ -562,8 +564,8 @@ where
|
|||||||
CentralizedEventManager<StdCentralizedInnerMgr<S, SP>, SP>,
|
CentralizedEventManager<StdCentralizedInnerMgr<S, SP>, SP>,
|
||||||
CoreId,
|
CoreId,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Launch a standard Centralized-based fuzzer
|
/// Launch a standard Centralized-based fuzzer
|
||||||
@ -601,8 +603,8 @@ where
|
|||||||
CentralizedEventManager<IM, SP>, // No hooks for centralized EM
|
CentralizedEventManager<IM, SP>, // No hooks for centralized EM
|
||||||
CoreId,
|
CoreId,
|
||||||
) -> Result<(), Error>,
|
) -> Result<(), Error>,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
/// Launch a Centralized-based fuzzer.
|
/// Launch a Centralized-based fuzzer.
|
||||||
@ -663,12 +665,22 @@ where
|
|||||||
log::info!("PID: {:#?} I am centralized broker", std::process::id());
|
log::info!("PID: {:#?} I am centralized broker", std::process::id());
|
||||||
self.shmem_provider.post_fork(true)?;
|
self.shmem_provider.post_fork(true)?;
|
||||||
|
|
||||||
let mut broker: CentralizedLlmpEventBroker<S::Input, SP> =
|
let llmp_centralized_hook = CentralizedLlmpHook::<S::Input, SP>::new()?;
|
||||||
CentralizedLlmpEventBroker::on_port(
|
|
||||||
|
// TODO switch to false after solving the bug
|
||||||
|
let mut broker = LlmpBroker::with_keep_pages_attach_to_tcp(
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
|
tuple_list!(llmp_centralized_hook),
|
||||||
self.centralized_broker_port,
|
self.centralized_broker_port,
|
||||||
|
true,
|
||||||
)?;
|
)?;
|
||||||
broker.broker_loop()?;
|
|
||||||
|
// Run in the broker until all clients exit
|
||||||
|
broker.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
||||||
|
|
||||||
|
log::info!("The last client quit. Exiting.");
|
||||||
|
|
||||||
|
return Err(Error::shutting_down());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
110
libafl/src/events/llmp/hooks/centralized.rs
Normal file
110
libafl/src/events/llmp/hooks/centralized.rs
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
use std::{fmt::Debug, marker::PhantomData};
|
||||||
|
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||||
|
use libafl_bolts::{
|
||||||
|
llmp::{Flags, LlmpBrokerState, LlmpHook, LlmpMsgHookResult, Tag},
|
||||||
|
shmem::ShMemProvider,
|
||||||
|
ClientId, Error,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
use crate::events::COMPRESS_THRESHOLD;
|
||||||
|
use crate::{
|
||||||
|
events::{BrokerEventResult, Event, _LLMP_TAG_TO_MAIN},
|
||||||
|
inputs::Input,
|
||||||
|
};
|
||||||
|
|
||||||
|
/// An LLMP-backed event manager for scalable multi-processed fuzzing
|
||||||
|
pub struct CentralizedLlmpHook<I, SP> {
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor,
|
||||||
|
phantom: PhantomData<(I, SP)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, SP> LlmpHook<SP> for CentralizedLlmpHook<I, SP>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
SP: ShMemProvider + 'static,
|
||||||
|
{
|
||||||
|
fn on_new_message(
|
||||||
|
&mut self,
|
||||||
|
_llmp_broker_state: &mut LlmpBrokerState<SP>,
|
||||||
|
client_id: ClientId,
|
||||||
|
msg_tag: &mut Tag,
|
||||||
|
msg_flags: &mut Flags,
|
||||||
|
msg: &mut [u8],
|
||||||
|
) -> Result<LlmpMsgHookResult, Error> {
|
||||||
|
if *msg_tag == _LLMP_TAG_TO_MAIN {
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let compressor = &self.compressor;
|
||||||
|
#[cfg(not(feature = "llmp_compression"))]
|
||||||
|
let event_bytes = msg;
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let compressed;
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let event_bytes = if *msg_flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
||||||
|
compressed = compressor.decompress(msg)?;
|
||||||
|
&compressed
|
||||||
|
} else {
|
||||||
|
&*msg
|
||||||
|
};
|
||||||
|
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
||||||
|
match Self::handle_in_broker(client_id, &event)? {
|
||||||
|
BrokerEventResult::Forward => Ok(LlmpMsgHookResult::ForwardToClients),
|
||||||
|
BrokerEventResult::Handled => Ok(LlmpMsgHookResult::Handled),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(LlmpMsgHookResult::ForwardToClients)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, SP> Debug for CentralizedLlmpHook<I, SP> {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
let mut debug_struct = f.debug_struct("CentralizedLlmpEventBroker");
|
||||||
|
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let debug_struct = debug_struct.field("compressor", &self.compressor);
|
||||||
|
|
||||||
|
debug_struct
|
||||||
|
.field("phantom", &self.phantom)
|
||||||
|
.finish_non_exhaustive()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, SP> CentralizedLlmpHook<I, SP>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
SP: ShMemProvider + 'static,
|
||||||
|
{
|
||||||
|
/// Create an event broker from a raw broker.
|
||||||
|
pub fn new() -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
||||||
|
phantom: PhantomData,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle arriving events in the broker
|
||||||
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
|
fn handle_in_broker(
|
||||||
|
_client_id: ClientId,
|
||||||
|
event: &Event<I>,
|
||||||
|
) -> Result<BrokerEventResult, Error> {
|
||||||
|
match &event {
|
||||||
|
Event::NewTestcase {
|
||||||
|
input: _,
|
||||||
|
client_config: _,
|
||||||
|
exit_kind: _,
|
||||||
|
corpus_size: _,
|
||||||
|
observers_buf: _,
|
||||||
|
time: _,
|
||||||
|
executions: _,
|
||||||
|
forward_id: _,
|
||||||
|
} => Ok(BrokerEventResult::Forward),
|
||||||
|
_ => Ok(BrokerEventResult::Handled),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,12 +1,13 @@
|
|||||||
//! LLMP broker
|
//! Standard LLMP hook
|
||||||
|
use core::marker::PhantomData;
|
||||||
use core::{marker::PhantomData, num::NonZeroUsize, time::Duration};
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
use std::net::ToSocketAddrs;
|
|
||||||
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
use libafl_bolts::{compress::GzipCompressor, llmp::LLMP_FLAG_COMPRESSED};
|
||||||
use libafl_bolts::{llmp, shmem::ShMemProvider, ClientId};
|
use libafl_bolts::{
|
||||||
|
llmp::{Flags, LlmpBrokerState, LlmpHook, LlmpMsgHookResult, Tag},
|
||||||
|
shmem::ShMemProvider,
|
||||||
|
ClientId,
|
||||||
|
};
|
||||||
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
use crate::events::llmp::COMPRESS_THRESHOLD;
|
use crate::events::llmp::COMPRESS_THRESHOLD;
|
||||||
@ -17,148 +18,85 @@ use crate::{
|
|||||||
Error,
|
Error,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// An LLMP-backed event manager for scalable multi-processed fuzzing
|
/// centralized hook
|
||||||
|
#[cfg(all(unix, feature = "std"))]
|
||||||
|
pub mod centralized;
|
||||||
|
|
||||||
|
/// An LLMP-backed event hook for scalable multi-processed fuzzing
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct LlmpEventBroker<I, MT, SP>
|
pub struct StdLlmpEventHook<I, MT, SP>
|
||||||
where
|
where
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
{
|
{
|
||||||
monitor: MT,
|
monitor: MT,
|
||||||
llmp: llmp::LlmpBroker<SP>,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor,
|
compressor: GzipCompressor,
|
||||||
phantom: PhantomData<I>,
|
phantom: PhantomData<(I, SP)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I, MT, SP> LlmpEventBroker<I, MT, SP>
|
impl<I, MT, SP> LlmpHook<SP> for StdLlmpEventHook<I, MT, SP>
|
||||||
|
where
|
||||||
|
I: Input,
|
||||||
|
MT: Monitor,
|
||||||
|
SP: ShMemProvider + 'static,
|
||||||
|
{
|
||||||
|
fn on_new_message(
|
||||||
|
&mut self,
|
||||||
|
_llmp_broker_state: &mut LlmpBrokerState<SP>,
|
||||||
|
client_id: ClientId,
|
||||||
|
msg_tag: &mut Tag,
|
||||||
|
#[cfg(feature = "llmp_compression")] msg_flags: &mut Flags,
|
||||||
|
#[cfg(not(feature = "llmp_compression"))] _msg_flags: &mut Flags,
|
||||||
|
msg: &mut [u8],
|
||||||
|
) -> Result<LlmpMsgHookResult, Error> {
|
||||||
|
let monitor = &mut self.monitor;
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let compressor = &self.compressor;
|
||||||
|
|
||||||
|
if *msg_tag == LLMP_TAG_EVENT_TO_BOTH {
|
||||||
|
#[cfg(not(feature = "llmp_compression"))]
|
||||||
|
let event_bytes = msg;
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let compressed;
|
||||||
|
#[cfg(feature = "llmp_compression")]
|
||||||
|
let event_bytes = if *msg_flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
||||||
|
compressed = compressor.decompress(msg)?;
|
||||||
|
&compressed
|
||||||
|
} else {
|
||||||
|
&*msg
|
||||||
|
};
|
||||||
|
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
||||||
|
match Self::handle_in_broker(monitor, client_id, &event)? {
|
||||||
|
BrokerEventResult::Forward => Ok(LlmpMsgHookResult::ForwardToClients),
|
||||||
|
BrokerEventResult::Handled => Ok(LlmpMsgHookResult::Handled),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Ok(LlmpMsgHookResult::ForwardToClients)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_timeout(&mut self) -> Result<(), Error> {
|
||||||
|
self.monitor.display("Broker Heartbeat", ClientId(0));
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I, MT, SP> StdLlmpEventHook<I, MT, SP>
|
||||||
where
|
where
|
||||||
I: Input,
|
I: Input,
|
||||||
SP: ShMemProvider + 'static,
|
SP: ShMemProvider + 'static,
|
||||||
MT: Monitor,
|
MT: Monitor,
|
||||||
{
|
{
|
||||||
/// Create an event broker from a raw broker.
|
/// Create an event broker from a raw broker.
|
||||||
pub fn new(llmp: llmp::LlmpBroker<SP>, monitor: MT) -> Result<Self, Error> {
|
pub fn new(monitor: MT) -> Result<Self, Error> {
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
monitor,
|
monitor,
|
||||||
llmp,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
#[cfg(feature = "llmp_compression")]
|
||||||
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
||||||
phantom: PhantomData,
|
phantom: PhantomData,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create an LLMP broker on a port.
|
|
||||||
///
|
|
||||||
/// The port must not be bound yet to have a broker.
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn on_port(shmem_provider: SP, monitor: MT, port: u16) -> Result<Self, Error> {
|
|
||||||
Ok(Self {
|
|
||||||
monitor,
|
|
||||||
llmp: llmp::LlmpBroker::create_attach_to_tcp(shmem_provider, port)?,
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
compressor: GzipCompressor::with_threshold(COMPRESS_THRESHOLD),
|
|
||||||
phantom: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Exit the broker process cleanly after at least `n` clients attached and all of them disconnected again
|
|
||||||
pub fn set_exit_cleanly_after(&mut self, n_clients: NonZeroUsize) {
|
|
||||||
self.llmp.set_exit_cleanly_after(n_clients);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Connect to an LLMP broker on the given address
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
pub fn connect_b2b<A>(&mut self, addr: A) -> Result<(), Error>
|
|
||||||
where
|
|
||||||
A: ToSocketAddrs,
|
|
||||||
{
|
|
||||||
self.llmp.connect_b2b(addr)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run forever in the broker
|
|
||||||
#[cfg(not(feature = "llmp_broker_timeouts"))]
|
|
||||||
pub fn broker_loop(&mut self) -> Result<(), Error> {
|
|
||||||
let monitor = &mut self.monitor;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressor = &self.compressor;
|
|
||||||
self.llmp.loop_forever(
|
|
||||||
&mut |client_id, tag, _flags, msg| {
|
|
||||||
if tag == LLMP_TAG_EVENT_TO_BOTH {
|
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
|
||||||
let event_bytes = msg;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressed;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let event_bytes = if _flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
|
||||||
compressed = compressor.decompress(msg)?;
|
|
||||||
&compressed
|
|
||||||
} else {
|
|
||||||
msg
|
|
||||||
};
|
|
||||||
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
|
||||||
match Self::handle_in_broker(monitor, client_id, &event)? {
|
|
||||||
BrokerEventResult::Forward => Ok(llmp::LlmpMsgHookResult::ForwardToClients),
|
|
||||||
BrokerEventResult::Handled => Ok(llmp::LlmpMsgHookResult::Handled),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Some(Duration::from_millis(5)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(all(feature = "std", feature = "llmp_debug"))]
|
|
||||||
println!("The last client quit. Exiting.");
|
|
||||||
|
|
||||||
Err(Error::shutting_down())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Run in the broker until all clients exit
|
|
||||||
#[cfg(feature = "llmp_broker_timeouts")]
|
|
||||||
pub fn broker_loop(&mut self) -> Result<(), Error> {
|
|
||||||
let monitor = &mut self.monitor;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressor = &self.compressor;
|
|
||||||
self.llmp.loop_with_timeouts(
|
|
||||||
&mut |msg_or_timeout| {
|
|
||||||
if let Some((client_id, tag, _flags, msg)) = msg_or_timeout {
|
|
||||||
if tag == LLMP_TAG_EVENT_TO_BOTH {
|
|
||||||
#[cfg(not(feature = "llmp_compression"))]
|
|
||||||
let event_bytes = msg;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let compressed;
|
|
||||||
#[cfg(feature = "llmp_compression")]
|
|
||||||
let event_bytes = if _flags & LLMP_FLAG_COMPRESSED == LLMP_FLAG_COMPRESSED {
|
|
||||||
compressed = compressor.decompress(msg)?;
|
|
||||||
&compressed
|
|
||||||
} else {
|
|
||||||
msg
|
|
||||||
};
|
|
||||||
let event: Event<I> = postcard::from_bytes(event_bytes)?;
|
|
||||||
match Self::handle_in_broker(monitor, client_id, &event)? {
|
|
||||||
BrokerEventResult::Forward => {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
BrokerEventResult::Handled => Ok(llmp::LlmpMsgHookResult::Handled),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
monitor.display("Broker Heartbeat", ClientId(0));
|
|
||||||
Ok(llmp::LlmpMsgHookResult::Handled)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Duration::from_secs(30),
|
|
||||||
Some(Duration::from_millis(5)),
|
|
||||||
);
|
|
||||||
|
|
||||||
#[cfg(feature = "llmp_debug")]
|
|
||||||
println!("The last client quit. Exiting.");
|
|
||||||
|
|
||||||
Err(Error::shutting_down())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Handle arriving events in the broker
|
/// Handle arriving events in the broker
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
#[allow(clippy::unnecessary_wraps)]
|
||||||
fn handle_in_broker(
|
fn handle_in_broker(
|
@ -24,14 +24,14 @@ use crate::{
|
|||||||
Error, HasMetadata,
|
Error, HasMetadata,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The llmp broker
|
|
||||||
pub mod broker;
|
|
||||||
pub use broker::*;
|
|
||||||
|
|
||||||
/// The llmp event manager
|
/// The llmp event manager
|
||||||
pub mod mgr;
|
pub mod mgr;
|
||||||
pub use mgr::*;
|
pub use mgr::*;
|
||||||
|
|
||||||
|
/// The llmp hooks
|
||||||
|
pub mod hooks;
|
||||||
|
pub use hooks::*;
|
||||||
|
|
||||||
/// The llmp restarting manager
|
/// The llmp restarting manager
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
pub mod restarting;
|
pub mod restarting;
|
||||||
|
@ -8,7 +8,7 @@ use alloc::vec::Vec;
|
|||||||
use core::ptr::addr_of_mut;
|
use core::ptr::addr_of_mut;
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use core::sync::atomic::{compiler_fence, Ordering};
|
use core::sync::atomic::{compiler_fence, Ordering};
|
||||||
#[cfg(all(feature = "std", feature = "adaptive_serialization"))]
|
#[cfg(feature = "std")]
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
use core::{marker::PhantomData, num::NonZeroUsize};
|
use core::{marker::PhantomData, num::NonZeroUsize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -24,11 +24,11 @@ use libafl_bolts::os::unix_signals::setup_signal_handler;
|
|||||||
use libafl_bolts::os::{fork, ForkResult};
|
use libafl_bolts::os::{fork, ForkResult};
|
||||||
#[cfg(feature = "adaptive_serialization")]
|
#[cfg(feature = "adaptive_serialization")]
|
||||||
use libafl_bolts::tuples::{Handle, Handled};
|
use libafl_bolts::tuples::{Handle, Handled};
|
||||||
|
use libafl_bolts::{llmp::LlmpBroker, shmem::ShMemProvider, tuples::tuple_list};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::LlmpConnection, os::CTRL_C_EXIT, shmem::StdShMemProvider, staterestore::StateRestorer,
|
llmp::LlmpConnection, os::CTRL_C_EXIT, shmem::StdShMemProvider, staterestore::StateRestorer,
|
||||||
};
|
};
|
||||||
use libafl_bolts::{shmem::ShMemProvider, tuples::tuple_list};
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use typed_builder::TypedBuilder;
|
use typed_builder::TypedBuilder;
|
||||||
@ -44,8 +44,8 @@ use crate::observers::TimeObserver;
|
|||||||
use crate::{
|
use crate::{
|
||||||
events::{
|
events::{
|
||||||
hooks::EventManagerHooksTuple, Event, EventConfig, EventFirer, EventManager,
|
hooks::EventManagerHooksTuple, Event, EventConfig, EventFirer, EventManager,
|
||||||
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, LlmpEventBroker,
|
EventManagerId, EventProcessor, EventRestarter, HasEventManagerId, LlmpEventManager,
|
||||||
LlmpEventManager, LlmpShouldSaveState, ProgressReporter,
|
LlmpShouldSaveState, ProgressReporter, StdLlmpEventHook,
|
||||||
},
|
},
|
||||||
executors::{Executor, HasObservers},
|
executors::{Executor, HasObservers},
|
||||||
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
|
fuzzer::{Evaluator, EvaluatorObservers, ExecutionProcessor},
|
||||||
@ -323,7 +323,7 @@ pub enum ManagerKind {
|
|||||||
/// The CPU core ID of this client
|
/// The CPU core ID of this client
|
||||||
cpu_core: Option<CoreId>,
|
cpu_core: Option<CoreId>,
|
||||||
},
|
},
|
||||||
/// A [`crate::events::llmp::broker::LlmpEventBroker`], forwarding the packets of local clients.
|
/// An [`LlmpBroker`], forwarding the packets of local clients.
|
||||||
Broker,
|
Broker,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,8 +344,8 @@ pub fn setup_restarting_mgr_std<MT, S>(
|
|||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
{
|
{
|
||||||
RestartingMgr::builder()
|
RestartingMgr::builder()
|
||||||
.shmem_provider(StdShMemProvider::new()?)
|
.shmem_provider(StdShMemProvider::new()?)
|
||||||
@ -375,8 +375,8 @@ pub fn setup_restarting_mgr_std<MT, S>(
|
|||||||
Error,
|
Error,
|
||||||
>
|
>
|
||||||
where
|
where
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
{
|
{
|
||||||
RestartingMgr::builder()
|
RestartingMgr::builder()
|
||||||
.shmem_provider(StdShMemProvider::new()?)
|
.shmem_provider(StdShMemProvider::new()?)
|
||||||
@ -448,8 +448,8 @@ impl<EMH, MT, S, SP> RestartingMgr<EMH, MT, S, SP>
|
|||||||
where
|
where
|
||||||
EMH: EventManagerHooksTuple<S> + Copy + Clone,
|
EMH: EventManagerHooksTuple<S> + Copy + Clone,
|
||||||
SP: ShMemProvider,
|
SP: ShMemProvider,
|
||||||
S: State + HasExecutions,
|
S: State + HasExecutions + 'static,
|
||||||
MT: Monitor + Clone,
|
MT: Monitor + Clone + 'static,
|
||||||
{
|
{
|
||||||
/// Launch the broker and the clients and fuzz
|
/// Launch the broker and the clients and fuzz
|
||||||
pub fn launch(&mut self) -> Result<(Option<S>, LlmpRestartingEventManager<EMH, S, SP>), Error> {
|
pub fn launch(&mut self) -> Result<(Option<S>, LlmpRestartingEventManager<EMH, S, SP>), Error> {
|
||||||
@ -457,18 +457,24 @@ where
|
|||||||
let (staterestorer, new_shmem_provider, core_id) = if std::env::var(_ENV_FUZZER_SENDER)
|
let (staterestorer, new_shmem_provider, core_id) = if std::env::var(_ENV_FUZZER_SENDER)
|
||||||
.is_err()
|
.is_err()
|
||||||
{
|
{
|
||||||
let broker_things = |mut broker: LlmpEventBroker<S::Input, MT, SP>,
|
let broker_things = |mut broker: LlmpBroker<_, SP>, remote_broker_addr| {
|
||||||
remote_broker_addr| {
|
|
||||||
if let Some(remote_broker_addr) = remote_broker_addr {
|
if let Some(remote_broker_addr) = remote_broker_addr {
|
||||||
log::info!("B2b: Connecting to {:?}", &remote_broker_addr);
|
log::info!("B2b: Connecting to {:?}", &remote_broker_addr);
|
||||||
broker.connect_b2b(remote_broker_addr)?;
|
broker.state_mut().connect_b2b(remote_broker_addr)?;
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(exit_cleanly_after) = self.exit_cleanly_after {
|
if let Some(exit_cleanly_after) = self.exit_cleanly_after {
|
||||||
broker.set_exit_cleanly_after(exit_cleanly_after);
|
broker
|
||||||
|
.state_mut()
|
||||||
|
.set_exit_cleanly_after(exit_cleanly_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
broker.broker_loop()
|
broker.loop_with_timeouts(Duration::from_secs(30), Some(Duration::from_millis(5)));
|
||||||
|
|
||||||
|
#[cfg(feature = "llmp_debug")]
|
||||||
|
log::info!("The last client quit. Exiting.");
|
||||||
|
|
||||||
|
Err(Error::shutting_down())
|
||||||
};
|
};
|
||||||
// We get here if we are on Unix, or we are a broker on Windows (or without forks).
|
// We get here if we are on Unix, or we are a broker on Windows (or without forks).
|
||||||
let (mgr, core_id) = match self.kind {
|
let (mgr, core_id) = match self.kind {
|
||||||
@ -477,8 +483,7 @@ where
|
|||||||
LlmpConnection::on_port(self.shmem_provider.clone(), self.broker_port)?;
|
LlmpConnection::on_port(self.shmem_provider.clone(), self.broker_port)?;
|
||||||
match connection {
|
match connection {
|
||||||
LlmpConnection::IsBroker { broker } => {
|
LlmpConnection::IsBroker { broker } => {
|
||||||
let event_broker = LlmpEventBroker::<S::Input, MT, SP>::new(
|
let llmp_hook = StdLlmpEventHook::<S::Input, MT, SP>::new(
|
||||||
broker,
|
|
||||||
self.monitor.take().unwrap(),
|
self.monitor.take().unwrap(),
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
@ -487,7 +492,10 @@ where
|
|||||||
"Doing broker things. Run this tool again to start fuzzing in a client."
|
"Doing broker things. Run this tool again to start fuzzing in a client."
|
||||||
);
|
);
|
||||||
|
|
||||||
broker_things(event_broker, self.remote_broker_addr)?;
|
broker_things(
|
||||||
|
broker.add_hooks(tuple_list!(llmp_hook)),
|
||||||
|
self.remote_broker_addr,
|
||||||
|
)?;
|
||||||
|
|
||||||
return Err(Error::shutting_down());
|
return Err(Error::shutting_down());
|
||||||
}
|
}
|
||||||
@ -511,13 +519,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
ManagerKind::Broker => {
|
ManagerKind::Broker => {
|
||||||
let event_broker = LlmpEventBroker::<S::Input, MT, SP>::on_port(
|
let llmp_hook = StdLlmpEventHook::new(self.monitor.take().unwrap())?;
|
||||||
|
|
||||||
|
let broker = LlmpBroker::create_attach_to_tcp(
|
||||||
self.shmem_provider.clone(),
|
self.shmem_provider.clone(),
|
||||||
self.monitor.take().unwrap(),
|
tuple_list!(llmp_hook),
|
||||||
self.broker_port,
|
self.broker_port,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
broker_things(event_broker, self.remote_broker_addr)?;
|
broker_things(broker, self.remote_broker_addr)?;
|
||||||
unreachable!("The broker may never return normally, only on errors or when shutting down.");
|
unreachable!("The broker may never return normally, only on errors or when shutting down.");
|
||||||
}
|
}
|
||||||
ManagerKind::Client { cpu_core } => {
|
ManagerKind::Client { cpu_core } => {
|
||||||
|
@ -772,7 +772,7 @@ where
|
|||||||
Ok(()) => {
|
Ok(()) => {
|
||||||
self.tcp.set_nonblocking(false).expect("set to blocking");
|
self.tcp.set_nonblocking(false).expect("set to blocking");
|
||||||
let len = u32::from_le_bytes(len_buf);
|
let len = u32::from_le_bytes(len_buf);
|
||||||
let mut buf = vec![0_u8; len as usize + 4_usize];
|
let mut buf = vec![0_u8; 4_usize + len as usize];
|
||||||
self.tcp.read_exact(&mut buf)?;
|
self.tcp.read_exact(&mut buf)?;
|
||||||
|
|
||||||
let mut client_id_buf = [0_u8; 4];
|
let mut client_id_buf = [0_u8; 4];
|
||||||
|
@ -5,15 +5,18 @@ extern crate alloc;
|
|||||||
|
|
||||||
#[cfg(not(target_os = "haiku"))]
|
#[cfg(not(target_os = "haiku"))]
|
||||||
use core::time::Duration;
|
use core::time::Duration;
|
||||||
|
use std::marker::PhantomData;
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
use std::{num::NonZeroUsize, thread, time};
|
use std::{num::NonZeroUsize, thread, time};
|
||||||
|
|
||||||
|
use libafl_bolts::{bolts_prelude::LlmpMsgHookResult, llmp::LlmpBrokerState};
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
use libafl_bolts::{
|
use libafl_bolts::{
|
||||||
llmp::{self, Tag},
|
llmp::{self, Flags, LlmpHook, Tag},
|
||||||
shmem::{ShMemProvider, StdShMemProvider},
|
shmem::{ShMemProvider, StdShMemProvider},
|
||||||
ClientId, Error, SimpleStderrLogger,
|
ClientId, Error, SimpleStderrLogger,
|
||||||
};
|
};
|
||||||
|
use tuple_list::tuple_list;
|
||||||
|
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
const _TAG_SIMPLE_U32_V1: Tag = Tag(0x5130_0321);
|
const _TAG_SIMPLE_U32_V1: Tag = Tag(0x5130_0321);
|
||||||
@ -90,40 +93,69 @@ fn large_msg_loop(port: u16) -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(clippy::unnecessary_wraps)]
|
pub struct LlmpExampleHook<SP> {
|
||||||
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
phantom: PhantomData<SP>,
|
||||||
fn broker_message_hook(
|
}
|
||||||
msg_or_timeout: Option<(ClientId, llmp::Tag, llmp::Flags, &[u8])>,
|
|
||||||
) -> Result<llmp::LlmpMsgHookResult, Error> {
|
|
||||||
let Some((client_id, tag, _flags, message)) = msg_or_timeout else {
|
|
||||||
println!(
|
|
||||||
"No client did anything for {} seconds..",
|
|
||||||
BROKER_TIMEOUT.as_secs()
|
|
||||||
);
|
|
||||||
return Ok(llmp::LlmpMsgHookResult::Handled);
|
|
||||||
};
|
|
||||||
|
|
||||||
match tag {
|
impl<SP> LlmpExampleHook<SP> {
|
||||||
|
#[must_use]
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
phantom: PhantomData,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<SP> Default for LlmpExampleHook<SP> {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(feature = "std", not(target_os = "haiku")))]
|
||||||
|
impl<SP> LlmpHook<SP> for LlmpExampleHook<SP>
|
||||||
|
where
|
||||||
|
SP: ShMemProvider + 'static,
|
||||||
|
{
|
||||||
|
fn on_new_message(
|
||||||
|
&mut self,
|
||||||
|
_llmp_broker_state: &mut LlmpBrokerState<SP>,
|
||||||
|
client_id: ClientId,
|
||||||
|
msg_tag: &mut Tag,
|
||||||
|
_msg_flags: &mut Flags,
|
||||||
|
msg: &mut [u8],
|
||||||
|
) -> Result<LlmpMsgHookResult, Error> {
|
||||||
|
match *msg_tag {
|
||||||
_TAG_SIMPLE_U32_V1 => {
|
_TAG_SIMPLE_U32_V1 => {
|
||||||
println!(
|
println!(
|
||||||
"Client {:?} sent message: {:?}",
|
"Client {:?} sent message: {:?}",
|
||||||
client_id,
|
client_id,
|
||||||
u32::from_le_bytes(message.try_into()?)
|
u32::from_le_bytes(msg.try_into()?)
|
||||||
);
|
);
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
Ok(LlmpMsgHookResult::ForwardToClients)
|
||||||
}
|
}
|
||||||
_TAG_MATH_RESULT_V1 => {
|
_TAG_MATH_RESULT_V1 => {
|
||||||
println!(
|
println!(
|
||||||
"Adder Client has this current result: {:?}",
|
"Adder Client has this current result: {:?}",
|
||||||
u32::from_le_bytes(message.try_into()?)
|
u32::from_le_bytes(msg.try_into()?)
|
||||||
);
|
);
|
||||||
Ok(llmp::LlmpMsgHookResult::Handled)
|
Ok(LlmpMsgHookResult::Handled)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("Unknown message id received: {tag:?}");
|
println!("Unknown message id received: {msg_tag:?}");
|
||||||
Ok(llmp::LlmpMsgHookResult::ForwardToClients)
|
Ok(LlmpMsgHookResult::ForwardToClients)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn on_timeout(&mut self) -> Result<(), Error> {
|
||||||
|
println!(
|
||||||
|
"No client did anything for {} seconds..",
|
||||||
|
BROKER_TIMEOUT.as_secs()
|
||||||
|
);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "haiku")]
|
#[cfg(target_os = "haiku")]
|
||||||
@ -154,26 +186,26 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|||||||
|
|
||||||
match mode.as_str() {
|
match mode.as_str() {
|
||||||
"broker" => {
|
"broker" => {
|
||||||
let mut broker = llmp::LlmpBroker::new(StdShMemProvider::new()?)?;
|
let mut broker = llmp::LlmpBroker::new(
|
||||||
broker.launch_tcp_listener_on(port)?;
|
StdShMemProvider::new()?,
|
||||||
|
tuple_list!(LlmpExampleHook::new()),
|
||||||
|
)?;
|
||||||
|
broker.state_mut().launch_tcp_listener_on(port)?;
|
||||||
// Exit when we got at least _n_ nodes, and all of them quit.
|
// Exit when we got at least _n_ nodes, and all of them quit.
|
||||||
broker.set_exit_cleanly_after(NonZeroUsize::new(1_usize).unwrap());
|
broker
|
||||||
broker.loop_with_timeouts(
|
.state_mut()
|
||||||
&mut broker_message_hook,
|
.set_exit_cleanly_after(NonZeroUsize::new(1_usize).unwrap());
|
||||||
BROKER_TIMEOUT,
|
broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS));
|
||||||
Some(SLEEP_BETWEEN_FORWARDS),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
"b2b" => {
|
"b2b" => {
|
||||||
let mut broker = llmp::LlmpBroker::new(StdShMemProvider::new()?)?;
|
let mut broker = llmp::LlmpBroker::new(
|
||||||
broker.launch_tcp_listener_on(b2b_port)?;
|
StdShMemProvider::new()?,
|
||||||
|
tuple_list!(LlmpExampleHook::new()),
|
||||||
|
)?;
|
||||||
|
broker.state_mut().launch_tcp_listener_on(b2b_port)?;
|
||||||
// connect back to the main broker.
|
// connect back to the main broker.
|
||||||
broker.connect_b2b(("127.0.0.1", port))?;
|
broker.state_mut().connect_b2b(("127.0.0.1", port))?;
|
||||||
broker.loop_with_timeouts(
|
broker.loop_with_timeouts(BROKER_TIMEOUT, Some(SLEEP_BETWEEN_FORWARDS));
|
||||||
&mut broker_message_hook,
|
|
||||||
BROKER_TIMEOUT,
|
|
||||||
Some(SLEEP_BETWEEN_FORWARDS),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
"ctr" => {
|
"ctr" => {
|
||||||
let mut client =
|
let mut client =
|
||||||
|
@ -235,7 +235,7 @@ fn set_for_current_helper(core_id: CoreId) -> Result<(), Error> {
|
|||||||
))]
|
))]
|
||||||
mod linux {
|
mod linux {
|
||||||
use alloc::{string::ToString, vec::Vec};
|
use alloc::{string::ToString, vec::Vec};
|
||||||
use std::mem;
|
use core::mem::{size_of, zeroed};
|
||||||
|
|
||||||
#[cfg(not(target_os = "freebsd"))]
|
#[cfg(not(target_os = "freebsd"))]
|
||||||
use libc::cpu_set_t;
|
use libc::cpu_set_t;
|
||||||
@ -276,7 +276,7 @@ mod linux {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
sched_setaffinity(
|
sched_setaffinity(
|
||||||
0, // Defaults to current thread
|
0, // Defaults to current thread
|
||||||
mem::size_of::<cpu_set_t>(),
|
size_of::<cpu_set_t>(),
|
||||||
&set,
|
&set,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -295,7 +295,7 @@ mod linux {
|
|||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
sched_getaffinity(
|
sched_getaffinity(
|
||||||
0, // Defaults to current thread
|
0, // Defaults to current thread
|
||||||
mem::size_of::<cpu_set_t>(),
|
size_of::<cpu_set_t>(),
|
||||||
&mut set,
|
&mut set,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
@ -310,7 +310,7 @@ mod linux {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn new_cpu_set() -> cpu_set_t {
|
fn new_cpu_set() -> cpu_set_t {
|
||||||
unsafe { mem::zeroed::<cpu_set_t>() }
|
unsafe { zeroed::<cpu_set_t>() }
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,18 +1,20 @@
|
|||||||
//! Unix `pipe` wrapper for `LibAFL`
|
//! Unix `pipe` wrapper for `LibAFL`
|
||||||
use alloc::rc::Rc;
|
|
||||||
use core::{borrow::Borrow, cell::RefCell};
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use std::{
|
use std::{
|
||||||
|
borrow::Borrow,
|
||||||
|
cell::RefCell,
|
||||||
io::{self, ErrorKind, Read, Write},
|
io::{self, ErrorKind, Read, Write},
|
||||||
os::{
|
os::{
|
||||||
fd::{AsFd, AsRawFd, OwnedFd},
|
fd::{AsFd, AsRawFd, OwnedFd},
|
||||||
unix::io::RawFd,
|
unix::io::RawFd,
|
||||||
},
|
},
|
||||||
|
rc::Rc,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
use nix::unistd::{pipe, read, write};
|
use nix::unistd::{pipe, read, write};
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
|
||||||
/// A unix pipe wrapper for `LibAFL`
|
/// A unix pipe wrapper for `LibAFL`
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
//! Signal handling for unix
|
//! Signal handling for unix
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
#[cfg(all(target_vendor = "apple", target_arch = "aarch64"))]
|
||||||
|
use core::mem::size_of;
|
||||||
#[cfg(feature = "alloc")]
|
#[cfg(feature = "alloc")]
|
||||||
use core::{
|
use core::{
|
||||||
cell::UnsafeCell,
|
cell::UnsafeCell,
|
||||||
@ -160,7 +162,7 @@ pub struct arm_thread_state64 {
|
|||||||
//#[repr(align(16))]
|
//#[repr(align(16))]
|
||||||
pub struct arm_neon_state64 {
|
pub struct arm_neon_state64 {
|
||||||
/// opaque
|
/// opaque
|
||||||
pub opaque: [u8; (32 * 16) + (2 * mem::size_of::<u32>())],
|
pub opaque: [u8; (32 * 16) + (2 * size_of::<u32>())],
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ```c
|
/// ```c
|
||||||
|
@ -7,7 +7,7 @@ use alloc::{rc::Rc, string::ToString, vec::Vec};
|
|||||||
use core::{cell::RefCell, fmt, fmt::Display, mem::ManuallyDrop};
|
use core::{cell::RefCell, fmt, fmt::Display, mem::ManuallyDrop};
|
||||||
use core::{
|
use core::{
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
mem,
|
mem::size_of,
|
||||||
ops::{Deref, DerefMut},
|
ops::{Deref, DerefMut},
|
||||||
};
|
};
|
||||||
#[cfg(feature = "std")]
|
#[cfg(feature = "std")]
|
||||||
@ -202,7 +202,7 @@ pub trait ShMem: Sized + Debug + Clone + DerefMut<Target = [u8]> {
|
|||||||
/// Convert to a ptr of a given type, checking the size.
|
/// Convert to a ptr of a given type, checking the size.
|
||||||
/// If the map is too small, returns `None`
|
/// If the map is too small, returns `None`
|
||||||
fn as_ptr_of<T: Sized>(&self) -> Option<*const T> {
|
fn as_ptr_of<T: Sized>(&self) -> Option<*const T> {
|
||||||
if self.len() >= mem::size_of::<T>() {
|
if self.len() >= size_of::<T>() {
|
||||||
Some(self.as_ptr() as *const T)
|
Some(self.as_ptr() as *const T)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -212,7 +212,7 @@ pub trait ShMem: Sized + Debug + Clone + DerefMut<Target = [u8]> {
|
|||||||
/// Convert to a mut ptr of a given type, checking the size.
|
/// Convert to a mut ptr of a given type, checking the size.
|
||||||
/// If the map is too small, returns `None`
|
/// If the map is too small, returns `None`
|
||||||
fn as_mut_ptr_of<T: Sized>(&mut self) -> Option<*mut T> {
|
fn as_mut_ptr_of<T: Sized>(&mut self) -> Option<*mut T> {
|
||||||
if self.len() >= mem::size_of::<T>() {
|
if self.len() >= size_of::<T>() {
|
||||||
Some(self.as_mut_ptr() as *mut T)
|
Some(self.as_mut_ptr() as *mut T)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
@ -267,7 +267,7 @@ pub trait ShMemProvider: Clone + Default + Debug {
|
|||||||
|
|
||||||
/// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value.
|
/// Create a new shared memory mapping to hold an object of the given type, and initializes it with the given value.
|
||||||
fn uninit_on_shmem<T: Sized + 'static>(&mut self) -> Result<Self::ShMem, Error> {
|
fn uninit_on_shmem<T: Sized + 'static>(&mut self) -> Result<Self::ShMem, Error> {
|
||||||
self.new_shmem(mem::size_of::<T>())
|
self.new_shmem(size_of::<T>())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a mapping given a description
|
/// Get a mapping given a description
|
||||||
|
@ -139,7 +139,7 @@ fn fuzz_many_forking<M>(
|
|||||||
monitor: M,
|
monitor: M,
|
||||||
) -> Result<(), Error>
|
) -> Result<(), Error>
|
||||||
where
|
where
|
||||||
M: Monitor + Clone + Debug,
|
M: Monitor + Clone + Debug + 'static,
|
||||||
{
|
{
|
||||||
destroy_output_fds(options);
|
destroy_output_fds(options);
|
||||||
let broker_port = std::env::var(PORT_PROVIDER_VAR)
|
let broker_port = std::env::var(PORT_PROVIDER_VAR)
|
||||||
|
@ -8,7 +8,8 @@ use alloc::{alloc::alloc_zeroed, boxed::Box, vec::Vec};
|
|||||||
use core::{
|
use core::{
|
||||||
alloc::Layout,
|
alloc::Layout,
|
||||||
fmt::{self, Debug, Formatter},
|
fmt::{self, Debug, Formatter},
|
||||||
mem, ptr, slice,
|
mem::{size_of, zeroed},
|
||||||
|
ptr, slice,
|
||||||
};
|
};
|
||||||
|
|
||||||
use libafl::{
|
use libafl::{
|
||||||
@ -30,11 +31,11 @@ pub const CMPLOG_RTN_LEN: usize = 32;
|
|||||||
|
|
||||||
/// The hight of a cmplog routine map
|
/// The hight of a cmplog routine map
|
||||||
pub const CMPLOG_MAP_RTN_H: usize =
|
pub const CMPLOG_MAP_RTN_H: usize =
|
||||||
(CMPLOG_MAP_H * mem::size_of::<CmpLogInstruction>()) / mem::size_of::<CmpLogRoutine>();
|
(CMPLOG_MAP_H * size_of::<CmpLogInstruction>()) / size_of::<CmpLogRoutine>();
|
||||||
|
|
||||||
/// The height of extended rountine map
|
/// The height of extended rountine map
|
||||||
pub const CMPLOG_MAP_RTN_EXTENDED_H: usize =
|
pub const CMPLOG_MAP_RTN_EXTENDED_H: usize =
|
||||||
CMPLOG_MAP_H * mem::size_of::<AFLppCmpLogOperands>() / mem::size_of::<AFLppCmpLogFnOperands>();
|
CMPLOG_MAP_H * size_of::<AFLppCmpLogOperands>() / size_of::<AFLppCmpLogFnOperands>();
|
||||||
|
|
||||||
/// `CmpLog` instruction kind
|
/// `CmpLog` instruction kind
|
||||||
pub const CMPLOG_KIND_INS: u8 = 0;
|
pub const CMPLOG_KIND_INS: u8 = 0;
|
||||||
@ -318,7 +319,7 @@ pub struct CmpLogMap {
|
|||||||
|
|
||||||
impl Default for CmpLogMap {
|
impl Default for CmpLogMap {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
unsafe { mem::zeroed() }
|
unsafe { zeroed() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -474,9 +475,8 @@ impl Serialize for AFLppCmpLogMap {
|
|||||||
where
|
where
|
||||||
S: Serializer,
|
S: Serializer,
|
||||||
{
|
{
|
||||||
let slice = unsafe {
|
let slice =
|
||||||
slice::from_raw_parts(ptr::from_ref(self) as *const u8, mem::size_of::<Self>())
|
unsafe { slice::from_raw_parts(ptr::from_ref(self) as *const u8, size_of::<Self>()) };
|
||||||
};
|
|
||||||
serializer.serialize_bytes(slice)
|
serializer.serialize_bytes(slice)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,7 @@ mod observers {
|
|||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
iter::Flatten,
|
iter::Flatten,
|
||||||
|
mem::size_of,
|
||||||
ptr::{addr_of, addr_of_mut},
|
ptr::{addr_of, addr_of_mut},
|
||||||
slice::{from_raw_parts, Iter, IterMut},
|
slice::{from_raw_parts, Iter, IterMut},
|
||||||
};
|
};
|
||||||
@ -161,7 +162,7 @@ mod observers {
|
|||||||
for map in unsafe { &*addr_of!(COUNTERS_MAPS) } {
|
for map in unsafe { &*addr_of!(COUNTERS_MAPS) } {
|
||||||
let slice = map.as_slice();
|
let slice = map.as_slice();
|
||||||
let ptr = slice.as_ptr();
|
let ptr = slice.as_ptr();
|
||||||
let map_size = slice.len() / core::mem::size_of::<u8>();
|
let map_size = slice.len() / size_of::<u8>();
|
||||||
unsafe {
|
unsafe {
|
||||||
hasher.write(from_raw_parts(ptr, map_size));
|
hasher.write(from_raw_parts(ptr, map_size));
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#[rustversion::nightly]
|
#[rustversion::nightly]
|
||||||
#[cfg(feature = "sancov_ngram4")]
|
#[cfg(feature = "sancov_ngram4")]
|
||||||
use core::simd::num::SimdUint;
|
use core::simd::num::SimdUint;
|
||||||
use core::{mem, ptr, slice};
|
use core::{mem::align_of, ptr, slice};
|
||||||
|
|
||||||
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ctx"))]
|
#[cfg(any(feature = "sancov_ngram4", feature = "sancov_ctx"))]
|
||||||
use libafl::executors::{hooks::ExecutorHook, HasObservers};
|
use libafl::executors::{hooks::ExecutorHook, HasObservers};
|
||||||
@ -346,7 +346,7 @@ pub fn sanitizer_cov_pc_table() -> Option<&'static [PcTableEntry]> {
|
|||||||
"PC Table size is not evens - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
"PC Table size is not evens - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
(PCS_BEG as usize) % mem::align_of::<PcTableEntry>(),
|
(PCS_BEG as usize) % align_of::<PcTableEntry>(),
|
||||||
0,
|
0,
|
||||||
"Unaligned PC Table - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
"Unaligned PC Table - start: {PCS_BEG:x?} end: {PCS_END:x?}"
|
||||||
);
|
);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user