https://linux.die.net/man/3/dlsym
void *dlsym(void *handle, const char *symbol);
The function dlsym() takes a “handle” of a dynamic library returned by dlopen() and the null-terminated symbol name, returning the address where that symbol is loaded into memory.
http://man7.org/linux/man-pages/man3/pthread_create.3.html
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
The pthread_create() function starts a new thread in the calling
process. The new thread starts execution by invoking
start_routine(); arg is passed as the sole argument of
start_routine().
https://linux.die.net/man/2/sigaction
int sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
The sigaction() system call is used to change the action taken by a process on receipt of a specific signal. (See signal(7) for an overview of signals.)
signum specifies the signal and can be any valid signal except SIGKILL and SIGSTOP.
If act is non-NULL, the new action for signal signum is installed from act. If oldact is non-NULL, the previous action is saved in oldact.
http://man7.org/linux/man-pages/man2/sigaltstack.2.html
int sigaltstack(const stack_t *ss, stack_t *old_ss);
sigaltstack() allows a process to define a new alternate signal stack
and/or retrieve the state of an existing alternate signal stack. An
alternate signal stack is used during the execution of a signal
handler if the establishment of that handler (see sigaction(2))
requested it.
The normal sequence of events for using an alternate signal stack is
the following:
1. Allocate an area of memory to be used for the alternate signal
stack.
2. Use sigaltstack() to inform the system of the existence and
location of the alternate signal stack.
3. When establishing a signal handler using sigaction(2), inform the
system that the signal handler should be executed on the alternate
signal stack by specifying the SA_ONSTACK flag.
The ss argument is used to specify a new alternate signal stack,
while the old_ss argument is used to retrieve information about the
currently established signal stack. If we are interested in
performing just one of these tasks, then the other argument can be
specified as NULL.
http://man7.org/linux/man-pages/man3/memcpy.3.html
void *memcpy(void *dest, const void *src, size_t n);
The memcpy() function copies n bytes from memory area src to memory
area dest. The memory areas must not overlap. Use memmove(3) if the
memory areas do overlap.
The memcpy() function returns a pointer to dest.
http://man7.org/linux/man-pages/man2/prctl.2.html
int prctl(int option, unsigned long arg2, unsigned long arg3,
unsigned long arg4, unsigned long arg5);
prctl() is called with a first argument describing what to do (with
values defined in <linux/prctl.h>), and further arguments with a
significance depending on the first one. The first argument can be:
PR_SET_PTRACER (since Linux 3.4)......
http://man7.org/linux/man-pages/man2/fork.2.html
pid_t fork(void);
fork() creates a new process by duplicating the calling process. The
new process is referred to as the child process. The calling process
is referred to as the parent process.
The child process and the parent process run in separate memory
spaces. At the time of fork() both memory spaces have the same
content. Memory writes, file mappings (mmap(2)), and unmappings
(munmap(2)) performed by one of the processes do not affect the
other.
RETURN VALUE top
On success, the PID of the child process is returned in the parent,
and 0 is returned in the child. On failure, -1 is returned in the
parent, no child process is created, and errno is set appropriately.
https://linux.die.net/man/3/waitpid
wait, waitpid - wait for a child process to stop or terminate
pid_t waitpid(pid_t pid, int *stat_loc, int options);
https://linux.die.net/man/3/execl
execl, execlp, execle, execv, execvp, execvpe - execute a file
int execl(const char *path, const char *arg, ...);
http://man7.org/linux/man-pages/man2/alarm.2.html
unsigned int alarm(unsigned int seconds);
alarm() arranges for a SIGALRM signal to be delivered to the calling
process in seconds seconds.
http://man7.org/linux/man-pages/man2/read.2.html
ssize_t read(int fd, void *buf, size_t count);
read() attempts to read up to count bytes from file descriptor fd
into the buffer starting at buf.
http://man7.org/linux/man-pages/man2/write.2.html
write - write to a file descriptor
ssize_t write(int fd, const void *buf, size_t count);
write() writes up to count bytes from the buffer starting at buf to
the file referred to by the file descriptor fd.
http://man7.org/linux/man-pages/man2/open.2.html
int open(const char *pathname, int flags);
The open() system call opens the file specified by pathname. If the
specified file does not exist, it may optionally (if O_CREAT is
specified in flags) be created by open().
http://man7.org/linux/man-pages/man2/ptrace.2.html
NAME top
ptrace - process trace
SYNOPSIS top
#include <sys/ptrace.h>
long ptrace(enum __ptrace_request request, pid_t pid,
void *addr, void *data);
PTRACE_ATTACH
Attach to the process specified in pid, making it a tracee of
the calling process. The tracee is sent a SIGSTOP, but will
not necessarily have stopped by the completion of this call;
use waitpid(2) to wait for the tracee to stop. See the
"Attaching and detaching" subsection for additional informa‐
tion. (addr and data are ignored.)
Permission to perform a PTRACE_ATTACH is governed by a ptrace
access mode PTRACE_MODE_ATTACH_REALCREDS check; see below.
Attaching and detaching
A thread can be attached to the tracer using the call
ptrace(PTRACE_ATTACH, tid, 0, 0);
or
ptrace(PTRACE_SEIZE, tid, 0, PTRACE_O_flags);
PTRACE_ATTACH sends SIGSTOP to this thread. If the tracer wants this
SIGSTOP to have no effect, it needs to suppress it.
PTRACE_GETREGSET (since Linux 2.6.34)
Read the tracee's registers. addr specifies, in an
architecture-dependent way, the type of registers to be read.
NT_PRSTATUS (with numerical value 1) usually results in
reading of general-purpose registers. If the CPU has, for
example, floating-point and/or vector registers, they can be
retrieved by setting addr to the corresponding NT_foo
constant. data points to a struct iovec, which describes the
destination buffer's location and length. On return, the
kernel modifies iov.len to indicate the actual number of bytes
returned.
PTRACE_PEEKTEXT, PTRACE_PEEKDATA
Read a word at the address addr in the tracee's memory,
returning the word as the result of the ptrace() call. Linux
does not have separate text and data address spaces, so these
two requests are currently equivalent. (data is ignored; but
see NOTES.)
RETURN VALUE top
On success, the PTRACE_PEEK* requests return the requested data (but
see NOTES), the PTRACE_SECCOMP_GET_FILTER request returns the number
of instructions in the BPF program, and other requests return zero.
On error, all requests return -1, and errno is set appropriately.
Since the value returned by a successful PTRACE_PEEK* request may be
-1, the caller must clear errno before the call, and then check it
afterward to determine whether or not an error occurred.
作用是suspend,可以通过SIGCONT恢复
http://man7.org/linux/man-pages/man2/eventfd.2.html
eventfd - create a file descriptor for event notification
#include <sys/eventfd.h>
int eventfd(unsigned int initval, int flags);
eventfd() creates an "eventfd object" that can be used as an event
wait/notify mechanism by user-space applications, and by the kernel
to notify user-space applications of events.
As its return value, eventfd() returns a new file descriptor that can
be used to refer to the eventfd object.
EFD_CLOEXEC (since Linux 2.6.27)
Set the close-on-exec (FD_CLOEXEC) flag on the new file
descriptor. See the description of the O_CLOEXEC flag in
open(2) for reasons why this may be useful.
http://man7.org/linux/man-pages/man2/dup.2.html
dup, dup2, dup3 - duplicate a file descriptor
int dup(int oldfd);
int dup2(int oldfd, int newfd);
int dup3(int oldfd, int newfd, int flags);
The dup() system call creates a copy of the file descriptor oldfd,
using the lowest-numbered unused file descriptor for the new
descriptor.
The dup2() system call performs the same task as dup(), but instead
of using the lowest-numbered unused file descriptor, it uses the file
descriptor number specified in newfd. If the file descriptor newfd
was previously open, it is silently closed before being reused.
http://man7.org/linux/man-pages/man2/syscall.2.html
syscall - indirect system call
long syscall(long number, ...);
http://man7.org/linux/man-pages/man2/mmap.2.html
mmap, munmap - map or unmap files or devices into memory
void *mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int munmap(void *addr, size_t length);
mmap() creates a new mapping in the virtual address space of the
calling process. The starting address for the new mapping is
specified in addr. The length argument specifies the length of the
mapping (which must be greater than 0).
If addr is NULL, then the kernel chooses the (page-aligned) address
at which to create the mapping; this is the most portable method of
creating a new mapping. If addr is not NULL, then the kernel takes
it as a hint about where to place the mapping; on Linux, the kernel
will pick a nearby page boundary (but always above or equal to the
value specified by /proc/sys/vm/mmap_min_addr) and attempt to create
the mapping there. If another mapping already exists there, the
kernel picks a new address that may or may not depend on the hint.
The address of the new mapping is returned as the result of the call.
MAP_PRIVATE
Create a private copy-on-write mapping. Updates to the
mapping are not visible to other processes mapping the same
file, and are not carried through to the underlying file. It
is unspecified whether changes made to the file after the
mmap() call are visible in the mapped region.
RETURN VALUE top
On success, mmap() returns a pointer to the mapped area. On error,
the value MAP_FAILED (that is, (void *) -1) is returned, and errno is
set to indicate the cause of the error.
On success, munmap() returns 0. On failure, it returns -1, and errno
is set to indicate the cause of the error (probably to EINVAL).
https://code.woboq.org/userspace/glibc/elf/link.h.html
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
#define ElfW(type) _ElfW (Elf, __ELF_NATIVE_CLASS, type)
#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
#define _ElfW_1(e,w,t) e##w##t
http://man7.org/linux/man-pages/man5/elf.5.html
ELF header (Ehdr)
The ELF header is described by the type Elf32_Ehdr or Elf64_Ehdr:
The ELF header is described by the type Elf32_Ehdr or Elf64_Ehdr:
#define EI_NIDENT 16
typedef struct {
unsigned char e_ident[EI_NIDENT];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
ElfN_Addr e_entry;
ElfN_Off e_phoff;
ElfN_Off e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
} ElfN_Ehdr;
Program header (Phdr)
Program header (Phdr)
An executable or shared object file's program header table is an
array of structures, each describing a segment or other information
the system needs to prepare the program for execution. An object
file segment contains one or more sections. Program headers are
meaningful only for executable and shared object files. A file spec‐
ifies its own program header size with the ELF header's e_phentsize
and e_phnum members. The ELF program header is described by the type
Elf32_Phdr or Elf64_Phdr depending on the architecture:
typedef struct {
uint32_t p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
} Elf32_Phdr;
typedef struct {
uint32_t p_type;
uint32_t p_flags;
Elf64_Off p_offset;
Elf64_Addr p_vaddr;
Elf64_Addr p_paddr;
uint64_t p_filesz;
uint64_t p_memsz;
uint64_t p_align;
}
The main difference between the 32-bit and the 64-bit program header
lies in the location of the p_flags member in the total struct.