|
10 | 10 | #include <pthread.h>
|
11 | 11 | #include <unistd.h>
|
12 | 12 | #include <linux/perf_event.h>
|
| 13 | +#include <linux/fs.h> |
| 14 | +#include <sys/ioctl.h> |
13 | 15 | #include <sys/mman.h>
|
14 | 16 | #include "trace_helpers.h"
|
15 | 17 | #include <linux/limits.h>
|
@@ -244,29 +246,91 @@ int kallsyms_find(const char *sym, unsigned long long *addr)
|
244 | 246 | return err;
|
245 | 247 | }
|
246 | 248 |
|
| 249 | +#ifdef PROCMAP_QUERY |
| 250 | +int env_verbosity __weak = 0; |
| 251 | + |
| 252 | +int procmap_query(int fd, const void *addr, __u32 query_flags, size_t *start, size_t *offset, int *flags) |
| 253 | +{ |
| 254 | + char path_buf[PATH_MAX], build_id_buf[20]; |
| 255 | + struct procmap_query q; |
| 256 | + int err; |
| 257 | + |
| 258 | + memset(&q, 0, sizeof(q)); |
| 259 | + q.size = sizeof(q); |
| 260 | + q.query_flags = query_flags; |
| 261 | + q.query_addr = (__u64)addr; |
| 262 | + q.vma_name_addr = (__u64)path_buf; |
| 263 | + q.vma_name_size = sizeof(path_buf); |
| 264 | + q.build_id_addr = (__u64)build_id_buf; |
| 265 | + q.build_id_size = sizeof(build_id_buf); |
| 266 | + |
| 267 | + err = ioctl(fd, PROCMAP_QUERY, &q); |
| 268 | + if (err < 0) { |
| 269 | + err = -errno; |
| 270 | + if (err == -ENOTTY) |
| 271 | + return -EOPNOTSUPP; /* ioctl() not implemented yet */ |
| 272 | + if (err == -ENOENT) |
| 273 | + return -ESRCH; /* vma not found */ |
| 274 | + return err; |
| 275 | + } |
| 276 | + |
| 277 | + if (env_verbosity >= 1) { |
| 278 | + printf("VMA FOUND (addr %08lx): %08lx-%08lx %c%c%c%c %08lx %02x:%02x %ld %s (build ID: %s, %d bytes)\n", |
| 279 | + (long)addr, (long)q.vma_start, (long)q.vma_end, |
| 280 | + (q.vma_flags & PROCMAP_QUERY_VMA_READABLE) ? 'r' : '-', |
| 281 | + (q.vma_flags & PROCMAP_QUERY_VMA_WRITABLE) ? 'w' : '-', |
| 282 | + (q.vma_flags & PROCMAP_QUERY_VMA_EXECUTABLE) ? 'x' : '-', |
| 283 | + (q.vma_flags & PROCMAP_QUERY_VMA_SHARED) ? 's' : 'p', |
| 284 | + (long)q.vma_offset, q.dev_major, q.dev_minor, (long)q.inode, |
| 285 | + q.vma_name_size ? path_buf : "", |
| 286 | + q.build_id_size ? "YES" : "NO", |
| 287 | + q.build_id_size); |
| 288 | + } |
| 289 | + |
| 290 | + *start = q.vma_start; |
| 291 | + *offset = q.vma_offset; |
| 292 | + *flags = q.vma_flags; |
| 293 | + return 0; |
| 294 | +} |
| 295 | +#else |
| 296 | +int procmap_query(int fd, const void *addr, size_t *start, size_t *offset, int *flags) |
| 297 | +{ |
| 298 | + return -EOPNOTSUPP; |
| 299 | +} |
| 300 | +#endif |
| 301 | + |
247 | 302 | ssize_t get_uprobe_offset(const void *addr)
|
248 | 303 | {
|
249 |
| - size_t start, end, base; |
250 |
| - char buf[256]; |
251 |
| - bool found = false; |
| 304 | + size_t start, base, end; |
252 | 305 | FILE *f;
|
| 306 | + char buf[256]; |
| 307 | + int err, flags; |
253 | 308 |
|
254 | 309 | f = fopen("/proc/self/maps", "r");
|
255 | 310 | if (!f)
|
256 | 311 | return -errno;
|
257 | 312 |
|
258 |
| - while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &base) == 4) { |
259 |
| - if (buf[2] == 'x' && (uintptr_t)addr >= start && (uintptr_t)addr < end) { |
260 |
| - found = true; |
261 |
| - break; |
| 313 | + /* requested executable VMA only */ |
| 314 | + err = procmap_query(fileno(f), addr, PROCMAP_QUERY_VMA_EXECUTABLE, &start, &base, &flags); |
| 315 | + if (err == -EOPNOTSUPP) { |
| 316 | + bool found = false; |
| 317 | + |
| 318 | + while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &base) == 4) { |
| 319 | + if (buf[2] == 'x' && (uintptr_t)addr >= start && (uintptr_t)addr < end) { |
| 320 | + found = true; |
| 321 | + break; |
| 322 | + } |
| 323 | + } |
| 324 | + if (!found) { |
| 325 | + fclose(f); |
| 326 | + return -ESRCH; |
262 | 327 | }
|
| 328 | + } else if (err) { |
| 329 | + fclose(f); |
| 330 | + return err; |
263 | 331 | }
|
264 |
| - |
265 | 332 | fclose(f);
|
266 | 333 |
|
267 |
| - if (!found) |
268 |
| - return -ESRCH; |
269 |
| - |
270 | 334 | #if defined(__powerpc64__) && defined(_CALL_ELF) && _CALL_ELF == 2
|
271 | 335 |
|
272 | 336 | #define OP_RT_RA_MASK 0xffff0000UL
|
@@ -307,15 +371,25 @@ ssize_t get_rel_offset(uintptr_t addr)
|
307 | 371 | size_t start, end, offset;
|
308 | 372 | char buf[256];
|
309 | 373 | FILE *f;
|
| 374 | + int err, flags; |
310 | 375 |
|
311 | 376 | f = fopen("/proc/self/maps", "r");
|
312 | 377 | if (!f)
|
313 | 378 | return -errno;
|
314 | 379 |
|
315 |
| - while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &offset) == 4) { |
316 |
| - if (addr >= start && addr < end) { |
317 |
| - fclose(f); |
318 |
| - return (size_t)addr - start + offset; |
| 380 | + err = procmap_query(fileno(f), (const void *)addr, 0, &start, &offset, &flags); |
| 381 | + if (err == 0) { |
| 382 | + fclose(f); |
| 383 | + return (size_t)addr - start + offset; |
| 384 | + } else if (err != -EOPNOTSUPP) { |
| 385 | + fclose(f); |
| 386 | + return err; |
| 387 | + } else if (err) { |
| 388 | + while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &offset) == 4) { |
| 389 | + if (addr >= start && addr < end) { |
| 390 | + fclose(f); |
| 391 | + return (size_t)addr - start + offset; |
| 392 | + } |
319 | 393 | }
|
320 | 394 | }
|
321 | 395 |
|
|
0 commit comments