FLiT icon indicating copy to clipboard operation
FLiT copied to clipboard

Symbol bisect cannot handle out-of-line inline functions

Open mikebentley15 opened this issue 6 years ago • 3 comments

When an inline function is not inlined, but instead generated out-of-line as a symbol, those symbols are collapsed at link time. This means that the linker is free to choose any one of the symbols and throw the rest of them away. This can be problematic if there were assumptions made by the compiler that the same inline function would be compiled in an identical way across all translation units. It also limits what symbol bisect can search.

There are a few approaches to maybe fix this issue:

  • Turn these object files into shared libraries, making the inline symbols hidden (so as to use the local definition using -fvisibility-inlines-hidden). This has the unfortunate side effect that it nullifies the entire symbol weak symbol approach.
  • Turn the inline symbols into strong symbols along with the -fno-inline option to disable inlining - making all instances out-of-line symbols. This has the unfortunate side effect of potentially disabling the optimization we are trying to identify by disabling inlining. I also have not found a way to make a local symbol or a weak symbol into a strong symbol yet. Also, you would run into the problem that we would have the symbol be local or weak in other object files as well.
  • Another approach is to make all inline functions be used locally. Maybe this can be done by telling the compiler to always inline, however that is not always possible such as with recursive inline functions. This could work if we could somehow mark all uses of inline functions as local, in the same way static functions are local only to the translation unit, and duplicate symbols with the same name do not collide. I have not yet found a compiler option or an objcopy option that can accomplish this task.
  • Another option is to somehow strip out the definition of certain symbols from one object file in order to force the compiler to use a particular version. I have had little luck in stripping out symbols from an object file using strip or objcopy and still be able to successfully link it into the executable. It may be that the only way to do this is to create my own tool to safely remove a function from an object file and turn that symbol into an undefined symbol.

These are at least some approaches that I have thought of at the moment. There may be more possibilities, so keep an open mind :).

mikebentley15 avatar May 11 '18 16:05 mikebentley15

Turns out I can do what I want with

objcopy --redefine-symbol <inlinefunc>=<newfuncname> ...

This will cause the symbol to have a new name within this object file, so it will use that one instead of the collapsed one from the other files.

However, this did not solve the problem of the inconsistent failures (e.g. segmentation fault, double free). So I'm back to not knowing what was causing the issue. It must be some other kind of optimization made with the assumption that the translation unit is the smallest indivisible unit of compilation. I am obviously violating that assumption by trying to mix and match two compilations of the same translation unit together.

mikebentley15 avatar Jun 07 '18 17:06 mikebentley15

There seem to be options in objcopy that I missed before. They may be useful in this regard, specifically

  • --localize-symbol: convert a global or weak symbol into a local symbol
  • --globalize-symbol: convert symbol into a global symbol (does this make it strong?)
  • --weaken-symbol: convert symbol into a weak symbol
  • --add-symbol: create a new symbol and tell it where to point
  • --redefine-sym: rename symbol both in the symbol table and at the call site

For this particular issue, I think --localize-symbol or --globalize-symbol may be useful.

mikebentley15 avatar Sep 16 '19 15:09 mikebentley15