| #!/bin/sh |
| # SPDX-License-Identifier: GPL-2.0 |
| # description: Generic dynamic event - add/remove/test uprobe events |
| # requires: uprobe_events |
| |
| if ! which readelf > /dev/null 2>&1 ; then |
| echo "No readelf found. skipped." |
| exit_unresolved |
| fi |
| |
| echo 0 > events/enable |
| echo > dynamic_events |
| |
| REALBIN=`readlink -f /bin/sh` |
| |
| # Get the entry point virtual address from ELF header |
| ENTRY=`readelf -hW ${REALBIN} | grep "Entry point" | awk '{print $NF}'` |
| |
| # Convert virtual address to file offset: find the LOAD segment containing |
| # the entry point, then compute file_offset = e_entry - p_vaddr + p_offset. |
| # For PIE binaries this is a no-op (vaddr == file offset), but for non-PIE |
| # executables the virtual address is much larger than the file size and |
| # must be converted, otherwise uprobe_register() rejects it with -EINVAL. |
| ENTRY_DEC=$(printf '%d' "$ENTRY") |
| OFFSET=$ENTRY |
| while IFS= read -r line; do |
| set -- $line |
| [ "$1" = "LOAD" ] || continue |
| VA_DEC=$(printf '%d' "$3") |
| OFF_DEC=$(printf '%d' "$2") |
| FSZ_DEC=$(printf '%d' "$5") |
| if [ "$ENTRY_DEC" -ge "$VA_DEC" ] && [ "$ENTRY_DEC" -lt "$((VA_DEC + FSZ_DEC))" ]; then |
| OFFSET=$(printf '0x%x' "$((ENTRY_DEC - VA_DEC + OFF_DEC))") |
| break |
| fi |
| done << EOF |
| $(readelf -lW ${REALBIN} | grep LOAD) |
| EOF |
| |
| echo "p:myevent ${REALBIN}:${OFFSET}" >> uprobe_events |
| |
| grep -q myevent uprobe_events |
| test -d events/uprobes/myevent |
| |
| echo 1 > events/uprobes/myevent/enable |
| echo 'ls' | /bin/sh > /dev/null |
| echo 0 > events/uprobes/myevent/enable |
| grep -q myevent trace |
| |
| echo "-:myevent" >> uprobe_events |
| ! grep -q myevent uprobe_events |
| |
| echo > uprobe_events |
| |
| clear_trace |