GDB (API)
/home/stan/gdb/src/gdb/coff-pe-read.c
Go to the documentation of this file.
00001 /* Read the export table symbols from a portable executable and
00002    convert to internal format, for GDB. Used as a last resort if no
00003    debugging symbols recognized.
00004 
00005    Copyright (C) 2003-2013 Free Software Foundation, Inc.
00006 
00007    This file is part of GDB.
00008 
00009    This program is free software; you can redistribute it and/or modify
00010    it under the terms of the GNU General Public License as published by
00011    the Free Software Foundation; either version 3 of the License, or
00012    (at your option) any later version.
00013 
00014    This program is distributed in the hope that it will be useful,
00015    but WITHOUT ANY WARRANTY; without even the implied warranty of
00016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017    GNU General Public License for more details.
00018 
00019    You should have received a copy of the GNU General Public License
00020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
00021 
00022    Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk).  */
00023 
00024 #include "defs.h"
00025 
00026 #include "coff-pe-read.h"
00027 
00028 #include "bfd.h"
00029 #include "gdbtypes.h"
00030 
00031 #include "command.h"
00032 #include "gdbcmd.h"
00033 #include "symtab.h"
00034 #include "symfile.h"
00035 #include "objfiles.h"
00036 #include "common/common-utils.h"
00037 #include "coff/internal.h"
00038 
00039 #include <ctype.h>
00040 
00041 /* Internal section information */
00042 
00043 /* Coff PE read debugging flag:
00044    default value is 0,
00045    value 1 outputs problems encountered while parsing PE file,
00046    value above 1 also lists all generated minimal symbols.  */
00047 static unsigned int debug_coff_pe_read;
00048 
00049 struct read_pe_section_data
00050 {
00051   CORE_ADDR vma_offset;         /* Offset to loaded address of section.  */
00052   unsigned long rva_start;      /* Start offset within the pe.  */
00053   unsigned long rva_end;        /* End offset within the pe.  */
00054   enum minimal_symbol_type ms_type;     /* Type to assign symbols in
00055                                            section.  */
00056   char *section_name;           /* Recorded section name.  */
00057 };
00058 
00059 #define IMAGE_SCN_CNT_CODE 0x20
00060 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40
00061 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80
00062 #define PE_SECTION_INDEX_TEXT     0
00063 #define PE_SECTION_INDEX_DATA     1
00064 #define PE_SECTION_INDEX_BSS      2
00065 #define PE_SECTION_TABLE_SIZE     3
00066 #define PE_SECTION_INDEX_INVALID -1
00067 
00068 /* Get the index of the named section in our own array, which contains
00069    text, data and bss in that order.  Return PE_SECTION_INDEX_INVALID
00070    if passed an unrecognised section name.  */
00071 
00072 static int
00073 read_pe_section_index (const char *section_name)
00074 {
00075   if (strcmp (section_name, ".text") == 0)
00076     {
00077       return PE_SECTION_INDEX_TEXT;
00078     }
00079 
00080   else if (strcmp (section_name, ".data") == 0)
00081     {
00082       return PE_SECTION_INDEX_DATA;
00083     }
00084 
00085   else if (strcmp (section_name, ".bss") == 0)
00086     {
00087       return PE_SECTION_INDEX_BSS;
00088     }
00089 
00090   else
00091     {
00092       return PE_SECTION_INDEX_INVALID;
00093     }
00094 }
00095 
00096 /* Get the index of the named section in our own full arrayi.
00097    text, data and bss in that order.  Return PE_SECTION_INDEX_INVALID
00098    if passed an unrecognised section name.  */
00099 
00100 static int
00101 get_pe_section_index (const char *section_name,
00102                       struct read_pe_section_data *sections,
00103                       int nb_sections)
00104 {
00105   int i;
00106 
00107   for (i = 0; i < nb_sections; i++)
00108     if (strcmp (sections[i].section_name, section_name) == 0)
00109       return i;
00110   return PE_SECTION_INDEX_INVALID;
00111 }
00112 
00113 /* Structure used by get_section_vmas function below
00114    to access section_data array and the size of the array
00115    stored in nb_sections field.  */
00116 struct pe_sections_info
00117 {
00118   int nb_sections;
00119   struct read_pe_section_data *sections;
00120 };
00121 
00122 /* Record the virtual memory address of a section.  */
00123 
00124 static void
00125 get_section_vmas (bfd *abfd, asection *sectp, void *context)
00126 {
00127   struct pe_sections_info *data = context;
00128   struct read_pe_section_data *sections = data->sections;
00129   int sectix = get_pe_section_index (sectp->name, sections,
00130                                      data->nb_sections);
00131 
00132   if (sectix != PE_SECTION_INDEX_INVALID)
00133     {
00134       /* Data within the section start at rva_start in the pe and at
00135          bfd_get_section_vma() within memory.  Store the offset.  */
00136 
00137       sections[sectix].vma_offset
00138         = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
00139     }
00140 }
00141 
00142 /* Create a minimal symbol entry for an exported symbol.
00143    SYM_NAME contains the exported name or NULL if exported by ordinal,
00144    FUNC_RVA contains the Relative Virtual Address of the symbol,
00145    ORDINAL is the ordinal index value of the symbol,
00146    SECTION_DATA contains information about the section in which the
00147    symbol is declared,
00148    DLL_NAME is the internal name of the DLL file,
00149    OBJFILE is the objfile struct of DLL_NAME.  */
00150 
00151 static void
00152 add_pe_exported_sym (const char *sym_name,
00153                      unsigned long func_rva,
00154                      int ordinal,
00155                      const struct read_pe_section_data *section_data,
00156                      const char *dll_name, struct objfile *objfile)
00157 {
00158   char *qualified_name, *bare_name;
00159   /* Add the stored offset to get the loaded address of the symbol.  */
00160   CORE_ADDR vma = func_rva + section_data->vma_offset;
00161 
00162   /* Generate a (hopefully unique) qualified name using the first part
00163      of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
00164      used by windbg from the "Microsoft Debugging Tools for Windows".  */
00165 
00166   if (sym_name == NULL || *sym_name == '\0')
00167     bare_name = xstrprintf ("#%d", ordinal);
00168   else
00169     bare_name = xstrdup (sym_name);
00170 
00171   qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
00172 
00173   if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
00174     fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\""
00175                         " for entry \"%s\" in dll \"%s\"\n"),
00176                         section_data->section_name, sym_name, dll_name);
00177 
00178   prim_record_minimal_symbol (qualified_name, vma,
00179                               section_data->ms_type, objfile);
00180 
00181   /* Enter the plain name as well, which might not be unique.  */
00182   prim_record_minimal_symbol (bare_name, vma, section_data->ms_type, objfile);
00183   if (debug_coff_pe_read > 1)
00184     fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
00185                         " in dll \"%s\"\n"), sym_name, dll_name);
00186   xfree (qualified_name);
00187   xfree (bare_name);
00188 }
00189 
00190 /* Create a minimal symbol entry for an exported forward symbol.
00191    Return 1 if the forwarded function was found 0 otherwise.
00192    SYM_NAME contains the exported name or NULL if exported by ordinal,
00193    FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides,
00194    FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
00195    ORDINAL is the ordinal index value of the symbol,
00196    DLL_NAME is the internal name of the DLL file,
00197    OBJFILE is the objfile struct of DLL_NAME.  */
00198 
00199 static int
00200 add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
00201                       const char *forward_func_name, int ordinal,
00202                       const char *dll_name, struct objfile *objfile)
00203 {
00204   CORE_ADDR vma;
00205   struct bound_minimal_symbol msymbol;
00206   enum minimal_symbol_type msymtype;
00207   char *qualified_name, *bare_name;
00208   int forward_dll_name_len = strlen (forward_dll_name);
00209   int forward_func_name_len = strlen (forward_func_name);
00210   int forward_len = forward_dll_name_len + forward_func_name_len + 2;
00211   char *forward_qualified_name = alloca (forward_len);
00212 
00213   xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
00214              forward_func_name);
00215 
00216 
00217   msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
00218 
00219   if (!msymbol.minsym)
00220     {
00221       int i;
00222 
00223       for (i = 0; i < forward_dll_name_len; i++)
00224         forward_qualified_name[i] = tolower (forward_qualified_name[i]);
00225       msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
00226     }
00227 
00228   if (!msymbol.minsym)
00229     {
00230       if (debug_coff_pe_read)
00231         fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
00232                             " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
00233                             forward_func_name, forward_dll_name, sym_name,
00234                             dll_name);
00235       return 0;
00236     }
00237 
00238   if (debug_coff_pe_read > 1)
00239     fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
00240                         " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
00241                         sym_name, dll_name, forward_qualified_name);
00242 
00243   vma = SYMBOL_VALUE_ADDRESS (msymbol.minsym);
00244   msymtype = MSYMBOL_TYPE (msymbol.minsym);
00245 
00246   /* Generate a (hopefully unique) qualified name using the first part
00247      of the dll name, e.g. KERNEL32!AddAtomA.  This matches the style
00248      used by windbg from the "Microsoft Debugging Tools for Windows".  */
00249 
00250   if (sym_name == NULL || *sym_name == '\0')
00251     bare_name = xstrprintf ("#%d", ordinal);
00252   else
00253     bare_name = xstrdup (sym_name);
00254 
00255   qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
00256 
00257   prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile);
00258 
00259   /* Enter the plain name as well, which might not be unique.  */
00260   prim_record_minimal_symbol (bare_name, vma, msymtype, objfile);
00261   xfree (qualified_name);
00262   xfree (bare_name);
00263 
00264   return 1;
00265 }
00266 
00267 /* Truncate a dll_name at the last dot character.  */
00268 
00269 static void
00270 read_pe_truncate_name (char *dll_name)
00271 {
00272   char *last_point = strrchr (dll_name, '.');
00273 
00274   if (last_point != NULL)
00275     *last_point = '\0';
00276 }
00277 
00278 /* Low-level support functions, direct from the ld module pe-dll.c.  */
00279 static unsigned int
00280 pe_get16 (bfd *abfd, int where)
00281 {
00282   unsigned char b[2];
00283 
00284   bfd_seek (abfd, (file_ptr) where, SEEK_SET);
00285   bfd_bread (b, (bfd_size_type) 2, abfd);
00286   return b[0] + (b[1] << 8);
00287 }
00288 
00289 static unsigned int
00290 pe_get32 (bfd *abfd, int where)
00291 {
00292   unsigned char b[4];
00293 
00294   bfd_seek (abfd, (file_ptr) where, SEEK_SET);
00295   bfd_bread (b, (bfd_size_type) 4, abfd);
00296   return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
00297 }
00298 
00299 static unsigned int
00300 pe_as16 (void *ptr)
00301 {
00302   unsigned char *b = ptr;
00303 
00304   return b[0] + (b[1] << 8);
00305 }
00306 
00307 static unsigned int
00308 pe_as32 (void *ptr)
00309 {
00310   unsigned char *b = ptr;
00311 
00312   return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
00313 }
00314 
00315 /* Read the (non-debug) export symbol table from a portable
00316    executable.  Code originally lifted from the ld function
00317    pe_implied_import_dll in pe-dll.c.  */
00318 
00319 void
00320 read_pe_exported_syms (struct objfile *objfile)
00321 {
00322   bfd *dll = objfile->obfd;
00323   unsigned long nbnormal, nbforward;
00324   unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
00325   unsigned long export_opthdrrva, export_opthdrsize;
00326   unsigned long export_rva, export_size, nsections, secptr, expptr;
00327   unsigned long exp_funcbase;
00328   unsigned char *expdata, *erva;
00329   unsigned long name_rvas, ordinals, nexp, ordbase;
00330   char *dll_name = (char *) dll->filename;
00331   int otherix = PE_SECTION_TABLE_SIZE;
00332   int is_pe64 = 0;
00333   int is_pe32 = 0;
00334 
00335   /* Array elements are for text, data and bss in that order
00336      Initialization with RVA_START > RVA_END guarantees that
00337      unused sections won't be matched.  */
00338   struct read_pe_section_data *section_data;
00339   struct pe_sections_info pe_sections_info;
00340 
00341   struct cleanup *back_to = make_cleanup (null_cleanup, 0);
00342 
00343   char const *target = bfd_get_target (objfile->obfd);
00344 
00345   section_data = xzalloc (PE_SECTION_TABLE_SIZE
00346                          * sizeof (struct read_pe_section_data));
00347 
00348   make_cleanup (free_current_contents, &section_data);
00349 
00350   for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
00351     {
00352       section_data[i].vma_offset = 0;
00353       section_data[i].rva_start = 1;
00354       section_data[i].rva_end = 0;
00355     };
00356   section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
00357   section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
00358   section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
00359   section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
00360   section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
00361   section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
00362 
00363   is_pe64 = (strcmp (target, "pe-x86-64") == 0
00364              || strcmp (target, "pei-x86-64") == 0);
00365   is_pe32 = (strcmp (target, "pe-i386") == 0
00366              || strcmp (target, "pei-i386") == 0
00367              || strcmp (target, "pe-arm-wince-little") == 0
00368              || strcmp (target, "pei-arm-wince-little") == 0);
00369   if (!is_pe32 && !is_pe64)
00370     {
00371       /* This is not a recognized PE format file.  Abort now, because
00372          the code is untested on anything else.  *FIXME* test on
00373          further architectures and loosen or remove this test.  */
00374       do_cleanups (back_to);
00375       return;
00376     }
00377 
00378   /* Get pe_header, optional header and numbers of export entries.  */
00379   pe_header_offset = pe_get32 (dll, 0x3c);
00380   opthdr_ofs = pe_header_offset + 4 + 20;
00381   if (is_pe64)
00382     num_entries = pe_get32 (dll, opthdr_ofs + 108);
00383   else
00384     num_entries = pe_get32 (dll, opthdr_ofs + 92);
00385 
00386   if (num_entries < 1)          /* No exports.  */
00387     {
00388       do_cleanups (back_to);
00389       return;
00390     }
00391   if (is_pe64)
00392     {
00393       export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
00394       export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
00395     }
00396   else
00397     {
00398       export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
00399       export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
00400     }
00401   nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
00402   secptr = (pe_header_offset + 4 + 20 +
00403             pe_get16 (dll, pe_header_offset + 4 + 16));
00404   expptr = 0;
00405   export_size = 0;
00406 
00407   /* Get the rva and size of the export section.  */
00408   for (i = 0; i < nsections; i++)
00409     {
00410       char sname[8];
00411       unsigned long secptr1 = secptr + 40 * i;
00412       unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
00413       unsigned long vsize = pe_get32 (dll, secptr1 + 16);
00414       unsigned long fptr = pe_get32 (dll, secptr1 + 20);
00415 
00416       bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
00417       bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);
00418 
00419       if ((strcmp (sname, ".edata") == 0)
00420           || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
00421         {
00422           if (strcmp (sname, ".edata") != 0)
00423             {
00424               if (debug_coff_pe_read)
00425                 fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll "
00426                                     "\"%s\" is in section \"%s\"\n"),
00427                                     dll_name, sname);
00428             }
00429           else if (export_opthdrrva != vaddr && debug_coff_pe_read)
00430             fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA"
00431                                 " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
00432                                 dll_name, export_opthdrrva, vaddr);
00433           expptr = fptr + (export_opthdrrva - vaddr);
00434           break;
00435         }
00436     }
00437 
00438   export_rva = export_opthdrrva;
00439   export_size = export_opthdrsize;
00440 
00441   if (export_size == 0)
00442     {
00443       /* Empty export table.  */
00444       do_cleanups (back_to);
00445       return;
00446     }
00447 
00448   /* Scan sections and store the base and size of the relevant
00449      sections.  */
00450   for (i = 0; i < nsections; i++)
00451     {
00452       unsigned long secptr1 = secptr + 40 * i;
00453       unsigned long vsize = pe_get32 (dll, secptr1 + 8);
00454       unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
00455       unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
00456       char sec_name[SCNNMLEN + 1];
00457       int sectix;
00458 
00459       bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
00460       bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll);
00461       sec_name[SCNNMLEN] = '\0';
00462 
00463       sectix = read_pe_section_index (sec_name);
00464 
00465       if (sectix != PE_SECTION_INDEX_INVALID)
00466         {
00467           section_data[sectix].rva_start = vaddr;
00468           section_data[sectix].rva_end = vaddr + vsize;
00469         }
00470       else
00471         {
00472           char *name;
00473 
00474           section_data = xrealloc (section_data, (otherix + 1)
00475                                    * sizeof (struct read_pe_section_data));
00476           name = xstrdup (sec_name);
00477           section_data[otherix].section_name = name;
00478           make_cleanup (xfree, name);
00479           section_data[otherix].rva_start = vaddr;
00480           section_data[otherix].rva_end = vaddr + vsize;
00481           section_data[otherix].vma_offset = 0;
00482           if (characteristics & IMAGE_SCN_CNT_CODE)
00483             section_data[otherix].ms_type = mst_text;
00484           else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
00485             section_data[otherix].ms_type = mst_data;
00486           else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
00487             section_data[otherix].ms_type = mst_bss;
00488           else
00489             section_data[otherix].ms_type = mst_unknown;
00490           otherix++;
00491         }
00492     }
00493 
00494   expdata = (unsigned char *) xmalloc (export_size);
00495   make_cleanup (xfree, expdata);
00496 
00497   bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
00498   bfd_bread (expdata, (bfd_size_type) export_size, dll);
00499   erva = expdata - export_rva;
00500 
00501   nexp = pe_as32 (expdata + 24);
00502   name_rvas = pe_as32 (expdata + 32);
00503   ordinals = pe_as32 (expdata + 36);
00504   ordbase = pe_as32 (expdata + 16);
00505   exp_funcbase = pe_as32 (expdata + 28);
00506 
00507   /* Use internal dll name instead of full pathname.  */
00508   dll_name = (char *) (pe_as32 (expdata + 12) + erva);
00509 
00510   pe_sections_info.nb_sections = otherix;
00511   pe_sections_info.sections = section_data;
00512 
00513   bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info);
00514 
00515   /* Adjust the vma_offsets in case this PE got relocated. This
00516      assumes that *all* sections share the same relocation offset
00517      as the text section.  */
00518   for (i = 0; i < otherix; i++)
00519     {
00520       section_data[i].vma_offset
00521         += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
00522     }
00523 
00524   /* Truncate name at first dot. Should maybe also convert to all
00525      lower case for convenience on Windows.  */
00526   read_pe_truncate_name (dll_name);
00527 
00528   if (debug_coff_pe_read)
00529     fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
00530                         " base=%ld\n"), dll_name, nexp, ordbase);
00531   nbforward = 0;
00532   nbnormal = 0;
00533   /* Iterate through the list of symbols.  */
00534   for (i = 0; i < nexp; i++)
00535     {
00536       /* Pointer to the names vector.  */
00537       unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
00538       /* Retrieve ordinal value.  */
00539 
00540       unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
00541 
00542 
00543       /* Pointer to the function address vector.  */
00544       /* This is relatived to ordinal value. */
00545       unsigned long func_rva = pe_as32 (erva + exp_funcbase +
00546                                         ordinal * 4);
00547 
00548       /* Find this symbol's section in our own array.  */
00549       int sectix = 0;
00550       int section_found = 0;
00551 
00552       /* First handle forward cases.  */
00553       if (func_rva >= export_rva && func_rva < export_rva + export_size)
00554         {
00555           char *forward_name = (char *) (erva + func_rva);
00556           char *funcname = (char *) (erva + name_rva);
00557           char *forward_dll_name = forward_name;
00558           char *forward_func_name = forward_name;
00559           char *sep = strrchr (forward_name, '.');
00560 
00561           if (sep)
00562             {
00563               int len = (int) (sep - forward_name);
00564 
00565               forward_dll_name = alloca (len + 1);
00566               strncpy (forward_dll_name, forward_name, len);
00567               forward_dll_name[len] = '\0';
00568               forward_func_name = ++sep;
00569             }
00570           if (add_pe_forwarded_sym (funcname, forward_dll_name,
00571                                     forward_func_name, ordinal,
00572                                     dll_name, objfile) != 0)
00573             ++nbforward;
00574           continue;
00575         }
00576 
00577       for (sectix = 0; sectix < otherix; ++sectix)
00578         {
00579           if ((func_rva >= section_data[sectix].rva_start)
00580               && (func_rva < section_data[sectix].rva_end))
00581             {
00582               char *sym_name = (char *) (erva + name_rva);
00583 
00584               section_found = 1;
00585               add_pe_exported_sym (sym_name, func_rva, ordinal,
00586                                    section_data + sectix, dll_name, objfile);
00587               ++nbnormal;
00588               break;
00589             }
00590         }
00591       if (!section_found)
00592         {
00593           char *funcname = (char *) (erva + name_rva);
00594 
00595           if (name_rva == 0)
00596             {
00597               add_pe_exported_sym (NULL, func_rva, ordinal,
00598                                    section_data, dll_name, objfile);
00599               ++nbnormal;
00600             }
00601           else if (debug_coff_pe_read)
00602             fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
00603                                 " RVA 0x%lx in dll \"%s\" not handled\n"),
00604                                 funcname, ordinal, func_rva, dll_name);
00605         }
00606     }
00607 
00608   if (debug_coff_pe_read)
00609     fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
00610                         " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
00611                         nbforward, nbnormal + nbforward, nexp);
00612   /* Discard expdata and section_data.  */
00613   do_cleanups (back_to);
00614 }
00615 
00616 /* Extract from ABFD the offset of the .text section.
00617    This offset is mainly related to the offset within the file.
00618    The value was previously expected to be 0x1000 for all files,
00619    but some Windows OS core DLLs seem to use 0x10000 section alignement
00620    which modified the return value of that function.
00621    Still return default 0x1000 value if ABFD is NULL or
00622    if '.text' section is not found, but that should not happen...  */
00623 
00624 #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
00625 
00626 CORE_ADDR
00627 pe_text_section_offset (struct bfd *abfd)
00628 
00629 {
00630   unsigned long pe_header_offset, i;
00631   unsigned long nsections, secptr;
00632   int is_pe64 = 0;
00633   int is_pe32 = 0;
00634   char const *target;
00635 
00636   if (!abfd)
00637     return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
00638 
00639   target = bfd_get_target (abfd);
00640 
00641   is_pe64 = (strcmp (target, "pe-x86-64") == 0
00642              || strcmp (target, "pei-x86-64") == 0);
00643   is_pe32 = (strcmp (target, "pe-i386") == 0
00644              || strcmp (target, "pei-i386") == 0
00645              || strcmp (target, "pe-arm-wince-little") == 0
00646              || strcmp (target, "pei-arm-wince-little") == 0);
00647 
00648   if (!is_pe32 && !is_pe64)
00649     {
00650       /* This is not a recognized PE format file.  Abort now, because
00651          the code is untested on anything else.  *FIXME* test on
00652          further architectures and loosen or remove this test.  */
00653       return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
00654     }
00655 
00656   /* Get pe_header, optional header and numbers of sections.  */
00657   pe_header_offset = pe_get32 (abfd, 0x3c);
00658   nsections = pe_get16 (abfd, pe_header_offset + 4 + 2);
00659   secptr = (pe_header_offset + 4 + 20 +
00660             pe_get16 (abfd, pe_header_offset + 4 + 16));
00661 
00662   /* Get the rva and size of the export section.  */
00663   for (i = 0; i < nsections; i++)
00664     {
00665       char sname[SCNNMLEN + 1];
00666       unsigned long secptr1 = secptr + 40 * i;
00667       unsigned long vaddr = pe_get32 (abfd, secptr1 + 12);
00668 
00669       bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET);
00670       bfd_bread (sname, (bfd_size_type) SCNNMLEN, abfd);
00671       sname[SCNNMLEN] = '\0';
00672       if (strcmp (sname, ".text") == 0)
00673         return vaddr;
00674     }
00675 
00676   return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
00677 }
00678 
00679 /* Implements "show debug coff_pe_read" command.  */
00680 
00681 static void
00682 show_debug_coff_pe_read (struct ui_file *file, int from_tty,
00683                          struct cmd_list_element *c, const char *value)
00684 {
00685   fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value);
00686 }
00687 
00688 /* Provide a prototype to silence -Wmissing-prototypes.  */
00689 
00690 void _initialize_coff_pe_read (void);
00691 
00692 /* Adds "Set/show debug coff_pe_read" commands.  */
00693 
00694 void
00695 _initialize_coff_pe_read (void)
00696 {
00697   add_setshow_zuinteger_cmd ("coff-pe-read", class_maintenance,
00698                              &debug_coff_pe_read,
00699                              _("Set coff PE read debugging."),
00700                              _("Show coff PE read debugging."),
00701                              _("When set, debugging messages for coff reading "
00702                                "of exported symbols are displayed."),
00703                              NULL, show_debug_coff_pe_read,
00704                              &setdebuglist, &showdebuglist);
00705 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines