Instrumenting Binaries
decides which functions of a program get instrumented and
either does it while the program runs or writes a new instrumented binary. For the
full, current flag list run
rocprof-sys-instrument --help
(use
--help | grep -A3 -- --<flag>
for one flag).
How to answer
Keep answers short: under about 1200 characters unless the user asks for more.
Lead with the direct answer and the command, then add only the caveats from this
skill that apply to the question (for example: binary rewrite skips shared libraries,
ignores
,
pairs with a lower
, how to list modules with
). Do not add alternatives or background nobody asked for.
Prerequisites
- and on ; if not, run
source <install-prefix>/share/rocprofiler-systems/setup-env.sh
.
- Build the target with when you can: modules are then source files and the
tool can report file and line information. Without debug info a whole binary is
one module named after the binary.
Runtime instrumentation vs binary rewrite
| Runtime instrumentation | Binary rewrite |
|---|
| Selected by | the default (no ) | |
| Command | rocprof-sys-instrument [opts] -- ./app args
| rocprof-sys-instrument [opts] -o app.inst -- ./app
|
| What gets instrumented | the executable and the shared libraries it loads | only the target's own code; shared libraries are not instrumented |
| Cost (upstream guidance) | more memory, slower to set up, more run-time overhead | much faster to set up, lower overhead |
| Runs the app | yes, immediately, with | no; run rocprof-sys-run -- ./app.inst args
later |
| Arguments after the target | passed to the app | ignored (give them when you run the result) |
- Pick runtime when the performance of the libraries the app loads matters.
- Pick binary rewrite for the lowest overhead, for repeated runs, and for MPI
applications (upstream guidance).
- (runtime only) leaves every shared library out;
--max-library-functions N
skips shared libraries with more than functions
(default 20000; disables the check).
- with no file name writes in the current directory (target in the
current directory) or for a library.
Function vs module
- A function is one symbol, for example or .
- A module is the container a function is defined in: its source file when
the binary has debug info (), otherwise the binary or library
itself (). Shared libraries appear as their own modules in runtime mode.
bash
rocprof-sys-instrument --simulate -o app.inst --print-available modules -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-available functions -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-available pair -- ./app
prints one
[module] --> [function][#instructions]
line per function.
Module options (
,
,
) act on every function in the matching modules;
function options (
,
,
) act on individual functions.
Including, excluding and restricting
| Option | Meaning |
|---|
| / (include) | Force these in, even if the size heuristics would skip them. Does not narrow anything else. |
| / (restrict) | Instrument only what matches, ignoring the size heuristics. |
| / (exclude) | Never instrument these. Always applied, and wins over include and restrict. |
Matching rules (all verified):
- Patterns are regular expressions matched anywhere in the name (substring, not
anchored). matches and ; write for an exact match.
- Several patterns after one option are OR'd: is the same as
.
- Module patterns match the module name (the source file or binary path). Function
patterns match the function name, and also the signature when is set
(so only works together with ).
- Exclude beats include at any level: instruments nothing.
- instruments every function of , including tiny ones and ones
with loops, regardless of the size thresholds.
Gotcha: if you give both
and
, the function
restriction is silently ignored.
-MR mod_a -R '^medium_b$'
instrumented all of
, not the union the upstream docs describe. Use one of the two, or combine
with
.
Examples:
bash
# Only one source file
rocprof-sys-instrument -o app.inst -MR 'solver\.cpp$' -- ./app
# Everything the heuristics pick, minus one noisy library
rocprof-sys-instrument -o app.inst -ME 'libm\.so' -- ./app
# Add a small function the heuristics skip
rocprof-sys-instrument -o app.inst -I '^small_helper$' -- ./app
Dry run
A dry run shows what would be instrumented without instrumenting anything.
bash
rocprof-sys-instrument --simulate [options] -- ./app
rocprof-sys-instrument --simulate -o app.inst --print-instrumented pair -- ./app
rocprof-sys-instrument --dump-info --simulate -o app.inst -- ./app
- Exits after the analysis. It does not run the application and does not
write the rewritten binary, even with .
- Prints a per-module summary (
N instrumented funcs in <module>
).
- With , , ,
or it also prints those lists. Each takes
, or ; the forms (, ) also show
the function signature when is used.
- Writes , , and reports as
and to
rocprofsys-<name>-output/instrumentation/
, where is
the target (runtime) or the output name (rewrite, e.g. rocprofsys-app.inst-output
).
- (or ) limits the formats. Set
to move the directory. had no effect in either build tested.
- The files list address, address range, instruction count, linkage,
visibility, module and function. The files add a per-function
block (see "Why is a function missing?").
- Without , still produces the rewritten binary as usual.
Workflow: dry run, read
and
, adjust the regexes or
thresholds, repeat, then drop
.
Granularity
A function is instrumented only if it passes both size checks (verified):
- at least instructions (default 1024), and
- an address range of at least bytes (default 4 x the
instruction minimum, so 4096).
Interactions that surprise people:
- Giving only sets the address-range minimum to 0 (only instruction count
matters), and giving only sets the instruction minimum to 0. Giving both
applies both. or therefore disables both size checks. It does not
instrument every function: a function must still have at least 2 instructions, be
instrumentable by Dyninst, and pass the exclude, overlap, trap, linkage and visibility
checks, and it is never taken from the profiler's own or system modules.
- The environment variable
ROCPROFSYS_DEFAULT_MIN_INSTRUCTIONS
changes the default
instruction minimum, and the default range with it.
- Functions that contain loops use and
, which follow the non-loop values unless set. These
options decide whether a function with a loop is instrumented at all.
- / additionally instruments the loops inside instrumented
functions. In a profile each loop shows as a child entry named with its source
range, for example
loop_a [{449,54}-{449,83}]
, and the function's own self time
drops accordingly.
Example from a small test program (instruction counts: 7, 16, 79, 429, 3657):
| Options | Instrumented functions |
|---|
| default | only the 3657-instruction function |
| the 429 and 3657 functions |
| 79, 429 and 3657 |
| all five |
| 429 and 3657 (the 79-instruction function is only 278 bytes) |
More detail means more overhead and a bigger trace. Lower the thresholds or add
to see inside hot code; raise them, restrict to modules, or use
to cut
overhead. Other gates (
,
,
,
,
,
) are described in
.
Why is a function missing, or why is there too much?
Missing function:
- List what was skipped:
--simulate --print-excluded pair
, or .
- Open , find the function and read its block
( is the verdict). The fields come in two kinds, and the
cause is a different value in each.
- Capability fields: false is the cause. ,
and false mean Dyninst has no usable
entry or exit point for the function. No option fixes that, so accept the gap or
instrument its callers.
- Constraint fields: true is the cause.
is_address_range_constrained
, is_num_instructions_constrained
(and the
variants): too small. Lower /, or add .
- : one of your / patterns matches it.
- : a / pattern did not match it.
is_overlapping_constrained
: needs .
is_entry_trap_constrained
, : needs .
- ,
is_visibility_constrained
: see , .
- : it belongs to the profiler's own libraries.
- : its module is one the profiler never instruments
(system library, Dyninst, or its own libraries).
- : its name is one the profiler never instruments.
- No field at all: a function with fewer than 2 instructions is always skipped.
If every capability field is true and no constraint field is true, check
(verified: a 1-instruction function stays excluded even with
).
- If the function is in a shared library, remember binary rewrite never sees it.
Too much data or too slow: raise
, restrict to the modules you care about
(
), exclude noisy ones (
), drop
, or add
.
Libraries, RPATH and troubleshooting
Rewriting a shared library so a normal executable loads the instrumented copy:
bash
rocprof-sys-instrument -o ./app.inst -- ./app
mkdir inst && rocprof-sys-instrument -o inst/libfoo.so -- ./libfoo.so
LD_LIBRARY_PATH=$PWD/inst:$LD_LIBRARY_PATH rocprof-sys-run -- ./app.inst
ldd ./app.inst | grep libfoo # must resolve into inst/
- Keep the same file name for the rewritten library (, or the soname
that shows) and write it to a different directory.
- RPATH vs RUNPATH: the loader searches directories before
, so if the original library is in an RPATH directory it is loaded
instead of your rewritten copy.
If the RPATH directories do not contain the library, is still used,
and a binary with searches first.
Check with
objdump -p <exe> | egrep 'RPATH|RUNPATH'
and . Only patch the
binary when shows the original library. Relink with ,
or change the entry with :
patchelf --remove-rpath <exe>
makes win, and
patchelf --set-rpath <dir> <exe>
writes a , so it does too. Adding
keeps a , which brings the problem back.
- Library as a runtime target:
rocprof-sys-instrument -- ./libfoo.so
prints
"is not executable ... Switching to binary rewrite mode and assuming
'--simulate --all-functions'", so you get a dry-run approximation and no run.
is only meant for executables whose name looks like a library;
forcing it on a real aborted inside Dyninst in testing.
- Main function not found: pass it with (or ).
- "Failed to transform trace ... in function '<f>'" (upstream guidance, not
reproduced): add . Functions that share code with it can still pull it
in; exclude those too, or exclude the whole module with .
Running the result and embedding defaults
- Run a rewritten binary with
rocprof-sys-run -- ./app.inst args
; the instrumented
functions then appear in the profile or trace like any other.
- embeds defaults in the new binary so a later session does not
need to export them. A variable set at run time still overrides the embedded value
(verified with ).
--label args file line return
adds that information to function names (for
example with ).
- instruments only to start and stop the sampler (verified), and
is deprecated upstream; for sampling use or a preset.
Common Mistakes
| Mistake | Fix |
|---|
| Expecting binary rewrite to instrument shared libraries | It only covers the target's own code. Use runtime mode, or rewrite the library too. |
| Using to narrow the selection | only adds. Narrow with /, or exclude with /. |
| Writing and expecting an exact match | Patterns are unanchored substrings. Use . |
| Combining and | The function restriction is ignored. Use one, or plus . |
| Lowering only and expecting range to still apply | One option given sets the other to 0. Pass both to apply both. |
| Passing app arguments after the target in a rewrite | They are ignored; pass them to rocprof-sys-run -- ./app.inst args
. |
| Putting a rewritten library next to a binary with | is ignored. Check with and relink or patch the rpath. |
| Expecting to produce the binary | A dry run writes only reports; remove . |
| Relying on | It had no effect in tested builds; use . |