The dwfl_linux_proc_find_elf callback does this as a skeletal example.
It uses this function (see libdwfl/elf-from-memory.c):
/* Reconstruct an ELF file by reading the segments out of remote memory
based on the ELF file header at EHDR_VMA and the ELF program headers it
points to. If not null, *LOADBASEP is filled in with the difference
between the addresses from which the segments were read, and the
addresses the file headers put them at.
The function READ_MEMORY is called to copy at least MINREAD and at most
MAXREAD bytes from the remote memory at target address ADDRESS into the
local buffer at DATA; it should return -1 for errors (with code in
`errno'), 0 if it failed to read at least MINREAD bytes due to EOF, or
the number of bytes read if >= MINREAD. ARG is passed through. */
Elf *
elf_from_remote_memory (GElf_Addr ehdr_vma,
GElf_Addr *loadbasep,
ssize_t (*read_memory) (void *arg, void *data,
GElf_Addr address,
size_t minread,
size_t maxread),
void *arg)
This is an internal function not exported in the DSO or declared anywhere.
I wrote it as the necessary and separable component (and analogous to the
BFD function bfd_elf_bfd_from_remote_memory I added for the gdb vDSO
support). I tested it via dwfl_linux_proc_find_elf (-p option to
eu-addr2line et al). (Back then, /proc/PID/mem had not been made so
"secure", so it even worked in eu-foo without ptrace.) I figured the
details of interface to that code and how it integrates with everything
would be ironed out when a real user came along. Now here we are.
The signature of the read_memory callback is arbitrary.
It just seemed like the roughly appropriate general thing.
It's easy to change.
This function doesn't really fit with the libelf interfaces. It could be
exposed by libdwfl in some fashion I suppose. I hadn't really figured out
what seemed right, which is why it's as it is. I could just change its
name and signature slightly, and export it from libdwfl.