Fix GHC ticket 2615 (linker scripts in .so files)

Simon Marlow marlowsd at gmail.com
Wed Dec 2 11:50:21 EST 2009


On 01/12/2009 06:49, Howard B. Golden wrote:
> Mon Nov 30 22:12:34 PST 2009  howard_b_golden at yahoo.com
>    * Fix GHC ticket 2615 (linker scripts in .so files)
>    This patch only applies to systems that use ELF format files.
>    The patch modifies the addDLL function so that it recognizes
>    "invalid ELF header" errors. If these occur, the file that was opened
>    is scanned for a linker script GROUP ( ... ) directive. If found,
>    the first file inside the GROUP ( ... ) will be sent to dlopen.
>    Any errors reported by dlopen then will be reported  to the caller.

Thanks Howard.  I think the patch could do with a round of tweaks before 
being pushed, comments below.

> +#define MIN(a,b) (((a)<  (b)) ? (a) : (b))
> +

See stg_min() in Rts.h.

>   #  define OBJFORMAT_ELF
> +#  include<regex.h>

Can we rely on the availability of regex.h and POSIX regexes?  Does this 
need a configure test?

>   void
> hunk ./rts/Linker.c 1111
>   initLinker( void )
>   {
>       RtsSymbolVal *sym;
> +    int compileResult;
>
>       /* Make initLinker idempotent, so we can call it
>          before evey relevant operation; that means we
> hunk ./rts/Linker.c 1138
>   #   else
>       dl_prog_handle = dlopen(NULL, RTLD_LAZY);
>   #   endif /* RTLD_DEFAULT */
> +    compileResult = regcomp(&re_invalid,
> +               "(/[^ \\t()]+\\.so[^ \\t():]*):[ \\t]*invalid ELF header",
> +               REG_EXTENDED);
> +    ASSERT( compileResult == 0 );
> +    compileResult = regcomp(&re_realso,
> +               "GROUP *\\( *(([^ \\)])+)",
> +               REG_EXTENDED);
> +    ASSERT( compileResult == 0 );
> +    atexit(initLinkerCleanup);

We don't generally use atexit() in the RTS, all the cleanup has to be 
done by hs_exit().  Typically each subsystem has an exitFoo() or 
freeFoo() function called by hs_exit().


> +   errmsg = NULL;
>      if (hdl == NULL) {
>         /* dlopen failed; return a ptr to the error msg. */
>         errmsg = dlerror();
> hunk ./rts/Linker.c 1227
>         if (errmsg == NULL) errmsg = "addDLL: unknown error";
> -      return errmsg;
> -   } else {
> +   }
> +   return errmsg;
> +}
> +#  endif
> +
> +const char *
> +addDLL( char *dll_name )
> +{
> +#  if defined(OBJFORMAT_ELF) || defined(OBJFORMAT_MACHO)
> +   /* ------------------- ELF DLL loader ------------------- */
> +
> +#define NMATCH 2
> +   regmatch_t match[NMATCH];
> +   char *errmsg;
> +   FILE* fp;
> +   size_t match_length;
> +#define MAXLINE 1000
> +   char line[MAXLINE];
> +
> +   initLinker();
> +
> +   debugBelch("addDLL: dll_name = '%s'\n", dll_name);
> +   errmsg = internal_dlopen(dll_name);
> +
> +   if (errmsg == NULL) {
>         return NULL;
>      }
> hunk ./rts/Linker.c 1254
> -   /*NOTREACHED*/
> +
> +   // see if the error message is due to an invalid ELF header
> +
> +   debugBelch("errmsg = '%s'\n", errmsg);

I think you left some debug output in here.  Suggest protecting it with 
IF_DEBUG(linker, ...).

Also I suggest adding a comment referring to the ticket number, and an 
brief description of the problem and solution.

Cheers,
	Simon



More information about the Cvs-ghc mailing list