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.


jeff


>

Attachment: pEpkey.asc
Description: application/pgp-keys

Reply via email to