More updated translations
[binutils-gdb.git] / gdb / coff-pe-read.c
blobbb85b000ca9ac715884d8876b816812e8c9a0e6a
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). */
25 #include "coff-pe-read.h"
27 #include "bfd.h"
28 #include "gdbtypes.h"
30 #include "command.h"
31 #include "cli/cli-cmds.h"
32 #include "symtab.h"
33 #include "symfile.h"
34 #include "objfiles.h"
35 #include "gdbsupport/common-utils.h"
36 #include "coff/internal.h"
38 #include <ctype.h>
40 /* Internal section information */
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;
48 struct read_pe_section_data
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 unsigned int index; /* BFD section number. */
56 std::string section_name; /* Recorded section name. */
59 #define IMAGE_SCN_CNT_CODE 0x20
60 #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40
61 #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80
62 #define PE_SECTION_INDEX_TEXT 0
63 #define PE_SECTION_INDEX_DATA 1
64 #define PE_SECTION_INDEX_BSS 2
65 #define PE_SECTION_TABLE_SIZE 3
66 #define PE_SECTION_INDEX_INVALID -1
68 /* Get the index of the named section in our own array, which contains
69 text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
70 if passed an unrecognised section name. */
72 static int
73 read_pe_section_index (const char *section_name)
75 if (strcmp (section_name, ".text") == 0)
77 return PE_SECTION_INDEX_TEXT;
80 else if (strcmp (section_name, ".data") == 0)
82 return PE_SECTION_INDEX_DATA;
85 else if (strcmp (section_name, ".bss") == 0)
87 return PE_SECTION_INDEX_BSS;
90 else
92 return PE_SECTION_INDEX_INVALID;
96 /* Get the index of the named section in our own full array.
97 text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
98 if passed an unrecognised section name. */
100 static int
101 get_pe_section_index (const char *section_name,
102 const std::vector<read_pe_section_data> &sections)
104 for (int i = 0; i < sections.size (); i++)
105 if (sections[i].section_name == section_name)
106 return i;
107 return PE_SECTION_INDEX_INVALID;
111 /* Create a minimal symbol entry for an exported symbol.
112 SYM_NAME contains the exported name or NULL if exported by ordinal,
113 FUNC_RVA contains the Relative Virtual Address of the symbol,
114 ORDINAL is the ordinal index value of the symbol,
115 SECTION_DATA contains information about the section in which the
116 symbol is declared,
117 DLL_NAME is the internal name of the DLL file,
118 OBJFILE is the objfile struct of DLL_NAME. */
120 static void
121 add_pe_exported_sym (minimal_symbol_reader &reader,
122 const char *sym_name,
123 unsigned long func_rva,
124 int ordinal,
125 const struct read_pe_section_data *section_data,
126 const char *dll_name, struct objfile *objfile)
128 /* Add the stored offset to get the loaded address of the symbol. */
129 unrelocated_addr vma = unrelocated_addr (func_rva
130 + section_data->vma_offset);
132 /* Generate a (hopefully unique) qualified name using the first part
133 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
134 used by windbg from the "Microsoft Debugging Tools for Windows". */
136 std::string bare_name;
137 if (sym_name == NULL || *sym_name == '\0')
138 bare_name = string_printf ("#%d", ordinal);
139 else
140 bare_name = sym_name;
142 std::string qualified_name
143 = string_printf ("%s!%s", dll_name, bare_name.c_str ());
145 if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
146 gdb_printf (gdb_stdlog , _("Unknown section type for \"%s\""
147 " for entry \"%s\" in dll \"%s\"\n"),
148 section_data->section_name.c_str (), sym_name,
149 dll_name);
151 reader.record_with_info (qualified_name.c_str (), vma, section_data->ms_type,
152 section_data->index);
154 /* Enter the plain name as well, which might not be unique. */
155 reader.record_with_info (bare_name.c_str (), vma, section_data->ms_type,
156 section_data->index);
157 if (debug_coff_pe_read > 1)
158 gdb_printf (gdb_stdlog, _("Adding exported symbol \"%s\""
159 " in dll \"%s\"\n"), sym_name, dll_name);
162 /* Create a minimal symbol entry for an exported forward symbol.
163 Return 1 if the forwarded function was found 0 otherwise.
164 SYM_NAME contains the exported name or NULL if exported by ordinal,
165 FORWARD_DLL_NAME is the name of the DLL in which the target symbol resides,
166 FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
167 ORDINAL is the ordinal index value of the symbol,
168 DLL_NAME is the internal name of the DLL file,
169 OBJFILE is the objfile struct of DLL_NAME. */
171 static int
172 add_pe_forwarded_sym (minimal_symbol_reader &reader,
173 const char *sym_name, const char *forward_dll_name,
174 const char *forward_func_name, int ordinal,
175 const char *dll_name, struct objfile *objfile)
177 enum minimal_symbol_type msymtype;
178 int forward_dll_name_len = strlen (forward_dll_name);
180 std::string forward_qualified_name = string_printf ("%s!%s",
181 forward_dll_name,
182 forward_func_name);
184 bound_minimal_symbol msymbol
185 = lookup_minimal_symbol (current_program_space,
186 forward_qualified_name.c_str ());
187 if (!msymbol.minsym)
189 int i;
191 for (i = 0; i < forward_dll_name_len; i++)
192 forward_qualified_name[i] = tolower (forward_qualified_name[i]);
193 msymbol = lookup_minimal_symbol (current_program_space,
194 forward_qualified_name.c_str ());
197 if (!msymbol.minsym)
199 if (debug_coff_pe_read)
200 gdb_printf (gdb_stdlog, _("Unable to find function \"%s\" in"
201 " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
202 forward_func_name, forward_dll_name, sym_name,
203 dll_name);
204 return 0;
207 if (debug_coff_pe_read > 1)
208 gdb_printf (gdb_stdlog, _("Adding forwarded exported symbol"
209 " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
210 sym_name, dll_name, forward_qualified_name.c_str ());
212 /* Calculate VMA as if it were relative to DLL_NAME/OBJFILE, even though
213 it actually points inside another dll (FORWARD_DLL_NAME). */
214 unrelocated_addr vma = unrelocated_addr (msymbol.value_address ()
215 - objfile->text_section_offset ());
216 msymtype = msymbol.minsym->type ();
217 int section = msymbol.minsym->section_index ();
219 /* Generate a (hopefully unique) qualified name using the first part
220 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
221 used by windbg from the "Microsoft Debugging Tools for Windows". */
223 std::string bare_name;
224 if (sym_name == NULL || *sym_name == '\0')
225 bare_name = string_printf ("#%d", ordinal);
226 else
227 bare_name = sym_name;
229 std::string qualified_name
230 = string_printf ("%s!%s", dll_name, bare_name.c_str ());
232 /* Note that this code makes a minimal symbol whose value may point
233 outside of any section in this objfile. These symbols can't
234 really be relocated properly, but nevertheless we make a stab at
235 it, choosing an approach consistent with the history of this
236 code. */
238 reader.record_with_info (qualified_name.c_str (), vma, msymtype, section);
240 /* Enter the plain name as well, which might not be unique. */
241 reader.record_with_info (bare_name.c_str(), vma, msymtype, section);
243 return 1;
246 /* Truncate a dll_name at the last dot character. */
248 static void
249 read_pe_truncate_name (char *dll_name)
251 char *last_point = strrchr (dll_name, '.');
253 if (last_point != NULL)
254 *last_point = '\0';
257 /* Low-level support functions, direct from the ld module pe-dll.c. */
258 static unsigned int
259 pe_get16 (bfd *abfd, int where, bool *fail)
261 unsigned char b[2];
263 if (bfd_seek (abfd, where, SEEK_SET) != 0
264 || bfd_read (b, 2, abfd) != 2)
266 *fail = true;
267 return 0;
269 return b[0] + (b[1] << 8);
272 static unsigned int
273 pe_get32 (bfd *abfd, int where, bool *fail)
275 unsigned char b[4];
277 if (bfd_seek (abfd, where, SEEK_SET) != 0
278 || bfd_read (b, 4, abfd) != 4)
280 *fail = true;
281 return 0;
283 return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
286 static unsigned int
287 pe_as16 (void *ptr)
289 unsigned char *b = (unsigned char *) ptr;
291 return b[0] + (b[1] << 8);
294 static unsigned int
295 pe_as32 (void *ptr)
297 unsigned char *b = (unsigned char *) ptr;
299 return b[0] + (b[1] << 8) + (b[2] << 16) + ((unsigned) b[3] << 24);
302 /* Read the (non-debug) export symbol table from a portable
303 executable. Code originally lifted from the ld function
304 pe_implied_import_dll in pe-dll.c. */
306 void
307 read_pe_exported_syms (minimal_symbol_reader &reader,
308 struct objfile *objfile)
310 bfd *dll = objfile->obfd.get ();
311 unsigned long nbnormal, nbforward;
312 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
313 unsigned long export_opthdrrva, export_opthdrsize;
314 unsigned long export_rva, export_size, nsections, secptr, expptr;
315 unsigned long exp_funcbase;
316 unsigned char *expdata, *erva;
317 unsigned long name_rvas, ordinals, nexp, ordbase;
318 int otherix = PE_SECTION_TABLE_SIZE;
319 int is_pe64 = 0;
320 int is_pe32 = 0;
322 char const *target = bfd_get_target (objfile->obfd.get ());
324 std::vector<struct read_pe_section_data> section_data
325 (PE_SECTION_TABLE_SIZE);
327 for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
329 section_data[i].vma_offset = 0;
330 section_data[i].rva_start = 1;
331 section_data[i].rva_end = 0;
333 section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
334 section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
335 section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
336 section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
337 section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
338 section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
340 is_pe64 = (strcmp (target, "pe-x86-64") == 0
341 || strcmp (target, "pei-x86-64") == 0
342 || strcmp (target, "pe-aarch64") == 0
343 || strcmp (target, "pei-aarch64") == 0);
344 is_pe32 = (strcmp (target, "pe-i386") == 0
345 || strcmp (target, "pei-i386") == 0
346 || strcmp (target, "pe-arm-wince-little") == 0
347 || strcmp (target, "pei-arm-wince-little") == 0);
349 /* Possibly print a debug message about DLL not having a valid format. */
350 auto maybe_print_debug_msg = [&] () -> void {
351 if (debug_coff_pe_read)
352 gdb_printf (gdb_stdlog, _("%s doesn't appear to be a DLL\n"),
353 bfd_get_filename (dll));
356 if (!is_pe32 && !is_pe64)
357 return maybe_print_debug_msg ();
359 /* Get pe_header, optional header and numbers of export entries. */
360 bool fail = false;
361 pe_header_offset = pe_get32 (dll, 0x3c, &fail);
362 if (fail)
363 return maybe_print_debug_msg ();
364 opthdr_ofs = pe_header_offset + 4 + 20;
365 if (is_pe64)
366 num_entries = pe_get32 (dll, opthdr_ofs + 108, &fail);
367 else
368 num_entries = pe_get32 (dll, opthdr_ofs + 92, &fail);
369 if (fail)
370 return maybe_print_debug_msg ();
372 if (num_entries < 1) /* No exports. */
373 return;
374 if (is_pe64)
376 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112, &fail);
377 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116, &fail);
379 else
381 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96, &fail);
382 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100, &fail);
384 if (fail)
385 return maybe_print_debug_msg ();
387 nsections = pe_get16 (dll, pe_header_offset + 4 + 2, &fail);
388 secptr = (pe_header_offset + 4 + 20 +
389 pe_get16 (dll, pe_header_offset + 4 + 16, &fail));
390 if (fail)
391 return maybe_print_debug_msg ();
392 expptr = 0;
393 export_size = 0;
395 /* Get the rva and size of the export section. */
396 for (i = 0; i < nsections; i++)
398 char sname[8];
399 unsigned long secptr1 = secptr + 40 * i;
400 unsigned long vaddr = pe_get32 (dll, secptr1 + 12, &fail);
401 unsigned long vsize = pe_get32 (dll, secptr1 + 16, &fail);
402 unsigned long fptr = pe_get32 (dll, secptr1 + 20, &fail);
404 if (fail
405 || bfd_seek (dll, secptr1, SEEK_SET) != 0
406 || bfd_read (sname, sizeof (sname), dll) != sizeof (sname))
407 return maybe_print_debug_msg ();
409 if ((strcmp (sname, ".edata") == 0)
410 || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
412 if (strcmp (sname, ".edata") != 0)
414 if (debug_coff_pe_read)
415 gdb_printf (gdb_stdlog, _("Export RVA for dll "
416 "\"%s\" is in section \"%s\"\n"),
417 bfd_get_filename (dll), sname);
419 else if (export_opthdrrva != vaddr && debug_coff_pe_read)
420 gdb_printf (gdb_stdlog, _("Wrong value of export RVA"
421 " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
422 bfd_get_filename (dll), export_opthdrrva, vaddr);
423 expptr = fptr + (export_opthdrrva - vaddr);
424 break;
428 if (expptr == 0)
430 /* no section contains export table rva */
431 return;
434 export_rva = export_opthdrrva;
435 export_size = export_opthdrsize;
437 if (export_size == 0)
439 /* Empty export table. */
440 return;
443 /* Scan sections and store the base and size of the relevant
444 sections. */
445 for (i = 0; i < nsections; i++)
447 unsigned long secptr1 = secptr + 40 * i;
448 unsigned long vsize = pe_get32 (dll, secptr1 + 8, &fail);
449 unsigned long vaddr = pe_get32 (dll, secptr1 + 12, &fail);
450 unsigned long characteristics = pe_get32 (dll, secptr1 + 36, &fail);
451 char sec_name[SCNNMLEN + 1];
452 int sectix;
453 unsigned int bfd_section_index;
454 asection *section;
456 if (fail
457 || bfd_seek (dll, secptr1 + 0, SEEK_SET) != 0
458 || bfd_read (sec_name, SCNNMLEN, dll) != SCNNMLEN)
459 return maybe_print_debug_msg ();
460 sec_name[SCNNMLEN] = '\0';
462 sectix = read_pe_section_index (sec_name);
463 section = bfd_get_section_by_name (dll, sec_name);
464 if (section)
465 bfd_section_index = section->index;
466 else
467 bfd_section_index = -1;
469 if (sectix != PE_SECTION_INDEX_INVALID)
471 section_data[sectix].rva_start = vaddr;
472 section_data[sectix].rva_end = vaddr + vsize;
473 section_data[sectix].index = bfd_section_index;
475 else
477 section_data.resize (otherix + 1);
478 section_data[otherix].section_name = sec_name;
479 section_data[otherix].rva_start = vaddr;
480 section_data[otherix].rva_end = vaddr + vsize;
481 section_data[otherix].vma_offset = 0;
482 section_data[otherix].index = bfd_section_index;
483 if (characteristics & IMAGE_SCN_CNT_CODE)
484 section_data[otherix].ms_type = mst_text;
485 else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
486 section_data[otherix].ms_type = mst_data;
487 else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
488 section_data[otherix].ms_type = mst_bss;
489 else
490 section_data[otherix].ms_type = mst_unknown;
491 otherix++;
495 gdb::def_vector<unsigned char> expdata_storage (export_size);
496 expdata = expdata_storage.data ();
498 if (bfd_seek (dll, expptr, SEEK_SET) != 0
499 || bfd_read (expdata, export_size, dll) != export_size)
500 return maybe_print_debug_msg ();
501 erva = expdata - export_rva;
503 nexp = pe_as32 (expdata + 24);
504 name_rvas = pe_as32 (expdata + 32);
505 ordinals = pe_as32 (expdata + 36);
506 ordbase = pe_as32 (expdata + 16);
507 exp_funcbase = pe_as32 (expdata + 28);
509 /* Use internal dll name instead of full pathname. */
510 char *dll_name = (char *) (pe_as32 (expdata + 12) + erva);
512 for (asection *sectp : gdb_bfd_sections (dll))
514 int sectix = get_pe_section_index (sectp->name, section_data);
515 if (sectix != PE_SECTION_INDEX_INVALID)
517 /* Data within the section start at rva_start in the pe and at
518 bfd_get_section_vma() within memory. Store the offset. */
519 section_data[sectix].vma_offset
520 = bfd_section_vma (sectp) - section_data[sectix].rva_start;
524 /* Truncate name at first dot. Should maybe also convert to all
525 lower case for convenience on Windows. */
526 read_pe_truncate_name (dll_name);
528 if (debug_coff_pe_read)
529 gdb_printf (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
530 " base=%ld\n"), dll_name, nexp, ordbase);
531 nbforward = 0;
532 nbnormal = 0;
533 /* Iterate through the list of symbols. */
534 for (i = 0; i < nexp; i++)
536 /* Pointer to the names vector. */
537 unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
538 /* Retrieve ordinal value. */
540 unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
543 /* Pointer to the function address vector. */
544 /* This is relative to ordinal value. */
545 unsigned long func_rva = pe_as32 (erva + exp_funcbase +
546 ordinal * 4);
548 /* Find this symbol's section in our own array. */
549 int sectix = 0;
550 int section_found = 0;
552 /* First handle forward cases. */
553 if (func_rva >= export_rva && func_rva < export_rva + export_size)
555 const char *forward_name = (const char *) (erva + func_rva);
556 const char *funcname = (const char *) (erva + name_rva);
557 const char *forward_dll_name = forward_name;
558 const char *forward_func_name = forward_name;
559 const char *sep = strrchr (forward_name, '.');
561 std::string name_storage;
562 if (sep != nullptr)
564 int len = (int) (sep - forward_name);
566 name_storage = std::string (forward_name, len);
567 forward_dll_name = name_storage.c_str ();
568 forward_func_name = sep + 1;
570 if (add_pe_forwarded_sym (reader, funcname, forward_dll_name,
571 forward_func_name, ordinal,
572 dll_name, objfile) != 0)
573 ++nbforward;
574 continue;
577 for (sectix = 0; sectix < otherix; ++sectix)
579 if ((func_rva >= section_data[sectix].rva_start)
580 && (func_rva < section_data[sectix].rva_end))
582 const char *sym_name = (const char *) (erva + name_rva);
584 section_found = 1;
585 add_pe_exported_sym (reader, sym_name, func_rva, ordinal,
586 &section_data[sectix], dll_name, objfile);
587 ++nbnormal;
588 break;
591 if (!section_found)
593 const char *funcname = (const char *) (erva + name_rva);
595 if (name_rva == 0)
597 add_pe_exported_sym (reader, NULL, func_rva, ordinal,
598 &section_data[0], dll_name, objfile);
599 ++nbnormal;
601 else if (debug_coff_pe_read)
602 gdb_printf (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
603 " RVA 0x%lx in dll \"%s\" not handled\n"),
604 funcname, ordinal, func_rva, dll_name);
608 if (debug_coff_pe_read)
609 gdb_printf (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
610 " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
611 nbforward, nbnormal + nbforward, nexp);
614 /* Extract from ABFD the offset of the .text section.
615 This offset is mainly related to the offset within the file.
616 The value was previously expected to be 0x1000 for all files,
617 but some Windows OS core DLLs seem to use 0x10000 section alignment
618 which modified the return value of that function.
619 Still return default 0x1000 value if ABFD is NULL or
620 if '.text' section is not found, but that should not happen... */
622 #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
624 CORE_ADDR
625 pe_text_section_offset (struct bfd *abfd)
628 unsigned long pe_header_offset, i;
629 unsigned long nsections, secptr;
630 int is_pe64 = 0;
631 int is_pe32 = 0;
632 char const *target;
634 if (!abfd)
635 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
637 target = bfd_get_target (abfd);
639 is_pe64 = (strcmp (target, "pe-x86-64") == 0
640 || strcmp (target, "pei-x86-64") == 0
641 || strcmp (target, "pe-aarch64") == 0
642 || strcmp (target, "pei-aarch64") == 0);
643 is_pe32 = (strcmp (target, "pe-i386") == 0
644 || strcmp (target, "pei-i386") == 0
645 || strcmp (target, "pe-arm-wince-little") == 0
646 || strcmp (target, "pei-arm-wince-little") == 0);
648 if (!is_pe32 && !is_pe64)
650 /* This is not a recognized PE format file. Abort now, because
651 the code is untested on anything else. *FIXME* test on
652 further architectures and loosen or remove this test. */
653 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
656 /* Get pe_header, optional header and numbers of sections. */
657 bool fail = false;
658 pe_header_offset = pe_get32 (abfd, 0x3c, &fail);
659 if (fail)
660 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
661 nsections = pe_get16 (abfd, pe_header_offset + 4 + 2, &fail);
662 secptr = (pe_header_offset + 4 + 20 +
663 pe_get16 (abfd, pe_header_offset + 4 + 16, &fail));
664 if (fail)
665 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
667 /* Get the rva and size of the export section. */
668 for (i = 0; i < nsections; i++)
670 char sname[SCNNMLEN + 1];
671 unsigned long secptr1 = secptr + 40 * i;
672 unsigned long vaddr = pe_get32 (abfd, secptr1 + 12, &fail);
674 if (fail
675 || bfd_seek (abfd, secptr1, SEEK_SET) != 0
676 || bfd_read (sname, SCNNMLEN, abfd) != SCNNMLEN)
677 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
678 sname[SCNNMLEN] = '\0';
679 if (strcmp (sname, ".text") == 0)
680 return vaddr;
683 return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
686 /* Implements "show debug coff_pe_read" command. */
688 static void
689 show_debug_coff_pe_read (struct ui_file *file, int from_tty,
690 struct cmd_list_element *c, const char *value)
692 gdb_printf (file, _("Coff PE read debugging is %s.\n"), value);
695 /* Adds "Set/show debug coff_pe_read" commands. */
697 void _initialize_coff_pe_read ();
698 void
699 _initialize_coff_pe_read ()
701 add_setshow_zuinteger_cmd ("coff-pe-read", class_maintenance,
702 &debug_coff_pe_read,
703 _("Set coff PE read debugging."),
704 _("Show coff PE read debugging."),
705 _("When set, debugging messages for coff reading "
706 "of exported symbols are displayed."),
707 NULL, show_debug_coff_pe_read,
708 &setdebuglist, &showdebuglist);