`override_syscall` performs integer-to-pointer conversion. This is
considered harmful on the newest Rust nightly which provides
`ptr::from_exposed_addr`, but there is no other way on Rust stable than
doing `as *const T`, which is what miri is unhappy about.
Signed-off-by: Michal Rostecki <vadorovsky@gmail.com>
Add `from_pinned` to allow loading BPF maps
from pinned points in the bpffs and
`from_fd` to allow loading BPF maps from
RawFds aquired via some other means eg
a unix socket.
These functions return an
aya::Map which has not been used previously
but will be the future abstraction once
all bpf maps are represented as an enum.
Signed-off-by: Andrew Stoycos <astoycos@redhat.com>
This commit allows for BTF maps in the .maps ELF section to be parsed.
It reads the necessary information from the BTF section of the ELF file.
While the btf_ids of Keys and Values types are stored, they are not (yet)
used.
When creating a BTF map, we pass the btf_key_type_id and
btf_value_type_id.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
This removes the ProgramFd trait with a struct that wraps a RawFd.
Program::fd() has been implemented as well as fd() for each Program
Type. This allows for a better API than requiring the use of the
ProgramFd trait.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
bpf_map_update_elem is used in lieu of bpf_map_push_elem to maintain support for kernel version < 4.20. The kernel expects a null pointer for the key for this use case. With this change, if you pass None as key to `bpf_map_update_elem`, it will pass null as key.
Since we support multiple maps in the same section, the section_index is
no longer a unique way to identify maps. This commit uses the symbol
index as the identifier, but falls back to section_index for rodata
and bss maps since we don't retrieve the symbol_index during parsing.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
This changes PerfBuffer::read_events() to call BytesMut::reserve()
internally, and deprecates PerfBufferError::MoreSpaceNeeded.
This makes for a more ergonomic API, and allows for a more idiomatic
usage of BytesMut. For example consider:
let mut buffers = vec![BytesMut::with_capacity(N), ...];
loop {
let events = oob_cpu_buf.read_events(&mut buffers).unwrap();
for buf in &mut buffers[..events.read] {
let sub: Bytes = buf.split_off(n).into();
process_sub_buf(sub);
}
...
}
This is a common way to process perf bufs, where a sub buffer is split
off from the original buffer and then processed. In the next iteration
of the loop when it's time to read again, two things can happen:
- if processing of the sub buffer is complete and `sub` has been
dropped, read_events() will call buf.reserve(sample_size) and hit a fast
path in BytesMut that will just restore the original capacity of the
buffer (assuming sample_size <= N).
- if processing of the sub buffer hasn't ended (eg the buffer has been
stored or is being processed in another thread),
buf.reserve(sample_size) will actually allocate the new memory required
to read the sample.
In other words, calling buf.reserve(sample_size) inside read_events()
simplifies doing zero-copy processing of buffers in many cases.
This commit marks .rodata maps as BPF_F_RDONLY_PROG when loaded to
prevent a BPF program mutating them.
Initial map data is populated by the loader using the new
`BpfLoader::set_global()` API. The loader will mark
is marked as frozen using bpf_map_freeze to prevent map data
being changed from userspace.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
Map iteration can yield stale keys and values by virtue of sharing a
data structure with BPF programs which can modify it. However, all
accesses remain perfectly safe and will not cause memory corruption or
data races.
Map and ProgramData objects had unnecessarily cloned strings for their
names, despite them being just as easily available to external users via
bpf.maps() and bpf.programs().
This commit adds 2 new methods to aya::sys
- bpf_pin_object
- bpf_get_object
Which allow the pinning and retrieval of programs/maps to bpffs.
It adds a `Program.pin` API, such that a loaded program can be pinned.
For map pinning, the user must ensure the `pinning u32` in the
`bpf_map_def` is set to 1, maps will be pinned using a new builder API.
BpfLoader::new().map_pin_path("/sys/fs/bpf/myapp").load_file("myapp.o")
This will pin all maps whose definition requests pinning to path + name.
Signed-off-by: Dave Tucker <dave@dtucker.co.uk>
Make MapKeys not use IterableMap. Leave only ProgramArray::get,
ProgramArray::set and ProgramArray::unset exposed as the other syscalls
don't work consistently for program arrays.
Change get() from -> Result<Option<V>, MapError> to -> Result<V,
MapError> where MapError::KeyNotFound is returned instead of Ok(None) to
signify that the key is not present.
Require callers to call try_into() explicitly. It's more characters, but
it's easier to understand/document.
Also introduce MapError::NotFound instead of returning Result<Option<_>>.
Change PerfMap API so that individual buffers can be read from multiple
threads.
Change the way maps are stored in the `Bpf` struct from RefCell to a
custom RwLock.