Regenerate AArch64 opcodes files
[binutils-gdb.git] / gdb / coff-pe-read.c
blob271076e6d8d96d49bd3422524b54296d87766f69
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.
5 Copyright (C) 2003-2024 Free Software Foundation, Inc.
7 This file is part of GDB.
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.
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.
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/>.
22 Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
24 #include "defs.h"
26 #include "coff-pe-read.h"
28 #include "bfd.h"
29 #include "gdbtypes.h"
31 #include "command.h"
32 #include "gdbcmd.h"
33 #include "symtab.h"
34 #include "symfile.h"
35 #include "objfiles.h"
36 #include "gdbsupport/common-utils.h"
37 #include "coff/internal.h"
39 #include <ctype.h>
41 /* Internal section information */
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;
49 struct read_pe_section_data
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 std::string section_name; /* Recorded section name. */
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
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. */
73 static int
74 read_pe_section_index (const char *section_name)
76 if (strcmp (section_name, ".text") == 0)
78 return PE_SECTION_INDEX_TEXT;
81 else if (strcmp (section_name, ".data") == 0)
83 return PE_SECTION_INDEX_DATA;
86 else if (strcmp (section_name, ".bss") == 0)
88 return PE_SECTION_INDEX_BSS;
91 else
93 return PE_SECTION_INDEX_INVALID;
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. */
101 static int
102 get_pe_section_index (const char *section_name,
103 const std::vector<read_pe_section_data> &sections)
105 for (int i = 0; i < sections.size (); i++)
106 if (sections[i].section_name == section_name)
107 return i;
108 return PE_SECTION_INDEX_INVALID;
112 /* Create a minimal symbol entry for an exported symbol.
113 SYM_NAME contains the exported name or NULL if exported by ordinal,
114 FUNC_RVA contains the Relative Virtual Address of the symbol,
115 ORDINAL is the ordinal index value of the symbol,
116 SECTION_DATA contains information about the section in which the
117 symbol is declared,
118 DLL_NAME is the internal name of the DLL file,
119 OBJFILE is the objfile struct of DLL_NAME. */
121 static void
122 add_pe_exported_sym (minimal_symbol_reader &reader,
123 const char *sym_name,
124 unsigned long func_rva,
125 int ordinal,
126 const struct read_pe_section_data *section_data,
127 const char *dll_name, struct objfile *objfile)
129 /* Add the stored offset to get the loaded address of the symbol. */
130 unrelocated_addr vma = unrelocated_addr (func_rva
131 + section_data->vma_offset);
133 /* Generate a (hopefully unique) qualified name using the first part
134 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
135 used by windbg from the "Microsoft Debugging Tools for Windows". */
137 std::string bare_name;
138 if (sym_name == NULL || *sym_name == '\0')
139 bare_name = string_printf ("#%d", ordinal);
140 else
141 bare_name = sym_name;
143 std::string qualified_name
144 = string_printf ("%s!%s", dll_name, bare_name.c_str ());
146 if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
147 gdb_printf (gdb_stdlog , _("Unknown section type for \"%s\""
148 " for entry \"%s\" in dll \"%s\"\n"),
149 section_data->section_name.c_str (), sym_name,
150 dll_name);
152 reader.record_with_info (qualified_name.c_str (), vma, section_data->ms_type,
153 section_data->index);
155 /* Enter the plain name as well, which might not be unique. */
156 reader.record_with_info (bare_name.c_str (), vma, section_data->ms_type,
157 section_data->index);
158 if (debug_coff_pe_read > 1)
159 gdb_printf (gdb_stdlog, _("Adding exported symbol \"%s\""
160 " in dll \"%s\"\n"), sym_name, dll_name);
163 /* Create a minimal symbol entry for an exported forward symbol.
164 Return 1 if the forwarded function was found 0 otherwise.
165 SYM_NAME contains the exported name or NULL if exported by ordinal,
166 FORWARD_DLL_NAME is the name of the DLL in which the target symbol resides,
167 FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
168 ORDINAL is the ordinal index value of the symbol,
169 DLL_NAME is the internal name of the DLL file,
170 OBJFILE is the objfile struct of DLL_NAME. */
172 static int
173 add_pe_forwarded_sym (minimal_symbol_reader &reader,
174 const char *sym_name, const char *forward_dll_name,
175 const char *forward_func_name, int ordinal,
176 const char *dll_name, struct objfile *objfile)
178 struct bound_minimal_symbol msymbol;
179 enum minimal_symbol_type msymtype;
180 int forward_dll_name_len = strlen (forward_dll_name);
181 short section;
183 std::string forward_qualified_name = string_printf ("%s!%s",
184 forward_dll_name,
185 forward_func_name);
187 msymbol = lookup_bound_minimal_symbol (forward_qualified_name.c_str ());
189 if (!msymbol.minsym)
191 int i;
193 for (i = 0; i < forward_dll_name_len; i++)
194 forward_qualified_name[i] = tolower (forward_qualified_name[i]);
195 msymbol = lookup_bound_minimal_symbol (forward_qualified_name.c_str ());
198 if (!msymbol.minsym)
200 if (debug_coff_pe_read)
201 gdb_printf (gdb_stdlog, _("Unable to find function \"%s\" in"
202 " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
203 forward_func_name, forward_dll_name, sym_name,
204 dll_name);
205 return 0;
208 if (debug_coff_pe_read > 1)
209 gdb_printf (gdb_stdlog, _("Adding forwarded exported symbol"
210 " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
211 sym_name, dll_name, forward_qualified_name.c_str ());
213 /* Calculate VMA as if it were relative to DLL_NAME/OBJFILE, even though
214 it actually points inside another dll (FORWARD_DLL_NAME). */
215 unrelocated_addr vma = unrelocated_addr (msymbol.value_address ()
216 - objfile->text_section_offset ());
217 msymtype = msymbol.minsym->type ();
218 section = msymbol.minsym->section_index ();
220 /* Generate a (hopefully unique) qualified name using the first part
221 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
222 used by windbg from the "Microsoft Debugging Tools for Windows". */
224 std::string bare_name;
225 if (sym_name == NULL || *sym_name == '\0')
226 bare_name = string_printf ("#%d", ordinal);
227 else
228 bare_name = sym_name;
230 std::string qualified_name
231 = string_printf ("%s!%s", dll_name, bare_name.c_str ());
233 /* Note that this code makes a minimal symbol whose value may point
234 outside of any section in this objfile. These symbols can't
235 really be relocated properly, but nevertheless we make a stab at
236 it, choosing an approach consistent with the history of this
237 code. */
239 reader.record_with_info (qualified_name.c_str (), vma, msymtype, section);
241 /* Enter the plain name as well, which might not be unique. */
242 reader.record_with_info (bare_name.c_str(), vma, msymtype, section);
244 return 1;
247 /* Truncate a dll_name at the last dot character. */
249 static void
250 read_pe_truncate_name (char *dll_name)
252 char *last_point = strrchr (dll_name, '.');
254 if (last_point != NULL)
255 *last_point = '\0';
258 /* Low-level support functions, direct from the ld module pe-dll.c. */
259 static unsigned int
260 pe_get16 (bfd *abfd, int where, bool *fail)
262 unsigned char b[2];
264 if (bfd_seek (abfd, where, SEEK_SET) != 0
265 || bfd_read (b, 2, abfd) != 2)
267 *fail = true;
268 return 0;
270 return b[0] + (b[1] << 8);
273 static unsigned int
274 pe_get32 (bfd *abfd, int where, bool *fail)
276 unsigned char b[4];
278 if (bfd_seek (abfd, where, SEEK_SET) != 0
279 || bfd_read (b, 4, abfd) != 4)
281 *fail = true;
282 return 0;
284 return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
287 static unsigned int
288 pe_as16 (void *ptr)
290 unsigned char *b = (unsigned char *) ptr;
292 return b[0] + (b[1] << 8);
295 static unsigned int
296 pe_as32 (void *ptr)
298 unsigned char *b = (unsigned char *) ptr;
300 return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
303 /* Read the (non-debug) export symbol table from a portable
304 executable. Code originally lifted from the ld function
305 pe_implied_import_dll in pe-dll.c. */
307 void
308 read_pe_exported_syms (minimal_symbol_reader &reader,
309 struct objfile *objfile)
311 bfd *dll = objfile->obfd.get ();
312 unsigned long nbnormal, nbforward;
313 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
314 unsigned long export_opthdrrva, export_opthdrsize;
315 unsigned long export_rva, export_size, nsections, secptr, expptr;
316 unsigned long exp_funcbase;
317 unsigned char *expdata, *erva;
318 unsigned long name_rvas, ordinals, nexp, ordbase;
319 int otherix = PE_SECTION_TABLE_SIZE;
320 int is_pe64 = 0;
321 int is_pe32 = 0;
323 char const *target = bfd_get_target (objfile->obfd.get ());
325 std::vector<struct read_pe_section_data> section_data
326 (PE_SECTION_TABLE_SIZE);
328 for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
330 section_data[i].vma_offset = 0;
331 section_data[i].rva_start = 1;
332 section_data[i].rva_end = 0;
334 section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
335 section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
336 section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
337 section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
338 section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
339 section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
341 is_pe64 = (strcmp (target, "pe-x86-64") == 0
342 || strcmp (target, "pei-x86-64") == 0
343 || strcmp (target, "pe-aarch64") == 0
344 || strcmp (target, "pei-aarch64") == 0);
345 is_pe32 = (strcmp (target, "pe-i386") == 0
346 || strcmp (target, "pei-i386") == 0
347 || strcmp (target, "pe-arm-wince-little") == 0
348 || strcmp (target, "pei-arm-wince-little") == 0);
350 /* Possibly print a debug message about DLL not having a valid format. */
351 auto maybe_print_debug_msg = [&] () -> void {
352 if (debug_coff_pe_read)
353 gdb_printf (gdb_stdlog, _("%s doesn't appear to be a DLL\n"),
354 bfd_get_filename (dll));
357 if (!is_pe32 && !is_pe64)
358 return maybe_print_debug_msg ();
360 /* Get pe_header, optional header and numbers of export entries. */
361 bool fail = false;
362 pe_header_offset = pe_get32 (dll, 0x3c, &fail);
363 if (fail)
364 return maybe_print_debug_msg ();
365 opthdr_ofs = pe_header_offset + 4 + 20;
366 if (is_pe64)
367 num_entries = pe_get32 (dll, opthdr_ofs + 108, &fail);
368 else
369 num_entries = pe_get32 (dll, opthdr_ofs + 92, &fail);
370 if (fail)
371 return maybe_print_debug_msg ();
373 if (num_entries < 1) /* No exports. */
374 return;
375 if (is_pe64)
377 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112, &fail);
378 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116, &fail);
380 else
382 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96, &fail);
383 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100, &fail);
385 if (fail)
386 return maybe_print_debug_msg ();
388 nsections = pe_get16 (dll, pe_header_offset + 4 + 2, &fail);
389 secptr = (pe_header_offset + 4 + 20 +
390 pe_get16 (dll, pe_header_offset + 4 + 16, &fail));
391 if (fail)
392 return maybe_print_debug_msg ();
393 expptr = 0;
394 export_size = 0;
396 /* Get the rva and size of the export section. */
397 for (i = 0; i < nsections; i++)
399 char sname[8];
400 unsigned long secptr1 = secptr + 40 * i;
401 unsigned long vaddr = pe_get32 (dll, secptr1 + 12, &fail);
402 unsigned long vsize = pe_get32 (dll, secptr1 + 16, &fail);
403 unsigned long fptr = pe_get32 (dll, secptr1 + 20, &fail);
405 if (fail
406 || bfd_seek (dll, secptr1, SEEK_SET) != 0
407 || bfd_read (sname, sizeof (sname), dll) != sizeof (sname))
408 return maybe_print_debug_msg ();
410 if ((strcmp (sname, ".edata") == 0)
411 || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
413 if (strcmp (sname, ".edata") != 0)
415 if (debug_coff_pe_read)
416 gdb_printf (gdb_stdlog, _("Export RVA for dll "
417 "\"%s\" is in section \"%s\"\n"),
418 bfd_get_filename (dll), sname);
420 else if (export_opthdrrva != vaddr && debug_coff_pe_read)
421 gdb_printf (gdb_stdlog, _("Wrong value of export RVA"
422 " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
423 bfd_get_filename (dll), export_opthdrrva, vaddr);
424 expptr = fptr + (export_opthdrrva - vaddr);
425 break;
429 if (expptr == 0)
431 /* no section contains export table rva */
432 return;
435 export_rva = export_opthdrrva;
436 export_size = export_opthdrsize;
438 if (export_size == 0)
440 /* Empty export table. */
441 return;
444 /* Scan sections and store the base and size of the relevant
445 sections. */
446 for (i = 0; i < nsections; i++)
448 unsigned long secptr1 = secptr + 40 * i;
449 unsigned long vsize = pe_get32 (dll, secptr1 + 8, &fail);
450 unsigned long vaddr = pe_get32 (dll, secptr1 + 12, &fail);
451 unsigned long characteristics = pe_get32 (dll, secptr1 + 36, &fail);
452 char sec_name[SCNNMLEN + 1];
453 int sectix;
454 unsigned int bfd_section_index;
455 asection *section;
457 if (fail
458 || bfd_seek (dll, secptr1 + 0, SEEK_SET) != 0
459 || bfd_read (sec_name, SCNNMLEN, dll) != SCNNMLEN)
460 return maybe_print_debug_msg ();
461 sec_name[SCNNMLEN] = '\0';
463 sectix = read_pe_section_index (sec_name);
464 section = bfd_get_section_by_name (dll, sec_name);
465 if (section)
466 bfd_section_index = section->index;
467 else
468 bfd_section_index = -1;
470 if (sectix != PE_SECTION_INDEX_INVALID)
472 section_data[sectix].rva_start = vaddr;
473 section_data[sectix].rva_end = vaddr + vsize;
474 section_data[sectix].index = bfd_section_index;
476 else
478 section_data.resize (otherix + 1);
479 section_data[otherix].section_name = sec_name;
480 section_data[otherix].rva_start = vaddr;
481 section_data[otherix].rva_end = vaddr + vsize;
482 section_data[otherix].vma_offset = 0;
483 section_data[otherix].index = bfd_section_index;
484 if (characteristics & IMAGE_SCN_CNT_CODE)
485 section_data[otherix].ms_type = mst_text;
486 else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
487 section_data[otherix].ms_type = mst_data;
488 else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
489 section_data[otherix].ms_type = mst_bss;
490 else
491 section_data[otherix].ms_type = mst_unknown;
492 otherix++;
496 gdb::def_vector<unsigned char> expdata_storage (export_size);
497 expdata = expdata_storage.data ();
499 if (bfd_seek (dll, expptr, SEEK_SET) != 0
500 || bfd_read (expdata, export_size, dll) != export_size)
501 return maybe_print_debug_msg ();
502 erva = expdata - export_rva;
504 nexp = pe_as32 (expdata + 24);
505 name_rvas = pe_as32 (expdata + 32);
506 ordinals = pe_as32 (expdata + 36);
507 ordbase = pe_as32 (expdata + 16);
508 exp_funcbase = pe_as32 (expdata + 28);
510 /* Use internal dll name instead of full pathname. */
511 char *dll_name = (char *) (pe_as32 (expdata + 12) + erva);
513 for (asection *sectp : gdb_bfd_sections (dll))
515 int sectix = get_pe_section_index (sectp->name, section_data);
516 if (sectix != PE_SECTION_INDEX_INVALID)
518 /* Data within the section start at rva_start in the pe and at
519 bfd_get_section_vma() within memory. Store the offset. */
520 section_data[sectix].vma_offset
521 = bfd_section_vma (sectp) - section_data[sectix].rva_start;
525 /* Truncate name at first dot. Should maybe also convert to all
526 lower case for convenience on Windows. */
527 read_pe_truncate_name (dll_name);
529 if (debug_coff_pe_read)
530 gdb_printf (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
531 " base=%ld\n"), dll_name, nexp, ordbase);
532 nbforward = 0;
533 nbnormal = 0;
534 /* Iterate through the list of symbols. */
535 for (i = 0; i < nexp; i++)
537 /* Pointer to the names vector. */
538 unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
539 /* Retrieve ordinal value. */
541 unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
544 /* Pointer to the function address vector. */
545 /* This is relative to ordinal value. */
546 unsigned long func_rva = pe_as32 (erva + exp_funcbase +
547 ordinal * 4);
549 /* Find this symbol's section in our own array. */
550 int sectix = 0;
551 int section_found = 0;
553 /* First handle forward cases. */
554 if (func_rva >= export_rva && func_rva < export_rva + export_size)
556 const char *forward_name = (const char *) (erva + func_rva);
557 const char *funcname = (const char *) (erva + name_rva);
558 const char *forward_dll_name = forward_name;
559 const char *forward_func_name = forward_name;
560 const char *sep = strrchr (forward_name, '.');
562 std::string name_storage;
563 if (sep != nullptr)
565 int len = (int) (sep - forward_name);
567 name_storage = std::string (forward_name, len);
568 forward_dll_name = name_storage.c_str ();
569 forward_func_name = sep + 1;
571 if (add_pe_forwarded_sym (reader, funcname, forward_dll_name,
572 forward_func_name, ordinal,
573 dll_name, objfile) != 0)
574 ++nbforward;
575 continue;
578 for (sectix = 0; sectix < otherix; ++sectix)
580 if ((func_rva >= section_data[sectix].rva_start)
581 && (func_rva < section_data[sectix].rva_end))
583 const char *sym_name = (const char *) (erva + name_rva);
585 section_found = 1;
586 add_pe_exported_sym (reader, sym_name, func_rva, ordinal,
587 &section_data[sectix], dll_name, objfile);
588 ++nbnormal;
589 break;
592 if (!section_found)
594 const char *funcname = (const char *) (erva + name_rva);
596 if (name_rva == 0)
598 add_pe_exported_sym (reader, NULL, func_rva, ordinal,
599 &section_data[0], dll_name, objfile);
600 ++nbnormal;
602 else if (debug_coff_pe_read)
603 gdb_printf (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
604 " RVA 0x%lx in dll \"%s\" not handled\n"),
605 funcname, ordinal, func_rva, dll_name);
609 if (debug_coff_pe_read)
610 gdb_printf (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
611 " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
612 nbforward, nbnormal + nbforward, nexp);
615 /* Extract from ABFD the offset of the .text section.
616 This offset is mainly related to the offset within the file.
617 The value was previously expected to be 0x1000 for all files,
618 but some Windows OS core DLLs seem to use 0x10000 section alignment
619 which modified the return value of that function.
620 Still return default 0x1000 value if ABFD is NULL or
621 if '.text' section is not found, but that should not happen... */
623 #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
625 CORE_ADDR
626 pe_text_section_offset (struct bfd *abfd)
629 unsigned long pe_header_offset, i;
630 unsigned long nsections, secptr;
631 int is_pe64 = 0;
632 int is_pe32 = 0;
633 char const *target;
635 if (!abfd)
636 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
638 target = bfd_get_target (abfd);
640 is_pe64 = (strcmp (target, "pe-x86-64") == 0
641 || strcmp (target, "pei-x86-64") == 0
642 || strcmp (target, "pe-aarch64") == 0
643 || strcmp (target, "pei-aarch64") == 0);
644 is_pe32 = (strcmp (target, "pe-i386") == 0
645 || strcmp (target, "pei-i386") == 0
646 || strcmp (target, "pe-arm-wince-little") == 0
647 || strcmp (target, "pei-arm-wince-little") == 0);
649 if (!is_pe32 && !is_pe64)
651 /* This is not a recognized PE format file. Abort now, because
652 the code is untested on anything else. *FIXME* test on
653 further architectures and loosen or remove this test. */
654 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
657 /* Get pe_header, optional header and numbers of sections. */
658 bool fail = false;
659 pe_header_offset = pe_get32 (abfd, 0x3c, &fail);
660 if (fail)
661 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
662 nsections = pe_get16 (abfd, pe_header_offset + 4 + 2, &fail);
663 secptr = (pe_header_offset + 4 + 20 +
664 pe_get16 (abfd, pe_header_offset + 4 + 16, &fail));
665 if (fail)
666 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
668 /* Get the rva and size of the export section. */
669 for (i = 0; i < nsections; i++)
671 char sname[SCNNMLEN + 1];
672 unsigned long secptr1 = secptr + 40 * i;
673 unsigned long vaddr = pe_get32 (abfd, secptr1 + 12, &fail);
675 if (fail
676 || bfd_seek (abfd, secptr1, SEEK_SET) != 0
677 || bfd_read (sname, SCNNMLEN, abfd) != SCNNMLEN)
678 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
679 sname[SCNNMLEN] = '\0';
680 if (strcmp (sname, ".text") == 0)
681 return vaddr;
684 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
687 /* Implements "show debug coff_pe_read" command. */
689 static void
690 show_debug_coff_pe_read (struct ui_file *file, int from_tty,
691 struct cmd_list_element *c, const char *value)
693 gdb_printf (file, _("Coff PE read debugging is %s.\n"), value);
696 /* Adds "Set/show debug coff_pe_read" commands. */
698 void _initialize_coff_pe_read ();
699 void
700 _initialize_coff_pe_read ()
702 add_setshow_zuinteger_cmd ("coff-pe-read", class_maintenance,
703 &debug_coff_pe_read,
704 _("Set coff PE read debugging."),
705 _("Show coff PE read debugging."),
706 _("When set, debugging messages for coff reading "
707 "of exported symbols are displayed."),
708 NULL, show_debug_coff_pe_read,
709 &setdebuglist, &showdebuglist);