If the problem is something outside the module needs the calling convention to stay the same, stop marking it static and/or leak the function address, compiler.used might do it.
This will create additional functions in the binary. In this particular case, we only want to record the new signatures (if different from old ones) and do not want to create additional actual functions.
If the problem is dwarf doesn’t reflect a change to the static function and otherwise you’re happy with the change, it’s a bug in llvm.
I am certainly okay to replace the old signature with the new signature. But see above, this may cause different behaviors in lldb.
Previously lldb will show func signature e.g. foo(a, b) from the source code. With new signature, lldb may show func signature like foo(a) which user may confuse since it does not match the source level one. There are some difference as well e.g., original func is foo(a, b) but new change may have foo.llvm.(a).
Another more complicated case. For example, foo(struct a *) in the source may become foo(int t1, int t2). User will definitely confuse what foo(int t1, int t2) mean in lldb since the source level func is foo(struct a *).
If the problem is dwarf doesn’t reflect a change to the static function and otherwise you’re happy with the change, it’s a bug in llvm.
?
Initially we can have a flag (e.g. -llvm enable-changed-func-dbinfo)? The default will be off. Later on, we may add an official clang level flag to control this?
I don’t think it’s quite right to call it a bug in LLVM. As discussed above we have the DWARF attribute DW_AT_calling_convention (DW_CC_nocall), which LLVM correctly applies in this case, which indicates to debuggers the function “does not obey standard calling conventions” (i.e., please don’t call it from the debugger).
IMO it’s more that @yonghong-song is looking to introduce a new feature that goes further, describing both the old and new signature and their relationship. The distinction is probably not important for the sentiment of what Jon is saying though.
Initially we can have a flag (e.g. -llvm enable-changed-func-dbinfo)? The default will be off. Later on, we may add an official clang level flag to control this?
Putting the feature behind a flag alleviates a lot of my concerns, as then the change won’t automatically affect all DWARF consumers, and people can try it out locally.
Which version of this are you currently looking to implement?
I wonder if it could be worth discussing your approach on the DWARF-discuss mailing list?
We have static functions that are optimised by changing the calling convention
We record that the calling convention is different but not how to call it
In a debugger, this makes branching to that function difficult
We don’t want a copy of the old function kept only for debugging
That suggests a few lines of attack. One is we could extend dwarf to describe what we’ve done.
Another is to keep a stub around with the original calling convention which jumps to the specialised one. That’ll cost a few bytes of machine code but is otherwise dead.
A third is to write new debug info describing the function as if it was written like that in the first place. I.e. change the debug info to reflect where we ended up, not where we started from.
I suspect the proper thing to do is option 3. Make the debug info right. I don’t personally know how to do that so would leave a stub function in the binary. The dwarf folks might have more ideas, worth reaching out.