Lines Matching +full:ecx +full:- +full:1000

1 // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
24 /* libbpf's USDT support consists of BPF-side state/code and user-space
25 * state/code working together in concert. BPF-side parts are defined in
26 * usdt.bpf.h header library. User-space state is encapsulated by struct
30 * and IP-to-spec-ID map, which is auxiliary map necessary for kernels that
38 * USDT-related until the very first call to bpf_program__attach_usdt(), which
42 * store it in bpf_object. USDT manager is per-BPF object construct, as each
44 * the expected USDT-related state. There is no coordination between two
46 * existence and libbpf is just oblivious, dealing with bpf_object-specific
51 * From user-space application's point of view, USDT is essentially just
53 * is being traced by some external entity (e.g, BPF-based tool). Here's how
56 * #include <sys/sdt.h> // provided by systemtap-sdt-devel package
61 * USDT is identified by it's <provider-name>:<probe-name> pair of names. Each
69 * `readelf -n <binary>`:
75 …* Arguments: -4@-1204(%rbp) -4@%edi -8@-1216(%rbp) -8@%r8 -4@$5 -8@%r9 8@%rdx 8@%r10 -4@$-9 -2@%…
83 * Semaphore above is and optional feature. It records an address of a 2-byte
89 * Recent enough kernel has built-in support for automatically managing this
98 * The part after @ sign is assembly-like definition of argument location
102 * 1) immediate constant, see 5th and 9th args above (-4@$5 and -4@-9);
103 * 2) register value, e.g., 8@%rdx, which means "unsigned 8-byte integer
105 * 3) memory dereference addressed by register, e.g., -4@-1204(%rbp), which
106 * specifies signed 32-bit integer stored at offset -1204 bytes from
112 * prepares `struct usdt_spec` (USDT spec), which is then provided to BPF-side
114 * actual value at runtime using a simple BPF-side code.
128 * macro invocations can end up being inlined many-many times, depending on
144 * about. This state has to be maintained per-BPF object and coordinate
151 * support BPF cookie, through IP-to-spec-ID map that libbpf maintains in such
155 * calculate absolute IP addresses for IP-to-spec-ID map, and thus such mode
161 * user-provided value that can be associated with USDT attachment. Note that
171 * that 1000 USDT call sites only need 5 different USDT specs, because all the
175 * on-the-fly deduplication during a single USDT attachment to only allocate
227 * "-4@%esi -4@-24(%rbp) -4@%ecx 2@%ax 8@%rdx"
265 return ERR_PTR(-ESRCH); in usdt_manager_new()
270 return ERR_PTR(-ENOMEM); in usdt_manager_new()
272 man->specs_map = specs_map; in usdt_manager_new()
273 man->ip_to_spec_id_map = ip_to_spec_id_map; in usdt_manager_new()
276 * We don't need IP-to-ID mapping if we can use BPF cookies. in usdt_manager_new()
279 man->has_bpf_cookie = kernel_supports(obj, FEAT_BPF_COOKIE); in usdt_manager_new()
283 * Added in: a6ca88b241d5 ("trace_uprobe: support reference counter in fd-based uprobe") in usdt_manager_new()
285 man->has_sema_refcnt = faccessat(AT_FDCWD, ref_ctr_sysfs_path, F_OK, AT_EACCESS) == 0; in usdt_manager_new()
295 free(man->free_spec_ids); in usdt_manager_free()
306 return -EBADF; in sanity_check_usdt_elf()
312 pr_warn("usdt: attaching to 64-bit ELF binary '%s' is not supported\n", path); in sanity_check_usdt_elf()
313 return -EBADF; in sanity_check_usdt_elf()
318 pr_warn("usdt: attaching to 32-bit ELF binary '%s' is not supported\n", path); in sanity_check_usdt_elf()
319 return -EBADF; in sanity_check_usdt_elf()
324 return -EBADF; in sanity_check_usdt_elf()
328 return -EINVAL; in sanity_check_usdt_elf()
333 return -EBADF; in sanity_check_usdt_elf()
345 return -EBADF; in sanity_check_usdt_elf()
357 return -EINVAL; in find_elf_sec_by_name()
361 return -EINVAL; in find_elf_sec_by_name()
367 return -EINVAL; in find_elf_sec_by_name()
369 name = elf_strptr(elf, shstrndx, shdr->sh_name); in find_elf_sec_by_name()
376 return -ENOENT; in find_elf_sec_by_name()
391 return a->start < b->start ? -1 : 1; in cmp_elf_segs()
405 err = -errno; in parse_elf_segs()
411 err = -errno; in parse_elf_segs()
423 return -ENOMEM; in parse_elf_segs()
429 seg->start = phdr.p_vaddr; in parse_elf_segs()
430 seg->end = phdr.p_vaddr + phdr.p_memsz; in parse_elf_segs()
431 seg->offset = phdr.p_offset; in parse_elf_segs()
432 seg->is_exec = phdr.p_flags & PF_X; in parse_elf_segs()
437 return -ESRCH; in parse_elf_segs()
463 lib_path, -errno); in parse_vma_segs()
471 err = -errno; in parse_vma_segs()
479 * 7f5c6f5d1000-7f5c6f5d3000 rw-p 001c7000 08:04 21238613 /usr/lib64/libc-2.17.so in parse_vma_segs()
480 * 7f5c6f5d3000-7f5c6f5d8000 rw-p 00000000 00:00 0 in parse_vma_segs()
481 …* 7f5c6f5d8000-7f5c6f5d9000 r-xp 00000000 103:01 362990598 /data/users/andriin/linux/tools/bpf/… in parse_vma_segs()
483 while (fscanf(f, "%zx-%zx %s %zx %*s %*d%[^\n]\n", in parse_vma_segs()
497 pr_debug("usdt: discovered segment for lib '%s': addrs %zx-%zx mode %s offset %zx\n", in parse_vma_segs()
500 /* ignore non-executable sections for shared libs */ in parse_vma_segs()
506 err = -ENOMEM; in parse_vma_segs()
514 seg->start = seg_start; in parse_vma_segs()
515 seg->end = seg_end; in parse_vma_segs()
516 seg->offset = seg_off; in parse_vma_segs()
517 seg->is_exec = true; in parse_vma_segs()
523 err = -ESRCH; in parse_vma_segs()
544 if (seg->start <= virtaddr && virtaddr < seg->end) in find_elf_seg()
557 * offset-based range of [offset_start, offset_end) in find_vma_seg()
560 if (seg->offset <= offset && offset < seg->offset + (seg->end - seg->start)) in find_vma_seg()
598 return -EINVAL; in collect_usdt_targets()
621 err = parse_usdt_note(elf, path, &nhdr, data->d_buf, name_off, desc_off, &note); in collect_usdt_targets()
631 * Each SDT probe also expands into a non-allocated ELF note. You can in collect_usdt_targets()
633 * see below for details. Because the note is non-allocated, it means in collect_usdt_targets()
645 * Each probe note records the link-time address of the .stapsdt.base in collect_usdt_targets()
657 usdt_abs_ip += base_addr - note.base_addr; in collect_usdt_targets()
666 err = -ESRCH; in collect_usdt_targets()
671 if (!seg->is_exec) { in collect_usdt_targets()
672 err = -ESRCH; in collect_usdt_targets()
674 path, seg->start, seg->end, usdt_provider, usdt_name, in collect_usdt_targets()
679 usdt_rel_ip = usdt_abs_ip - seg->start + seg->offset; in collect_usdt_targets()
681 if (ehdr.e_type == ET_DYN && !man->has_bpf_cookie) { in collect_usdt_targets()
697 err = -ENOTSUP; in collect_usdt_targets()
713 err = -ESRCH; in collect_usdt_targets()
719 usdt_abs_ip = seg->start - seg->offset + usdt_rel_ip; in collect_usdt_targets()
725 seg ? seg->start : 0, seg ? seg->end : 0, seg ? seg->offset : 0); in collect_usdt_targets()
729 if (!man->has_sema_refcnt) { in collect_usdt_targets()
732 err = -ENOTSUP; in collect_usdt_targets()
738 err = -ESRCH; in collect_usdt_targets()
743 if (seg->is_exec) { in collect_usdt_targets()
744 err = -ESRCH; in collect_usdt_targets()
746 path, seg->start, seg->end, usdt_provider, usdt_name, in collect_usdt_targets()
751 usdt_sema_off = note.sema_addr - seg->start + seg->offset; in collect_usdt_targets()
756 seg->start, seg->end, seg->offset); in collect_usdt_targets()
762 err = -ENOMEM; in collect_usdt_targets()
770 target->abs_ip = usdt_abs_ip; in collect_usdt_targets()
771 target->rel_ip = usdt_rel_ip; in collect_usdt_targets()
772 target->sema_off = usdt_sema_off; in collect_usdt_targets()
777 target->spec_str = note.args; in collect_usdt_targets()
779 err = parse_usdt_spec(&target->spec, &note, usdt_cookie); in collect_usdt_targets()
816 struct usdt_manager *man = usdt_link->usdt_man; in bpf_link_usdt_detach()
819 for (i = 0; i < usdt_link->uprobe_cnt; i++) { in bpf_link_usdt_detach()
821 bpf_link__destroy(usdt_link->uprobes[i].link); in bpf_link_usdt_detach()
828 if (!man->has_bpf_cookie) { in bpf_link_usdt_detach()
830 (void)bpf_map_delete_elem(bpf_map__fd(man->ip_to_spec_id_map), in bpf_link_usdt_detach()
831 &usdt_link->uprobes[i].abs_ip); in bpf_link_usdt_detach()
838 if (!man->free_spec_ids) { in bpf_link_usdt_detach()
840 man->free_spec_ids = usdt_link->spec_ids; in bpf_link_usdt_detach()
841 man->free_spec_cnt = usdt_link->spec_cnt; in bpf_link_usdt_detach()
842 usdt_link->spec_ids = NULL; in bpf_link_usdt_detach()
845 size_t new_cnt = man->free_spec_cnt + usdt_link->spec_cnt; in bpf_link_usdt_detach()
848 new_free_ids = libbpf_reallocarray(man->free_spec_ids, new_cnt, in bpf_link_usdt_detach()
857 memcpy(new_free_ids + man->free_spec_cnt, usdt_link->spec_ids, in bpf_link_usdt_detach()
858 usdt_link->spec_cnt * sizeof(*usdt_link->spec_ids)); in bpf_link_usdt_detach()
859 man->free_spec_ids = new_free_ids; in bpf_link_usdt_detach()
860 man->free_spec_cnt = new_cnt; in bpf_link_usdt_detach()
871 free(usdt_link->spec_ids); in bpf_link_usdt_dealloc()
872 free(usdt_link->uprobes); in bpf_link_usdt_dealloc()
899 if (hashmap__find(specs_hash, target->spec_str, &tmp)) { in allocate_spec_id()
908 tmp = libbpf_reallocarray(link->spec_ids, link->spec_cnt + 1, sizeof(*link->spec_ids)); in allocate_spec_id()
910 return -ENOMEM; in allocate_spec_id()
911 link->spec_ids = tmp; in allocate_spec_id()
914 if (man->free_spec_cnt) { in allocate_spec_id()
915 *spec_id = man->free_spec_ids[man->free_spec_cnt - 1]; in allocate_spec_id()
918 err = hashmap__add(specs_hash, target->spec_str, (void *)(long)*spec_id); in allocate_spec_id()
922 man->free_spec_cnt--; in allocate_spec_id()
925 if (man->next_free_spec_id >= bpf_map__max_entries(man->specs_map)) in allocate_spec_id()
926 return -E2BIG; in allocate_spec_id()
928 *spec_id = man->next_free_spec_id; in allocate_spec_id()
931 err = hashmap__add(specs_hash, target->spec_str, (void *)(long)*spec_id); in allocate_spec_id()
935 man->next_free_spec_id++; in allocate_spec_id()
939 link->spec_ids[link->spec_cnt] = *spec_id; in allocate_spec_id()
940 link->spec_cnt++; in allocate_spec_id()
958 spec_map_fd = bpf_map__fd(man->specs_map); in usdt_manager_attach_usdt()
959 ip_map_fd = bpf_map__fd(man->ip_to_spec_id_map); in usdt_manager_attach_usdt()
964 err = -errno; in usdt_manager_attach_usdt()
971 err = -EBADF; in usdt_manager_attach_usdt()
972 pr_warn("usdt: failed to parse ELF binary '%s': %s\n", path, elf_errmsg(-1)); in usdt_manager_attach_usdt()
982 pid = -1; in usdt_manager_attach_usdt()
992 err = (err == 0) ? -ENOENT : err; in usdt_manager_attach_usdt()
1004 err = -ENOMEM; in usdt_manager_attach_usdt()
1008 link->usdt_man = man; in usdt_manager_attach_usdt()
1009 link->link.detach = &bpf_link_usdt_detach; in usdt_manager_attach_usdt()
1010 link->link.dealloc = &bpf_link_usdt_dealloc; in usdt_manager_attach_usdt()
1012 link->uprobes = calloc(target_cnt, sizeof(*link->uprobes)); in usdt_manager_attach_usdt()
1013 if (!link->uprobes) { in usdt_manager_attach_usdt()
1014 err = -ENOMEM; in usdt_manager_attach_usdt()
1036 if (is_new && bpf_map_update_elem(spec_map_fd, &spec_id, &target->spec, BPF_ANY)) { in usdt_manager_attach_usdt()
1037 err = -errno; in usdt_manager_attach_usdt()
1042 if (!man->has_bpf_cookie && in usdt_manager_attach_usdt()
1043 bpf_map_update_elem(ip_map_fd, &target->abs_ip, &spec_id, BPF_NOEXIST)) { in usdt_manager_attach_usdt()
1044 err = -errno; in usdt_manager_attach_usdt()
1045 if (err == -EEXIST) { in usdt_manager_attach_usdt()
1050 target->abs_ip, spec_id, usdt_provider, usdt_name, in usdt_manager_attach_usdt()
1056 opts.ref_ctr_offset = target->sema_off; in usdt_manager_attach_usdt()
1057 opts.bpf_cookie = man->has_bpf_cookie ? spec_id : 0; in usdt_manager_attach_usdt()
1059 target->rel_ip, &opts); in usdt_manager_attach_usdt()
1067 link->uprobes[i].link = uprobe_link; in usdt_manager_attach_usdt()
1068 link->uprobes[i].abs_ip = target->abs_ip; in usdt_manager_attach_usdt()
1069 link->uprobe_cnt++; in usdt_manager_attach_usdt()
1077 return &link->link; in usdt_manager_attach_usdt()
1081 bpf_link__destroy(&link->link); in usdt_manager_attach_usdt()
1102 if (strncmp(data + name_off, USDT_NOTE_NAME, nhdr->n_namesz) != 0) in parse_usdt_note()
1103 return -EINVAL; in parse_usdt_note()
1104 if (nhdr->n_type != USDT_NOTE_TYPE) in parse_usdt_note()
1105 return -EINVAL; in parse_usdt_note()
1108 len = nhdr->n_descsz; in parse_usdt_note()
1113 return -EINVAL; in parse_usdt_note()
1121 name = (const char *)memchr(provider, '\0', data + len - provider); in parse_usdt_note()
1122 if (!name) /* non-zero-terminated provider */ in parse_usdt_note()
1123 return -EINVAL; in parse_usdt_note()
1126 return -EINVAL; in parse_usdt_note()
1128 args = memchr(name, '\0', data + len - name); in parse_usdt_note()
1129 if (!args) /* non-zero-terminated name */ in parse_usdt_note()
1130 return -EINVAL; in parse_usdt_note()
1133 return -EINVAL; in parse_usdt_note()
1135 note->provider = provider; in parse_usdt_note()
1136 note->name = name; in parse_usdt_note()
1138 note->args = ""; in parse_usdt_note()
1140 note->args = args; in parse_usdt_note()
1141 note->loc_addr = addrs[0]; in parse_usdt_note()
1142 note->base_addr = addrs[1]; in parse_usdt_note()
1143 note->sema_addr = addrs[2]; in parse_usdt_note()
1155 spec->usdt_cookie = usdt_cookie; in parse_usdt_spec()
1156 spec->arg_cnt = 0; in parse_usdt_spec()
1158 s = note->args; in parse_usdt_spec()
1160 if (spec->arg_cnt >= USDT_MAX_ARG_CNT) { in parse_usdt_spec()
1162 USDT_MAX_ARG_CNT, note->provider, note->name, note->args); in parse_usdt_spec()
1163 return -E2BIG; in parse_usdt_spec()
1166 len = parse_usdt_arg(s, spec->arg_cnt, &spec->args[spec->arg_cnt]); in parse_usdt_spec()
1171 spec->arg_cnt++; in parse_usdt_spec()
1177 /* Architecture-specific logic for parsing USDT argument location specs */
1195 { {"rcx", "ecx", "cx", "cl"}, reg_off(rcx, ecx) }, in calc_pt_regs_off()
1223 return -ENOENT; in calc_pt_regs_off()
1233 /* Memory dereference case, e.g., -4@-20(%rbp) */ in parse_usdt_arg()
1234 arg->arg_type = USDT_ARG_REG_DEREF; in parse_usdt_arg()
1235 arg->val_off = off; in parse_usdt_arg()
1240 arg->reg_off = reg_off; in parse_usdt_arg()
1242 /* Register read case, e.g., -4@%eax */ in parse_usdt_arg()
1243 arg->arg_type = USDT_ARG_REG; in parse_usdt_arg()
1244 arg->val_off = 0; in parse_usdt_arg()
1250 arg->reg_off = reg_off; in parse_usdt_arg()
1253 arg->arg_type = USDT_ARG_CONST; in parse_usdt_arg()
1254 arg->val_off = off; in parse_usdt_arg()
1255 arg->reg_off = 0; in parse_usdt_arg()
1258 return -EINVAL; in parse_usdt_arg()
1261 arg->arg_signed = arg_sz < 0; in parse_usdt_arg()
1263 arg_sz = -arg_sz; in parse_usdt_arg()
1267 arg->arg_bitshift = 64 - arg_sz * 8; in parse_usdt_arg()
1272 return -EINVAL; in parse_usdt_arg()
1280 /* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */
1289 /* Memory dereference case, e.g., -2@-28(%r15) */ in parse_usdt_arg()
1290 arg->arg_type = USDT_ARG_REG_DEREF; in parse_usdt_arg()
1291 arg->val_off = off; in parse_usdt_arg()
1294 return -EINVAL; in parse_usdt_arg()
1296 arg->reg_off = offsetof(user_pt_regs, gprs[reg]); in parse_usdt_arg()
1298 /* Register read case, e.g., -8@%r0 */ in parse_usdt_arg()
1299 arg->arg_type = USDT_ARG_REG; in parse_usdt_arg()
1300 arg->val_off = 0; in parse_usdt_arg()
1303 return -EINVAL; in parse_usdt_arg()
1305 arg->reg_off = offsetof(user_pt_regs, gprs[reg]); in parse_usdt_arg()
1308 arg->arg_type = USDT_ARG_CONST; in parse_usdt_arg()
1309 arg->val_off = off; in parse_usdt_arg()
1310 arg->reg_off = 0; in parse_usdt_arg()
1313 return -EINVAL; in parse_usdt_arg()
1316 arg->arg_signed = arg_sz < 0; in parse_usdt_arg()
1318 arg_sz = -arg_sz; in parse_usdt_arg()
1322 arg->arg_bitshift = 64 - arg_sz * 8; in parse_usdt_arg()
1327 return -EINVAL; in parse_usdt_arg()
1346 return -ENOENT; in calc_pt_regs_off()
1355 if (sscanf(arg_str, " %d @ \[ %m[a-z0-9], %ld ] %n", &arg_sz, &reg_name, &off, &len) == 3) { in parse_usdt_arg()
1356 /* Memory dereference case, e.g., -4@[sp, 96] */ in parse_usdt_arg()
1357 arg->arg_type = USDT_ARG_REG_DEREF; in parse_usdt_arg()
1358 arg->val_off = off; in parse_usdt_arg()
1363 arg->reg_off = reg_off; in parse_usdt_arg()
1364 } else if (sscanf(arg_str, " %d @ \[ %m[a-z0-9] ] %n", &arg_sz, &reg_name, &len) == 2) { in parse_usdt_arg()
1365 /* Memory dereference case, e.g., -4@[sp] */ in parse_usdt_arg()
1366 arg->arg_type = USDT_ARG_REG_DEREF; in parse_usdt_arg()
1367 arg->val_off = 0; in parse_usdt_arg()
1372 arg->reg_off = reg_off; in parse_usdt_arg()
1375 arg->arg_type = USDT_ARG_CONST; in parse_usdt_arg()
1376 arg->val_off = off; in parse_usdt_arg()
1377 arg->reg_off = 0; in parse_usdt_arg()
1378 } else if (sscanf(arg_str, " %d @ %m[a-z0-9] %n", &arg_sz, &reg_name, &len) == 2) { in parse_usdt_arg()
1379 /* Register read case, e.g., -8@x4 */ in parse_usdt_arg()
1380 arg->arg_type = USDT_ARG_REG; in parse_usdt_arg()
1381 arg->val_off = 0; in parse_usdt_arg()
1386 arg->reg_off = reg_off; in parse_usdt_arg()
1389 return -EINVAL; in parse_usdt_arg()
1392 arg->arg_signed = arg_sz < 0; in parse_usdt_arg()
1394 arg_sz = -arg_sz; in parse_usdt_arg()
1398 arg->arg_bitshift = 64 - arg_sz * 8; in parse_usdt_arg()
1403 return -EINVAL; in parse_usdt_arg()
1457 return -ENOENT; in calc_pt_regs_off()
1466 if (sscanf(arg_str, " %d @ %ld ( %m[a-z0-9] ) %n", &arg_sz, &off, &reg_name, &len) == 3) { in parse_usdt_arg()
1467 /* Memory dereference case, e.g., -8@-88(s0) */ in parse_usdt_arg()
1468 arg->arg_type = USDT_ARG_REG_DEREF; in parse_usdt_arg()
1469 arg->val_off = off; in parse_usdt_arg()
1474 arg->reg_off = reg_off; in parse_usdt_arg()
1477 arg->arg_type = USDT_ARG_CONST; in parse_usdt_arg()
1478 arg->val_off = off; in parse_usdt_arg()
1479 arg->reg_off = 0; in parse_usdt_arg()
1480 } else if (sscanf(arg_str, " %d @ %m[a-z0-9] %n", &arg_sz, &reg_name, &len) == 2) { in parse_usdt_arg()
1481 /* Register read case, e.g., -8@a1 */ in parse_usdt_arg()
1482 arg->arg_type = USDT_ARG_REG; in parse_usdt_arg()
1483 arg->val_off = 0; in parse_usdt_arg()
1488 arg->reg_off = reg_off; in parse_usdt_arg()
1491 return -EINVAL; in parse_usdt_arg()
1494 arg->arg_signed = arg_sz < 0; in parse_usdt_arg()
1496 arg_sz = -arg_sz; in parse_usdt_arg()
1500 arg->arg_bitshift = 64 - arg_sz * 8; in parse_usdt_arg()
1505 return -EINVAL; in parse_usdt_arg()
1516 return -ENOTSUP; in parse_usdt_arg()