<table border="1" cellspacing="0" cellpadding="8">
    <tr>
        <th>Issue</th>
        <td>
            <a href=https://github.com/llvm/llvm-project/issues/105588>105588</a>
        </td>
    </tr>

    <tr>
        <th>Summary</th>
        <td>
            Reduce silent footgun likelihood with [[clang::preserve_most]] and _dl_runtime_resolve()
        </td>
    </tr>

    <tr>
      <th>Labels</th>
      <td>
            clang
      </td>
    </tr>

    <tr>
      <th>Assignees</th>
      <td>
      </td>
    </tr>

    <tr>
      <th>Reporter</th>
      <td>
          pkasting
      </td>
    </tr>
</table>

<pre>
    `[[clang::preserve_most]]` (only functional on some platforms) modifies the calling convention on a per-function basis to require the callee to save most registers it uses.

This interacts badly with lazy binding on some platforms, where function calls may go through the PLT, which in turn may call `_dl_runtime_resolve()` to determine the function address. Because this function assumes the normal calling convention, it can trash registers, leading to cryptic bugs.

At a minimum, I think Clang should warn users if any `preserve_most` call will be indirected through the PLT. At least in this case, users would get a compiler warning that their code could break in odd ways if they use lazy binding.

Slightly better might be to somehow encode this calling convention into the symbol (or a section flag with `-ffunction-sections`), so that the linker could be aware of it and warn only when lazy binding; users could work around via eager binding (`-Wl,-z,now`) at the expense of slower startup.

Doing more than that would likely require coordination with libc vendors. A bad solution would be to mark `_dl_runtime_resolve()` as `[[clang::preserve_most]]` itself; while safe, this would significantly pessimize performance, since that calling convention is meant for cold functions, which this isn't.

A better solution might be for libc vendors to provide an alternate `_dl_runtime_resolve_preserve_most()`, which the linker could selectively invoke based on the calling convention. This would require encoding the calling convention as noted above, and would still have a perf impact if `preserve_most` was used extensively (which it ought not to be).

Maybe there is a better possibility that doesn't require so much libc coordination, e.g. some kind of linker-provided trampoline in this case, but I'm not familiar enough to know if such a thing is sane.
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJyUVltrI0cT_TWjl8Ji1LZuD3rwBcPC90FIFvJoaqZLMxX1RenqkVb760P1SLK18ZIEjI3Vlzp16pzTQhHuAtGmmj9V85cJDrmPabPfoWQO3aSJ9rSpFnVZfmodhq66f6zuH_eJhNKB3nyUXM1f9GdRQ2VWMbgTbIfQZo4BHcQAEj3B3mHexuSlMmvw0fKWSSD3BC06x6GDNoYDBT2mhxD2lO4uF0GDwgI5QqI_B050PUmknwoeCBQLJOpYMiUBzjAIybSqX6r6cfz9tWcBDpkStlmgQetOcOTcg8PvJ2g4WIXyCehnOPaU6NpaKS7g8QRdhNynOHR9QfXL_76O27ntgQPkIYWyT09AtajfrHtLQ8js6S2RRHegyqwqs1YKcwRLmZLnMDZ5LYjWJhKZwhO1OIiusnxYFhn8mdIQk0f3CbMKjDO0GCAnlP6dLl1xhKX9HKFNp33mFpqhu2XwMQOC58B-8Hrmi8IIO3hWcYD0cXAWjpiCkq9T2AKGk7Z9q5lFPfJxZOegIVDmE7WZ7I9kTuExKzTJhU1tukUhLT6WOJaaHSmyNvo9O0oFQumlx6w3cYI2WoK2bG4S4U6vi1bRngrO3NNJr7zRwk3zvznu-uxO0FDOlMDrv4peJRg99fEIFEqdM86_SZtDjqUzOfkmumKZBAhC4xi3DrtRkdWivttexnt3Xhd1o1lr8xKvzYHjsKN0aY4Aj5gI4laHjeE8kGLNY0_hpsHq_unM43j6GNMOMMUhWDgwAmFH6eoMFeqivvvdVeb57ntlnkM8jpDgDIW-7SlIKS4uHimBZEx52N8w-RL1Nh-Lk1WN2sk4SMc7cqer0dsYk-WAhZ3Rqty0cKBgY5IpPKqLQaIbxh0XCnIEj2n3j4ZDgf-QcJyF3FY5O_bsCAS3RYll3GNtjVTecotBlbInEfb8nTTPNEswtOWEcGhp7PszmQh4wpBhG3Wszl6NLu_hUoqyhMos861JLwK90nJVqt73kUDlaZ_igS0BBkCXKQXM9BPe3m55ubD4EdMPahRyKt2DzpTDIe5Iw5yshuzn8T-Fr-9sXmRQbDUa-tMnAwVC1PTAJh4KwUX3I4SsIdPrG1GelS2w32Ob1fSfBdMRRS1hgb5lCjJir8zqHOkZNJ6y1lP2GqrM-ob-_-OpKeGdSAeJl2nsowg37DifxsHbSOP0rm1KBD-0Z41_lL52RNNuOj5MOw5WHTYyfXceoNVQ9_vo9O34MSubIcOXyix9wb1Fz44xAYUxayPsQjwqI6L1scR6p_AFA00ndnNv1_drnNBmtjQPZjlfPCwm_aaldt6sZojbBa0ezINd1LQyzdKsbFOvZvMJb0xtHuqVmZmZWZrFdLa0K9vWi_vlfD2fzRbVQ00e2U2dO_hpTN2ERQbazOr5fLWaOGzISfmGYsxoUGP0y0ra6IE7faGqh9qxZHm_InN2tPmV7NASCDsqVoq5G8IYMNzHaM9B-y-8X9T00xyZDMlt-pz3oheY18q8dpz7oZm20VfmVWGd_-is_qA2V-a1tCmVeT13etiYvwIAAP__Z4tT_g">