GDB (xrefs)
/tmp/gdb-7.10/gdb/coff-pe-read.c
Go to the documentation of this file.
1 /* Read the export table symbols from a portable executable and
2  convert to internal format, for GDB. Used as a last resort if no
3  debugging symbols recognized.
4 
5  Copyright (C) 2003-2015 Free Software Foundation, Inc.
6 
7  This file is part of GDB.
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 3 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program. If not, see <http://www.gnu.org/licenses/>.
21 
22  Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
23 
24 #include "defs.h"
25 
26 #include "coff-pe-read.h"
27 
28 #include "bfd.h"
29 #include "gdbtypes.h"
30 
31 #include "command.h"
32 #include "gdbcmd.h"
33 #include "symtab.h"
34 #include "symfile.h"
35 #include "objfiles.h"
36 #include "common/common-utils.h"
37 #include "coff/internal.h"
38 
39 #include <ctype.h>
40 
41 /* Internal section information */
42 
43 /* Coff PE read debugging flag:
44  default value is 0,
45  value 1 outputs problems encountered while parsing PE file,
46  value above 1 also lists all generated minimal symbols. */
47 static unsigned int debug_coff_pe_read;
48 
50 {
51  CORE_ADDR vma_offset; /* Offset to loaded address of section. */
52  unsigned long rva_start; /* Start offset within the pe. */
53  unsigned long rva_end; /* End offset within the pe. */
54  enum minimal_symbol_type ms_type; /* Type to assign symbols in
55  section. */
56  unsigned int index; /* BFD section number. */
57  char *section_name; /* Recorded section name. */
58 };
59 
60 #define IMAGE_SCN_CNT_CODE 0x20
61 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40
62 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80
63 #define PE_SECTION_INDEX_TEXT 0
64 #define PE_SECTION_INDEX_DATA 1
65 #define PE_SECTION_INDEX_BSS 2
66 #define PE_SECTION_TABLE_SIZE 3
67 #define PE_SECTION_INDEX_INVALID -1
68 
69 /* Get the index of the named section in our own array, which contains
70  text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
71  if passed an unrecognised section name. */
72 
73 static int
74 read_pe_section_index (const char *section_name)
75 {
76  if (strcmp (section_name, ".text") == 0)
77  {
78  return PE_SECTION_INDEX_TEXT;
79  }
80 
81  else if (strcmp (section_name, ".data") == 0)
82  {
83  return PE_SECTION_INDEX_DATA;
84  }
85 
86  else if (strcmp (section_name, ".bss") == 0)
87  {
88  return PE_SECTION_INDEX_BSS;
89  }
90 
91  else
92  {
94  }
95 }
96 
97 /* Get the index of the named section in our own full array.
98  text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
99  if passed an unrecognised section name. */
100 
101 static int
102 get_pe_section_index (const char *section_name,
103  struct read_pe_section_data *sections,
104  int nb_sections)
105 {
106  int i;
107 
108  for (i = 0; i < nb_sections; i++)
109  if (strcmp (sections[i].section_name, section_name) == 0)
110  return i;
112 }
113 
114 /* Structure used by get_section_vmas function below
115  to access section_data array and the size of the array
116  stored in nb_sections field. */
118 {
121 };
122 
123 /* Record the virtual memory address of a section. */
124 
125 static void
126 get_section_vmas (bfd *abfd, asection *sectp, void *context)
127 {
128  struct pe_sections_info *data = context;
129  struct read_pe_section_data *sections = data->sections;
130  int sectix = get_pe_section_index (sectp->name, sections,
131  data->nb_sections);
132 
133  if (sectix != PE_SECTION_INDEX_INVALID)
134  {
135  /* Data within the section start at rva_start in the pe and at
136  bfd_get_section_vma() within memory. Store the offset. */
137 
138  sections[sectix].vma_offset
139  = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
140  }
141 }
142 
143 /* Create a minimal symbol entry for an exported symbol.
144  SYM_NAME contains the exported name or NULL if exported by ordinal,
145  FUNC_RVA contains the Relative Virtual Address of the symbol,
146  ORDINAL is the ordinal index value of the symbol,
147  SECTION_DATA contains information about the section in which the
148  symbol is declared,
149  DLL_NAME is the internal name of the DLL file,
150  OBJFILE is the objfile struct of DLL_NAME. */
151 
152 static void
153 add_pe_exported_sym (const char *sym_name,
154  unsigned long func_rva,
155  int ordinal,
156  const struct read_pe_section_data *section_data,
157  const char *dll_name, struct objfile *objfile)
158 {
159  char *qualified_name, *bare_name;
160  /* Add the stored offset to get the loaded address of the symbol. */
161  CORE_ADDR vma = func_rva + section_data->vma_offset;
162 
163  /* Generate a (hopefully unique) qualified name using the first part
164  of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
165  used by windbg from the "Microsoft Debugging Tools for Windows". */
166 
167  if (sym_name == NULL || *sym_name == '\0')
168  bare_name = xstrprintf ("#%d", ordinal);
169  else
170  bare_name = xstrdup (sym_name);
171 
172  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
173 
174  if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
175  fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\""
176  " for entry \"%s\" in dll \"%s\"\n"),
177  section_data->section_name, sym_name, dll_name);
178 
179  prim_record_minimal_symbol_and_info (qualified_name, vma,
180  section_data->ms_type,
181  section_data->index, objfile);
182 
183  /* Enter the plain name as well, which might not be unique. */
184  prim_record_minimal_symbol_and_info (bare_name, vma, section_data->ms_type,
185  section_data->index, objfile);
186  if (debug_coff_pe_read > 1)
187  fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
188  " in dll \"%s\"\n"), sym_name, dll_name);
189  xfree (qualified_name);
190  xfree (bare_name);
191 }
192 
193 /* Create a minimal symbol entry for an exported forward symbol.
194  Return 1 if the forwarded function was found 0 otherwise.
195  SYM_NAME contains the exported name or NULL if exported by ordinal,
196  FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides,
197  FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
198  ORDINAL is the ordinal index value of the symbol,
199  DLL_NAME is the internal name of the DLL file,
200  OBJFILE is the objfile struct of DLL_NAME. */
201 
202 static int
203 add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
204  const char *forward_func_name, int ordinal,
205  const char *dll_name, struct objfile *objfile)
206 {
207  CORE_ADDR vma, baseaddr;
208  struct bound_minimal_symbol msymbol;
209  enum minimal_symbol_type msymtype;
210  char *qualified_name, *bare_name;
211  int forward_dll_name_len = strlen (forward_dll_name);
212  int forward_func_name_len = strlen (forward_func_name);
213  int forward_len = forward_dll_name_len + forward_func_name_len + 2;
214  char *forward_qualified_name = alloca (forward_len);
215  short section;
216 
217  xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
218  forward_func_name);
219 
220 
221  msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
222 
223  if (!msymbol.minsym)
224  {
225  int i;
226 
227  for (i = 0; i < forward_dll_name_len; i++)
228  forward_qualified_name[i] = tolower (forward_qualified_name[i]);
229  msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name);
230  }
231 
232  if (!msymbol.minsym)
233  {
234  if (debug_coff_pe_read)
235  fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
236  " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
237  forward_func_name, forward_dll_name, sym_name,
238  dll_name);
239  return 0;
240  }
241 
242  if (debug_coff_pe_read > 1)
243  fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
244  " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
245  sym_name, dll_name, forward_qualified_name);
246 
247  vma = BMSYMBOL_VALUE_ADDRESS (msymbol);
248  msymtype = MSYMBOL_TYPE (msymbol.minsym);
249  section = MSYMBOL_SECTION (msymbol.minsym);
250 
251  /* Generate a (hopefully unique) qualified name using the first part
252  of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
253  used by windbg from the "Microsoft Debugging Tools for Windows". */
254 
255  if (sym_name == NULL || *sym_name == '\0')
256  bare_name = xstrprintf ("#%d", ordinal);
257  else
258  bare_name = xstrdup (sym_name);
259 
260  qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
261 
262  /* Note that this code makes a minimal symbol whose value may point
263  outside of any section in this objfile. These symbols can't
264  really be relocated properly, but nevertheless we make a stab at
265  it, choosing an approach consistent with the history of this
266  code. */
267  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
268 
269  prim_record_minimal_symbol_and_info (qualified_name, vma - baseaddr,
270  msymtype, section, objfile);
271 
272  /* Enter the plain name as well, which might not be unique. */
273  prim_record_minimal_symbol_and_info (bare_name, vma - baseaddr, msymtype,
274  section, objfile);
275  xfree (qualified_name);
276  xfree (bare_name);
277 
278  return 1;
279 }
280 
281 /* Truncate a dll_name at the last dot character. */
282 
283 static void
284 read_pe_truncate_name (char *dll_name)
285 {
286  char *last_point = strrchr (dll_name, '.');
287 
288  if (last_point != NULL)
289  *last_point = '\0';
290 }
291 
292 /* Low-level support functions, direct from the ld module pe-dll.c. */
293 static unsigned int
294 pe_get16 (bfd *abfd, int where)
295 {
296  unsigned char b[2];
297 
298  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
299  bfd_bread (b, (bfd_size_type) 2, abfd);
300  return b[0] + (b[1] << 8);
301 }
302 
303 static unsigned int
304 pe_get32 (bfd *abfd, int where)
305 {
306  unsigned char b[4];
307 
308  bfd_seek (abfd, (file_ptr) where, SEEK_SET);
309  bfd_bread (b, (bfd_size_type) 4, abfd);
310  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
311 }
312 
313 static unsigned int
314 pe_as16 (void *ptr)
315 {
316  unsigned char *b = ptr;
317 
318  return b[0] + (b[1] << 8);
319 }
320 
321 static unsigned int
322 pe_as32 (void *ptr)
323 {
324  unsigned char *b = ptr;
325 
326  return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
327 }
328 
329 /* Read the (non-debug) export symbol table from a portable
330  executable. Code originally lifted from the ld function
331  pe_implied_import_dll in pe-dll.c. */
332 
333 void
335 {
336  bfd *dll = objfile->obfd;
337  unsigned long nbnormal, nbforward;
338  unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
339  unsigned long export_opthdrrva, export_opthdrsize;
340  unsigned long export_rva, export_size, nsections, secptr, expptr;
341  unsigned long exp_funcbase;
342  unsigned char *expdata, *erva;
343  unsigned long name_rvas, ordinals, nexp, ordbase;
344  char *dll_name = (char *) dll->filename;
345  int otherix = PE_SECTION_TABLE_SIZE;
346  int is_pe64 = 0;
347  int is_pe32 = 0;
348 
349  /* Array elements are for text, data and bss in that order
350  Initialization with RVA_START > RVA_END guarantees that
351  unused sections won't be matched. */
352  struct read_pe_section_data *section_data;
354 
355  struct cleanup *back_to = make_cleanup (null_cleanup, 0);
356 
357  char const *target = bfd_get_target (objfile->obfd);
358 
359  section_data = xzalloc (PE_SECTION_TABLE_SIZE
360  * sizeof (struct read_pe_section_data));
361 
362  make_cleanup (free_current_contents, &section_data);
363 
364  for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
365  {
366  section_data[i].vma_offset = 0;
367  section_data[i].rva_start = 1;
368  section_data[i].rva_end = 0;
369  };
370  section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
371  section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
372  section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
373  section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
374  section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
375  section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
376 
377  is_pe64 = (strcmp (target, "pe-x86-64") == 0
378  || strcmp (target, "pei-x86-64") == 0);
379  is_pe32 = (strcmp (target, "pe-i386") == 0
380  || strcmp (target, "pei-i386") == 0
381  || strcmp (target, "pe-arm-wince-little") == 0
382  || strcmp (target, "pei-arm-wince-little") == 0);
383  if (!is_pe32 && !is_pe64)
384  {
385  /* This is not a recognized PE format file. Abort now, because
386  the code is untested on anything else. *FIXME* test on
387  further architectures and loosen or remove this test. */
388  do_cleanups (back_to);
389  return;
390  }
391 
392  /* Get pe_header, optional header and numbers of export entries. */
393  pe_header_offset = pe_get32 (dll, 0x3c);
394  opthdr_ofs = pe_header_offset + 4 + 20;
395  if (is_pe64)
396  num_entries = pe_get32 (dll, opthdr_ofs + 108);
397  else
398  num_entries = pe_get32 (dll, opthdr_ofs + 92);
399 
400  if (num_entries < 1) /* No exports. */
401  {
402  do_cleanups (back_to);
403  return;
404  }
405  if (is_pe64)
406  {
407  export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
408  export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
409  }
410  else
411  {
412  export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
413  export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
414  }
415  nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
416  secptr = (pe_header_offset + 4 + 20 +
417  pe_get16 (dll, pe_header_offset + 4 + 16));
418  expptr = 0;
419  export_size = 0;
420 
421  /* Get the rva and size of the export section. */
422  for (i = 0; i < nsections; i++)
423  {
424  char sname[8];
425  unsigned long secptr1 = secptr + 40 * i;
426  unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
427  unsigned long vsize = pe_get32 (dll, secptr1 + 16);
428  unsigned long fptr = pe_get32 (dll, secptr1 + 20);
429 
430  bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
431  bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);
432 
433  if ((strcmp (sname, ".edata") == 0)
434  || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
435  {
436  if (strcmp (sname, ".edata") != 0)
437  {
438  if (debug_coff_pe_read)
439  fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll "
440  "\"%s\" is in section \"%s\"\n"),
441  dll_name, sname);
442  }
443  else if (export_opthdrrva != vaddr && debug_coff_pe_read)
444  fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA"
445  " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
446  dll_name, export_opthdrrva, vaddr);
447  expptr = fptr + (export_opthdrrva - vaddr);
448  break;
449  }
450  }
451 
452  export_rva = export_opthdrrva;
453  export_size = export_opthdrsize;
454 
455  if (export_size == 0)
456  {
457  /* Empty export table. */
458  do_cleanups (back_to);
459  return;
460  }
461 
462  /* Scan sections and store the base and size of the relevant
463  sections. */
464  for (i = 0; i < nsections; i++)
465  {
466  unsigned long secptr1 = secptr + 40 * i;
467  unsigned long vsize = pe_get32 (dll, secptr1 + 8);
468  unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
469  unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
470  char sec_name[SCNNMLEN + 1];
471  int sectix;
472  unsigned int bfd_section_index;
473  asection *section;
474 
475  bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
476  bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll);
477  sec_name[SCNNMLEN] = '\0';
478 
479  sectix = read_pe_section_index (sec_name);
480  section = bfd_get_section_by_name (dll, sec_name);
481  if (section)
482  bfd_section_index = section->index;
483  else
484  bfd_section_index = -1;
485 
486  if (sectix != PE_SECTION_INDEX_INVALID)
487  {
488  section_data[sectix].rva_start = vaddr;
489  section_data[sectix].rva_end = vaddr + vsize;
490  section_data[sectix].index = bfd_section_index;
491  }
492  else
493  {
494  char *name;
495 
496  section_data = xrealloc (section_data, (otherix + 1)
497  * sizeof (struct read_pe_section_data));
498  name = xstrdup (sec_name);
499  section_data[otherix].section_name = name;
500  make_cleanup (xfree, name);
501  section_data[otherix].rva_start = vaddr;
502  section_data[otherix].rva_end = vaddr + vsize;
503  section_data[otherix].vma_offset = 0;
504  section_data[otherix].index = bfd_section_index;
505  if (characteristics & IMAGE_SCN_CNT_CODE)
506  section_data[otherix].ms_type = mst_text;
507  else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
508  section_data[otherix].ms_type = mst_data;
509  else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
510  section_data[otherix].ms_type = mst_bss;
511  else
512  section_data[otherix].ms_type = mst_unknown;
513  otherix++;
514  }
515  }
516 
517  expdata = (unsigned char *) xmalloc (export_size);
518  make_cleanup (xfree, expdata);
519 
520  bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
521  bfd_bread (expdata, (bfd_size_type) export_size, dll);
522  erva = expdata - export_rva;
523 
524  nexp = pe_as32 (expdata + 24);
525  name_rvas = pe_as32 (expdata + 32);
526  ordinals = pe_as32 (expdata + 36);
527  ordbase = pe_as32 (expdata + 16);
528  exp_funcbase = pe_as32 (expdata + 28);
529 
530  /* Use internal dll name instead of full pathname. */
531  dll_name = (char *) (pe_as32 (expdata + 12) + erva);
532 
533  pe_sections_info.nb_sections = otherix;
534  pe_sections_info.sections = section_data;
535 
536  bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info);
537 
538  /* Truncate name at first dot. Should maybe also convert to all
539  lower case for convenience on Windows. */
540  read_pe_truncate_name (dll_name);
541 
542  if (debug_coff_pe_read)
543  fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
544  " base=%ld\n"), dll_name, nexp, ordbase);
545  nbforward = 0;
546  nbnormal = 0;
547  /* Iterate through the list of symbols. */
548  for (i = 0; i < nexp; i++)
549  {
550  /* Pointer to the names vector. */
551  unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
552  /* Retrieve ordinal value. */
553 
554  unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
555 
556 
557  /* Pointer to the function address vector. */
558  /* This is relatived to ordinal value. */
559  unsigned long func_rva = pe_as32 (erva + exp_funcbase +
560  ordinal * 4);
561 
562  /* Find this symbol's section in our own array. */
563  int sectix = 0;
564  int section_found = 0;
565 
566  /* First handle forward cases. */
567  if (func_rva >= export_rva && func_rva < export_rva + export_size)
568  {
569  char *forward_name = (char *) (erva + func_rva);
570  char *funcname = (char *) (erva + name_rva);
571  char *forward_dll_name = forward_name;
572  char *forward_func_name = forward_name;
573  char *sep = strrchr (forward_name, '.');
574 
575  if (sep)
576  {
577  int len = (int) (sep - forward_name);
578 
579  forward_dll_name = alloca (len + 1);
580  strncpy (forward_dll_name, forward_name, len);
581  forward_dll_name[len] = '\0';
582  forward_func_name = ++sep;
583  }
584  if (add_pe_forwarded_sym (funcname, forward_dll_name,
585  forward_func_name, ordinal,
586  dll_name, objfile) != 0)
587  ++nbforward;
588  continue;
589  }
590 
591  for (sectix = 0; sectix < otherix; ++sectix)
592  {
593  if ((func_rva >= section_data[sectix].rva_start)
594  && (func_rva < section_data[sectix].rva_end))
595  {
596  char *sym_name = (char *) (erva + name_rva);
597 
598  section_found = 1;
599  add_pe_exported_sym (sym_name, func_rva, ordinal,
600  section_data + sectix, dll_name, objfile);
601  ++nbnormal;
602  break;
603  }
604  }
605  if (!section_found)
606  {
607  char *funcname = (char *) (erva + name_rva);
608 
609  if (name_rva == 0)
610  {
611  add_pe_exported_sym (NULL, func_rva, ordinal,
612  section_data, dll_name, objfile);
613  ++nbnormal;
614  }
615  else if (debug_coff_pe_read)
616  fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
617  " RVA 0x%lx in dll \"%s\" not handled\n"),
618  funcname, ordinal, func_rva, dll_name);
619  }
620  }
621 
622  if (debug_coff_pe_read)
623  fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
624  " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
625  nbforward, nbnormal + nbforward, nexp);
626  /* Discard expdata and section_data. */
627  do_cleanups (back_to);
628 }
629 
630 /* Extract from ABFD the offset of the .text section.
631  This offset is mainly related to the offset within the file.
632  The value was previously expected to be 0x1000 for all files,
633  but some Windows OS core DLLs seem to use 0x10000 section alignement
634  which modified the return value of that function.
635  Still return default 0x1000 value if ABFD is NULL or
636  if '.text' section is not found, but that should not happen... */
637 
638 #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
639 
640 CORE_ADDR
641 pe_text_section_offset (struct bfd *abfd)
642 
643 {
644  unsigned long pe_header_offset, i;
645  unsigned long nsections, secptr;
646  int is_pe64 = 0;
647  int is_pe32 = 0;
648  char const *target;
649 
650  if (!abfd)
652 
653  target = bfd_get_target (abfd);
654 
655  is_pe64 = (strcmp (target, "pe-x86-64") == 0
656  || strcmp (target, "pei-x86-64") == 0);
657  is_pe32 = (strcmp (target, "pe-i386") == 0
658  || strcmp (target, "pei-i386") == 0
659  || strcmp (target, "pe-arm-wince-little") == 0
660  || strcmp (target, "pei-arm-wince-little") == 0);
661 
662  if (!is_pe32 && !is_pe64)
663  {
664  /* This is not a recognized PE format file. Abort now, because
665  the code is untested on anything else. *FIXME* test on
666  further architectures and loosen or remove this test. */
668  }
669 
670  /* Get pe_header, optional header and numbers of sections. */
671  pe_header_offset = pe_get32 (abfd, 0x3c);
672  nsections = pe_get16 (abfd, pe_header_offset + 4 + 2);
673  secptr = (pe_header_offset + 4 + 20 +
674  pe_get16 (abfd, pe_header_offset + 4 + 16));
675 
676  /* Get the rva and size of the export section. */
677  for (i = 0; i < nsections; i++)
678  {
679  char sname[SCNNMLEN + 1];
680  unsigned long secptr1 = secptr + 40 * i;
681  unsigned long vaddr = pe_get32 (abfd, secptr1 + 12);
682 
683  bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET);
684  bfd_bread (sname, (bfd_size_type) SCNNMLEN, abfd);
685  sname[SCNNMLEN] = '\0';
686  if (strcmp (sname, ".text") == 0)
687  return vaddr;
688  }
689 
691 }
692 
693 /* Implements "show debug coff_pe_read" command. */
694 
695 static void
696 show_debug_coff_pe_read (struct ui_file *file, int from_tty,
697  struct cmd_list_element *c, const char *value)
698 {
699  fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value);
700 }
701 
702 /* Provide a prototype to silence -Wmissing-prototypes. */
703 
704 void _initialize_coff_pe_read (void);
705 
706 /* Adds "Set/show debug coff_pe_read" commands. */
707 
708 void
710 {
713  _("Set coff PE read debugging."),
714  _("Show coff PE read debugging."),
715  _("When set, debugging messages for coff reading "
716  "of exported symbols are displayed."),
719 }
CORE_ADDR pe_text_section_offset(struct bfd *abfd)
Definition: coff-pe-read.c:641
bfd * obfd
Definition: objfiles.h:313
#define SECT_OFF_TEXT(objfile)
Definition: objfiles.h:683
void add_setshow_zuinteger_cmd(const char *name, enum command_class theclass, unsigned int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:763
bfd_vma CORE_ADDR
Definition: common-types.h:41
unsigned long rva_end
Definition: coff-pe-read.c:53
unsigned int index
Definition: coff-pe-read.c:56
void xfree(void *)
Definition: common-utils.c:97
#define BMSYMBOL_VALUE_ADDRESS(symbol)
Definition: symtab.h:393
static int get_pe_section_index(const char *section_name, struct read_pe_section_data *sections, int nb_sections)
Definition: coff-pe-read.c:102
static unsigned int pe_get16(bfd *abfd, int where)
Definition: coff-pe-read.c:294
#define IMAGE_SCN_CNT_INITIALIZED_DATA
Definition: coff-pe-read.c:61
#define PE_SECTION_TABLE_SIZE
Definition: coff-pe-read.c:66
static unsigned int pe_as32(void *ptr)
Definition: coff-pe-read.c:322
struct minimal_symbol * prim_record_minimal_symbol_and_info(const char *name, CORE_ADDR address, enum minimal_symbol_type ms_type, int section, struct objfile *objfile)
Definition: minsyms.c:1043
#define _(String)
Definition: gdb_locale.h:40
#define PE_SECTION_INDEX_DATA
Definition: coff-pe-read.c:64
unsigned long rva_start
Definition: coff-pe-read.c:52
static int add_pe_forwarded_sym(const char *sym_name, const char *forward_dll_name, const char *forward_func_name, int ordinal, const char *dll_name, struct objfile *objfile)
Definition: coff-pe-read.c:203
void null_cleanup(void *arg)
Definition: cleanups.c:295
const char *const name
Definition: aarch64-tdep.c:68
void fprintf_filtered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2351
void * xzalloc(size_t size)
Definition: common-utils.c:91
struct bound_minimal_symbol lookup_minimal_symbol_and_objfile(const char *name)
Definition: minsyms.c:881
void fprintf_unfiltered(struct ui_file *stream, const char *format,...)
Definition: utils.c:2361
void free_current_contents(void *ptr)
Definition: utils.c:476
static void show_debug_coff_pe_read(struct ui_file *file, int from_tty, struct cmd_list_element *c, const char *value)
Definition: coff-pe-read.c:696
#define IMAGE_SCN_CNT_UNINITIALIZED_DATA
Definition: coff-pe-read.c:62
struct cleanup * make_cleanup(make_cleanup_ftype *function, void *arg)
Definition: cleanups.c:117
#define ANOFFSET(secoff, whichone)
Definition: symtab.h:910
static void get_section_vmas(bfd *abfd, asection *sectp, void *context)
Definition: coff-pe-read.c:126
#define PE_SECTION_INDEX_BSS
Definition: coff-pe-read.c:65
static void add_pe_exported_sym(const char *sym_name, unsigned long func_rva, int ordinal, const struct read_pe_section_data *section_data, const char *dll_name, struct objfile *objfile)
Definition: coff-pe-read.c:153
static unsigned int pe_get32(bfd *abfd, int where)
Definition: coff-pe-read.c:304
#define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET
Definition: coff-pe-read.c:638
char * xstrprintf(const char *format,...)
Definition: common-utils.c:107
struct cmd_list_element * setdebuglist
Definition: cli-cmds.c:173
void * xmalloc(YYSIZE_T)
struct ui_file * gdb_stdlog
Definition: main.c:73
Definition: value.c:172
enum minimal_symbol_type ms_type
Definition: coff-pe-read.c:54
void read_pe_exported_syms(struct objfile *objfile)
Definition: coff-pe-read.c:334
PTR xrealloc(PTR ptr, size_t size)
Definition: common-utils.c:51
static unsigned int pe_as16(void *ptr)
Definition: coff-pe-read.c:314
void _initialize_coff_pe_read(void)
Definition: coff-pe-read.c:709
const char const char int
Definition: command.h:229
#define MSYMBOL_TYPE(msymbol)
Definition: symtab.h:382
#define SEEK_SET
Definition: defs.h:87
#define PE_SECTION_INDEX_TEXT
Definition: coff-pe-read.c:63
#define PE_SECTION_INDEX_INVALID
Definition: coff-pe-read.c:67
int xsnprintf(char *str, size_t size, const char *format,...)
Definition: common-utils.c:134
struct minimal_symbol * minsym
Definition: minsyms.h:32
#define MSYMBOL_SECTION(symbol)
Definition: symtab.h:401
struct read_pe_section_data * sections
Definition: coff-pe-read.c:120
static void read_pe_truncate_name(char *dll_name)
Definition: coff-pe-read.c:284
struct cmd_list_element * showdebuglist
Definition: cli-cmds.c:175
static int read_pe_section_index(const char *section_name)
Definition: coff-pe-read.c:74
#define IMAGE_SCN_CNT_CODE
Definition: coff-pe-read.c:60
struct section_offsets * section_offsets
Definition: objfiles.h:362
minimal_symbol_type
Definition: symtab.h:287
static unsigned int debug_coff_pe_read
Definition: coff-pe-read.c:47
void do_cleanups(struct cleanup *old_chain)
Definition: cleanups.c:175
const ULONGEST const LONGEST len
Definition: target.h:309