delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp-workers/2013/06/18/14:27:43

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/O0K8k9UfOwGcZMx6vTfoO9Fg+W7Us5iOrzZGpKQ
NX8y/yxDw4XY0T
Message-ID: <51C0A3B4.4010205@gmx.de>
Date: Tue, 18 Jun 2013 20:15:16 +0200
From: Juan Manuel Guerrero <juan DOT guerrero AT gmx DOT de>
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:16.0) Gecko/20121025 Thunderbird/16.0.2
MIME-Version: 1.0
To: djgpp-workers AT delorie DOT com
Subject: Autoresolving __[de]register_frame_info symbols in DXE modules when
required.
X-Y-GMX-Trusted: 0
Reply-To: djgpp-workers AT delorie DOT com

Starting with gcc 4.6.1, the C compiler inserts .eh_frames into
the object files.  This has the consequence that dxe3gen links
init and fini code into DXE module that calls the __[de]register_frame_info
functions.  This either breaks the module generation due to unresolved
symbols or creates broken modules that do not work at run-time.

The patch below will allow to autoresolve these symbols iff it is
recognized that there is no exception handling support by the language
or compiler used.  If the object file has different e_value for the
___EH_FRAME_BEGIN__ and ___EH_FRAME_END__ symbols, then the .eh_frame
of the original object file (not the dxe_tmp.o) will be scanned for
its CIE record.  If the CIE is valid and it has a 'zR' augmentation
string, it will be assumed that the programing language or compiler
does not really provide exception handling support and both symbols
will be autoresolved.  Any other augmentation string will inhibit
the autoresolve process of the symbols and dxe3gen will abort with
the usual error message about unresolved symbols.

To read the first few fields of the CIE, the dwarf_cie structure is
used as defined in unwind-dw2-fde.h of gcc-4.6.1.  If this structure
changes, the code will need to be adjusted.  The as valid recognized
CIE ID and augmentation strings are those defined by LSB-Core-generic.pdf.

All files that will be linked into a DXE module will be scanned for
the 'zR' augmentation string.  If a single file has an augmentation
string different from 'zR' then the symbols will not be autoresolved
and the user will have to link the application with the appropriate
library that will provide working versions of __[de]register_frame_info.
This is libgcc.a for g++ when exceptions are enabled.

That the 'zR' augmentation string is the right choice is a information
that I gained by trial-and-error.

To autoresolve the symbols two new init and fini files are provided.
This are copies of those that call the functions, but dummy functions
have been added, so the symbols can be resolved by the linker.

With the proposed modifications the dxe test suite of the library
passes again without needing to modify neither the C and C++ code
nor the Makefile.

As usual, suggestions, objections and comments are welcome.


Regards,
Juan M. Guerrero




cvs ci -m"Info about dxe3gen added."  djgpp/src/docs/kb/wc204.txi
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/dxe3gen.c
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/makefile
cvs add djgpp/src/dxe/fini4.S
cvs add djgpp/src/dxe/fini5.S
cvs add djgpp/src/dxe/init4.S
cvs add djgpp/src/dxe/init5.S
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/fini4.S
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/fini5.S
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/init4.S
cvs ci -m"Support autoresolving __[de]register_frame_info in DXE moduls 
if the programing language does not provide EH support." 
djgpp/src/dxe/init5.S



Logging in to :pserver:anonymous AT cvs DOT delorie DOT com:2401/cvs/djgpp
? djgpp/src/dxe/fini4.S
? djgpp/src/dxe/fini5.S
? djgpp/src/dxe/init4.S
? djgpp/src/dxe/init5.S
Index: djgpp/src/docs/kb/wc204.txi
===================================================================
RCS file: /cvs/djgpp/djgpp/src/docs/kb/wc204.txi,v
retrieving revision 1.207
diff -p -U 5 -r1.207 wc204.txi
--- djgpp/src/docs/kb/wc204.txi    23 Mar 2013 11:54:58 -0000  1.207
+++ djgpp/src/docs/kb/wc204.txi    16 Jun 2013 13:01:43 -0000
@@ -1234,14 +1234,19 @@ function from the Windows 95 long filena
  @code{AX} register after return from the API function call. Depending 
on the function type,
  the function will ignore, fail or fall back on the corresponding SFN 
API function if the
  LFN API function is not provided by the @acronym{LFN} driver used.

  @pindex dxe3gen AT r{, resolving @code{__[de]register_frame_info} symbols 
in @acronym{DXE} moduls}
-When dxe3gen detects that one of the object files that shall be linked 
into a
-@acronym{DXE} modul contains a @code{.eh_frame} section it 
automatically links
-the modul with @code{libc.a} to resolve both 
@code{__register_frame_info} and
-@code{__deregister_frame_info} symbols.
+The dxe3gen program inspects the @code{Augmentation String} of the 
@code{CIE} record
+contained in the @code{.eh_frame} section to decide if both 
@code{__register_frame_info}
+and @code{__deregister_frame_info} symbols that exist in the object 
file shall be
+auto-resolved or not.  They will be resolved by the dxe3gen program if 
the used
+programing language does not support exception handling like 
@acronym{C}.  They will not
+be resolved if the used programing language supports exception handling 
like
+@acronym{C++} and the exception handling has been enabled with an 
option like
+@option{-fexceptions}.  In this case the application has to be linked with
+@file{libgcc.a} to resolve both symbols.

  @findex STYP_NRELOC_OVFL AT r{, new flag bit added to @code{s_flags} of 
@acronym{COFF} section header}
  The @code{s_flags} of the @acronym{COFF} section header now honors the 
new @code{STYP_NRELOC_OVFL} bit
  that signals that the section contains extended relocations and that 
the @code{s_nreloc} counter has
  overflown.  The bit set in case of overflow by @code{STYP_NRELOC_OVFL} 
is @code{0x01000000}.
Index: djgpp/src/dxe/dxe3gen.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/dxe/dxe3gen.c,v
retrieving revision 1.17
diff -p -U 5 -r1.17 dxe3gen.c
--- djgpp/src/dxe/dxe3gen.c    16 Jun 2013 02:40:10 -0000    1.17
+++ djgpp/src/dxe/dxe3gen.c    18 Jun 2013 17:02:15 -0000
@@ -176,11 +176,11 @@
  /* Always include local copies of sys/dxe.h and coff.h because of
   * NATIVE_TYPES stuff. */
  #include "../../include/sys/dxe.h"
  #include "../../include/coff.h"

-#define VERSION  "1.0.2"
+#define VERSION  "1.0.3"

  #define TEMP_BASE    "dxe_tmp"       /* 7 chars, 1 char suffix */
  #define TEMP_O_FILE  TEMP_BASE".o"
  #define TEMP_S_FILE  TEMP_BASE".s"

@@ -190,10 +190,14 @@
  #define IS_DIR_SEPARATOR(path)  (IS_SLASH(path) || ((path) == ':'))

  #define NUMBER_OF_LINKER_ARGS             10
  #define NUMBER_OF_ADDITIONAL_LOADED_LIBS  0

+#define IS_VALID_CIE(id)        ((id) == 0)
+#define IS_zR_AUGMENTATION(s)   (s[0] == 'z' && s[1] == 'R' && s[2] == 
'\0')
+
+
  typedef enum
  {
    FALSE = 0,
    TRUE = !FALSE
  } BOOL;
@@ -206,32 +210,45 @@ static
  #include "fini1.h"
  static
  #include "fini2.h"
  static
  #include "fini3.h"
+static
+#include "fini4.h"
+static
+#include "fini5.h"

  static
  #include "init1.h"
  static
  #include "init2.h"
  static
  #include "init3.h"
+static
+#include "init4.h"
+static
+#include "init5.h"

  static struct
  {
    void *data;
    int size;
-} inits[3] = {
+} inits[5] = {
    {init1, sizeof(init1)},
    {init2, sizeof(init2)},
-  {init3, sizeof(init3)}
-}, finis[3] = {
+  {init3, sizeof(init3)},
+  {init4, sizeof(init4)},
+  {init5, sizeof(init5)}
+}, finis[5] = {
    {fini1, sizeof(fini1)},
    {fini2, sizeof(fini2)},
-  {fini3, sizeof(fini3)}
+  {fini3, sizeof(fini3)},
+  {fini4, sizeof(fini4)},
+  {fini5, sizeof(fini5)}
  };

+
  /* Command-line options */
  static struct
  {
    BOOL legacy;                  /* legacy DXE1 */
    BOOL unresolved;              /* allow unresolved symbols in output */
@@ -559,10 +576,149 @@ static int my_spawn(const char **argv)
    return system(cmd);
  }



+/* Desc: check if the augmentation string is different from 'zR'
+ * in on of the object files that will be linked into the DXE file.
+ * If the augmentation string in the CIE is different to zR, it is
+ * assumed that the programing language offers exception handling
+ * and the [de]register info symbols must be resolved by linking
+ * the application with a language/compiler specific library like
+ * libgcc that will provide working version of the 
__[de]register_frame_info
+ * functions.  Else the symbols will be autoresolved using the
+ * dummy functions compiled into this program.
+ *
+ * In  : linker command line to provide list of object files to scan
+ * Out : TRUE if different from 'zR' augmentation else FALSE
+ *
+ * Note: -
+ */
+static BOOL have_EH_support(const char *argv[])
+{
+  BOOL found_zR_augmentation = FALSE;
+  int i;
+
+  for (i = 0; argv[i]; i++)
+  {
+    const char *dot = strrchr(argv[i], '.');
+
+    if (dot && !strcasecmp(dot, ".o") && strcasecmp(dot - sizeof 
TEMP_BASE + 1, TEMP_O_FILE))
+    {
+      FILE *f = fopen(argv[i], "rb");
+
+      if (f == NULL)
+      {
+        fprintf(stderr, "%s: cannot open object file `%s' for 
reading\n", progname, argv[i]);
+        exit(-2);
+      }
+      else
+      {
+        FILHDR fh;
+        SYMENT *sym;
+        char *strings;
+        ULONG32 stsz;
+        unsigned int n;
+
+        /* Read file header */
+        fread(&fh, FILHSZ, 1, f);
+
+        /* Read all symbols */
+        sym = (SYMENT *)malloc(fh.f_nsyms * sizeof(SYMENT));
+        fseek(f, fh.f_symptr, SEEK_SET);
+        fread(sym, SYMESZ, fh.f_nsyms, f);
+
+        /* Read symbol name table */
+        fread(&stsz, sizeof(stsz), 1, f);
+        strings = (char *)malloc(stsz);
+        fread(strings + 4, 1, stsz - 4, f);
+        strings[0] = 0;
+
+        /* Find .eh_frame section */
+        for (found_zR_augmentation = TRUE, n = 0; n < fh.f_nsyms; n += 
1 + sym[n].e_numaux)
+        {
+          char tmp[E_SYMNMLEN + 1], *name;
+
+          if (sym[n].e.e.e_zeroes)
+          {
+            memcpy(tmp, sym[n].e.e_name, E_SYMNMLEN);
+            tmp[E_SYMNMLEN] = 0;
+            name = tmp;
+          }
+          else
+            name = strings + sym[n].e.e.e_offset;
+
+          if (!strcmp(name, ".eh_frame"))
+          {
+            SCNHDR eh_frame_scnhdr;
+
+            /* Skip file header, optional header and all other section
+               headers existing before the .eh_frame section header */
+            fseek(f, FILHSZ + fh.f_opthdr + (sym[n].e_scnum - 1) * 
(size_t)SCNHSZ, SEEK_SET);
+
+            /* Read the .eh_frame section header and
+               extract the CIE (Common Information Entry) */
+            if (fread(&eh_frame_scnhdr, (size_t)SCNHSZ, 1, f) == 1
+                && !fseek(f, eh_frame_scnhdr.s_scnptr, SEEK_SET))
+            {
+              /*
+               * To read the first few fields of the CIE record
+               * the struct dwarf_cie as defined in unwind-dw2-fde.h
+               * of gcc 4.6.1 is used.  If this structure changes
+               * then this code will need to be adjusted accordingly.
+               * For a reference about the possible values of the
+               * augmentation string look at LSB-Core-generic.pdf.
+               */
+
+
+              typedef          int  sword __attribute__ ((mode (SI)));
+              typedef unsigned int  uword __attribute__ ((mode (SI)));
+              typedef unsigned int  uaddr __attribute__ ((mode (pointer)));
+              typedef          int  saddr __attribute__ ((mode (pointer)));
+              typedef unsigned char ubyte;
+
+              struct dwarf_cie
+              {
+                uword length;
+                sword CIE_id;
+                ubyte version;
+                unsigned char augmentation[];
+              } __attribute__ ((packed, aligned (__alignof__ (void *))));
+
+
+              /* If it is a CIE, read the augmentation string */
+              struct dwarf_cie cie;
+              fread(&cie, sizeof(cie), 1, f);
+              if (IS_VALID_CIE(cie.CIE_id) && 
!IS_zR_AUGMENTATION(cie.augmentation))
+              {
+                /*
+                 * At least one of the object files linked into
+                 * the DXE module requires exception handling.
+                 * The application must be linked with libgcc.a
+                 * to provide the required frame unwinding functionality.
+                 * Stop checking other object files.
+                 */
+                found_zR_augmentation = FALSE;
+                break;
+              }
+            }
+          }
+        }
+
+        free(strings);
+        free(sym);
+      }
+
+      fclose(f);
+    }
+  }
+
+  return !found_zR_augmentation;
+}
+
+
+
  /* Desc: run linker to obtain relocatable output
   *
   * In  : linker command line, ptr to store output header
   * Out : file ptr of resulting file
   *
@@ -604,10 +760,11 @@ static FILE *run_ld(const char *argv[],
      ULONG32 stsz;
      SYMENT *sym;
      char *strings;
      long int frame_begin = -1, frame_end = -1;
      long int first_ctor = -1, last_ctor = -1, first_dtor = -1, 
last_dtor = -1;
+    BOOL resolve_register_deregister_info_symbols = FALSE;

      int init, fini;

      /* Read all symbols */
      sym = (SYMENT *)malloc(fh->f_nsyms * sizeof(SYMENT));
@@ -635,10 +792,12 @@ static FILE *run_ld(const char *argv[],

        if (!strcmp(name, "___EH_FRAME_BEGIN__"))
          frame_begin = sym[i].e_value;
        else if (!strcmp(name, "___EH_FRAME_END__"))
          frame_end = sym[i].e_value;
+      else if (!strcmp(name, ".eh_frame"))
+        resolve_register_deregister_info_symbols = !have_EH_support(argv);
        else if (!strcmp(name, "djgpp_first_ctor"))
          first_ctor = sym[i].e_value;
        else if (!strcmp(name, "djgpp_last_ctor"))
          last_ctor = sym[i].e_value;
        else if (!strcmp(name, "djgpp_first_dtor"))
@@ -646,19 +805,20 @@ static FILE *run_ld(const char *argv[],
        else if (!strcmp(name, "djgpp_last_dtor"))
          last_dtor = sym[i].e_value;
      }


-    /* 3 = ctor + frame
+    /*
+     * 3 = ctor + frame
       * 2 = frame
       * 1 = ctor
       * 0 = <none>
       */
      if (frame_begin != frame_end)
      {
-      init = (first_ctor != last_ctor) ? 3 : 2;
-      fini = (first_dtor != last_dtor) ? 3 : 2;
+      init = resolve_register_deregister_info_symbols ? (first_ctor != 
last_ctor) ? 5 : 4 : (first_ctor != last_ctor) ? 3 : 2;
+      fini = resolve_register_deregister_info_symbols ? (first_ctor != 
last_ctor) ? 5 : 4 : (first_ctor != last_ctor) ? 3 : 2;
      }
      else
      {
        init = (first_ctor != last_ctor) ? 1 : 0;
        fini = (first_dtor != last_dtor) ? 1 : 0;
Index: djgpp/src/dxe/makefile
===================================================================
RCS file: /cvs/djgpp/djgpp/src/dxe/makefile,v
retrieving revision 1.7
diff -p -U 5 -r1.7 makefile
--- djgpp/src/dxe/makefile    14 May 2003 02:33:50 -0000    1.7
+++ djgpp/src/dxe/makefile    16 Jun 2013 13:01:44 -0000
@@ -1,5 +1,6 @@
+# Copyright (C) 2013 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 2003 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 2001 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 1998 DJ Delorie, see COPYING.DJ for details
  # Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details

@@ -29,10 +30,10 @@ $(BIN)/dxegen.exe : $(HOSTBIN)/stubify.e

  $(BIN)/dxe3res.exe : $(C) dxe3res.o $(L)
      $(LINK)
      $(EXE)

-$(HOSTBIN)/dxegen.exe : dxe3gen.c init1.h init2.h init3.h fini1.h 
fini2.h fini3.h
+$(HOSTBIN)/dxegen.exe : dxe3gen.c init1.h init2.h init3.h init4.h 
init5.h fini1.h fini2.h fini3.h fini4.h fini5.h
      $(GCC) -DDXE_LD=\"$(CROSS_LD)\" dxe3gen.c -o $@

  clean ::
      @-$(MISC) rm *.o *.h $(HOSTBIN)/dxegen.exe
diff -aprNU5 --no-dereference djgpp.orig/src/dxe/fini4.S 
djgpp/src/dxe/fini4.S
--- djgpp.orig/src/dxe/fini4.S    1970-01-01 00:00:00 +0000
+++ djgpp/src/dxe/fini4.S    2013-06-16 14:06:38 +0000
@@ -0,0 +1,24 @@
+/*
+ * DXE3: frame info deregistration
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca AT yahoo DOT com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+        .text
+
+        .p2align 2,,3
+        .globl    _fini
+_fini:
+        pushl    $___EH_FRAME_BEGIN__
+        call    ___deregister_frame_info
+        popl    %eax
+        ret
+
+___deregister_frame_info:
+        pushl    %ebp
+        movl    %esp, %ebp
+        popl    %ebp
+        ret
diff -aprNU5 --no-dereference djgpp.orig/src/dxe/fini5.S 
djgpp/src/dxe/fini5.S
--- djgpp.orig/src/dxe/fini5.S    1970-01-01 00:00:00 +0000
+++ djgpp/src/dxe/fini5.S    2013-06-16 14:06:38 +0000
@@ -0,0 +1,34 @@
+/*
+ * DXE3: destruction + frame info deregistration
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca AT yahoo DOT com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+        .text
+
+        .p2align 2,,3
+        .globl    _fini
+_fini:
+        pushl    %ebx
+        movl    $djgpp_first_dtor, %ebx
+    0:
+        cmpl    $djgpp_last_dtor, %ebx
+        jnb    1f
+        call    *(%ebx)
+        addl    $4, %ebx
+        jmp    0b
+    1:
+        popl    %ebx
+        pushl    $___EH_FRAME_BEGIN__
+        call    ___deregister_frame_info
+        popl    %eax
+        ret
+
+___deregister_frame_info:
+        pushl    %ebp
+        movl    %esp, %ebp
+        popl    %ebp
+        ret
diff -aprNU5 --no-dereference djgpp.orig/src/dxe/init4.S 
djgpp/src/dxe/init4.S
--- djgpp.orig/src/dxe/init4.S    1970-01-01 00:00:00 +0000
+++ djgpp/src/dxe/init4.S    2013-06-16 14:06:38 +0000
@@ -0,0 +1,28 @@
+/*
+ * DXE3: frame info registration
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca AT yahoo DOT com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+        .text
+
+        .p2align 2,,3
+        .globl    _init
+_init:
+        pushl    $eh_frame
+        pushl    $___EH_FRAME_BEGIN__
+        call    ___register_frame_info
+        popl    %eax
+        popl    %edx
+        ret
+
+___register_frame_info:
+        pushl    %ebp
+        movl    %esp, %ebp
+        popl    %ebp
+        ret
+
+.lcomm        eh_frame, 32
diff -aprNU5 --no-dereference djgpp.orig/src/dxe/init5.S 
djgpp/src/dxe/init5.S
--- djgpp.orig/src/dxe/init5.S    1970-01-01 00:00:00 +0000
+++ djgpp/src/dxe/init5.S    2013-06-16 14:06:38 +0000
@@ -0,0 +1,38 @@
+/*
+ * DXE3: frame info registration + construction
+ *
+ *  Copyright (C) 2002 - Borca Daniel
+ *  Email : dborca AT yahoo DOT com
+ *  Web   : http://www.geocities.com/dborca
+ */
+
+
+        .text
+
+        .p2align 2,,3
+        .globl    _init
+_init:
+        pushl    $eh_frame
+        pushl    $___EH_FRAME_BEGIN__
+        call    ___register_frame_info
+        popl    %eax
+        popl    %edx
+        pushl    %ebx
+        movl    $djgpp_first_ctor, %ebx
+    0:
+        cmpl    $djgpp_last_ctor, %ebx
+        jnb    1f
+        call    *(%ebx)
+        addl    $4, %ebx
+        jmp    0b
+    1:
+        popl    %ebx
+        ret
+
+___register_frame_info:
+        pushl    %ebp
+        movl    %esp, %ebp
+        popl    %ebp
+        ret
+
+.lcomm        eh_frame, 32

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019