133 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#include <stdio.h>4#include <string.h>5#include <stdbool.h>6#include <stdint.h>7#include <sys/mman.h>8#include <unistd.h>9#include <sdt.h>10 11#ifndef MADV_POPULATE_READ12#define MADV_POPULATE_READ 2213#endif14 15int __attribute__((weak)) uprobe(void)16{17 return 0;18}19 20#define __PASTE(a, b) a##b21#define PASTE(a, b) __PASTE(a, b)22 23#define NAME(name, idx) PASTE(name, idx)24 25#define DEF(name, idx) int __attribute__((weak)) NAME(name, idx)(void) { return 0; }26#define CALL(name, idx) NAME(name, idx)();27 28#define F(body, name, idx) body(name, idx)29 30#define F10(body, name, idx) \31 F(body, PASTE(name, idx), 0) F(body, PASTE(name, idx), 1) F(body, PASTE(name, idx), 2) \32 F(body, PASTE(name, idx), 3) F(body, PASTE(name, idx), 4) F(body, PASTE(name, idx), 5) \33 F(body, PASTE(name, idx), 6) F(body, PASTE(name, idx), 7) F(body, PASTE(name, idx), 8) \34 F(body, PASTE(name, idx), 9)35 36#define F100(body, name, idx) \37 F10(body, PASTE(name, idx), 0) F10(body, PASTE(name, idx), 1) F10(body, PASTE(name, idx), 2) \38 F10(body, PASTE(name, idx), 3) F10(body, PASTE(name, idx), 4) F10(body, PASTE(name, idx), 5) \39 F10(body, PASTE(name, idx), 6) F10(body, PASTE(name, idx), 7) F10(body, PASTE(name, idx), 8) \40 F10(body, PASTE(name, idx), 9)41 42#define F1000(body, name, idx) \43 F100(body, PASTE(name, idx), 0) F100(body, PASTE(name, idx), 1) F100(body, PASTE(name, idx), 2) \44 F100(body, PASTE(name, idx), 3) F100(body, PASTE(name, idx), 4) F100(body, PASTE(name, idx), 5) \45 F100(body, PASTE(name, idx), 6) F100(body, PASTE(name, idx), 7) F100(body, PASTE(name, idx), 8) \46 F100(body, PASTE(name, idx), 9)47 48#define F10000(body, name, idx) \49 F1000(body, PASTE(name, idx), 0) F1000(body, PASTE(name, idx), 1) F1000(body, PASTE(name, idx), 2) \50 F1000(body, PASTE(name, idx), 3) F1000(body, PASTE(name, idx), 4) F1000(body, PASTE(name, idx), 5) \51 F1000(body, PASTE(name, idx), 6) F1000(body, PASTE(name, idx), 7) F1000(body, PASTE(name, idx), 8) \52 F1000(body, PASTE(name, idx), 9)53 54F10000(DEF, uprobe_multi_func_, 0)55F10000(DEF, uprobe_multi_func_, 1)56F10000(DEF, uprobe_multi_func_, 2)57F10000(DEF, uprobe_multi_func_, 3)58F10000(DEF, uprobe_multi_func_, 4)59 60static int bench(void)61{62 F10000(CALL, uprobe_multi_func_, 0)63 F10000(CALL, uprobe_multi_func_, 1)64 F10000(CALL, uprobe_multi_func_, 2)65 F10000(CALL, uprobe_multi_func_, 3)66 F10000(CALL, uprobe_multi_func_, 4)67 return 0;68}69 70#define PROBE STAP_PROBE(test, usdt);71 72#define PROBE10 PROBE PROBE PROBE PROBE PROBE \73 PROBE PROBE PROBE PROBE PROBE74#define PROBE100 PROBE10 PROBE10 PROBE10 PROBE10 PROBE10 \75 PROBE10 PROBE10 PROBE10 PROBE10 PROBE1076#define PROBE1000 PROBE100 PROBE100 PROBE100 PROBE100 PROBE100 \77 PROBE100 PROBE100 PROBE100 PROBE100 PROBE10078#define PROBE10000 PROBE1000 PROBE1000 PROBE1000 PROBE1000 PROBE1000 \79 PROBE1000 PROBE1000 PROBE1000 PROBE1000 PROBE100080 81static int usdt(void)82{83 PROBE1000084 PROBE1000085 PROBE1000086 PROBE1000087 PROBE1000088 return 0;89}90 91extern char build_id_start[];92extern char build_id_end[];93 94int __attribute__((weak)) trigger_uprobe(bool build_id_resident)95{96 int page_sz = sysconf(_SC_PAGESIZE);97 void *addr;98 99 /* page-align build ID start */100 addr = (void *)((uintptr_t)&build_id_start & ~(page_sz - 1));101 102 /* to guarantee MADV_PAGEOUT work reliably, we need to ensure that103 * memory range is mapped into current process, so we unconditionally104 * do MADV_POPULATE_READ, and then MADV_PAGEOUT, if necessary105 */106 madvise(addr, page_sz, MADV_POPULATE_READ);107 if (!build_id_resident)108 madvise(addr, page_sz, MADV_PAGEOUT);109 110 (void)uprobe();111 112 return 0;113}114 115int main(int argc, char **argv)116{117 if (argc != 2)118 goto error;119 120 if (!strcmp("bench", argv[1]))121 return bench();122 if (!strcmp("usdt", argv[1]))123 return usdt();124 if (!strcmp("uprobe-paged-out", argv[1]))125 return trigger_uprobe(false /* page-out build ID */);126 if (!strcmp("uprobe-paged-in", argv[1]))127 return trigger_uprobe(true /* page-in build ID */);128 129error:130 fprintf(stderr, "usage: %s <bench|usdt>\n", argv[0]);131 return -1;132}133