static int show_map(int pid) { mapinfo *milist; mapinfo *mi; unsigned shared_dirty = 0; unsigned shared_clean = 0; unsigned private_dirty = 0; unsigned private_clean = 0; unsigned swap = 0; unsigned rss = 0; unsigned pss = 0; unsigned size = 0; unsigned count = 0; milist = load_maps(pid, addresses, !verbose && !addresses); if (milist == NULL) { return 1; } print_header(); print_divider(); for (mi = milist; mi;) { mapinfo* last = mi; shared_clean += mi->shared_clean; shared_dirty += mi->shared_dirty; private_clean += mi->private_clean; private_dirty += mi->private_dirty; swap += mi->swap; rss += mi->rss; pss += mi->pss; size += mi->size; count += mi->count; if (terse && !mi->private_dirty) { goto out; } if (addresses) { printf("%08x %08x ", mi->start, mi->end); } printf("%8d %8d %8d %8d %8d %8d %8d %8d", mi->size, mi->rss, mi->pss, mi->shared_clean, mi->shared_dirty, mi->private_clean, mi->private_dirty, mi->swap); if (!verbose && !addresses) { printf("%4d ", mi->count); } printf("%s%s\n", mi->name, mi->is_bss ? " [bss]" : ""); out: mi = mi->next; free(last); } print_divider(); print_header(); print_divider(); if (addresses) { printf(" "); } printf("%8d %8d %8d %8d %8d %8d %8d %8d", size, rss, pss, shared_clean, shared_dirty, private_clean, private_dirty, swap); if (!verbose && !addresses) { printf("%4d ", count); } printf("TOTAL\n"); return 0; }
int load_bpf_file(char *path) { int fd, i; Elf *elf; GElf_Ehdr ehdr; GElf_Shdr shdr, shdr_prog; Elf_Data *data, *data_prog, *symbols = NULL; char *shname, *shname_prog; if (elf_version(EV_CURRENT) == EV_NONE) return 1; fd = open(path, O_RDONLY, 0); if (fd < 0) return 1; elf = elf_begin(fd, ELF_C_READ, NULL); if (!elf) return 1; if (gelf_getehdr(elf, &ehdr) != &ehdr) return 1; /* clear all kprobes */ i = system("echo \"\" > /sys/kernel/debug/tracing/kprobe_events"); /* scan over all elf sections to get license and map info */ for (i = 1; i < ehdr.e_shnum; i++) { if (get_sec(elf, i, &ehdr, &shname, &shdr, &data)) continue; if (0) /* helpful for llvm debugging */ printf("section %d:%s data %p size %zd link %d flags %d\n", i, shname, data->d_buf, data->d_size, shdr.sh_link, (int) shdr.sh_flags); if (strcmp(shname, "license") == 0) { processed_sec[i] = true; memcpy(license, data->d_buf, data->d_size); } else if (strcmp(shname, "version") == 0) { processed_sec[i] = true; if (data->d_size != sizeof(int)) { printf("invalid size of version section %zd\n", data->d_size); return 1; } memcpy(&kern_version, data->d_buf, sizeof(int)); } else if (strcmp(shname, "maps") == 0) { processed_sec[i] = true; if (load_maps(data->d_buf, data->d_size)) return 1; } else if (shdr.sh_type == SHT_SYMTAB) { symbols = data; } } /* load programs that need map fixup (relocations) */ for (i = 1; i < ehdr.e_shnum; i++) { if (get_sec(elf, i, &ehdr, &shname, &shdr, &data)) continue; if (shdr.sh_type == SHT_REL) { struct bpf_insn *insns; if (get_sec(elf, shdr.sh_info, &ehdr, &shname_prog, &shdr_prog, &data_prog)) continue; if (shdr_prog.sh_type != SHT_PROGBITS || !(shdr_prog.sh_flags & SHF_EXECINSTR)) continue; insns = (struct bpf_insn *) data_prog->d_buf; processed_sec[shdr.sh_info] = true; processed_sec[i] = true; if (parse_relo_and_apply(data, symbols, &shdr, insns)) continue; if (memcmp(shname_prog, "kprobe/", 7) == 0 || memcmp(shname_prog, "kretprobe/", 10) == 0 || memcmp(shname_prog, "tracepoint/", 11) == 0 || memcmp(shname_prog, "xdp", 3) == 0 || memcmp(shname_prog, "perf_event", 10) == 0 || memcmp(shname_prog, "socket", 6) == 0 || memcmp(shname_prog, "cgroup/", 7) == 0) load_and_attach(shname_prog, insns, data_prog->d_size); } } /* load programs that don't use maps */ for (i = 1; i < ehdr.e_shnum; i++) { if (processed_sec[i]) continue; if (get_sec(elf, i, &ehdr, &shname, &shdr, &data)) continue; if (memcmp(shname, "kprobe/", 7) == 0 || memcmp(shname, "kretprobe/", 10) == 0 || memcmp(shname, "tracepoint/", 11) == 0 || memcmp(shname, "xdp", 3) == 0 || memcmp(shname, "perf_event", 10) == 0 || memcmp(shname, "socket", 6) == 0 || memcmp(shname, "cgroup/", 7) == 0) load_and_attach(shname, data->d_buf, data->d_size); } close(fd); return 0; }
int show_map(int pid) { mapinfo *milist; mapinfo *mi; unsigned shared_dirty = 0; unsigned shared_clean = 0; unsigned private_dirty = 0; unsigned private_clean = 0; unsigned rss = 0; unsigned pss = 0; unsigned size = 0; milist = load_maps(pid, verbose); if(milist == 0) { fprintf(stderr,"cannot get /proc/smaps for pid %d\n", pid); return 1; } if(addresses) { printf("start end shared private object\n"); printf("-------- -------- -------- -------- ------------------------------\n"); } else { printf("virtual shared shared private private\n"); printf("size RSS PSS clean dirty clean dirty object\n"); printf("-------- -------- -------- -------- -------- -------- -------- ------------------------------\n"); } for(mi = milist; mi; mi = mi->next){ shared_clean += mi->shared_clean; shared_dirty += mi->shared_dirty; private_clean += mi->private_clean; private_dirty += mi->private_dirty; rss += mi->rss; pss += mi->pss; size += mi->size; if(terse && !mi->private_dirty) continue; if(addresses) { printf("%08x %08x %8d %8d %s\n", mi->start, mi->end, mi->shared_clean + mi->shared_dirty, mi->private_clean + mi->private_dirty, mi->name); } else { printf("%8d %8d %8d %8d %8d %8d %8d %s\n", mi->size, mi->rss, mi->pss, mi->shared_clean, mi->shared_dirty, mi->private_clean, mi->private_dirty, mi->name); } } if(addresses) { printf("-------- -------- -------- -------- ------------------------------\n"); printf(" %8d %8d TOTAL\n", shared_dirty + shared_clean, private_dirty + private_clean); } else { printf("-------- -------- -------- -------- -------- -------- -------- ------------------------------\n"); printf("%8d %8d %8d %8d %8d %8d %8d TOTAL\n", size, rss, pss, shared_clean, shared_dirty, private_clean, private_dirty); } return 0; }