<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/104678>104678</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
Function Signature Change Without Obvious Indication
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
yonghong-song
</td>
</tr>
</table>
<pre>
BPF is a linux kernel technology which allows to run some custom
codes in kernel. Specially, BPF allows to tracing kernel functions
given a function signature. For example in [1], in include/linux/hrtimer.h,
we have
```
extern void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
u64 range_ns, const enum hrtimer_mode mode);
```
The following bpf program can be written to trace kernel function
hrtimer_start_range_ns():
```
SEC("fentry/hrtimer_start_range_ns")
int BPF_PROG(handle__fentry, struct hrtimer *timer, ktime_t tim, u64 delta_ns,
const enum hrtimer_mode mode)
{
if (tim == MY_TV_NSEC)
fentry_called = true;
return 0;
}
```
The function 'hrtimer_start_range_ns' needs to be in kernel /proc/kallsyms
so proper kernel address can be found for the to-be-traced function.
```
$ cat /proc/kallsyms | grep hrtimer_start_range_ns
ffffffff8134fd90 T __pfx_hrtimer_start_range_ns
ffffffff8134fda0 T hrtimer_start_range_ns
ffffffff84dec2c8 r __ksymtab_hrtimer_start_range_ns
```
But in clang, it seems possible that function signature might be changed
during optimization without changing function names. I tried
kernel/bpf/syscall.c with additional option '-mllvm -debug-only=deadargelim'
which intends to print out some information for DeadArgumentElimination pass.
Eventually, I found three function signature changes:
```
DeadArgumentEliminationPass - Removing argument 1 (uattr.coerce0) from map_update_elem
DeadArgumentEliminationPass - Removing argument 1 (uattr.coerce0) from map_delete_elem
DeadArgumentEliminationPass - Removing argument 3 (count) from strncpy_from_bpfptr
```
The following are IR before and after DeadArgumentEliminationPass:
Before:
```
define internal fastcc i32 @map_update_elem(ptr noundef %attr, ptr nocapture readnone %uattr.coerce0, i8 %uattr.coerce1)
define internal fastcc i32 @map_delete_elem(ptr noundef %attr, ptr nocapture readnone %uattr.coerce0, i8 %uattr.coerce1)
define internal fastcc i64 @strncpy_from_bpfptr(ptr noundef %dst, ptr %src.coerce0, i8 %src.coerce1, i64 noundef %count)
```
After:
```
define internal fastcc i32 @map_update_elem(ptr noundef %attr, i8 %uattr.coerce1)
define internal fastcc i32 @map_delete_elem(ptr noundef %attr, i8 %uattr.coerce1)
define internal fastcc i64 @strncpy_from_bpfptr(ptr noundef %dst, ptr %src.coerce0, i8 %src.coerce1)
$ nm kernel/bpf/syscall.o | grep map_update_elem
...
000000000000b6b0 t map_update_elem
$ nm kernel/bpf/syscall.o | grep map_delete_elem
000000000000bd00 t map_delete_elem
$ nm kernel/bpf/syscall.o | grep strncpy_from_bpfptr
0000000000015d90 t strncpy_from_bpfptr
$
```
You can see the above function name remains the same in symbol table but actually
the number of arguments have changed.
ArgumentPromotion could also change function signature without change function names.
This pass is enabled at -O3 or with LTO. Let us say thinLTO is enabled to build the kernel
and "-mllvm -debug-only=argpromotion" is added to dump certain transformation info.
I hit a case with file tools/lib/subcmd/exec-cmd.c.
Before:
```
define internal fastcc void @report(ptr nocapture noundef readnone %prefix, ptr nocapture noundef readonly %err, ptr noundef %params)
```
After:
```
define internal fastcc void @report(ptr nocapture noundef readonly %err, ptr noundef %params)
$ nm exec-cmd.o | grep 'report'
0000000000000790 t report
```
gcc has various suffix like .constprop.<n>, .part.<n>, .isra.<n> to indicate
func signature having changed. For clang, looks like PartialInlining is not enabled by default.
The above ArgumentPromotion is quite similar to .constprop.<n>. I am not sure whether clang
does .isra.<n>-like transformation or not.
If clang optimization changes a function signature, ideally case we could
like to have changed signature somewhere (e.g. dwarf) for users easily to do bpf func tracing.
But at least we could have a way to encode such signature change information somewhere
(dwarf, adding suffix, etc.)?
[1] https://github.com/torvalds/linux
[2] https://github.com/torvalds/linux/blob/master/tools/testing/selftests/bpf/progs/test_vmlinux.c#L81-L88
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJzMWFtv47oR_jXMy8CCTDux8-CHTbIuAmy7i92gxXkyKHIksaFIlRw5cX99QUryJbH3bNDTi7HYSBTnwrl8M0MRgq4s4opd37HrhyvRUe38audsVTtbTYKz1VXh1G51920NOoAAo233Cs_oLRoglLV1xlU7eKm1rEEY414CkAPfWQiuQZBdINew_IHln6RTGEDbgT6DHy1KLYzZMX4PUcaBAXkhta1GUWVnJWlnQ8-p0lu0IPbLEA8iqPOYAaydB3wVTWswCmPXd1N2_RBFaAvaStMpZHydjsL4uvakG_RZzfh9z_0FoRZb7F_YTT78S68A-EroLWydVjDQbgIJTxsvbIUbGxhfBvKdpPE7MP4pPUQlnuPThoB0s5cI3c0cDuT3IJ0NBGi7Zi-jcQoh_sf4LZvdndXuqUYoXTRitF3RltB6V3nRgBQWCoQXr4nQjhbGt_bt2Vw8VhL96bxhfny-Tzt4iZb87mDZd2x4ZDNYU1uKnt98-_71T4wva2GVwc1m5HEPv2zJZEOFhkRvw1HCye_37DrQsMXdKbkugfEl6QbY7IHNHuDPv22e_rr5Szr0SNYrvZHCGFRxI5DvcO-rkZdH6ryF_OgDWzxc9ucY44wvLll0ARZRpcQp8JBhwPi69U4yvn4WxoRdM-RPcDEwWvTjRqGUxxDGMCldZxWUzgPVCOQmBU5SvKi9Otn5KGB8DlLQGcnAFvdQeWwvZc1gi3L4Laezealuc3iCzaYtXzcfIROR7BcJ5goll0vwsNk8h11DoviprDdHvusoWlwaYasEMgQBsQnQuhB0YRCoFnQGqqDRVU3R3LKOAlTPT3U-Jq9rSTf6nyLRvGiqXUf9xvh1z82KBkMGj0Bejxx6nzK-LtqS8XXYhRiSmUxsoqt1JBUmyegDa9IYs21gorDoqomzZsdmDwqFEr5CE_NrMWBjAnptCW0fb62PKRyVS3ivbel802sd4-cBhfrkq65BS5-NbrTtv7UihCGEPm_RUjeWgcch-Kj2iOes1hsrXMShSyK_iRBgAt-xcdtoQjFsgWlM7U4Q-Uw69BJzxm-h9K6BRrSbrlWCcIMGhzL2RwtQaPBUwIclzKIE6TpLe86BvJXtbhNfNkVbtuR_oWQIj_D4HQosnUcQVoEoCS-6MSp0cESfDon0sncUltpiiiAfY7AUgaQEPePA5vlbg_NlSx5sjAiMEHwdrRjDpF-Wok0x4VEo6yzGHW8MfQ96-XZ5egT1v6_PsX_-d_rczKM-57z6TicVaFSJ8evg5Xvph8VpWryZHzMYI-msCz_FgPiP-_e_4rT_O0_cHmcSpGJqG7iA5-5QUc_jFGRZNj7mR7_ipsiBLhF9SOgZ7DqRpPJR0pmdvyzpIpYdC5tex2aBfrI5Cjwbtb-5LnU-ATE1PKJwWzytseCxEdqG9D2IVOkg7JrCGSARq3zREQg5FLLENm61XVOgB1fuwTqk4WKs-dmxx0eE_eZd45Jo6TqjQJjgBoJzFfGkO8C3vcEI8zqkohvnOLRRYwWCYPJ1Bs73ncGXp68ZfEGCLkAQO6Ba2y9PX48pYoPZaaOSGQbHJf6xVDDOz_YRwlfteCLGeZokleq5qa5pQaInoW0cSWw49A-xlxjUf4RaEwiQIvTnhVLHzso5E9IsV8TI6QrZKMbX-IpyIhuVyezfKkppxmPz3GPrPO3Te0T5MdGP0b71WOrX9xXheG80S9yL_qh07DGjFV404Y9F3w8c5GPKnWby3u5Hucv4YpS6OAcR-SJl7bDn3KkqKaEWAbbCaxdDsytL_QpGPyNkaaCLs0zGZveWzT5HpbNWeDpZ0MGLcSGGnbZKS0HDjB8z5iifapG6qzFD04XCvr03zj2HXvg34UkL82iNtpFAB7CO9rlS7KI7RGcoO7RaPbS8T3Qd4B-dJoSgG22Ej0q-P1xs9EWTpISU-TVSjaN2_fjgMJyed5KUfZNbLrqVTtDnsez5nI4eQ7t99rIlVTGFEfGGzMQesXqGvVx3gndHZo7zwkuNPubNErMqA_UifJk6WOehC-gDoAja7BJSuHShkXw13A5lhwlMEBgUgfYq9FIFvIhEjVbGOT90sn43S5wMLXutBtPw5aDVfZqcbDXEX1xAklm6Elm_SYf-yglqojb1x3zN-LrSVHdFJl3D-Jqc3wqjwv4i6kDKP0rK14VxEQAbESI6xC09LhIG0jFu1wFNGd_Cvs623lXjns22Sawyyfjsy3I6-bJcXqnVTN3ObsUVrqYLPrudXi-Ws6t6tZSlnOY5XxQlLyRO-ZLnYnnNb_E2lwuVX-kVz_k8X04X0wW_nc8yMS1nS5yJ2U055_O8YPM8VlOTxWKROV9d6RA6XE3z-c1ieWVEgSakW0nOLb5A-sp4NMyVX0WiSdFVgc1zowOFAxvSZHC1HgP1x97R972j_zZUyq_FNkHJYw8D2tmrzpvVT4weRQx_Jq13f0dJjK-TYtGIg-bbFf9XAAAA__8ZtftA">