This is the mail archive of the libc-help@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: pthread_cancel and static libgcc libgcc_eh without libc bits



On 14/10/2016 05:29, Sylvain BERTRAND wrote:
> On Thu, Oct 13, 2016 at 09:44:07PM +0200, Waldemar Brodkorb wrote:
>> Hi,
>> sylvain.bertrand@gmail.com wrote,
>>
>>> Hi,
>>>
>>> Correct me if I'm wrong: pthread_cancel does work properly when linking a shared nptl lib with
>>> static libgcc and libgcc_eh, which where compiled without their libc bits?
>>>
>>> Or the shared libgcc_s is _mandatory_ for pthread_cancel to work in a shared nptl lib?
>>
>> I asked a similar question once. See the archives.
>> libgcc_s is mandatory and is used via dlopen.
>>
>> best regards
>>  Waldemar
> 
> 
> Ok. Did anybody try to make pthread_cancel work with code in static libgcc and linbgcc_eh?
> 
> It seems it is related only to the unwind code. Right?
> 

In theory yes, although by doing it is may add different unwinders 
into process (potentially one for each shared object plus the binary one)
that will make things messy, as indicated by Carlos initial response 
to Waldemar [1].

I tried to play with this, but without success.  The patch below should
make pthread cancel handling initialization for shared mode to work
in global symbols from the object (although I am almost sure it does
*not* implements the required synchronization to call dl_sym).

The problem is how libgcc_eh.a is build and how to actually export the
symbol in a way the lookup will work without extensive hacking.  On my
system, for instance, libgcc_eh export the '_Unwind_Resume' as:

00000000000027f0 g     F .text  00000000000000ba .hidden _Unwind_Resume
00000000000028b0 g     F .text  00000000000000da .hidden _Unwind_Resume_or_Rethrow

So a default ' -Wl,-static,--whole-archive -lgcc_eh' will set the symbols
as global hidden (objdump -t on the final binary):

0000000000409ad0 g     F .text  00000000000000da              .hidden _Unwind_Resume_or_Rethrow
0000000000409a10 g     F .text  00000000000000ba              .hidden _Unwind_Resume

This won't help since _dl_lookup_symbol_x will ignore this binding.  You
can try and export dynamic symbol with --export-dynamic, but system
linker (binutils 2.26.1) will make the global hidden as local:

0000000000409de0 l     F .text  00000000000000da              _Unwind_Resume_or_Rethrow
0000000000409d20 l     F .text  00000000000000ba              _Unwind_Resume

[1] https://sourceware.org/ml/libc-help/2014-07/msg00000.html

Off course it would be possible to hack away the scope limitation for
symbol lookup, but that is definitely not the way to do it.

My understanding is the symbol visibility for libgcc_eh.a is exactly as it
to avoid this scenario: the global hidden visibility is meant to be
used with static build (either by -static or -static-libgc++) to bind
the used unwinder to supported libstdc++ (since in this scenario
ideally you won't have different binded libstdc++).

--

diff --git a/elf/dl-libc.c b/elf/dl-libc.c
index d56de1a..f31938f 100644
--- a/elf/dl-libc.c
+++ b/elf/dl-libc.c
@@ -94,9 +94,12 @@ do_dlsym (void *ptr)
 {
   struct do_dlsym_args *args = (struct do_dlsym_args *) ptr;
   args->ref = NULL;
+#if 0
   args->loadbase = GLRO(dl_lookup_symbol_x) (args->name, args->map, &args->ref,
 					     args->map->l_local_scope, NULL, 0,
 					     DL_LOOKUP_RETURN_NEWEST, NULL);
+#endif
+  args->loadbase = _dl_sym (args->map, args->name, NULL);
 }
 
 static void
@@ -207,8 +210,11 @@ __libc_dlsym (void *map, const char *name)
   if (__glibc_unlikely (_dl_open_hook != NULL))
     return _dl_open_hook->dlsym (map, name);
 #endif
+#if 0
   return (dlerror_run (do_dlsym, &args) ? NULL
 	  : (void *) (DL_SYMBOL_ADDRESS (args.loadbase, args.ref)));
+#endif
+  return (dlerror_run (do_dlsym, &args) ? NULL : args.loadbase);
 }
 libc_hidden_def (__libc_dlsym)
 
diff --git a/sysdeps/nptl/unwind-forcedunwind.c b/sysdeps/nptl/unwind-forcedunwind.c
index ca757c4..624c5bc 100644
--- a/sysdeps/nptl/unwind-forcedunwind.c
+++ b/sysdeps/nptl/unwind-forcedunwind.c
@@ -49,10 +49,19 @@ pthread_cancel_init (void)
       return;
     }
 
-  handle = __libc_dlopen (LIBGCC_S_SO);
+  /* Try to get the symbol from a static libgcc first (it will work iff the
+     program is linked with -rdynamic.  */
+  handle = RTLD_DEFAULT;
+  resume = __libc_dlsym (handle, "_Unwind_Resume");
+  if (resume == NULL)
+    {
+      handle = __libc_dlopen (LIBGCC_S_SO);
+      if (handle == NULL)
+	__libc_fatal (LIBGCC_S_SO " must be installed for pthread_cancel to work\n");
+      resume = __libc_dlsym (handle, "_Unwind_Resume");
+    }
 
-  if (handle == NULL
-      || (resume = __libc_dlsym (handle, "_Unwind_Resume")) == NULL
+  if ((resume == NULL)
       || (personality = __libc_dlsym (handle, "__gcc_personality_v0")) == NULL
       || (forcedunwind = __libc_dlsym (handle, "_Unwind_ForcedUnwind"))
 	 == NULL


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]