Currently pseudo probe encoding for a function is like:
- For the first probe, a relocation from it to its physical position in the code body
- For subsequent probes, an incremental offset from the current probe to the previous probe
The relocation could potentially cause relocation overflow during link time. I'm now replacing it with an offset from the first probe to the function start address.
A source function could be lowered into multiple split functions due to outlining (e.g, coro-split). Since those split functions have independent link-time layout, to really avoid relocations from .pseudo_probe sections to .text sections, the offset to replace with should really be the offset from the probe's enclosing split function, rather than from the entry of the source function. This requires some changes to previous section-based emission scheme which now switches to be function-based. The assembly form of pseudo probe directive is also changed correspondingly, i.e, reflecting the split function name.
A sentinel probe is emitted for each of the functions with a different name from the source. The sentinel probe indicates the elf symbol name to differentiate subsequent probes from the ones from a different split function. For examples, given source function
Foo() { … Probe 1 … Probe 2 }
If it is transformed into two split functions:
Foo: … Foo.outlined: …
The encoding for the two split functions will be separate:
GUID of Foo Probe 1 GUID of Foo Sentinel probe of Foo.outlined Probe 2
Then probe1 will be decoded against binary Foo's address, and Probe 2 will be decoded against Foo.outlined. The sentinel probe of Foo.outlined makes sure there's not accidental relocation from Foo.outlined's probes to Foo's entry address.
Decoding change will be in separate patch.
nit on comment: split function entry address? main body doesn't have it.