Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Elena Zannoni <ezannoni@redhat.com>
To: RaoulGough@yahoo.co.uk
Cc: Eli Zaretskii <eliz@is.elta.co.il>, gdb-patches@sources.redhat.com
Subject: Re: coffread.c extension for DLLs without debugging symbols
Date: Mon, 06 Jan 2003 17:10:00 -0000	[thread overview]
Message-ID: <15897.47288.570835.988631@localhost.redhat.com> (raw)
In-Reply-To: <2110-Sat04Jan2003130101+0200-eliz@is.elta.co.il>

Eli Zaretskii writes:
 > > From: "Raoul Gough" <RaoulGough@yahoo.co.uk>
 > > Date: Fri, 3 Jan 2003 19:39:31 -0000
 > > 
 > > This is my *first* gdb patch submission,
 > > so someone with more experience should probably take a good look at
 > > (e.g. is coffread.c the right place for this kind of code?).
 > 
 > Lesson number 1: post the diffs as plain text, not uuencoded or
 > otherwise encoded.  Some people, such as myself, don't have time to
 > open binary attachments, but do have time to read a patch that's in
 > plain text.
 > 
 > Also, please include "[RFA]" in the subject, so that we know you are
 > seeking an approval for your patch.
 > 
 > > Proposed ChangeLog entry, assuming the code is accepted:
 > > 
 > > 2003-01-03  Raoul Gough  <RaoulGough@yahoo.co.uk>
 > > 
 > >  * coffread.c: Support non-debug export symbols for win32 DLLs
 > 
 > This should mention every function where changes are made, preferably
 > with a description of a change in each one of them.
 > 
 > And thanks for working on this.


I am including the plain text of the last version of the patch.
I have noticed a few functions are using K&R style, please use ISO C.
Also the formatting for functions should be

int
foo (int par1, int par2)

so that grep ^foo will work.

(sorry, I have to ask) Do you have a copyright assignment with the FSF?

As far as the new code being triggered, could you do it based on the
existance of some particular section/data in the objfile?  I see that
you bail out of read_pe_exported_syms if there are no exports, could
something on the same flavour be done? (like using bfd_get_flavour, 
or bfd_get_section_by_name, etc)

About location of the code, add maybe a coff-pe-read.c? (ulgh) But
since it deals with reading symbols, I would think it more logical to
stay in some object/debug format related file rather than in a target
related file.

Elena


Index: coffread.c
===================================================================
RCS file: /cvs/src/src/gdb/coffread.c,v
retrieving revision 1.32
diff -c -p -r1.32 coffread.c
*** coffread.c	17 Dec 2002 00:39:07 -0000	1.32
--- coffread.c	3 Jan 2003 18:24:39 -0000
*************** static void read_one_sym (struct coff_sy
*** 179,184 ****
--- 179,186 ----
  			  struct internal_syment *, union internal_auxent *);
  
  static void coff_symtab_read (long, unsigned int, struct objfile *);
+ 
+ static void read_pe_exported_syms (struct objfile *objfile);
  \f
  /* We are called once per section from coff_symfile_read.  We
     need to examine each section we are passed, check to see
*************** coff_symtab_read (long symtab_offset, un
*** 1086,1091 ****
--- 1088,1109 ----
  	}
      }
  
+   if ((nsyms == 0) && (pe_file))
+     {
+       /* We've got no debugging symbols, but know how to read the list
+ 	 of exported symbols (on i386 at least). The code _might_ work
+ 	 on other architectures, but hasn't been tested. Check the
+ 	 target name to be on the safe side */
+ 
+       char const *target = bfd_get_target (objfile->obfd);
+ 
+       if ((strncmp (target, "pe-i386", 3) == 0)
+ 	  || (strncmp (target, "pei-i386", 4) == 0))
+ 	{
+ 	  read_pe_exported_syms (objfile);
+ 	}
+     }
+ 
    if (last_source_file)
      coff_end_symtab (objfile);
  
*************** read_one_sym (register struct coff_symbo
*** 1166,1171 ****
--- 1184,1488 ----
  	  break;
  	}
      }
+ }
+ \f
+ /* Additional section information recorded just for the purposes of
+  * read_pe_exported_syms */
+ 
+ struct read_pe_section_data
+ {
+   CORE_ADDR vma_offset;               /* Offset to loaded address of section */
+   unsigned long rva_start;            /* Start offset within the pe */
+   unsigned long rva_end;              /* End offset within the pe */
+   enum minimal_symbol_type ms_type;   /* Type to assign symbols in section */
+ };
+ 
+ #define PE_SECTION_INDEX_TEXT     0
+ #define PE_SECTION_INDEX_DATA     1
+ #define PE_SECTION_INDEX_BSS      2
+ #define PE_SECTION_TABLE_SIZE     3
+ #define PE_SECTION_INDEX_INVALID -1
+ 
+ /* Get the index of the named section in our own array, which contains
+  * text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
+  * if passed an unrecognised section name */
+ static int read_pe_section_index (const char *section_name)
+ {
+   if (strcmp (section_name, ".text") == 0)
+     {
+       return PE_SECTION_INDEX_TEXT;
+     }
+ 
+   else if (strcmp (section_name, ".data") == 0)
+     {
+       return PE_SECTION_INDEX_DATA;
+     }
+ 
+   else if (strcmp (section_name, ".bss") == 0)
+     {
+       return PE_SECTION_INDEX_BSS;
+     }
+ 
+   else
+     {
+       return PE_SECTION_INDEX_INVALID;
+     }
+ }
+ 
+ /* Record the virtual memory address of a section */
+ static void get_section_vmas (bfd *abfd, asection *sectp, void *context)
+ {
+   struct read_pe_section_data *sections = context;
+   int sectix = read_pe_section_index (sectp->name);
+ 
+   if (sectix != PE_SECTION_INDEX_INVALID)
+     {
+       /* Data within the section start at rva_start in the pe and at
+        * bfd_get_section_vma() within memory. Store the offset */
+ 
+       sections[sectix].vma_offset
+ 	= bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
+     }
+ }
+ \f
+ /* Create a minimal symbol entry for an exported symbol */
+ static void
+ add_pe_exported_sym (char *sym_name,
+ 		     unsigned long func_rva,
+ 		     const struct read_pe_section_data *section_data,
+ 		     const char *dll_name,
+ 		     struct objfile *objfile)
+ {
+   /* Add the stored offset to get the loaded address of the symbol */
+   CORE_ADDR vma = func_rva + section_data->vma_offset;
+   char *qualified_name = 0;
+   int dll_name_len = strlen (dll_name);
+   int count;
+ 
+   /* Generate a (hopefully unique) qualified name using the first part
+    * of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
+    * used by windbg from the "Microsoft Debugging Tools for Windows" */
+ 
+   qualified_name = xmalloc (dll_name_len + strlen (sym_name) + 2);
+ 
+   strncpy (qualified_name, dll_name, dll_name_len);
+   qualified_name[dll_name_len] = '!';
+   strcpy (qualified_name + dll_name_len + 1, sym_name);
+ 
+   record_minimal_symbol (qualified_name,
+ 			 vma,
+ 			 section_data->ms_type,
+ 			 objfile);
+ 
+   xfree (qualified_name);
+ 
+   /* Enter the plain name as well, which might not be unique */
+   record_minimal_symbol (sym_name,
+ 			 vma,
+ 			 section_data->ms_type,
+ 			 objfile);
+ }
+ 
+ /* Truncate a dll_name at the first dot character */
+ static void read_pe_truncate_name (char *dll_name)
+ {
+   while (*dll_name)
+     {
+       if ((*dll_name) == '.')
+ 	{
+ 	  *dll_name = '\0'; /* truncates and causes loop exit */
+ 	}
+ 
+       else
+ 	{
+ 	  ++dll_name;
+ 	}
+     }
+ }
+ \f
+ /* Last-resort support for (non-debug) symbols exported from portable
+  * executables, used when there are no other recognized symbols. Code
+  * lifted (with modifications) from pe-dll.c from ld */
+ 
+ static unsigned int
+ pe_get16 (abfd, where)
+      bfd *abfd;
+      int where;
+ {
+   unsigned char b[2];
+ 
+   bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+   bfd_bread (b, (bfd_size_type) 2, abfd);
+   return b[0] + (b[1] << 8);
+ }
+ 
+ static unsigned int
+ pe_get32 (abfd, where)
+      bfd *abfd;
+      int where;
+ {
+   unsigned char b[4];
+ 
+   bfd_seek (abfd, (file_ptr) where, SEEK_SET);
+   bfd_bread (b, (bfd_size_type) 4, abfd);
+   return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+ }
+ 
+ static unsigned int
+ pe_as32 (ptr)
+      void *ptr;
+ {
+   unsigned char *b = ptr;
+ 
+   return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
+ }
+ 
+ /* Read the (non-debug) export symbol table from a portable
+  * executable.  originally from the ld function pe_implied_import_dll
+  * from pe-dll.c */
+ 
+ static void read_pe_exported_syms (struct objfile *objfile)
+ {
+   bfd *dll = objfile->obfd;
+   unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
+   unsigned long export_rva, export_size, nsections, secptr, expptr;
+   unsigned long exp_funcbase;
+   unsigned char *expdata, *erva;
+   unsigned long name_rvas, ordinals, nexp, ordbase;
+   char *dll_name;
+ 
+   /* Array elements are for text, data and bss in that order
+      Initialization with start_rva > end_rva guarantees that
+      unused sections won't be matched */
+   struct read_pe_section_data section_data[PE_SECTION_TABLE_SIZE]
+     = { {0, 1, 0, mst_text},
+ 	{0, 1, 0, mst_data},
+ 	{0, 1, 0, mst_bss} };
+ 
+   struct cleanup *back_to = 0;
+ 
+   /* Get pe_header, optional header and numbers of export entries.  */
+   pe_header_offset = pe_get32 (dll, 0x3c);
+   opthdr_ofs = pe_header_offset + 4 + 20;
+   num_entries = pe_get32 (dll, opthdr_ofs + 92);
+ 
+   if (num_entries < 1) /* No exports.  */
+     {
+       return;
+     }
+ 
+   export_rva = pe_get32 (dll, opthdr_ofs + 96);
+   export_size = pe_get32 (dll, opthdr_ofs + 100);
+   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
+   secptr = (pe_header_offset + 4 + 20 +
+ 	    pe_get16 (dll, pe_header_offset + 4 + 16));
+   expptr = 0;
+ 
+   /* Get the rva and size of the export section.  */ 
+   for (i = 0; i < nsections; i++)
+     {
+       char sname[8];
+       unsigned long secptr1 = secptr + 40 * i;
+       unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+       unsigned long vsize = pe_get32 (dll, secptr1 + 16);
+       unsigned long fptr = pe_get32 (dll, secptr1 + 20);
+ 
+       bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
+       bfd_bread (sname, (bfd_size_type) 8, dll);
+ 
+       if (vaddr <= export_rva && vaddr + vsize > export_rva)
+ 	{
+ 	  expptr = fptr + (export_rva - vaddr);
+ 	  if (export_rva + export_size > vaddr + vsize)
+ 	    export_size = vsize - (export_rva - vaddr);
+ 	  break;
+ 	}
+     }
+ 
+   if (export_size == 0)
+     {
+       /* Empty export table */
+       return;
+     }
+ 
+   /* Scan sections and store the base and size of the relevant sections */
+   for (i = 0; i < nsections; i++)
+     {
+       unsigned long secptr1 = secptr + 40 * i;
+       unsigned long vsize = pe_get32 (dll, secptr1 + 8);
+       unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
+       unsigned long flags = pe_get32 (dll, secptr1 + 36);
+       char sec_name[9];
+       int sectix;
+ 
+       sec_name[8] = '\0';
+       bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
+       bfd_bread (sec_name, (bfd_size_type) 8, dll);
+ 
+       sectix = read_pe_section_index (sec_name);
+ 
+       if (sectix != PE_SECTION_INDEX_INVALID)
+ 	{
+ 	  section_data[sectix].rva_start = vaddr;
+ 	  section_data[sectix].rva_end = vaddr + vsize;
+ 	}
+     }
+ 
+   expdata = (unsigned char *) xmalloc (export_size);
+   back_to = make_cleanup (xfree, expdata);
+ 
+   bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
+   bfd_bread (expdata, (bfd_size_type) export_size, dll);
+   erva = expdata - export_rva;
+ 
+   nexp = pe_as32 (expdata + 24);
+   name_rvas = pe_as32 (expdata + 32);
+   ordinals = pe_as32 (expdata + 36);
+   ordbase = pe_as32 (expdata + 16);
+   exp_funcbase = pe_as32 (expdata + 28);
+ 
+   /* Use internal dll name instead of full pathname */
+   dll_name = pe_as32 (expdata + 12) + erva;
+ 
+   bfd_map_over_sections (dll, get_section_vmas, section_data);
+ 
+   printf_filtered ("Minimal symbols from %s...", dll_name);
+   wrap_here ("");
+ 
+   /* Truncate name at first dot to avoid problems with the qualified
+      names we generate. Should maybe also convert to all lower case
+      for convenience on Windows */
+   read_pe_truncate_name (dll_name);
+ 
+   /* Iterate through the list of symbols.  */
+   for (i = 0; i < nexp; i++)
+     {
+       /* Pointer to the names vector.  */
+       unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
+ 
+       /* Pointer to the function address vector.  */ 
+       unsigned long func_rva = pe_as32 (erva + exp_funcbase + i * 4);
+ 
+       /* Find this symbol's section in our own array */
+       int sectix = 0;
+ 
+       for (sectix = 0; sectix < PE_SECTION_TABLE_SIZE; ++sectix)
+ 	{
+ 	  if ((func_rva >= section_data[sectix].rva_start)
+ 	      && (func_rva < section_data[sectix].rva_end))
+ 	    {
+ 	      add_pe_exported_sym (erva + name_rva,
+ 				   func_rva,
+ 				   section_data + sectix,
+ 				   dll_name,
+ 				   objfile);
+ 	      break;
+ 	    }
+ 	}
+     }
+ 
+   /* discard expdata */
+   do_cleanups (back_to);
  }
  \f
  /* Support for string table handling */


  parent reply	other threads:[~2003-01-06 17:10 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-01-03 19:41 Raoul Gough
2003-01-04  0:53 ` Michael Snyder
2003-01-04  4:43 ` Christopher Faylor
2003-01-04 16:31   ` Raoul Gough
2003-01-04 17:54     ` Eli Zaretskii
2003-01-04 20:51     ` Christopher Faylor
2003-01-05 14:44       ` Mark Kettenis
2003-01-05 17:18         ` Christopher Faylor
2003-01-05 17:40           ` Daniel Jacobowitz
2003-01-07  1:03       ` Raoul Gough
2003-01-07  1:12         ` Daniel Jacobowitz
2003-01-07 13:11       ` Raoul Gough
2003-01-07 16:46         ` Christopher Faylor
2003-01-07  2:28     ` Michael Snyder
2003-01-07  2:24   ` Michael Snyder
2003-01-04 11:03 ` Eli Zaretskii
2003-01-04 16:21   ` Raoul Gough
2003-01-06 17:10   ` Elena Zannoni [this message]
2003-01-06 17:41     ` Christopher Faylor
2003-01-07  0:46     ` Raoul Gough
2003-01-07  1:53       ` Elena Zannoni
2003-01-10 22:45         ` Raoul Gough
2003-01-07  1:00     ` Andrew Cagney
2003-01-10 22:37       ` Raoul Gough
2003-01-04 16:42 Michael Elizabeth Chastain
2003-01-05 15:40 ` Andrew Cagney

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=15897.47288.570835.988631@localhost.redhat.com \
    --to=ezannoni@redhat.com \
    --cc=RaoulGough@yahoo.co.uk \
    --cc=eliz@is.elta.co.il \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox