* coff-pe-read.h (pe_text_section_offset): Declare new function.
[deliverable/binutils-gdb.git] / gdb / coff-pe-read.c
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, 2007-2012 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
38 #include <ctype.h>
39
40 /* Internal section information */
41
42 /* Coff PE read debugging flag:
43 default value is 0,
44 value 1 outputs problems encountered while parsing PE file,
45 value above 1 also lists all generated minimal symbols. */
46 static unsigned int debug_coff_pe_read;
47
48 struct read_pe_section_data
49 {
50 CORE_ADDR vma_offset; /* Offset to loaded address of section. */
51 unsigned long rva_start; /* Start offset within the pe. */
52 unsigned long rva_end; /* End offset within the pe. */
53 enum minimal_symbol_type ms_type; /* Type to assign symbols in
54 section. */
55 char *section_name; /* Recorded section name. */
56 };
57
58 #ifndef IMAGE_SCN_CNT_CODE
59 # define IMAGE_SCN_CNT_CODE 0x20
60 #endif
61 #ifndef IMAGE_SCN_CNT_INITIALIZED_DATA
62 # define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40
63 #endif
64 #ifndef IMAGE_SCN_CNT_UNINITIALIZED_DATA
65 # define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80
66 #endif
67 #define PE_SECTION_INDEX_TEXT 0
68 #define PE_SECTION_INDEX_DATA 1
69 #define PE_SECTION_INDEX_BSS 2
70 #define PE_SECTION_TABLE_SIZE 3
71 #define PE_SECTION_INDEX_INVALID -1
72 \f
73 /* Get the index of the named section in our own array, which contains
74 text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
75 if passed an unrecognised section name. */
76
77 static int
78 read_pe_section_index (const char *section_name)
79 {
80 if (strcmp (section_name, ".text") == 0)
81 {
82 return PE_SECTION_INDEX_TEXT;
83 }
84
85 else if (strcmp (section_name, ".data") == 0)
86 {
87 return PE_SECTION_INDEX_DATA;
88 }
89
90 else if (strcmp (section_name, ".bss") == 0)
91 {
92 return PE_SECTION_INDEX_BSS;
93 }
94
95 else
96 {
97 return PE_SECTION_INDEX_INVALID;
98 }
99 }
100
101 /* Get the index of the named section in our own full arrayi.
102 text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
103 if passed an unrecognised section name. */
104
105 static int
106 get_pe_section_index (const char *section_name,
107 struct read_pe_section_data *sections,
108 int nb_sections)
109 {
110 int i;
111
112 for (i = 0; i < nb_sections; i++)
113 if (strcmp (sections[i].section_name, section_name) == 0)
114 return i;
115 return PE_SECTION_INDEX_INVALID;
116 }
117
118 /* Structure used by get_section_vmas function below
119 to access section_data array and the size of the array
120 stored in nb_sections field. */
121 struct pe_sections_info
122 {
123 int nb_sections;
124 struct read_pe_section_data *sections;
125 };
126
127 /* Record the virtual memory address of a section. */
128
129 static void
130 get_section_vmas (bfd *abfd, asection *sectp, void *context)
131 {
132 struct pe_sections_info *data = context;
133 struct read_pe_section_data *sections = data->sections;
134 int sectix = get_pe_section_index (sectp->name, sections,
135 data->nb_sections);
136
137 if (sectix != PE_SECTION_INDEX_INVALID)
138 {
139 /* Data within the section start at rva_start in the pe and at
140 bfd_get_section_vma() within memory. Store the offset. */
141
142 sections[sectix].vma_offset
143 = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
144 }
145 }
146 \f
147 /* Create a minimal symbol entry for an exported symbol.
148 SYM_NAME contains the exported name or NULL if exported by ordinal,
149 FUNC_RVA contains the Relative Virtual Address of the symbol,
150 ORDINAL is the ordinal index value of the symbol,
151 SECTION_DATA contains information about the section in which the
152 symbol is declared,
153 DLL_NAME is the internal name of the DLL file,
154 OBJFILE is the objfile struct of DLL_NAME. */
155
156 static void
157 add_pe_exported_sym (const char *sym_name,
158 unsigned long func_rva,
159 int ordinal,
160 const struct read_pe_section_data *section_data,
161 const char *dll_name, struct objfile *objfile)
162 {
163 char *qualified_name, *bare_name;
164 /* Add the stored offset to get the loaded address of the symbol. */
165 CORE_ADDR vma = func_rva + section_data->vma_offset;
166 int dll_name_len = strlen (dll_name);
167
168 /* Generate a (hopefully unique) qualified name using the first part
169 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
170 used by windbg from the "Microsoft Debugging Tools for Windows". */
171
172 if (sym_name == NULL || *sym_name == '\0')
173 bare_name = xstrprintf ("#%d", ordinal);
174 else
175 bare_name = xstrdup (sym_name);
176
177 qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
178
179 if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
180 fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\""
181 " for entry \"%s\" in dll \"%s\"\n"),
182 section_data->section_name, sym_name, dll_name);
183
184 prim_record_minimal_symbol (qualified_name, vma,
185 section_data->ms_type, objfile);
186
187 /* Enter the plain name as well, which might not be unique. */
188 prim_record_minimal_symbol (bare_name, vma, section_data->ms_type, objfile);
189 if (debug_coff_pe_read > 1)
190 fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
191 " in dll \"%s\"\n"), sym_name, dll_name);
192 xfree (qualified_name);
193 xfree (bare_name);
194 }
195
196 /* Create a minimal symbol entry for an exported forward symbol.
197 Return 1 if the forwarded function was found 0 otherwise.
198 SYM_NAME contains the exported name or NULL if exported by ordinal,
199 FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides,
200 FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
201 ORDINAL is the ordinal index value of the symbol,
202 DLL_NAME is the internal name of the DLL file,
203 OBJFILE is the objfile struct of DLL_NAME. */
204
205 static int
206 add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
207 const char *forward_func_name, int ordinal,
208 const char *dll_name, struct objfile *objfile)
209 {
210 CORE_ADDR vma;
211 struct objfile *forward_objfile;
212 struct minimal_symbol *msymbol;
213 short section;
214 enum minimal_symbol_type msymtype;
215 int dll_name_len = strlen (dll_name);
216 char *qualified_name, *bare_name;
217 int forward_dll_name_len = strlen (forward_dll_name);
218 int forward_func_name_len = strlen (forward_func_name);
219 int forward_len = forward_dll_name_len + forward_func_name_len + 2;
220 char *forward_qualified_name = alloca (forward_len);
221
222 xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
223 forward_func_name);
224
225
226 msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name,
227 &forward_objfile);
228
229 if (!msymbol)
230 {
231 int i;
232
233 for (i = 0; i < forward_dll_name_len; i++)
234 forward_qualified_name[i] = tolower (forward_qualified_name[i]);
235 msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name,
236 &forward_objfile);
237 }
238
239 if (!msymbol)
240 {
241 if (debug_coff_pe_read)
242 fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
243 " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
244 forward_func_name, forward_dll_name, sym_name,
245 dll_name);
246 return 0;
247 }
248
249 if (debug_coff_pe_read > 1)
250 fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
251 " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
252 sym_name, dll_name, forward_qualified_name);
253
254 vma = SYMBOL_VALUE_ADDRESS (msymbol);
255 section = SYMBOL_SECTION (msymbol);
256 msymtype = MSYMBOL_TYPE (msymbol);
257
258 /* Generate a (hopefully unique) qualified name using the first part
259 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
260 used by windbg from the "Microsoft Debugging Tools for Windows". */
261
262 if (sym_name == NULL || *sym_name == '\0')
263 bare_name = xstrprintf ("#%d", ordinal);
264 else
265 bare_name = xstrdup (sym_name);
266
267 qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
268
269 prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile);
270
271 /* Enter the plain name as well, which might not be unique. */
272 prim_record_minimal_symbol (bare_name, vma, msymtype, objfile);
273 xfree (qualified_name);
274 xfree (bare_name);
275
276 return 1;
277 }
278
279 /* Truncate a dll_name at the last dot character. */
280
281 static void
282 read_pe_truncate_name (char *dll_name)
283 {
284 char *last_point = strrchr (dll_name, '.');
285
286 if (last_point != NULL)
287 *last_point = '\0';
288 }
289 \f
290 /* Low-level support functions, direct from the ld module pe-dll.c. */
291 static unsigned int
292 pe_get16 (bfd *abfd, int where)
293 {
294 unsigned char b[2];
295
296 bfd_seek (abfd, (file_ptr) where, SEEK_SET);
297 bfd_bread (b, (bfd_size_type) 2, abfd);
298 return b[0] + (b[1] << 8);
299 }
300
301 static unsigned int
302 pe_get32 (bfd *abfd, int where)
303 {
304 unsigned char b[4];
305
306 bfd_seek (abfd, (file_ptr) where, SEEK_SET);
307 bfd_bread (b, (bfd_size_type) 4, abfd);
308 return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
309 }
310
311 static unsigned int
312 pe_as16 (void *ptr)
313 {
314 unsigned char *b = ptr;
315
316 return b[0] + (b[1] << 8);
317 }
318
319 static unsigned int
320 pe_as32 (void *ptr)
321 {
322 unsigned char *b = ptr;
323
324 return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
325 }
326 \f
327 /* Read the (non-debug) export symbol table from a portable
328 executable. Code originally lifted from the ld function
329 pe_implied_import_dll in pe-dll.c. */
330
331 void
332 read_pe_exported_syms (struct objfile *objfile)
333 {
334 bfd *dll = objfile->obfd;
335 unsigned long nbnormal, nbforward;
336 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
337 unsigned long export_opthdrrva, export_opthdrsize;
338 unsigned long export_rva, export_size, nsections, secptr, expptr;
339 unsigned long exp_funcbase;
340 unsigned char *expdata, *erva;
341 unsigned long name_rvas, ordinals, nexp, ordbase;
342 char *dll_name = (char *) dll->filename;
343 int otherix = PE_SECTION_TABLE_SIZE;
344 int exportix = -1;
345 int is_pe64 = 0;
346 int is_pe32 = 0;
347
348 /* Array elements are for text, data and bss in that order
349 Initialization with RVA_START > RVA_END guarantees that
350 unused sections won't be matched. */
351 struct read_pe_section_data *section_data;
352 struct pe_sections_info pe_sections_info;
353
354 struct cleanup *back_to = make_cleanup (null_cleanup, 0);
355
356 char const *target = bfd_get_target (objfile->obfd);
357
358 section_data = xzalloc (PE_SECTION_TABLE_SIZE
359 * sizeof (struct read_pe_section_data));
360
361 make_cleanup (free_current_contents, &section_data);
362
363 for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
364 {
365 section_data[i].vma_offset = 0;
366 section_data[i].rva_start = 1;
367 section_data[i].rva_end = 0;
368 };
369 section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
370 section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
371 section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
372 section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
373 section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
374 section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
375
376 is_pe64 = (strcmp (target, "pe-x86-64") == 0
377 || strcmp (target, "pei-x86-64") == 0);
378 is_pe32 = (strcmp (target, "pe-i386") == 0
379 || strcmp (target, "pei-i386") == 0
380 || strcmp (target, "pe-arm-wince-little") == 0
381 || strcmp (target, "pei-arm-wince-little") == 0);
382 if (!is_pe32 && !is_pe64)
383 {
384 /* This is not a recognized PE format file. Abort now, because
385 the code is untested on anything else. *FIXME* test on
386 further architectures and loosen or remove this test. */
387 return;
388 }
389
390 /* Get pe_header, optional header and numbers of export entries. */
391 pe_header_offset = pe_get32 (dll, 0x3c);
392 opthdr_ofs = pe_header_offset + 4 + 20;
393 if (is_pe64)
394 num_entries = pe_get32 (dll, opthdr_ofs + 108);
395 else
396 num_entries = pe_get32 (dll, opthdr_ofs + 92);
397
398 if (num_entries < 1) /* No exports. */
399 {
400 return;
401 }
402 if (is_pe64)
403 {
404 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
405 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
406 }
407 else
408 {
409 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
410 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
411 }
412 nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
413 secptr = (pe_header_offset + 4 + 20 +
414 pe_get16 (dll, pe_header_offset + 4 + 16));
415 expptr = 0;
416 export_size = 0;
417
418 /* Get the rva and size of the export section. */
419 for (i = 0; i < nsections; i++)
420 {
421 char sname[8];
422 unsigned long secptr1 = secptr + 40 * i;
423 unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
424 unsigned long vsize = pe_get32 (dll, secptr1 + 16);
425 unsigned long fptr = pe_get32 (dll, secptr1 + 20);
426
427 bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
428 bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);
429
430 if ((strcmp (sname, ".edata") == 0)
431 || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
432 {
433 if (strcmp (sname, ".edata") != 0)
434 {
435 if (debug_coff_pe_read)
436 fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll "
437 "\"%s\" is in section \"%s\"\n"),
438 dll_name, sname);
439 }
440 else if (export_opthdrrva != vaddr && debug_coff_pe_read)
441 fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA"
442 " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
443 dll_name, export_opthdrrva, vaddr);
444 expptr = fptr + (export_opthdrrva - vaddr);
445 exportix = i;
446 break;
447 }
448 }
449
450 export_rva = export_opthdrrva;
451 export_size = export_opthdrsize;
452
453 if (export_size == 0)
454 {
455 /* Empty export table. */
456 return;
457 }
458
459 /* Scan sections and store the base and size of the relevant
460 sections. */
461 for (i = 0; i < nsections; i++)
462 {
463 unsigned long secptr1 = secptr + 40 * i;
464 unsigned long vsize = pe_get32 (dll, secptr1 + 8);
465 unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
466 unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
467 char sec_name[9];
468 int sectix;
469
470 memset (sec_name, 0, sizeof (sec_name));
471 bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
472 bfd_bread (sec_name, (bfd_size_type) 8, dll);
473
474 sectix = read_pe_section_index (sec_name);
475
476 if (sectix != PE_SECTION_INDEX_INVALID)
477 {
478 section_data[sectix].rva_start = vaddr;
479 section_data[sectix].rva_end = vaddr + vsize;
480 }
481 else
482 {
483 char *name;
484
485 section_data = xrealloc (section_data, (otherix + 1)
486 * sizeof (struct read_pe_section_data));
487 name = xstrdup (sec_name);
488 section_data[otherix].section_name = name;
489 make_cleanup (xfree, name);
490 section_data[otherix].rva_start = vaddr;
491 section_data[otherix].rva_end = vaddr + vsize;
492 section_data[otherix].vma_offset = 0;
493 if (characteristics & IMAGE_SCN_CNT_CODE)
494 section_data[otherix].ms_type = mst_text;
495 else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
496 section_data[otherix].ms_type = mst_data;
497 else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
498 section_data[otherix].ms_type = mst_bss;
499 else
500 section_data[otherix].ms_type = mst_unknown;
501 otherix++;
502 }
503 }
504
505 expdata = (unsigned char *) xmalloc (export_size);
506 make_cleanup (xfree, expdata);
507
508 bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
509 bfd_bread (expdata, (bfd_size_type) export_size, dll);
510 erva = expdata - export_rva;
511
512 nexp = pe_as32 (expdata + 24);
513 name_rvas = pe_as32 (expdata + 32);
514 ordinals = pe_as32 (expdata + 36);
515 ordbase = pe_as32 (expdata + 16);
516 exp_funcbase = pe_as32 (expdata + 28);
517
518 /* Use internal dll name instead of full pathname. */
519 dll_name = pe_as32 (expdata + 12) + erva;
520
521 pe_sections_info.nb_sections = otherix;
522 pe_sections_info.sections = section_data;
523
524 bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info);
525
526 /* Adjust the vma_offsets in case this PE got relocated. This
527 assumes that *all* sections share the same relocation offset
528 as the text section. */
529 for (i = 0; i < otherix; i++)
530 {
531 section_data[i].vma_offset
532 += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
533 }
534
535 /* Truncate name at first dot. Should maybe also convert to all
536 lower case for convenience on Windows. */
537 read_pe_truncate_name (dll_name);
538
539 if (debug_coff_pe_read)
540 fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
541 " base=%ld\n"), dll_name, nexp, ordbase);
542 nbforward = 0;
543 nbnormal = 0;
544 /* Iterate through the list of symbols. */
545 for (i = 0; i < nexp; i++)
546 {
547 /* Pointer to the names vector. */
548 unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
549 /* Retrieve ordinal value. */
550
551 unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
552
553
554 /* Pointer to the function address vector. */
555 /* This is relatived to ordinal value. */
556 unsigned long func_rva = pe_as32 (erva + exp_funcbase +
557 ordinal * 4);
558
559 /* Find this symbol's section in our own array. */
560 int sectix = 0;
561 int section_found = 0;
562
563 /* First handle forward cases. */
564 if (func_rva >= export_rva && func_rva < export_rva + export_size)
565 {
566 char *forward_name = (char *) (erva + func_rva);
567 char *funcname = (char *) (erva + name_rva);
568 char *forward_dll_name = forward_name;
569 char *forward_func_name = forward_name;
570 char *sep = strrchr (forward_name, '.');
571
572 if (sep)
573 {
574 int len = (int) (sep - forward_name);
575
576 forward_dll_name = alloca (len + 1);
577 strncpy (forward_dll_name, forward_name, len);
578 forward_dll_name[len] = '\0';
579 forward_func_name = ++sep;
580 }
581 if (add_pe_forwarded_sym (funcname, forward_dll_name,
582 forward_func_name, ordinal,
583 dll_name, objfile) != 0)
584 ++nbforward;
585 continue;
586 }
587
588 for (sectix = 0; sectix < otherix; ++sectix)
589 {
590 if ((func_rva >= section_data[sectix].rva_start)
591 && (func_rva < section_data[sectix].rva_end))
592 {
593 section_found = 1;
594 add_pe_exported_sym (erva + name_rva,
595 func_rva, ordinal,
596 section_data + sectix, dll_name, objfile);
597 ++nbnormal;
598 break;
599 }
600 }
601 if (!section_found)
602 {
603 char *funcname = (char *) (erva + name_rva);
604
605 if (name_rva == 0)
606 {
607 add_pe_exported_sym (NULL, func_rva, ordinal,
608 section_data, dll_name, objfile);
609 ++nbnormal;
610 }
611 else if (debug_coff_pe_read)
612 fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
613 " RVA 0x%lx in dll \"%s\" not handled\n"),
614 funcname, ordinal, func_rva, dll_name);
615 }
616 }
617
618 if (debug_coff_pe_read)
619 fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
620 " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
621 nbforward, nbnormal + nbforward, nexp);
622 /* Discard expdata and section_data. */
623 do_cleanups (back_to);
624 }
625
626 /* Extract from ABFD the offset of the .text section.
627 This offset is mainly related to the offset within the file.
628 The value was previously expected to be 0x1000 for all files,
629 but some Windows OS core DLLs seem to use 0x10000 section alignement
630 which modified the return value of that function.
631 Still return default 0x1000 value if ABFD is NULL or
632 if '.text' section is not found, but that should not happen... */
633
634 #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
635
636 CORE_ADDR
637 pe_text_section_offset (struct bfd *abfd)
638
639 {
640 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
641 unsigned long export_rva, export_size, nsections, secptr, expptr;
642 unsigned long exp_funcbase;
643 unsigned char *expdata, *erva;
644 unsigned long name_rvas, ordinals, nexp, ordbase;
645 char *dll_name;
646 int is_pe64 = 0;
647 int is_pe32 = 0;
648 char const *target;
649
650 if (!abfd)
651 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
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. */
667 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
668 }
669
670 /* Get pe_header, optional header and numbers of sections. */
671 pe_header_offset = pe_get32 (abfd, 0x3c);
672 opthdr_ofs = pe_header_offset + 4 + 20;
673 nsections = pe_get16 (abfd, pe_header_offset + 4 + 2);
674 secptr = (pe_header_offset + 4 + 20 +
675 pe_get16 (abfd, pe_header_offset + 4 + 16));
676
677 /* Get the rva and size of the export section. */
678 for (i = 0; i < nsections; i++)
679 {
680 char sname[8];
681 unsigned long secptr1 = secptr + 40 * i;
682 unsigned long vaddr = pe_get32 (abfd, secptr1 + 12);
683
684 bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET);
685 bfd_bread (sname, (bfd_size_type) 8, abfd);
686 if (strcmp (sname, ".text") == 0)
687 return vaddr;
688 }
689
690 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
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
709 _initialize_coff_pe_read (void)
710 {
711 add_setshow_uinteger_cmd ("coff_pe_read", class_maintenance,
712 &debug_coff_pe_read,
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."),
717 NULL, show_debug_coff_pe_read,
718 &setdebuglist, &showdebuglist);
719 }
This page took 0.046741 seconds and 5 git commands to generate.