X-Authentication-Warning: delorie.com: mail set sender to djgpp-workers-bounces using -f X-Recipient: djgpp-workers AT delorie DOT com X-Authenticated: #27081556 X-Provags-ID: V01U2FsdGVkX1/VSrIjyMnVWul2MI2P0Qdxp1NkI22kC4Lrkl4PAS EPsdli5iNv1jI4 From: Juan Manuel Guerrero To: djgpp-workers AT delorie DOT com Subject: Re: dxe and gcc 4.6.1 difficulties. Date: Tue, 20 Dec 2011 22:53:56 +0100 User-Agent: KMail/1.9.10 References: <201108141841 DOT 15711 DOT juan DOT guerrero AT gmx DOT de> <201112191706 DOT pBJH6O0l014645 AT envy DOT delorie DOT com> <4EF02233 DOT 4070004 AT iki DOT fi> In-Reply-To: <4EF02233.4070004@iki.fi> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: 7bit Content-Disposition: inline Message-Id: <201112202253.56277.juan.guerrero@gmx.de> X-Y-GMX-Trusted: 0 Reply-To: djgpp-workers AT delorie DOT com Am Dienstag, 20. Dezember 2011 schrieb Andris Pavenis: > On 12/19/2011 06:06 PM, DJ Delorie wrote: > >> Is there any reason why there is no __deregister_frame_info in libc? > > I don't know, perhaps it isn't needed? > Or maybe it was not needed when using earlier GCC versions before 4.6. > I would suggest to add it and see whether problems with using DXE > goes away (when using gcc-4.6). I have not used DXE myself, so I do not > have earlier experience with them > > Andris Starting with gcc 4.5.X gcc generates .eh_frame in the objects files by default. DXE has 3 initX.S files. Depending if ctor, frame or ctor and frame are defined in the object file one of those is used. These means that they generate the calls to __[de]register_frame_info. There is probably no way to resolve those symbols at runtime so I have resolved them when the .dxe file is created by the linker. To this purpose I have allowed to evaluate the LD_PRELOAD environment variable allowing to specifiy an library that will be used to resolve the unresolved symbols when linking. First I tried to use libgcc.a. This library provide the needed symbols but introduce a lot of others that will appear as unresolved at runtime. The better solution was to provide a __deregister_frame_info in libc.a. If only __[de]register_frame_info shall be resolved, the user does not need to set LD_PRELOAD at all, because libc.a is used anyway to resolve those symbols. If the compiler does not generate any frames, then all these changes have no impact. For libc.a I have added an dummy __deregister_frame_info implementation. Suggestions, objections, comments are welcome. Regards, Juan M. Guerrero 2011-12-20 Juan Manuel Guerrero * src/dxe/dxe3gen.c: If object file has frames honor the LD_PRELOAD environment variable to allow to link with a library that will resolve unresolved variables introduced by frames defined in the file. * src/libc/crt0/rfinfo.c: Define __deregister_frame_info. diff -aprNU5 djgpp.orig/src/dxe/dxe3gen.c djgpp/src/dxe/dxe3gen.c --- djgpp.orig/src/dxe/dxe3gen.c 2011-12-20 21:22:38 +0000 +++ djgpp/src/dxe/dxe3gen.c 2011-12-20 21:34:14 +0000 @@ -1,5 +1,6 @@ +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 2003 Borca Daniel * Copyright (C) 2000 Andrew Zabolotny * Partly based on work by Charles Sandmann and DJ Delorie. * Usage of this library is not restricted in any way. @@ -38,10 +39,13 @@ #define TEMP_O_FILE TEMP_BASE".o" #define TEMP_S_FILE TEMP_BASE".s" #define VALID_RELOC(r) ((r.r_type != RELOC_REL32) && (r.r_symndx != (ULONG32)-1)) +#define NUMBER_OF_LINKER_ARGS 10 +#define NUMBER_OF_PRELOADED_LIBS 2 + typedef enum { FALSE = 0, TRUE = !FALSE } BOOL; @@ -123,10 +127,31 @@ static struct { NULL }; +/* Desc: replaces backslash with slash in a path + * + * In : path string + * Out : path string + * + * Note: - + */ +static void canonicalize_path(char *path) +{ + if (path) + { + char *scan = path; + + for (; *scan; scan++) + if (*scan == '\\') + *scan = '/'; + } +} + + + /* Desc: remove temporary files * * In : - * Out : - * @@ -229,20 +254,21 @@ static void display_help (void) static void process_args (int argc, char *argv[], const char *new_argv[]) { static char libdir[FILENAME_MAX]; char *p; int i; - int new_argc = 10; + int new_argc = NUMBER_OF_LINKER_ARGS; p = getenv("DXE_LD_LIBRARY_PATH"); if (p) strcpy(libdir, p); else { p = getenv("DJDIR"); if (p) { strcpy(libdir, p); strcat(libdir, "/lib"); + canonicalize_path(libdir); } else { fprintf(stderr, "Error: neither DXE_LD_LIBRARY_PATH nor DJDIR are set in environment\n"); exit(1); } } @@ -335,11 +361,11 @@ static void process_args (int argc, char new_argv[new_argc++] = argv[i]; dot = strrchr(argv[i], '.'); if (dot) { if (!strcasecmp(dot, ".o") || !strcasecmp(dot, ".a")) { opt.objcount++; - } else if (!strcasecmp(dot, ".dxe")) { + } else if (!strcasecmp(dot, ".dxe") || !strcasecmp(dot, ".so")) { opt.dxefile = argv[i]; } } } } @@ -452,10 +478,12 @@ static FILE *run_ld (const char *argv[], init = (first_ctor != last_ctor) ? 1 : 0; fini = (first_dtor != last_dtor) ? 1 : 0; } if ((init > 0) || (fini > 0)) { + char *p, ld_preload_lib[FILENAME_MAX]; + fclose(f); for (i = 0; argv[i] != NULL; i++) ; @@ -469,10 +497,25 @@ static FILE *run_ld (const char *argv[], f = fopen(TEMP_BASE"f.o", "wb"); fwrite(finis[fini - 1].data, finis[fini - 1].size, 1, f); fclose(f); argv[i++] = TEMP_BASE"f.o"; } + + /* Append the library defined by LD_PRELOAD + * and also libc. This shall allow to + * resolve certain symbols introduced + * by a defined EH frame and by other + * frames. + */ + p = getenv("LD_PRELOAD"); + if (p) + { + strcpy(ld_preload_lib, p); + canonicalize_path(ld_preload_lib); + argv[i++] = ld_preload_lib; + } + argv[i++] = "/dev/env/DJDIR/lib/libc.a"; /* libc will resolve [de]register_frame_* symbols. */ argv[i] = NULL; rv = myspawn(argv); if (init > 0) { @@ -1112,17 +1155,18 @@ int main (int argc, char **argv) const char **new_argv; progname = argv[0]; /* Prepare the command line for ld */ new_argv = (const char **)malloc((argc - 1 + 11 + 2) * sizeof(char *)); + new_argv = (const char **)malloc((argc - 1 + NUMBER_OF_LINKER_ARGS + NUMBER_OF_PRELOADED_LIBS + 2 + 1) * sizeof(char *)); process_args(argc, argv, new_argv); if (opt.showdep || opt.showexp || opt.showunres) { for (i = 1; i < argc; i++) { if (argv[i][0] != '-') { char *dot = strchr(argv[i], '.'); - if (dot && !strcasecmp(dot, ".dxe")) { + if (dot && (!strcasecmp(dot, ".dxe") || !strcasecmp(dot, ".so"))) { if ((rv = show_symbols(argv[i])) != 0) { return rv; } } } diff -aprNU5 djgpp.orig/src/libc/crt0/rfinfo.c djgpp/src/libc/crt0/rfinfo.c --- djgpp.orig/src/libc/crt0/rfinfo.c 2011-12-20 21:22:38 +0000 +++ djgpp/src/libc/crt0/rfinfo.c 2011-12-20 21:25:36 +0000 @@ -1,7 +1,14 @@ +/* Copyright (C) 2011 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details */ -void __register_frame_info(void *begin __attribute__((unused)), - void *object __attribute__((unused))); -void __register_frame_info(void *begin __attribute__((unused)), - void *object __attribute__((unused))) +void __register_frame_info(const void *begin __attribute__((unused)), + const void *object __attribute__((unused))); +void __register_frame_info(const void *begin __attribute__((unused)), + const void *object __attribute__((unused))) { } + + +void __deregister_frame_info(const void *begin __attribute__((unused))); +void __deregister_frame_info(const void *begin __attribute__((unused))) + { + }