On Wed, Sep 16, 2020 at 10:24 AM Jeff Law <l...@redhat.com> wrote:
>
>
> On 9/16/20 11:13 AM, H.J. Lu wrote:
> > 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.
>
> Do you mean ensure they're all in a partition together?  I think that
> might work in the immediate term, but is probably brittle in the long
> term.  I'd tend to lean towards forcing these static data objects to be
> STB_GNU_UNIQUE -- that seems more robust to me.

Isn't STB_GNU_UNIQUE binding global?  How does it work with

static const int foo;

and

static const double foo;

in different files?

-- 
H.J.

Reply via email to