* coff-pe-read.h (pe_text_section_offset): Declare new function.
[deliverable/binutils-gdb.git] / gdb / coff-pe-read.c
CommitLineData
1b6bc7e0
CF
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
0b302171 5 Copyright (C) 2003, 2007-2012 Free Software Foundation, Inc.
1b6bc7e0
CF
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
a9762ec7 11 the Free Software Foundation; either version 3 of the License, or
1b6bc7e0
CF
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
a9762ec7 20 along with this program. If not, see <http://www.gnu.org/licenses/>.
1b6bc7e0 21
aff410f1 22 Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
1b6bc7e0 23
0baeab03
PA
24#include "defs.h"
25
1b6bc7e0
CF
26#include "coff-pe-read.h"
27
81de56be 28#include "bfd.h"
1b6bc7e0
CF
29#include "gdbtypes.h"
30
3999122f
PM
31#include "command.h"
32#include "gdbcmd.h"
1b6bc7e0
CF
33#include "symtab.h"
34#include "symfile.h"
35#include "objfiles.h"
3999122f
PM
36#include "common/common-utils.h"
37
38#include <ctype.h>
1b6bc7e0
CF
39
40/* Internal section information */
41
3999122f
PM
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. */
46static unsigned int debug_coff_pe_read;
47
1b6bc7e0
CF
48struct read_pe_section_data
49{
aff410f1
MS
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. */
3999122f 55 char *section_name; /* Recorded section name. */
1b6bc7e0
CF
56};
57
3999122f
PM
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
1b6bc7e0
CF
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
aff410f1
MS
74 text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
75 if passed an unrecognised section name. */
1b6bc7e0
CF
76
77static int
78read_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
3999122f
PM
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
105static int
106get_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. */
121struct pe_sections_info
122{
123 int nb_sections;
124 struct read_pe_section_data *sections;
125};
126
aff410f1 127/* Record the virtual memory address of a section. */
1b6bc7e0
CF
128
129static void
130get_section_vmas (bfd *abfd, asection *sectp, void *context)
131{
3999122f
PM
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);
1b6bc7e0
CF
136
137 if (sectix != PE_SECTION_INDEX_INVALID)
138 {
139 /* Data within the section start at rva_start in the pe and at
aff410f1 140 bfd_get_section_vma() within memory. Store the offset. */
1b6bc7e0
CF
141
142 sections[sectix].vma_offset
143 = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
144 }
145}
146\f
3999122f
PM
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. */
1b6bc7e0
CF
155
156static void
3999122f 157add_pe_exported_sym (const char *sym_name,
1b6bc7e0 158 unsigned long func_rva,
3999122f 159 int ordinal,
1b6bc7e0
CF
160 const struct read_pe_section_data *section_data,
161 const char *dll_name, struct objfile *objfile)
162{
3999122f 163 char *qualified_name, *bare_name;
aff410f1 164 /* Add the stored offset to get the loaded address of the symbol. */
1b6bc7e0 165 CORE_ADDR vma = func_rva + section_data->vma_offset;
1b6bc7e0 166 int dll_name_len = strlen (dll_name);
1b6bc7e0
CF
167
168 /* Generate a (hopefully unique) qualified name using the first part
aff410f1
MS
169 of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
170 used by windbg from the "Microsoft Debugging Tools for Windows". */
1b6bc7e0 171
3999122f
PM
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);
1b6bc7e0 178
3999122f
PM
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);
1b6bc7e0 183
3999122f
PM
184 prim_record_minimal_symbol (qualified_name, vma,
185 section_data->ms_type, objfile);
1b6bc7e0 186
3999122f
PM
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);
1b6bc7e0 192 xfree (qualified_name);
3999122f
PM
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
205static int
206add_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);
1b6bc7e0 270
aff410f1 271 /* Enter the plain name as well, which might not be unique. */
3999122f
PM
272 prim_record_minimal_symbol (bare_name, vma, msymtype, objfile);
273 xfree (qualified_name);
274 xfree (bare_name);
275
276 return 1;
1b6bc7e0
CF
277}
278
3999122f 279/* Truncate a dll_name at the last dot character. */
1b6bc7e0
CF
280
281static void
282read_pe_truncate_name (char *dll_name)
283{
3999122f 284 char *last_point = strrchr (dll_name, '.');
1b6bc7e0 285
3999122f
PM
286 if (last_point != NULL)
287 *last_point = '\0';
1b6bc7e0
CF
288}
289\f
aff410f1 290/* Low-level support functions, direct from the ld module pe-dll.c. */
1b6bc7e0
CF
291static unsigned int
292pe_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
301static unsigned int
302pe_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
3999122f
PM
311static unsigned int
312pe_as16 (void *ptr)
313{
314 unsigned char *b = ptr;
315
316 return b[0] + (b[1] << 8);
317}
318
1b6bc7e0
CF
319static unsigned int
320pe_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
aff410f1
MS
328 executable. Code originally lifted from the ld function
329 pe_implied_import_dll in pe-dll.c. */
1b6bc7e0
CF
330
331void
332read_pe_exported_syms (struct objfile *objfile)
333{
334 bfd *dll = objfile->obfd;
3999122f 335 unsigned long nbnormal, nbforward;
1b6bc7e0 336 unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
3999122f 337 unsigned long export_opthdrrva, export_opthdrsize;
1b6bc7e0
CF
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;
3999122f
PM
342 char *dll_name = (char *) dll->filename;
343 int otherix = PE_SECTION_TABLE_SIZE;
344 int exportix = -1;
a68ddad5
KT
345 int is_pe64 = 0;
346 int is_pe32 = 0;
1b6bc7e0
CF
347
348 /* Array elements are for text, data and bss in that order
3999122f 349 Initialization with RVA_START > RVA_END guarantees that
aff410f1 350 unused sections won't be matched. */
3999122f
PM
351 struct read_pe_section_data *section_data;
352 struct pe_sections_info pe_sections_info;
1b6bc7e0 353
3999122f 354 struct cleanup *back_to = make_cleanup (null_cleanup, 0);
1b6bc7e0
CF
355
356 char const *target = bfd_get_target (objfile->obfd);
357
3999122f
PM
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
5e13bd89
PA
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);
a68ddad5 382 if (!is_pe32 && !is_pe64)
1b6bc7e0 383 {
5e13bd89
PA
384 /* This is not a recognized PE format file. Abort now, because
385 the code is untested on anything else. *FIXME* test on
aff410f1 386 further architectures and loosen or remove this test. */
1b6bc7e0
CF
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;
a68ddad5 393 if (is_pe64)
1dac1b47 394 num_entries = pe_get32 (dll, opthdr_ofs + 108);
a68ddad5
KT
395 else
396 num_entries = pe_get32 (dll, opthdr_ofs + 92);
1b6bc7e0
CF
397
398 if (num_entries < 1) /* No exports. */
399 {
400 return;
401 }
a68ddad5
KT
402 if (is_pe64)
403 {
3999122f
PM
404 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
405 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
a68ddad5
KT
406 }
407 else
408 {
3999122f
PM
409 export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
410 export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
a68ddad5 411 }
1b6bc7e0
CF
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;
3999122f 416 export_size = 0;
1b6bc7e0
CF
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);
3999122f 428 bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);
1b6bc7e0 429
3999122f
PM
430 if ((strcmp (sname, ".edata") == 0)
431 || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
1b6bc7e0 432 {
3999122f
PM
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;
1b6bc7e0
CF
446 break;
447 }
448 }
449
3999122f
PM
450 export_rva = export_opthdrrva;
451 export_size = export_opthdrsize;
452
1b6bc7e0
CF
453 if (export_size == 0)
454 {
aff410f1 455 /* Empty export table. */
1b6bc7e0
CF
456 return;
457 }
458
aff410f1
MS
459 /* Scan sections and store the base and size of the relevant
460 sections. */
1b6bc7e0
CF
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);
3999122f 466 unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
1b6bc7e0
CF
467 char sec_name[9];
468 int sectix;
469
3999122f 470 memset (sec_name, 0, sizeof (sec_name));
1b6bc7e0
CF
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 }
3999122f
PM
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 }
1b6bc7e0
CF
503 }
504
505 expdata = (unsigned char *) xmalloc (export_size);
3999122f 506 make_cleanup (xfree, expdata);
1b6bc7e0
CF
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
aff410f1 518 /* Use internal dll name instead of full pathname. */
1b6bc7e0
CF
519 dll_name = pe_as32 (expdata + 12) + erva;
520
3999122f
PM
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);
1b6bc7e0
CF
525
526 /* Adjust the vma_offsets in case this PE got relocated. This
527 assumes that *all* sections share the same relocation offset
aff410f1 528 as the text section. */
3999122f 529 for (i = 0; i < otherix; i++)
1b6bc7e0
CF
530 {
531 section_data[i].vma_offset
532 += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
533 }
534
1b6bc7e0 535 /* Truncate name at first dot. Should maybe also convert to all
aff410f1 536 lower case for convenience on Windows. */
1b6bc7e0
CF
537 read_pe_truncate_name (dll_name);
538
3999122f
PM
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;
1b6bc7e0
CF
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);
3999122f
PM
549 /* Retrieve ordinal value. */
550
551 unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
552
1b6bc7e0
CF
553
554 /* Pointer to the function address vector. */
3999122f
PM
555 /* This is relatived to ordinal value. */
556 unsigned long func_rva = pe_as32 (erva + exp_funcbase +
557 ordinal * 4);
1b6bc7e0 558
aff410f1 559 /* Find this symbol's section in our own array. */
1b6bc7e0 560 int sectix = 0;
3999122f
PM
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);
1b6bc7e0 575
3999122f
PM
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)
1b6bc7e0
CF
589 {
590 if ((func_rva >= section_data[sectix].rva_start)
591 && (func_rva < section_data[sectix].rva_end))
592 {
3999122f 593 section_found = 1;
1b6bc7e0 594 add_pe_exported_sym (erva + name_rva,
3999122f 595 func_rva, ordinal,
1b6bc7e0 596 section_data + sectix, dll_name, objfile);
3999122f 597 ++nbnormal;
1b6bc7e0
CF
598 break;
599 }
600 }
3999122f
PM
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 }
1b6bc7e0
CF
616 }
617
3999122f
PM
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. */
1b6bc7e0
CF
623 do_cleanups (back_to);
624}
3999122f
PM
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
636CORE_ADDR
637pe_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
695static void
696show_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
704void _initialize_coff_pe_read (void);
705
706/* Adds "Set/show debug coff_pe_read" commands. */
707
708void
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.671893 seconds and 4 git commands to generate.