mirror of
https://github.com/eunomia-bpf/bpf-developer-tutorial.git
synced 2026-02-11 22:25:13 +08:00
fix the link to tutorial
This commit is contained in:
@@ -129,11 +129,8 @@ $(patsubst %,$(OUTPUT)/%.o,$(BZS_APPS)): $(LIBBLAZESYM_HEADER)
|
||||
|
||||
$(BZS_APPS): $(LIBBLAZESYM_OBJ)
|
||||
|
||||
uprobe_helpers.o: uprobe_helpers.c
|
||||
$(call msg,CC,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $(INCLUDES) -c $(filter %.c,$^) -o $@
|
||||
# Build application binary
|
||||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) uprobe_helpers.o | $(OUTPUT)
|
||||
$(APPS): %: $(OUTPUT)/%.o $(LIBBPF_OBJ) | $(OUTPUT)
|
||||
$(call msg,BINARY,$@)
|
||||
$(Q)$(CC) $(CFLAGS) $^ $(ALL_LDFLAGS) -lelf -lz -o $@
|
||||
|
||||
|
||||
@@ -307,7 +307,7 @@ TIME CPU PID GC TIME
|
||||
10:00:05 11% 12345 50ms
|
||||
```
|
||||
|
||||
源代码:
|
||||
完整源代码:
|
||||
|
||||
- <https://github.com/eunomia-bpf/bpf-developer-tutorial/tree/main/src/15-javagc>
|
||||
|
||||
@@ -322,4 +322,4 @@ TIME CPU PID GC TIME
|
||||
|
||||
此外,我们也介绍了一些关于 Java GC、USDT 和 eBPF 的基础知识和实践技巧,这些知识和技巧对于想要在网络和系统性能分析领域深入研究的开发者来说是非常有价值的。
|
||||
|
||||
如果您希望学习更多关于 eBPF 的知识和实践,请查阅 eunomia-bpf 的官方文档:<https://github.com/eunomia-bpf/eunomia-bpf> 。您还可以访问我们的教程代码仓库 <https://github.com/eunomia-bpf/bpf-developer-tutorial> 以获取更多示例和完整的教程。
|
||||
如果您希望学习更多关于 eBPF 的知识和实践,可以访问我们的教程代码仓库 <https://github.com/eunomia-bpf/bpf-developer-tutorial> 以获取更多示例和完整的教程。
|
||||
|
||||
@@ -1,294 +0,0 @@
|
||||
// SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
|
||||
/* Copyright (c) 2021 Google LLC. */
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <gelf.h>
|
||||
|
||||
#define warn(...) fprintf(stderr, __VA_ARGS__)
|
||||
|
||||
/*
|
||||
* Returns 0 on success; -1 on failure. On sucess, returns via `path` the full
|
||||
* path to the program for pid.
|
||||
*/
|
||||
int get_pid_binary_path(pid_t pid, char *path, size_t path_sz)
|
||||
{
|
||||
ssize_t ret;
|
||||
char proc_pid_exe[32];
|
||||
|
||||
if (snprintf(proc_pid_exe, sizeof(proc_pid_exe), "/proc/%d/exe", pid)
|
||||
>= sizeof(proc_pid_exe)) {
|
||||
warn("snprintf /proc/PID/exe failed");
|
||||
return -1;
|
||||
}
|
||||
ret = readlink(proc_pid_exe, path, path_sz);
|
||||
if (ret < 0) {
|
||||
warn("No such pid %d\n", pid);
|
||||
return -1;
|
||||
}
|
||||
if (ret >= path_sz) {
|
||||
warn("readlink truncation");
|
||||
return -1;
|
||||
}
|
||||
path[ret] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success; -1 on failure. On success, returns via `path` the full
|
||||
* path to a library matching the name `lib` that is loaded into pid's address
|
||||
* space.
|
||||
*/
|
||||
int get_pid_lib_path(pid_t pid, const char *lib, char *path, size_t path_sz)
|
||||
{
|
||||
FILE *maps;
|
||||
char *p;
|
||||
char proc_pid_maps[32];
|
||||
char line_buf[1024];
|
||||
char path_buf[1024];
|
||||
|
||||
if (snprintf(proc_pid_maps, sizeof(proc_pid_maps), "/proc/%d/maps", pid)
|
||||
>= sizeof(proc_pid_maps)) {
|
||||
warn("snprintf /proc/PID/maps failed");
|
||||
return -1;
|
||||
}
|
||||
maps = fopen(proc_pid_maps, "r");
|
||||
if (!maps) {
|
||||
warn("No such pid %d\n", pid);
|
||||
return -1;
|
||||
}
|
||||
while (fgets(line_buf, sizeof(line_buf), maps)) {
|
||||
if (sscanf(line_buf, "%*x-%*x %*s %*x %*s %*u %s", path_buf) != 1)
|
||||
continue;
|
||||
/* e.g. /usr/lib/x86_64-linux-gnu/libc-2.31.so */
|
||||
p = strrchr(path_buf, '/');
|
||||
if (!p)
|
||||
continue;
|
||||
if (strncmp(p, "/lib", 4))
|
||||
continue;
|
||||
p += 4;
|
||||
if (strncmp(lib, p, strlen(lib)))
|
||||
continue;
|
||||
p += strlen(lib);
|
||||
/* libraries can have - or . after the name */
|
||||
if (*p != '.' && *p != '-')
|
||||
continue;
|
||||
if (strnlen(path_buf, 1024) >= path_sz) {
|
||||
warn("path size too small\n");
|
||||
return -1;
|
||||
}
|
||||
strcpy(path, path_buf);
|
||||
fclose(maps);
|
||||
return 0;
|
||||
}
|
||||
|
||||
warn("Cannot find library %s\n", lib);
|
||||
fclose(maps);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success; -1 on failure. On success, returns via `path` the full
|
||||
* path to the program.
|
||||
*/
|
||||
static int which_program(const char *prog, char *path, size_t path_sz)
|
||||
{
|
||||
FILE *which;
|
||||
char cmd[100];
|
||||
|
||||
if (snprintf(cmd, sizeof(cmd), "which %s", prog) >= sizeof(cmd)) {
|
||||
warn("snprintf which prog failed");
|
||||
return -1;
|
||||
}
|
||||
which = popen(cmd, "r");
|
||||
if (!which) {
|
||||
warn("which failed");
|
||||
return -1;
|
||||
}
|
||||
if (!fgets(path, path_sz, which)) {
|
||||
warn("fgets which failed");
|
||||
pclose(which);
|
||||
return -1;
|
||||
}
|
||||
/* which has a \n at the end of the string */
|
||||
path[strlen(path) - 1] = '\0';
|
||||
pclose(which);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns 0 on success; -1 on failure. On success, returns via `path` the full
|
||||
* path to the binary for the given pid.
|
||||
* 1) pid == x, binary == "" : returns the path to x's program
|
||||
* 2) pid == x, binary == "foo" : returns the path to libfoo linked in x
|
||||
* 3) pid == 0, binary == "" : failure: need a pid or a binary
|
||||
* 4) pid == 0, binary == "bar" : returns the path to `which bar`
|
||||
*
|
||||
* For case 4), ideally we'd like to search for libbar too, but we don't support
|
||||
* that yet.
|
||||
*/
|
||||
int resolve_binary_path(const char *binary, pid_t pid, char *path, size_t path_sz)
|
||||
{
|
||||
if (!strcmp(binary, "")) {
|
||||
if (!pid) {
|
||||
warn("Uprobes need a pid or a binary\n");
|
||||
return -1;
|
||||
}
|
||||
return get_pid_binary_path(pid, path, path_sz);
|
||||
}
|
||||
if (pid)
|
||||
return get_pid_lib_path(pid, binary, path, path_sz);
|
||||
|
||||
if (which_program(binary, path, path_sz)) {
|
||||
/*
|
||||
* If the user is tracing a program by name, we can find it.
|
||||
* But we can't find a library by name yet. We'd need to parse
|
||||
* ld.so.cache or something similar.
|
||||
*/
|
||||
warn("Can't find %s (Need a PID if this is a library)\n", binary);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Opens an elf at `path` of kind ELF_K_ELF. Returns NULL on failure. On
|
||||
* success, close with close_elf(e, fd_close).
|
||||
*/
|
||||
Elf *open_elf(const char *path, int *fd_close)
|
||||
{
|
||||
int fd;
|
||||
Elf *e;
|
||||
|
||||
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||
warn("elf init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
warn("Could not open %s\n", path);
|
||||
return NULL;
|
||||
}
|
||||
e = elf_begin(fd, ELF_C_READ, NULL);
|
||||
if (!e) {
|
||||
warn("elf_begin failed: %s\n", elf_errmsg(-1));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
if (elf_kind(e) != ELF_K_ELF) {
|
||||
warn("elf kind %d is not ELF_K_ELF\n", elf_kind(e));
|
||||
elf_end(e);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
*fd_close = fd;
|
||||
return e;
|
||||
}
|
||||
|
||||
Elf *open_elf_by_fd(int fd)
|
||||
{
|
||||
Elf *e;
|
||||
|
||||
if (elf_version(EV_CURRENT) == EV_NONE) {
|
||||
warn("elf init failed\n");
|
||||
return NULL;
|
||||
}
|
||||
e = elf_begin(fd, ELF_C_READ, NULL);
|
||||
if (!e) {
|
||||
warn("elf_begin failed: %s\n", elf_errmsg(-1));
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
if (elf_kind(e) != ELF_K_ELF) {
|
||||
warn("elf kind %d is not ELF_K_ELF\n", elf_kind(e));
|
||||
elf_end(e);
|
||||
close(fd);
|
||||
return NULL;
|
||||
}
|
||||
return e;
|
||||
}
|
||||
|
||||
void close_elf(Elf *e, int fd_close)
|
||||
{
|
||||
elf_end(e);
|
||||
close(fd_close);
|
||||
}
|
||||
|
||||
/* Returns the offset of a function in the elf file `path`, or -1 on failure. */
|
||||
off_t get_elf_func_offset(const char *path, const char *func)
|
||||
{
|
||||
off_t ret = -1;
|
||||
int i, fd = -1;
|
||||
Elf *e;
|
||||
Elf_Scn *scn;
|
||||
Elf_Data *data;
|
||||
GElf_Ehdr ehdr;
|
||||
GElf_Shdr shdr[1];
|
||||
GElf_Phdr phdr;
|
||||
GElf_Sym sym[1];
|
||||
size_t shstrndx, nhdrs;
|
||||
char *n;
|
||||
|
||||
e = open_elf(path, &fd);
|
||||
|
||||
if (!gelf_getehdr(e, &ehdr))
|
||||
goto out;
|
||||
|
||||
if (elf_getshdrstrndx(e, &shstrndx) != 0)
|
||||
goto out;
|
||||
|
||||
scn = NULL;
|
||||
while ((scn = elf_nextscn(e, scn))) {
|
||||
if (!gelf_getshdr(scn, shdr))
|
||||
continue;
|
||||
if (!(shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM))
|
||||
continue;
|
||||
data = NULL;
|
||||
while ((data = elf_getdata(scn, data))) {
|
||||
for (i = 0; gelf_getsym(data, i, sym); i++) {
|
||||
n = elf_strptr(e, shdr->sh_link, sym->st_name);
|
||||
if (!n)
|
||||
continue;
|
||||
if (GELF_ST_TYPE(sym->st_info) != STT_FUNC)
|
||||
continue;
|
||||
if (!strcmp(n, func)) {
|
||||
ret = sym->st_value;
|
||||
goto check;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
check:
|
||||
if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN) {
|
||||
if (elf_getphdrnum(e, &nhdrs) != 0) {
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < (int)nhdrs; i++) {
|
||||
if (!gelf_getphdr(e, i, &phdr))
|
||||
continue;
|
||||
if (phdr.p_type != PT_LOAD || !(phdr.p_flags & PF_X))
|
||||
continue;
|
||||
if (phdr.p_vaddr <= ret && ret < (phdr.p_vaddr + phdr.p_memsz)) {
|
||||
ret = ret - phdr.p_vaddr + phdr.p_offset;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
ret = -1;
|
||||
}
|
||||
out:
|
||||
close_elf(e, fd);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
/* SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause) */
|
||||
/* Copyright (c) 2021 Google LLC. */
|
||||
#ifndef __UPROBE_HELPERS_H
|
||||
#define __UPROBE_HELPERS_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <gelf.h>
|
||||
|
||||
int get_pid_binary_path(pid_t pid, char *path, size_t path_sz);
|
||||
int get_pid_lib_path(pid_t pid, const char *lib, char *path, size_t path_sz);
|
||||
int resolve_binary_path(const char *binary, pid_t pid, char *path, size_t path_sz);
|
||||
off_t get_elf_func_offset(const char *path, const char *func);
|
||||
Elf *open_elf(const char *path, int *fd_close);
|
||||
Elf *open_elf_by_fd(int fd);
|
||||
void close_elf(Elf *e, int fd_close);
|
||||
|
||||
#endif /* __UPROBE_HELPERS_H */
|
||||
Reference in New Issue
Block a user