15796c8dcSSimon Schubert /* Read the export table symbols from a portable executable and
25796c8dcSSimon Schubert convert to internal format, for GDB. Used as a last resort if no
35796c8dcSSimon Schubert debugging symbols recognized.
45796c8dcSSimon Schubert
5*ef5ccd6cSJohn Marino Copyright (C) 2003-2013 Free Software Foundation, Inc.
65796c8dcSSimon Schubert
75796c8dcSSimon Schubert This file is part of GDB.
85796c8dcSSimon Schubert
95796c8dcSSimon Schubert This program is free software; you can redistribute it and/or modify
105796c8dcSSimon Schubert it under the terms of the GNU General Public License as published by
115796c8dcSSimon Schubert the Free Software Foundation; either version 3 of the License, or
125796c8dcSSimon Schubert (at your option) any later version.
135796c8dcSSimon Schubert
145796c8dcSSimon Schubert This program is distributed in the hope that it will be useful,
155796c8dcSSimon Schubert but WITHOUT ANY WARRANTY; without even the implied warranty of
165796c8dcSSimon Schubert MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
175796c8dcSSimon Schubert GNU General Public License for more details.
185796c8dcSSimon Schubert
195796c8dcSSimon Schubert You should have received a copy of the GNU General Public License
205796c8dcSSimon Schubert along with this program. If not, see <http://www.gnu.org/licenses/>.
215796c8dcSSimon Schubert
225796c8dcSSimon Schubert Contributed by Raoul M. Gough (RaoulGough@yahoo.co.uk). */
235796c8dcSSimon Schubert
24*ef5ccd6cSJohn Marino #include "defs.h"
25*ef5ccd6cSJohn Marino
265796c8dcSSimon Schubert #include "coff-pe-read.h"
275796c8dcSSimon Schubert
28a45ae5f8SJohn Marino #include "bfd.h"
295796c8dcSSimon Schubert #include "gdbtypes.h"
305796c8dcSSimon Schubert
31*ef5ccd6cSJohn Marino #include "command.h"
32*ef5ccd6cSJohn Marino #include "gdbcmd.h"
335796c8dcSSimon Schubert #include "symtab.h"
345796c8dcSSimon Schubert #include "symfile.h"
355796c8dcSSimon Schubert #include "objfiles.h"
36*ef5ccd6cSJohn Marino #include "common/common-utils.h"
37*ef5ccd6cSJohn Marino #include "coff/internal.h"
38*ef5ccd6cSJohn Marino
39*ef5ccd6cSJohn Marino #include <ctype.h>
405796c8dcSSimon Schubert
415796c8dcSSimon Schubert /* Internal section information */
425796c8dcSSimon Schubert
43*ef5ccd6cSJohn Marino /* Coff PE read debugging flag:
44*ef5ccd6cSJohn Marino default value is 0,
45*ef5ccd6cSJohn Marino value 1 outputs problems encountered while parsing PE file,
46*ef5ccd6cSJohn Marino value above 1 also lists all generated minimal symbols. */
47*ef5ccd6cSJohn Marino static unsigned int debug_coff_pe_read;
48*ef5ccd6cSJohn Marino
495796c8dcSSimon Schubert struct read_pe_section_data
505796c8dcSSimon Schubert {
515796c8dcSSimon Schubert CORE_ADDR vma_offset; /* Offset to loaded address of section. */
525796c8dcSSimon Schubert unsigned long rva_start; /* Start offset within the pe. */
535796c8dcSSimon Schubert unsigned long rva_end; /* End offset within the pe. */
54c50c785cSJohn Marino enum minimal_symbol_type ms_type; /* Type to assign symbols in
55c50c785cSJohn Marino section. */
56*ef5ccd6cSJohn Marino char *section_name; /* Recorded section name. */
575796c8dcSSimon Schubert };
585796c8dcSSimon Schubert
59*ef5ccd6cSJohn Marino #define IMAGE_SCN_CNT_CODE 0x20
60*ef5ccd6cSJohn Marino #define IMAGE_SCN_CNT_INITIALIZED_DATA 0x40
61*ef5ccd6cSJohn Marino #define IMAGE_SCN_CNT_UNINITIALIZED_DATA 0x80
625796c8dcSSimon Schubert #define PE_SECTION_INDEX_TEXT 0
635796c8dcSSimon Schubert #define PE_SECTION_INDEX_DATA 1
645796c8dcSSimon Schubert #define PE_SECTION_INDEX_BSS 2
655796c8dcSSimon Schubert #define PE_SECTION_TABLE_SIZE 3
665796c8dcSSimon Schubert #define PE_SECTION_INDEX_INVALID -1
675796c8dcSSimon Schubert
685796c8dcSSimon Schubert /* Get the index of the named section in our own array, which contains
695796c8dcSSimon Schubert text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
705796c8dcSSimon Schubert if passed an unrecognised section name. */
715796c8dcSSimon Schubert
725796c8dcSSimon Schubert static int
read_pe_section_index(const char * section_name)735796c8dcSSimon Schubert read_pe_section_index (const char *section_name)
745796c8dcSSimon Schubert {
755796c8dcSSimon Schubert if (strcmp (section_name, ".text") == 0)
765796c8dcSSimon Schubert {
775796c8dcSSimon Schubert return PE_SECTION_INDEX_TEXT;
785796c8dcSSimon Schubert }
795796c8dcSSimon Schubert
805796c8dcSSimon Schubert else if (strcmp (section_name, ".data") == 0)
815796c8dcSSimon Schubert {
825796c8dcSSimon Schubert return PE_SECTION_INDEX_DATA;
835796c8dcSSimon Schubert }
845796c8dcSSimon Schubert
855796c8dcSSimon Schubert else if (strcmp (section_name, ".bss") == 0)
865796c8dcSSimon Schubert {
875796c8dcSSimon Schubert return PE_SECTION_INDEX_BSS;
885796c8dcSSimon Schubert }
895796c8dcSSimon Schubert
905796c8dcSSimon Schubert else
915796c8dcSSimon Schubert {
925796c8dcSSimon Schubert return PE_SECTION_INDEX_INVALID;
935796c8dcSSimon Schubert }
945796c8dcSSimon Schubert }
955796c8dcSSimon Schubert
96*ef5ccd6cSJohn Marino /* Get the index of the named section in our own full arrayi.
97*ef5ccd6cSJohn Marino text, data and bss in that order. Return PE_SECTION_INDEX_INVALID
98*ef5ccd6cSJohn Marino if passed an unrecognised section name. */
99*ef5ccd6cSJohn Marino
100*ef5ccd6cSJohn Marino static int
get_pe_section_index(const char * section_name,struct read_pe_section_data * sections,int nb_sections)101*ef5ccd6cSJohn Marino get_pe_section_index (const char *section_name,
102*ef5ccd6cSJohn Marino struct read_pe_section_data *sections,
103*ef5ccd6cSJohn Marino int nb_sections)
104*ef5ccd6cSJohn Marino {
105*ef5ccd6cSJohn Marino int i;
106*ef5ccd6cSJohn Marino
107*ef5ccd6cSJohn Marino for (i = 0; i < nb_sections; i++)
108*ef5ccd6cSJohn Marino if (strcmp (sections[i].section_name, section_name) == 0)
109*ef5ccd6cSJohn Marino return i;
110*ef5ccd6cSJohn Marino return PE_SECTION_INDEX_INVALID;
111*ef5ccd6cSJohn Marino }
112*ef5ccd6cSJohn Marino
113*ef5ccd6cSJohn Marino /* Structure used by get_section_vmas function below
114*ef5ccd6cSJohn Marino to access section_data array and the size of the array
115*ef5ccd6cSJohn Marino stored in nb_sections field. */
116*ef5ccd6cSJohn Marino struct pe_sections_info
117*ef5ccd6cSJohn Marino {
118*ef5ccd6cSJohn Marino int nb_sections;
119*ef5ccd6cSJohn Marino struct read_pe_section_data *sections;
120*ef5ccd6cSJohn Marino };
121*ef5ccd6cSJohn Marino
1225796c8dcSSimon Schubert /* Record the virtual memory address of a section. */
1235796c8dcSSimon Schubert
1245796c8dcSSimon Schubert static void
get_section_vmas(bfd * abfd,asection * sectp,void * context)1255796c8dcSSimon Schubert get_section_vmas (bfd *abfd, asection *sectp, void *context)
1265796c8dcSSimon Schubert {
127*ef5ccd6cSJohn Marino struct pe_sections_info *data = context;
128*ef5ccd6cSJohn Marino struct read_pe_section_data *sections = data->sections;
129*ef5ccd6cSJohn Marino int sectix = get_pe_section_index (sectp->name, sections,
130*ef5ccd6cSJohn Marino data->nb_sections);
1315796c8dcSSimon Schubert
1325796c8dcSSimon Schubert if (sectix != PE_SECTION_INDEX_INVALID)
1335796c8dcSSimon Schubert {
1345796c8dcSSimon Schubert /* Data within the section start at rva_start in the pe and at
1355796c8dcSSimon Schubert bfd_get_section_vma() within memory. Store the offset. */
1365796c8dcSSimon Schubert
1375796c8dcSSimon Schubert sections[sectix].vma_offset
1385796c8dcSSimon Schubert = bfd_get_section_vma (abfd, sectp) - sections[sectix].rva_start;
1395796c8dcSSimon Schubert }
1405796c8dcSSimon Schubert }
1415796c8dcSSimon Schubert
142*ef5ccd6cSJohn Marino /* Create a minimal symbol entry for an exported symbol.
143*ef5ccd6cSJohn Marino SYM_NAME contains the exported name or NULL if exported by ordinal,
144*ef5ccd6cSJohn Marino FUNC_RVA contains the Relative Virtual Address of the symbol,
145*ef5ccd6cSJohn Marino ORDINAL is the ordinal index value of the symbol,
146*ef5ccd6cSJohn Marino SECTION_DATA contains information about the section in which the
147*ef5ccd6cSJohn Marino symbol is declared,
148*ef5ccd6cSJohn Marino DLL_NAME is the internal name of the DLL file,
149*ef5ccd6cSJohn Marino OBJFILE is the objfile struct of DLL_NAME. */
1505796c8dcSSimon Schubert
1515796c8dcSSimon Schubert static void
add_pe_exported_sym(const char * sym_name,unsigned long func_rva,int ordinal,const struct read_pe_section_data * section_data,const char * dll_name,struct objfile * objfile)152*ef5ccd6cSJohn Marino add_pe_exported_sym (const char *sym_name,
1535796c8dcSSimon Schubert unsigned long func_rva,
154*ef5ccd6cSJohn Marino int ordinal,
1555796c8dcSSimon Schubert const struct read_pe_section_data *section_data,
1565796c8dcSSimon Schubert const char *dll_name, struct objfile *objfile)
1575796c8dcSSimon Schubert {
158*ef5ccd6cSJohn Marino char *qualified_name, *bare_name;
1595796c8dcSSimon Schubert /* Add the stored offset to get the loaded address of the symbol. */
1605796c8dcSSimon Schubert CORE_ADDR vma = func_rva + section_data->vma_offset;
1615796c8dcSSimon Schubert int dll_name_len = strlen (dll_name);
1625796c8dcSSimon Schubert
1635796c8dcSSimon Schubert /* Generate a (hopefully unique) qualified name using the first part
1645796c8dcSSimon Schubert of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
1655796c8dcSSimon Schubert used by windbg from the "Microsoft Debugging Tools for Windows". */
1665796c8dcSSimon Schubert
167*ef5ccd6cSJohn Marino if (sym_name == NULL || *sym_name == '\0')
168*ef5ccd6cSJohn Marino bare_name = xstrprintf ("#%d", ordinal);
169*ef5ccd6cSJohn Marino else
170*ef5ccd6cSJohn Marino bare_name = xstrdup (sym_name);
1715796c8dcSSimon Schubert
172*ef5ccd6cSJohn Marino qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
1735796c8dcSSimon Schubert
174*ef5ccd6cSJohn Marino if ((section_data->ms_type == mst_unknown) && debug_coff_pe_read)
175*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog , _("Unknown section type for \"%s\""
176*ef5ccd6cSJohn Marino " for entry \"%s\" in dll \"%s\"\n"),
177*ef5ccd6cSJohn Marino section_data->section_name, sym_name, dll_name);
1785796c8dcSSimon Schubert
179*ef5ccd6cSJohn Marino prim_record_minimal_symbol (qualified_name, vma,
180*ef5ccd6cSJohn Marino section_data->ms_type, objfile);
1815796c8dcSSimon Schubert
1825796c8dcSSimon Schubert /* Enter the plain name as well, which might not be unique. */
183*ef5ccd6cSJohn Marino prim_record_minimal_symbol (bare_name, vma, section_data->ms_type, objfile);
184*ef5ccd6cSJohn Marino if (debug_coff_pe_read > 1)
185*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Adding exported symbol \"%s\""
186*ef5ccd6cSJohn Marino " in dll \"%s\"\n"), sym_name, dll_name);
187*ef5ccd6cSJohn Marino xfree (qualified_name);
188*ef5ccd6cSJohn Marino xfree (bare_name);
1895796c8dcSSimon Schubert }
1905796c8dcSSimon Schubert
191*ef5ccd6cSJohn Marino /* Create a minimal symbol entry for an exported forward symbol.
192*ef5ccd6cSJohn Marino Return 1 if the forwarded function was found 0 otherwise.
193*ef5ccd6cSJohn Marino SYM_NAME contains the exported name or NULL if exported by ordinal,
194*ef5ccd6cSJohn Marino FORWARD_DLL_NAME is the name of the DLL in which the target symobl resides,
195*ef5ccd6cSJohn Marino FORWARD_FUNC_NAME is the name of the target symbol in that DLL,
196*ef5ccd6cSJohn Marino ORDINAL is the ordinal index value of the symbol,
197*ef5ccd6cSJohn Marino DLL_NAME is the internal name of the DLL file,
198*ef5ccd6cSJohn Marino OBJFILE is the objfile struct of DLL_NAME. */
199*ef5ccd6cSJohn Marino
200*ef5ccd6cSJohn Marino static int
add_pe_forwarded_sym(const char * sym_name,const char * forward_dll_name,const char * forward_func_name,int ordinal,const char * dll_name,struct objfile * objfile)201*ef5ccd6cSJohn Marino add_pe_forwarded_sym (const char *sym_name, const char *forward_dll_name,
202*ef5ccd6cSJohn Marino const char *forward_func_name, int ordinal,
203*ef5ccd6cSJohn Marino const char *dll_name, struct objfile *objfile)
204*ef5ccd6cSJohn Marino {
205*ef5ccd6cSJohn Marino CORE_ADDR vma;
206*ef5ccd6cSJohn Marino struct objfile *forward_objfile;
207*ef5ccd6cSJohn Marino struct minimal_symbol *msymbol;
208*ef5ccd6cSJohn Marino short section;
209*ef5ccd6cSJohn Marino enum minimal_symbol_type msymtype;
210*ef5ccd6cSJohn Marino int dll_name_len = strlen (dll_name);
211*ef5ccd6cSJohn Marino char *qualified_name, *bare_name;
212*ef5ccd6cSJohn Marino int forward_dll_name_len = strlen (forward_dll_name);
213*ef5ccd6cSJohn Marino int forward_func_name_len = strlen (forward_func_name);
214*ef5ccd6cSJohn Marino int forward_len = forward_dll_name_len + forward_func_name_len + 2;
215*ef5ccd6cSJohn Marino char *forward_qualified_name = alloca (forward_len);
216*ef5ccd6cSJohn Marino
217*ef5ccd6cSJohn Marino xsnprintf (forward_qualified_name, forward_len, "%s!%s", forward_dll_name,
218*ef5ccd6cSJohn Marino forward_func_name);
219*ef5ccd6cSJohn Marino
220*ef5ccd6cSJohn Marino
221*ef5ccd6cSJohn Marino msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name,
222*ef5ccd6cSJohn Marino &forward_objfile);
223*ef5ccd6cSJohn Marino
224*ef5ccd6cSJohn Marino if (!msymbol)
225*ef5ccd6cSJohn Marino {
226*ef5ccd6cSJohn Marino int i;
227*ef5ccd6cSJohn Marino
228*ef5ccd6cSJohn Marino for (i = 0; i < forward_dll_name_len; i++)
229*ef5ccd6cSJohn Marino forward_qualified_name[i] = tolower (forward_qualified_name[i]);
230*ef5ccd6cSJohn Marino msymbol = lookup_minimal_symbol_and_objfile (forward_qualified_name,
231*ef5ccd6cSJohn Marino &forward_objfile);
232*ef5ccd6cSJohn Marino }
233*ef5ccd6cSJohn Marino
234*ef5ccd6cSJohn Marino if (!msymbol)
235*ef5ccd6cSJohn Marino {
236*ef5ccd6cSJohn Marino if (debug_coff_pe_read)
237*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Unable to find function \"%s\" in"
238*ef5ccd6cSJohn Marino " dll \"%s\", forward of \"%s\" in dll \"%s\"\n"),
239*ef5ccd6cSJohn Marino forward_func_name, forward_dll_name, sym_name,
240*ef5ccd6cSJohn Marino dll_name);
241*ef5ccd6cSJohn Marino return 0;
242*ef5ccd6cSJohn Marino }
243*ef5ccd6cSJohn Marino
244*ef5ccd6cSJohn Marino if (debug_coff_pe_read > 1)
245*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Adding forwarded exported symbol"
246*ef5ccd6cSJohn Marino " \"%s\" in dll \"%s\", pointing to \"%s\"\n"),
247*ef5ccd6cSJohn Marino sym_name, dll_name, forward_qualified_name);
248*ef5ccd6cSJohn Marino
249*ef5ccd6cSJohn Marino vma = SYMBOL_VALUE_ADDRESS (msymbol);
250*ef5ccd6cSJohn Marino section = SYMBOL_SECTION (msymbol);
251*ef5ccd6cSJohn Marino msymtype = MSYMBOL_TYPE (msymbol);
252*ef5ccd6cSJohn Marino
253*ef5ccd6cSJohn Marino /* Generate a (hopefully unique) qualified name using the first part
254*ef5ccd6cSJohn Marino of the dll name, e.g. KERNEL32!AddAtomA. This matches the style
255*ef5ccd6cSJohn Marino used by windbg from the "Microsoft Debugging Tools for Windows". */
256*ef5ccd6cSJohn Marino
257*ef5ccd6cSJohn Marino if (sym_name == NULL || *sym_name == '\0')
258*ef5ccd6cSJohn Marino bare_name = xstrprintf ("#%d", ordinal);
259*ef5ccd6cSJohn Marino else
260*ef5ccd6cSJohn Marino bare_name = xstrdup (sym_name);
261*ef5ccd6cSJohn Marino
262*ef5ccd6cSJohn Marino qualified_name = xstrprintf ("%s!%s", dll_name, bare_name);
263*ef5ccd6cSJohn Marino
264*ef5ccd6cSJohn Marino prim_record_minimal_symbol (qualified_name, vma, msymtype, objfile);
265*ef5ccd6cSJohn Marino
266*ef5ccd6cSJohn Marino /* Enter the plain name as well, which might not be unique. */
267*ef5ccd6cSJohn Marino prim_record_minimal_symbol (bare_name, vma, msymtype, objfile);
268*ef5ccd6cSJohn Marino xfree (qualified_name);
269*ef5ccd6cSJohn Marino xfree (bare_name);
270*ef5ccd6cSJohn Marino
271*ef5ccd6cSJohn Marino return 1;
272*ef5ccd6cSJohn Marino }
273*ef5ccd6cSJohn Marino
274*ef5ccd6cSJohn Marino /* Truncate a dll_name at the last dot character. */
2755796c8dcSSimon Schubert
2765796c8dcSSimon Schubert static void
read_pe_truncate_name(char * dll_name)2775796c8dcSSimon Schubert read_pe_truncate_name (char *dll_name)
2785796c8dcSSimon Schubert {
279*ef5ccd6cSJohn Marino char *last_point = strrchr (dll_name, '.');
2805796c8dcSSimon Schubert
281*ef5ccd6cSJohn Marino if (last_point != NULL)
282*ef5ccd6cSJohn Marino *last_point = '\0';
2835796c8dcSSimon Schubert }
2845796c8dcSSimon Schubert
2855796c8dcSSimon Schubert /* Low-level support functions, direct from the ld module pe-dll.c. */
2865796c8dcSSimon Schubert static unsigned int
pe_get16(bfd * abfd,int where)2875796c8dcSSimon Schubert pe_get16 (bfd *abfd, int where)
2885796c8dcSSimon Schubert {
2895796c8dcSSimon Schubert unsigned char b[2];
2905796c8dcSSimon Schubert
2915796c8dcSSimon Schubert bfd_seek (abfd, (file_ptr) where, SEEK_SET);
2925796c8dcSSimon Schubert bfd_bread (b, (bfd_size_type) 2, abfd);
2935796c8dcSSimon Schubert return b[0] + (b[1] << 8);
2945796c8dcSSimon Schubert }
2955796c8dcSSimon Schubert
2965796c8dcSSimon Schubert static unsigned int
pe_get32(bfd * abfd,int where)2975796c8dcSSimon Schubert pe_get32 (bfd *abfd, int where)
2985796c8dcSSimon Schubert {
2995796c8dcSSimon Schubert unsigned char b[4];
3005796c8dcSSimon Schubert
3015796c8dcSSimon Schubert bfd_seek (abfd, (file_ptr) where, SEEK_SET);
3025796c8dcSSimon Schubert bfd_bread (b, (bfd_size_type) 4, abfd);
3035796c8dcSSimon Schubert return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
3045796c8dcSSimon Schubert }
3055796c8dcSSimon Schubert
3065796c8dcSSimon Schubert static unsigned int
pe_as16(void * ptr)307*ef5ccd6cSJohn Marino pe_as16 (void *ptr)
308*ef5ccd6cSJohn Marino {
309*ef5ccd6cSJohn Marino unsigned char *b = ptr;
310*ef5ccd6cSJohn Marino
311*ef5ccd6cSJohn Marino return b[0] + (b[1] << 8);
312*ef5ccd6cSJohn Marino }
313*ef5ccd6cSJohn Marino
314*ef5ccd6cSJohn Marino static unsigned int
pe_as32(void * ptr)3155796c8dcSSimon Schubert pe_as32 (void *ptr)
3165796c8dcSSimon Schubert {
3175796c8dcSSimon Schubert unsigned char *b = ptr;
3185796c8dcSSimon Schubert
3195796c8dcSSimon Schubert return b[0] + (b[1] << 8) + (b[2] << 16) + (b[3] << 24);
3205796c8dcSSimon Schubert }
3215796c8dcSSimon Schubert
3225796c8dcSSimon Schubert /* Read the (non-debug) export symbol table from a portable
3235796c8dcSSimon Schubert executable. Code originally lifted from the ld function
3245796c8dcSSimon Schubert pe_implied_import_dll in pe-dll.c. */
3255796c8dcSSimon Schubert
3265796c8dcSSimon Schubert void
read_pe_exported_syms(struct objfile * objfile)3275796c8dcSSimon Schubert read_pe_exported_syms (struct objfile *objfile)
3285796c8dcSSimon Schubert {
3295796c8dcSSimon Schubert bfd *dll = objfile->obfd;
330*ef5ccd6cSJohn Marino unsigned long nbnormal, nbforward;
3315796c8dcSSimon Schubert unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
332*ef5ccd6cSJohn Marino unsigned long export_opthdrrva, export_opthdrsize;
3335796c8dcSSimon Schubert unsigned long export_rva, export_size, nsections, secptr, expptr;
3345796c8dcSSimon Schubert unsigned long exp_funcbase;
3355796c8dcSSimon Schubert unsigned char *expdata, *erva;
3365796c8dcSSimon Schubert unsigned long name_rvas, ordinals, nexp, ordbase;
337*ef5ccd6cSJohn Marino char *dll_name = (char *) dll->filename;
338*ef5ccd6cSJohn Marino int otherix = PE_SECTION_TABLE_SIZE;
339*ef5ccd6cSJohn Marino int exportix = -1;
3405796c8dcSSimon Schubert int is_pe64 = 0;
3415796c8dcSSimon Schubert int is_pe32 = 0;
3425796c8dcSSimon Schubert
3435796c8dcSSimon Schubert /* Array elements are for text, data and bss in that order
344*ef5ccd6cSJohn Marino Initialization with RVA_START > RVA_END guarantees that
3455796c8dcSSimon Schubert unused sections won't be matched. */
346*ef5ccd6cSJohn Marino struct read_pe_section_data *section_data;
347*ef5ccd6cSJohn Marino struct pe_sections_info pe_sections_info;
3485796c8dcSSimon Schubert
349*ef5ccd6cSJohn Marino struct cleanup *back_to = make_cleanup (null_cleanup, 0);
3505796c8dcSSimon Schubert
3515796c8dcSSimon Schubert char const *target = bfd_get_target (objfile->obfd);
3525796c8dcSSimon Schubert
353*ef5ccd6cSJohn Marino section_data = xzalloc (PE_SECTION_TABLE_SIZE
354*ef5ccd6cSJohn Marino * sizeof (struct read_pe_section_data));
355*ef5ccd6cSJohn Marino
356*ef5ccd6cSJohn Marino make_cleanup (free_current_contents, §ion_data);
357*ef5ccd6cSJohn Marino
358*ef5ccd6cSJohn Marino for (i=0; i < PE_SECTION_TABLE_SIZE; i++)
359*ef5ccd6cSJohn Marino {
360*ef5ccd6cSJohn Marino section_data[i].vma_offset = 0;
361*ef5ccd6cSJohn Marino section_data[i].rva_start = 1;
362*ef5ccd6cSJohn Marino section_data[i].rva_end = 0;
363*ef5ccd6cSJohn Marino };
364*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_TEXT].ms_type = mst_text;
365*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_TEXT].section_name = ".text";
366*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_DATA].ms_type = mst_data;
367*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_DATA].section_name = ".data";
368*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_BSS].ms_type = mst_bss;
369*ef5ccd6cSJohn Marino section_data[PE_SECTION_INDEX_BSS].section_name = ".bss";
370*ef5ccd6cSJohn Marino
3715796c8dcSSimon Schubert is_pe64 = (strcmp (target, "pe-x86-64") == 0
3725796c8dcSSimon Schubert || strcmp (target, "pei-x86-64") == 0);
3735796c8dcSSimon Schubert is_pe32 = (strcmp (target, "pe-i386") == 0
3745796c8dcSSimon Schubert || strcmp (target, "pei-i386") == 0
3755796c8dcSSimon Schubert || strcmp (target, "pe-arm-wince-little") == 0
3765796c8dcSSimon Schubert || strcmp (target, "pei-arm-wince-little") == 0);
3775796c8dcSSimon Schubert if (!is_pe32 && !is_pe64)
3785796c8dcSSimon Schubert {
3795796c8dcSSimon Schubert /* This is not a recognized PE format file. Abort now, because
3805796c8dcSSimon Schubert the code is untested on anything else. *FIXME* test on
3815796c8dcSSimon Schubert further architectures and loosen or remove this test. */
382*ef5ccd6cSJohn Marino do_cleanups (back_to);
3835796c8dcSSimon Schubert return;
3845796c8dcSSimon Schubert }
3855796c8dcSSimon Schubert
3865796c8dcSSimon Schubert /* Get pe_header, optional header and numbers of export entries. */
3875796c8dcSSimon Schubert pe_header_offset = pe_get32 (dll, 0x3c);
3885796c8dcSSimon Schubert opthdr_ofs = pe_header_offset + 4 + 20;
3895796c8dcSSimon Schubert if (is_pe64)
3905796c8dcSSimon Schubert num_entries = pe_get32 (dll, opthdr_ofs + 108);
3915796c8dcSSimon Schubert else
3925796c8dcSSimon Schubert num_entries = pe_get32 (dll, opthdr_ofs + 92);
3935796c8dcSSimon Schubert
3945796c8dcSSimon Schubert if (num_entries < 1) /* No exports. */
3955796c8dcSSimon Schubert {
396*ef5ccd6cSJohn Marino do_cleanups (back_to);
3975796c8dcSSimon Schubert return;
3985796c8dcSSimon Schubert }
3995796c8dcSSimon Schubert if (is_pe64)
4005796c8dcSSimon Schubert {
401*ef5ccd6cSJohn Marino export_opthdrrva = pe_get32 (dll, opthdr_ofs + 112);
402*ef5ccd6cSJohn Marino export_opthdrsize = pe_get32 (dll, opthdr_ofs + 116);
4035796c8dcSSimon Schubert }
4045796c8dcSSimon Schubert else
4055796c8dcSSimon Schubert {
406*ef5ccd6cSJohn Marino export_opthdrrva = pe_get32 (dll, opthdr_ofs + 96);
407*ef5ccd6cSJohn Marino export_opthdrsize = pe_get32 (dll, opthdr_ofs + 100);
4085796c8dcSSimon Schubert }
4095796c8dcSSimon Schubert nsections = pe_get16 (dll, pe_header_offset + 4 + 2);
4105796c8dcSSimon Schubert secptr = (pe_header_offset + 4 + 20 +
4115796c8dcSSimon Schubert pe_get16 (dll, pe_header_offset + 4 + 16));
4125796c8dcSSimon Schubert expptr = 0;
413*ef5ccd6cSJohn Marino export_size = 0;
4145796c8dcSSimon Schubert
4155796c8dcSSimon Schubert /* Get the rva and size of the export section. */
4165796c8dcSSimon Schubert for (i = 0; i < nsections; i++)
4175796c8dcSSimon Schubert {
4185796c8dcSSimon Schubert char sname[8];
4195796c8dcSSimon Schubert unsigned long secptr1 = secptr + 40 * i;
4205796c8dcSSimon Schubert unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
4215796c8dcSSimon Schubert unsigned long vsize = pe_get32 (dll, secptr1 + 16);
4225796c8dcSSimon Schubert unsigned long fptr = pe_get32 (dll, secptr1 + 20);
4235796c8dcSSimon Schubert
4245796c8dcSSimon Schubert bfd_seek (dll, (file_ptr) secptr1, SEEK_SET);
425*ef5ccd6cSJohn Marino bfd_bread (sname, (bfd_size_type) sizeof (sname), dll);
4265796c8dcSSimon Schubert
427*ef5ccd6cSJohn Marino if ((strcmp (sname, ".edata") == 0)
428*ef5ccd6cSJohn Marino || (vaddr <= export_opthdrrva && export_opthdrrva < vaddr + vsize))
4295796c8dcSSimon Schubert {
430*ef5ccd6cSJohn Marino if (strcmp (sname, ".edata") != 0)
431*ef5ccd6cSJohn Marino {
432*ef5ccd6cSJohn Marino if (debug_coff_pe_read)
433*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Export RVA for dll "
434*ef5ccd6cSJohn Marino "\"%s\" is in section \"%s\"\n"),
435*ef5ccd6cSJohn Marino dll_name, sname);
436*ef5ccd6cSJohn Marino }
437*ef5ccd6cSJohn Marino else if (export_opthdrrva != vaddr && debug_coff_pe_read)
438*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Wrong value of export RVA"
439*ef5ccd6cSJohn Marino " for dll \"%s\": 0x%lx instead of 0x%lx\n"),
440*ef5ccd6cSJohn Marino dll_name, export_opthdrrva, vaddr);
441*ef5ccd6cSJohn Marino expptr = fptr + (export_opthdrrva - vaddr);
442*ef5ccd6cSJohn Marino exportix = i;
4435796c8dcSSimon Schubert break;
4445796c8dcSSimon Schubert }
4455796c8dcSSimon Schubert }
4465796c8dcSSimon Schubert
447*ef5ccd6cSJohn Marino export_rva = export_opthdrrva;
448*ef5ccd6cSJohn Marino export_size = export_opthdrsize;
449*ef5ccd6cSJohn Marino
4505796c8dcSSimon Schubert if (export_size == 0)
4515796c8dcSSimon Schubert {
4525796c8dcSSimon Schubert /* Empty export table. */
453*ef5ccd6cSJohn Marino do_cleanups (back_to);
4545796c8dcSSimon Schubert return;
4555796c8dcSSimon Schubert }
4565796c8dcSSimon Schubert
457c50c785cSJohn Marino /* Scan sections and store the base and size of the relevant
458c50c785cSJohn Marino sections. */
4595796c8dcSSimon Schubert for (i = 0; i < nsections; i++)
4605796c8dcSSimon Schubert {
4615796c8dcSSimon Schubert unsigned long secptr1 = secptr + 40 * i;
4625796c8dcSSimon Schubert unsigned long vsize = pe_get32 (dll, secptr1 + 8);
4635796c8dcSSimon Schubert unsigned long vaddr = pe_get32 (dll, secptr1 + 12);
464*ef5ccd6cSJohn Marino unsigned long characteristics = pe_get32 (dll, secptr1 + 36);
465*ef5ccd6cSJohn Marino char sec_name[SCNNMLEN + 1];
4665796c8dcSSimon Schubert int sectix;
4675796c8dcSSimon Schubert
4685796c8dcSSimon Schubert bfd_seek (dll, (file_ptr) secptr1 + 0, SEEK_SET);
469*ef5ccd6cSJohn Marino bfd_bread (sec_name, (bfd_size_type) SCNNMLEN, dll);
470*ef5ccd6cSJohn Marino sec_name[SCNNMLEN] = '\0';
4715796c8dcSSimon Schubert
4725796c8dcSSimon Schubert sectix = read_pe_section_index (sec_name);
4735796c8dcSSimon Schubert
4745796c8dcSSimon Schubert if (sectix != PE_SECTION_INDEX_INVALID)
4755796c8dcSSimon Schubert {
4765796c8dcSSimon Schubert section_data[sectix].rva_start = vaddr;
4775796c8dcSSimon Schubert section_data[sectix].rva_end = vaddr + vsize;
4785796c8dcSSimon Schubert }
479*ef5ccd6cSJohn Marino else
480*ef5ccd6cSJohn Marino {
481*ef5ccd6cSJohn Marino char *name;
482*ef5ccd6cSJohn Marino
483*ef5ccd6cSJohn Marino section_data = xrealloc (section_data, (otherix + 1)
484*ef5ccd6cSJohn Marino * sizeof (struct read_pe_section_data));
485*ef5ccd6cSJohn Marino name = xstrdup (sec_name);
486*ef5ccd6cSJohn Marino section_data[otherix].section_name = name;
487*ef5ccd6cSJohn Marino make_cleanup (xfree, name);
488*ef5ccd6cSJohn Marino section_data[otherix].rva_start = vaddr;
489*ef5ccd6cSJohn Marino section_data[otherix].rva_end = vaddr + vsize;
490*ef5ccd6cSJohn Marino section_data[otherix].vma_offset = 0;
491*ef5ccd6cSJohn Marino if (characteristics & IMAGE_SCN_CNT_CODE)
492*ef5ccd6cSJohn Marino section_data[otherix].ms_type = mst_text;
493*ef5ccd6cSJohn Marino else if (characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
494*ef5ccd6cSJohn Marino section_data[otherix].ms_type = mst_data;
495*ef5ccd6cSJohn Marino else if (characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
496*ef5ccd6cSJohn Marino section_data[otherix].ms_type = mst_bss;
497*ef5ccd6cSJohn Marino else
498*ef5ccd6cSJohn Marino section_data[otherix].ms_type = mst_unknown;
499*ef5ccd6cSJohn Marino otherix++;
500*ef5ccd6cSJohn Marino }
5015796c8dcSSimon Schubert }
5025796c8dcSSimon Schubert
5035796c8dcSSimon Schubert expdata = (unsigned char *) xmalloc (export_size);
504*ef5ccd6cSJohn Marino make_cleanup (xfree, expdata);
5055796c8dcSSimon Schubert
5065796c8dcSSimon Schubert bfd_seek (dll, (file_ptr) expptr, SEEK_SET);
5075796c8dcSSimon Schubert bfd_bread (expdata, (bfd_size_type) export_size, dll);
5085796c8dcSSimon Schubert erva = expdata - export_rva;
5095796c8dcSSimon Schubert
5105796c8dcSSimon Schubert nexp = pe_as32 (expdata + 24);
5115796c8dcSSimon Schubert name_rvas = pe_as32 (expdata + 32);
5125796c8dcSSimon Schubert ordinals = pe_as32 (expdata + 36);
5135796c8dcSSimon Schubert ordbase = pe_as32 (expdata + 16);
5145796c8dcSSimon Schubert exp_funcbase = pe_as32 (expdata + 28);
5155796c8dcSSimon Schubert
5165796c8dcSSimon Schubert /* Use internal dll name instead of full pathname. */
5175796c8dcSSimon Schubert dll_name = pe_as32 (expdata + 12) + erva;
5185796c8dcSSimon Schubert
519*ef5ccd6cSJohn Marino pe_sections_info.nb_sections = otherix;
520*ef5ccd6cSJohn Marino pe_sections_info.sections = section_data;
521*ef5ccd6cSJohn Marino
522*ef5ccd6cSJohn Marino bfd_map_over_sections (dll, get_section_vmas, &pe_sections_info);
5235796c8dcSSimon Schubert
5245796c8dcSSimon Schubert /* Adjust the vma_offsets in case this PE got relocated. This
5255796c8dcSSimon Schubert assumes that *all* sections share the same relocation offset
5265796c8dcSSimon Schubert as the text section. */
527*ef5ccd6cSJohn Marino for (i = 0; i < otherix; i++)
5285796c8dcSSimon Schubert {
5295796c8dcSSimon Schubert section_data[i].vma_offset
5305796c8dcSSimon Schubert += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
5315796c8dcSSimon Schubert }
5325796c8dcSSimon Schubert
5335796c8dcSSimon Schubert /* Truncate name at first dot. Should maybe also convert to all
5345796c8dcSSimon Schubert lower case for convenience on Windows. */
5355796c8dcSSimon Schubert read_pe_truncate_name (dll_name);
5365796c8dcSSimon Schubert
537*ef5ccd6cSJohn Marino if (debug_coff_pe_read)
538*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("DLL \"%s\" has %ld export entries,"
539*ef5ccd6cSJohn Marino " base=%ld\n"), dll_name, nexp, ordbase);
540*ef5ccd6cSJohn Marino nbforward = 0;
541*ef5ccd6cSJohn Marino nbnormal = 0;
5425796c8dcSSimon Schubert /* Iterate through the list of symbols. */
5435796c8dcSSimon Schubert for (i = 0; i < nexp; i++)
5445796c8dcSSimon Schubert {
5455796c8dcSSimon Schubert /* Pointer to the names vector. */
5465796c8dcSSimon Schubert unsigned long name_rva = pe_as32 (erva + name_rvas + i * 4);
547*ef5ccd6cSJohn Marino /* Retrieve ordinal value. */
548*ef5ccd6cSJohn Marino
549*ef5ccd6cSJohn Marino unsigned long ordinal = pe_as16 (erva + ordinals + i * 2);
550*ef5ccd6cSJohn Marino
5515796c8dcSSimon Schubert
5525796c8dcSSimon Schubert /* Pointer to the function address vector. */
553*ef5ccd6cSJohn Marino /* This is relatived to ordinal value. */
554*ef5ccd6cSJohn Marino unsigned long func_rva = pe_as32 (erva + exp_funcbase +
555*ef5ccd6cSJohn Marino ordinal * 4);
5565796c8dcSSimon Schubert
5575796c8dcSSimon Schubert /* Find this symbol's section in our own array. */
5585796c8dcSSimon Schubert int sectix = 0;
559*ef5ccd6cSJohn Marino int section_found = 0;
5605796c8dcSSimon Schubert
561*ef5ccd6cSJohn Marino /* First handle forward cases. */
562*ef5ccd6cSJohn Marino if (func_rva >= export_rva && func_rva < export_rva + export_size)
563*ef5ccd6cSJohn Marino {
564*ef5ccd6cSJohn Marino char *forward_name = (char *) (erva + func_rva);
565*ef5ccd6cSJohn Marino char *funcname = (char *) (erva + name_rva);
566*ef5ccd6cSJohn Marino char *forward_dll_name = forward_name;
567*ef5ccd6cSJohn Marino char *forward_func_name = forward_name;
568*ef5ccd6cSJohn Marino char *sep = strrchr (forward_name, '.');
569*ef5ccd6cSJohn Marino
570*ef5ccd6cSJohn Marino if (sep)
571*ef5ccd6cSJohn Marino {
572*ef5ccd6cSJohn Marino int len = (int) (sep - forward_name);
573*ef5ccd6cSJohn Marino
574*ef5ccd6cSJohn Marino forward_dll_name = alloca (len + 1);
575*ef5ccd6cSJohn Marino strncpy (forward_dll_name, forward_name, len);
576*ef5ccd6cSJohn Marino forward_dll_name[len] = '\0';
577*ef5ccd6cSJohn Marino forward_func_name = ++sep;
578*ef5ccd6cSJohn Marino }
579*ef5ccd6cSJohn Marino if (add_pe_forwarded_sym (funcname, forward_dll_name,
580*ef5ccd6cSJohn Marino forward_func_name, ordinal,
581*ef5ccd6cSJohn Marino dll_name, objfile) != 0)
582*ef5ccd6cSJohn Marino ++nbforward;
583*ef5ccd6cSJohn Marino continue;
584*ef5ccd6cSJohn Marino }
585*ef5ccd6cSJohn Marino
586*ef5ccd6cSJohn Marino for (sectix = 0; sectix < otherix; ++sectix)
5875796c8dcSSimon Schubert {
5885796c8dcSSimon Schubert if ((func_rva >= section_data[sectix].rva_start)
5895796c8dcSSimon Schubert && (func_rva < section_data[sectix].rva_end))
5905796c8dcSSimon Schubert {
591*ef5ccd6cSJohn Marino section_found = 1;
5925796c8dcSSimon Schubert add_pe_exported_sym (erva + name_rva,
593*ef5ccd6cSJohn Marino func_rva, ordinal,
5945796c8dcSSimon Schubert section_data + sectix, dll_name, objfile);
595*ef5ccd6cSJohn Marino ++nbnormal;
5965796c8dcSSimon Schubert break;
5975796c8dcSSimon Schubert }
5985796c8dcSSimon Schubert }
599*ef5ccd6cSJohn Marino if (!section_found)
600*ef5ccd6cSJohn Marino {
601*ef5ccd6cSJohn Marino char *funcname = (char *) (erva + name_rva);
602*ef5ccd6cSJohn Marino
603*ef5ccd6cSJohn Marino if (name_rva == 0)
604*ef5ccd6cSJohn Marino {
605*ef5ccd6cSJohn Marino add_pe_exported_sym (NULL, func_rva, ordinal,
606*ef5ccd6cSJohn Marino section_data, dll_name, objfile);
607*ef5ccd6cSJohn Marino ++nbnormal;
608*ef5ccd6cSJohn Marino }
609*ef5ccd6cSJohn Marino else if (debug_coff_pe_read)
610*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Export name \"%s\" ord. %lu,"
611*ef5ccd6cSJohn Marino " RVA 0x%lx in dll \"%s\" not handled\n"),
612*ef5ccd6cSJohn Marino funcname, ordinal, func_rva, dll_name);
613*ef5ccd6cSJohn Marino }
6145796c8dcSSimon Schubert }
6155796c8dcSSimon Schubert
616*ef5ccd6cSJohn Marino if (debug_coff_pe_read)
617*ef5ccd6cSJohn Marino fprintf_unfiltered (gdb_stdlog, _("Finished reading \"%s\", exports %ld,"
618*ef5ccd6cSJohn Marino " forwards %ld, total %ld/%ld.\n"), dll_name, nbnormal,
619*ef5ccd6cSJohn Marino nbforward, nbnormal + nbforward, nexp);
620*ef5ccd6cSJohn Marino /* Discard expdata and section_data. */
6215796c8dcSSimon Schubert do_cleanups (back_to);
6225796c8dcSSimon Schubert }
623*ef5ccd6cSJohn Marino
624*ef5ccd6cSJohn Marino /* Extract from ABFD the offset of the .text section.
625*ef5ccd6cSJohn Marino This offset is mainly related to the offset within the file.
626*ef5ccd6cSJohn Marino The value was previously expected to be 0x1000 for all files,
627*ef5ccd6cSJohn Marino but some Windows OS core DLLs seem to use 0x10000 section alignement
628*ef5ccd6cSJohn Marino which modified the return value of that function.
629*ef5ccd6cSJohn Marino Still return default 0x1000 value if ABFD is NULL or
630*ef5ccd6cSJohn Marino if '.text' section is not found, but that should not happen... */
631*ef5ccd6cSJohn Marino
632*ef5ccd6cSJohn Marino #define DEFAULT_COFF_PE_TEXT_SECTION_OFFSET 0x1000
633*ef5ccd6cSJohn Marino
634*ef5ccd6cSJohn Marino CORE_ADDR
pe_text_section_offset(struct bfd * abfd)635*ef5ccd6cSJohn Marino pe_text_section_offset (struct bfd *abfd)
636*ef5ccd6cSJohn Marino
637*ef5ccd6cSJohn Marino {
638*ef5ccd6cSJohn Marino unsigned long pe_header_offset, opthdr_ofs, num_entries, i;
639*ef5ccd6cSJohn Marino unsigned long export_rva, export_size, nsections, secptr, expptr;
640*ef5ccd6cSJohn Marino unsigned long exp_funcbase;
641*ef5ccd6cSJohn Marino unsigned char *expdata, *erva;
642*ef5ccd6cSJohn Marino unsigned long name_rvas, ordinals, nexp, ordbase;
643*ef5ccd6cSJohn Marino char *dll_name;
644*ef5ccd6cSJohn Marino int is_pe64 = 0;
645*ef5ccd6cSJohn Marino int is_pe32 = 0;
646*ef5ccd6cSJohn Marino char const *target;
647*ef5ccd6cSJohn Marino
648*ef5ccd6cSJohn Marino if (!abfd)
649*ef5ccd6cSJohn Marino return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
650*ef5ccd6cSJohn Marino
651*ef5ccd6cSJohn Marino target = bfd_get_target (abfd);
652*ef5ccd6cSJohn Marino
653*ef5ccd6cSJohn Marino is_pe64 = (strcmp (target, "pe-x86-64") == 0
654*ef5ccd6cSJohn Marino || strcmp (target, "pei-x86-64") == 0);
655*ef5ccd6cSJohn Marino is_pe32 = (strcmp (target, "pe-i386") == 0
656*ef5ccd6cSJohn Marino || strcmp (target, "pei-i386") == 0
657*ef5ccd6cSJohn Marino || strcmp (target, "pe-arm-wince-little") == 0
658*ef5ccd6cSJohn Marino || strcmp (target, "pei-arm-wince-little") == 0);
659*ef5ccd6cSJohn Marino
660*ef5ccd6cSJohn Marino if (!is_pe32 && !is_pe64)
661*ef5ccd6cSJohn Marino {
662*ef5ccd6cSJohn Marino /* This is not a recognized PE format file. Abort now, because
663*ef5ccd6cSJohn Marino the code is untested on anything else. *FIXME* test on
664*ef5ccd6cSJohn Marino further architectures and loosen or remove this test. */
665*ef5ccd6cSJohn Marino return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
666*ef5ccd6cSJohn Marino }
667*ef5ccd6cSJohn Marino
668*ef5ccd6cSJohn Marino /* Get pe_header, optional header and numbers of sections. */
669*ef5ccd6cSJohn Marino pe_header_offset = pe_get32 (abfd, 0x3c);
670*ef5ccd6cSJohn Marino opthdr_ofs = pe_header_offset + 4 + 20;
671*ef5ccd6cSJohn Marino nsections = pe_get16 (abfd, pe_header_offset + 4 + 2);
672*ef5ccd6cSJohn Marino secptr = (pe_header_offset + 4 + 20 +
673*ef5ccd6cSJohn Marino pe_get16 (abfd, pe_header_offset + 4 + 16));
674*ef5ccd6cSJohn Marino
675*ef5ccd6cSJohn Marino /* Get the rva and size of the export section. */
676*ef5ccd6cSJohn Marino for (i = 0; i < nsections; i++)
677*ef5ccd6cSJohn Marino {
678*ef5ccd6cSJohn Marino char sname[SCNNMLEN + 1];
679*ef5ccd6cSJohn Marino unsigned long secptr1 = secptr + 40 * i;
680*ef5ccd6cSJohn Marino unsigned long vaddr = pe_get32 (abfd, secptr1 + 12);
681*ef5ccd6cSJohn Marino
682*ef5ccd6cSJohn Marino bfd_seek (abfd, (file_ptr) secptr1, SEEK_SET);
683*ef5ccd6cSJohn Marino bfd_bread (sname, (bfd_size_type) SCNNMLEN, abfd);
684*ef5ccd6cSJohn Marino sname[SCNNMLEN] = '\0';
685*ef5ccd6cSJohn Marino if (strcmp (sname, ".text") == 0)
686*ef5ccd6cSJohn Marino return vaddr;
687*ef5ccd6cSJohn Marino }
688*ef5ccd6cSJohn Marino
689*ef5ccd6cSJohn Marino return DEFAULT_COFF_PE_TEXT_SECTION_OFFSET;
690*ef5ccd6cSJohn Marino }
691*ef5ccd6cSJohn Marino
692*ef5ccd6cSJohn Marino /* Implements "show debug coff_pe_read" command. */
693*ef5ccd6cSJohn Marino
694*ef5ccd6cSJohn Marino static void
show_debug_coff_pe_read(struct ui_file * file,int from_tty,struct cmd_list_element * c,const char * value)695*ef5ccd6cSJohn Marino show_debug_coff_pe_read (struct ui_file *file, int from_tty,
696*ef5ccd6cSJohn Marino struct cmd_list_element *c, const char *value)
697*ef5ccd6cSJohn Marino {
698*ef5ccd6cSJohn Marino fprintf_filtered (file, _("Coff PE read debugging is %s.\n"), value);
699*ef5ccd6cSJohn Marino }
700*ef5ccd6cSJohn Marino
701*ef5ccd6cSJohn Marino /* Provide a prototype to silence -Wmissing-prototypes. */
702*ef5ccd6cSJohn Marino
703*ef5ccd6cSJohn Marino void _initialize_coff_pe_read (void);
704*ef5ccd6cSJohn Marino
705*ef5ccd6cSJohn Marino /* Adds "Set/show debug coff_pe_read" commands. */
706*ef5ccd6cSJohn Marino
707*ef5ccd6cSJohn Marino void
_initialize_coff_pe_read(void)708*ef5ccd6cSJohn Marino _initialize_coff_pe_read (void)
709*ef5ccd6cSJohn Marino {
710*ef5ccd6cSJohn Marino add_setshow_zuinteger_cmd ("coff-pe-read", class_maintenance,
711*ef5ccd6cSJohn Marino &debug_coff_pe_read,
712*ef5ccd6cSJohn Marino _("Set coff PE read debugging."),
713*ef5ccd6cSJohn Marino _("Show coff PE read debugging."),
714*ef5ccd6cSJohn Marino _("When set, debugging messages for coff reading "
715*ef5ccd6cSJohn Marino "of exported symbols are displayed."),
716*ef5ccd6cSJohn Marino NULL, show_debug_coff_pe_read,
717*ef5ccd6cSJohn Marino &setdebuglist, &showdebuglist);
718*ef5ccd6cSJohn Marino }
719