|
108 | 108 | * code through spec map. This allows BPF applications to quickly fetch the
|
109 | 109 | * actual value at runtime using a simple BPF-side code.
|
110 | 110 | *
|
111 |
| - * With basics out of the way, let's go over less immeditately obvious aspects |
| 111 | + * With basics out of the way, let's go over less immediately obvious aspects |
112 | 112 | * of supporting USDTs.
|
113 | 113 | *
|
114 | 114 | * First, there is no special USDT BPF program type. It is actually just
|
|
189 | 189 | #define USDT_NOTE_TYPE 3
|
190 | 190 | #define USDT_NOTE_NAME "stapsdt"
|
191 | 191 |
|
192 |
| -/* should match exactly enum __bpf_usdt_arg_type from bpf_usdt.bpf.h */ |
| 192 | +/* should match exactly enum __bpf_usdt_arg_type from usdt.bpf.h */ |
193 | 193 | enum usdt_arg_type {
|
194 | 194 | USDT_ARG_CONST,
|
195 | 195 | USDT_ARG_REG,
|
196 | 196 | USDT_ARG_REG_DEREF,
|
197 | 197 | };
|
198 | 198 |
|
199 |
| -/* should match exactly struct __bpf_usdt_arg_spec from bpf_usdt.bpf.h */ |
| 199 | +/* should match exactly struct __bpf_usdt_arg_spec from usdt.bpf.h */ |
200 | 200 | struct usdt_arg_spec {
|
201 | 201 | __u64 val_off;
|
202 | 202 | enum usdt_arg_type arg_type;
|
@@ -328,9 +328,9 @@ static int sanity_check_usdt_elf(Elf *elf, const char *path)
|
328 | 328 | return -EBADF;
|
329 | 329 | }
|
330 | 330 |
|
331 |
| -#if __BYTE_ORDER == __LITTLE_ENDIAN |
| 331 | +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ |
332 | 332 | endianness = ELFDATA2LSB;
|
333 |
| -#elif __BYTE_ORDER == __BIG_ENDIAN |
| 333 | +#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ |
334 | 334 | endianness = ELFDATA2MSB;
|
335 | 335 | #else
|
336 | 336 | # error "Unrecognized __BYTE_ORDER__"
|
@@ -843,7 +843,7 @@ static int bpf_link_usdt_detach(struct bpf_link *link)
|
843 | 843 | sizeof(*new_free_ids));
|
844 | 844 | /* If we couldn't resize free_spec_ids, we'll just leak
|
845 | 845 | * a bunch of free IDs; this is very unlikely to happen and if
|
846 |
| - * system is so exausted on memory, it's the least of user's |
| 846 | + * system is so exhausted on memory, it's the least of user's |
847 | 847 | * concerns, probably.
|
848 | 848 | * So just do our best here to return those IDs to usdt_manager.
|
849 | 849 | */
|
@@ -1269,6 +1269,63 @@ static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec
|
1269 | 1269 | return len;
|
1270 | 1270 | }
|
1271 | 1271 |
|
| 1272 | +#elif defined(__s390x__) |
| 1273 | + |
| 1274 | +/* Do not support __s390__ for now, since user_pt_regs is broken with -m31. */ |
| 1275 | + |
| 1276 | +static int parse_usdt_arg(const char *arg_str, int arg_num, |
| 1277 | + struct usdt_arg_spec *arg) |
| 1278 | +{ |
| 1279 | + unsigned int reg; |
| 1280 | + int sz, len; |
| 1281 | + long off; |
| 1282 | + |
| 1283 | + if (sscanf(arg_str, " %d @ %ld ( %%r%u ) %n", &sz, &off, ®, &len) == 3) { |
| 1284 | + /* Memory dereference case, e.g., -2@-28(%r15) */ |
| 1285 | + arg->arg_type = USDT_ARG_REG_DEREF; |
| 1286 | + arg->val_off = off; |
| 1287 | + if (reg > 15) { |
| 1288 | + pr_warn("usdt: unrecognized register '%%r%u'\n", reg); |
| 1289 | + return -EINVAL; |
| 1290 | + } |
| 1291 | + arg->reg_off = offsetof(user_pt_regs, gprs[reg]); |
| 1292 | + } else if (sscanf(arg_str, " %d @ %%r%u %n", &sz, ®, &len) == 2) { |
| 1293 | + /* Register read case, e.g., -8@%r0 */ |
| 1294 | + arg->arg_type = USDT_ARG_REG; |
| 1295 | + arg->val_off = 0; |
| 1296 | + if (reg > 15) { |
| 1297 | + pr_warn("usdt: unrecognized register '%%r%u'\n", reg); |
| 1298 | + return -EINVAL; |
| 1299 | + } |
| 1300 | + arg->reg_off = offsetof(user_pt_regs, gprs[reg]); |
| 1301 | + } else if (sscanf(arg_str, " %d @ %ld %n", &sz, &off, &len) == 2) { |
| 1302 | + /* Constant value case, e.g., 4@71 */ |
| 1303 | + arg->arg_type = USDT_ARG_CONST; |
| 1304 | + arg->val_off = off; |
| 1305 | + arg->reg_off = -1; |
| 1306 | + } else { |
| 1307 | + pr_warn("usdt: unrecognized arg #%d spec '%s'\n", arg_num, |
| 1308 | + arg_str); |
| 1309 | + return -EINVAL; |
| 1310 | + } |
| 1311 | + |
| 1312 | + arg->arg_signed = sz < 0; |
| 1313 | + if (sz < 0) |
| 1314 | + sz = -sz; |
| 1315 | + |
| 1316 | + switch (sz) { |
| 1317 | + case 1: case 2: case 4: case 8: |
| 1318 | + arg->arg_bitshift = 64 - sz * 8; |
| 1319 | + break; |
| 1320 | + default: |
| 1321 | + pr_warn("usdt: unsupported arg #%d (spec '%s') size: %d\n", |
| 1322 | + arg_num, arg_str, sz); |
| 1323 | + return -EINVAL; |
| 1324 | + } |
| 1325 | + |
| 1326 | + return len; |
| 1327 | +} |
| 1328 | + |
1272 | 1329 | #else
|
1273 | 1330 |
|
1274 | 1331 | static int parse_usdt_arg(const char *arg_str, int arg_num, struct usdt_arg_spec *arg)
|
|
0 commit comments