On Wed, Sep 16, 2020 at 10:10 AM Jeff Law <l...@redhat.com> wrote: > > > On 9/16/20 11:05 AM, H.J. Lu wrote: > > On Wed, Sep 16, 2020 at 9:53 AM Jeff Law via Gcc-patches > > <gcc-patches@gcc.gnu.org> wrote: > >> > >> Consider a TU with file scoped "static const object utf8_sb_map". A > >> routine within the TU will stuff &utf8_sb_map into an object, something > >> like: > >> > >> fu (...) > >> > >> { > >> > >> if (cond) > >> > >> dfa->sb_char = utf8_sb_map; > >> > >> else > >> > >> dfa->sb_char = malloc (...); > >> > >> } > >> > >> > >> There is another routine in the TU which looks like > >> > >> bar (...) > >> > >> { > >> > >> if (dfa->sb_char != utf8_sb_map) > >> > >> free (dfa->sb_char); > >> > >> } > >> > >> > >> Now imagine that the TU is compiled (with LTO) into a static library, > >> libgl.a and there's a DSO (libdso.so) which gets linked against libgl.a > >> and references the first routine (fu). We get a copy of fu in the DSO > >> along with a copy of utf8_sb_map. > >> > >> > >> Then imagine there's a main executable that dynamicly links against > >> libdso.so, then links statically against libgl.a. Assume the main > >> executable does not directly reference fu(), but does call a routine in > >> libdso.so which eventually calls fu(). Also assume the main executable > >> directly calls bar(). Again, remember we're compiling with LTO, so we > >> don't suck in the entire TU, just the routines/data we need. > >> > >> > >> In this scenario, both libdso.so and the main executable are going to a > >> copy of utf8_sb_map and they'll be at different addresses. So when the > >> main executable calls into libdso.so which in turn calls libdso's copy > >> of fu() which stuffs the address of utf8_sb_map from the DSO into > >> dfa->sb_char. Later the main executable calls bar() that's in the main > >> executable. It does the comparison to see if dfa->sb_char is equal to > >> utf8_sb_map -- but it's using the main executable's copy of utf8_sb_map > >> and naturally free() blows us because it was passed a static object, not > >> a malloc'd object. > >> > >> > >> ISTM this is a lot like the problem we have where we inline functions > >> with static data. To fix those we use STB_GNU_UNIQUE. But I don't see > >> any code in the C front-end which would utilize STB_GNU_UNIQUE. It's > >> support seems limited to C++. > >> > >> > >> How is this supposed to work for C? > >> > >> > >> Jeff > >> > >> > > Can you group utf8_sb_map, fu and bar together so that they are defined > > together? > > They're all defined within the same TU in gnulib. It's the LTO > dead/unreachable code elimination that results in just parts of the TU > being copied into the DSO and a different set copied into the main > executable. In many ways LTO makes this look a lot like the static data > member problems we've had to deal with in the C++ world.
In this case, LTO should treat them as in a single group. Removing one group member should remove the whole group. Keep one member should keep the whole group. -- H.J.