* pe-arm-wince.c (pe_print_compressed_pdata): Define new function to
[platform/upstream/binutils.git] / bfd / pe-arm-wince.c
1 /* BFD back-end for ARM WINCE PE files.
2    Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
3
4    This file is part of BFD, the Binary File Descriptor library.
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
20
21 #define TARGET_UNDERSCORE    0
22 #define USER_LABEL_PREFIX    ""
23
24 #define TARGET_LITTLE_SYM    arm_wince_pe_little_vec
25 #define TARGET_LITTLE_NAME   "pe-arm-wince-little"
26 #define TARGET_BIG_SYM       arm_wince_pe_big_vec
27 #define TARGET_BIG_NAME      "pe-arm-wince-big"
28
29 #define bfd_arm_allocate_interworking_sections \
30   bfd_arm_wince_pe_allocate_interworking_sections
31 #define bfd_arm_get_bfd_for_interworking \
32   bfd_arm_wince_pe_get_bfd_for_interworking
33 #define bfd_arm_process_before_allocation \
34   bfd_arm_wince_pe_process_before_allocation
35
36 #define LOCAL_LABEL_PREFIX "."
37
38 #include "sysdep.h"
39 #include "bfd.h"
40
41 #undef  bfd_pe_print_pdata
42 #define bfd_pe_print_pdata   pe_print_ce_compressed_pdata
43 extern bfd_boolean pe_print_ce_compressed_pdata (bfd *, void *);
44
45 #include "pe-arm.c"
46
47 typedef struct sym_cache
48 {
49   int symcount;
50   asymbol **syms;
51 } sym_cache;
52
53 static asymbol **
54 slurp_symtab (bfd *abfd, sym_cache *psc)
55 {
56   asymbol **sy = NULL;
57   long storage;
58
59   if (!(bfd_get_file_flags (abfd) & HAS_SYMS))
60     {
61       psc->symcount = 0;
62       return NULL;
63     }
64
65   storage = bfd_get_symtab_upper_bound (abfd);
66   if (storage < 0)
67     return NULL;
68   if (storage)
69     sy = bfd_malloc (storage);
70
71   psc->symcount = bfd_canonicalize_symtab (abfd, sy);
72   if (psc->symcount < 0)
73     return NULL;
74   return sy;
75 }
76
77 static const char *
78 my_symbol_for_address (bfd *abfd, bfd_vma func, sym_cache *psc)
79 {
80   int i;
81
82   if (psc->syms == 0)
83     psc->syms = slurp_symtab (abfd, psc);
84
85   for (i = 0; i < psc->symcount; i++)
86     {
87       if (psc->syms[i]->section->vma + psc->syms[i]->value == func)
88         return psc->syms[i]->name;
89     }
90
91   return NULL;
92 }
93
94 static void
95 cleanup_syms (sym_cache *psc)
96 {
97   psc->symcount = 0;
98   free (psc->syms);
99   psc->syms = NULL;
100 }
101
102 /* This is the version for "compressed" pdata.  */
103
104 bfd_boolean
105 pe_print_ce_compressed_pdata (bfd * abfd, void * vfile)
106 {
107 # define PDATA_ROW_SIZE (2 * 4)
108   FILE *file = (FILE *) vfile;
109   bfd_byte *data = 0;
110   asection *section = bfd_get_section_by_name (abfd, ".pdata");
111   bfd_size_type datasize = 0;
112   bfd_size_type i;
113   bfd_size_type start, stop;
114   int onaline = PDATA_ROW_SIZE;
115   struct sym_cache sym_cache = {0, 0} ;
116
117   if (section == NULL
118       || coff_section_data (abfd, section) == NULL
119       || pei_section_data (abfd, section) == NULL)
120     return TRUE;
121
122   stop = pei_section_data (abfd, section)->virt_size;
123   if ((stop % onaline) != 0)
124     fprintf (file,
125              _("Warning, .pdata section size (%ld) is not a multiple of %d\n"),
126              (long) stop, onaline);
127
128   fprintf (file,
129            _("\nThe Function Table (interpreted .pdata section contents)\n"));
130
131   fprintf (file, _("\
132  vma:\t\tBegin    Prolog   Function Flags    Exception EH\n\
133      \t\tAddress  Length   Length   32b exc  Handler   Data\n"));
134
135   datasize = section->size;
136   if (datasize == 0)
137     return TRUE;
138
139   if (! bfd_malloc_and_get_section (abfd, section, &data))
140     {
141       if (data != NULL)
142         free (data);
143       return FALSE;
144     }
145
146   start = 0;
147
148   for (i = start; i < stop; i += onaline)
149     {
150       bfd_vma begin_addr;
151       bfd_vma other_data;
152       bfd_vma prolog_length, function_length;
153       int flag32bit, exception_flag;
154       bfd_byte *tdata = 0;
155       asection *tsection;
156
157       if (i + PDATA_ROW_SIZE > stop)
158         break;
159
160       begin_addr = GET_PDATA_ENTRY (abfd, data + i     );
161       other_data = GET_PDATA_ENTRY (abfd, data + i +  4);
162
163       if (begin_addr == 0 && other_data == 0)
164         /* We are probably into the padding of the section now.  */
165         break;
166
167       prolog_length = (other_data & 0x000000FF);
168       function_length = (other_data & 0x3FFFFF00) >> 8;
169       flag32bit = (int)((other_data & 0x40000000) >> 30);
170       exception_flag = (int)((other_data & 0x80000000) >> 31);
171
172       fputc (' ', file);
173       fprintf_vma (file, i + section->vma); fputc ('\t', file);
174       fprintf_vma (file, begin_addr); fputc (' ', file);
175       fprintf_vma (file, prolog_length); fputc (' ', file);
176       fprintf_vma (file, function_length); fputc (' ', file);
177       fprintf (file, "%2d  %2d   ", flag32bit, exception_flag);
178
179       /* Get the exception handler's address and the data passed from the
180          .text section. This is really the data that belongs with the .pdata
181          but got "compressed" out for the ARM and SH4 architectures.  */
182       tsection = bfd_get_section_by_name (abfd, ".text");
183       if (tsection && coff_section_data (abfd, tsection)
184           && pei_section_data (abfd, tsection))
185         {
186           if (bfd_malloc_and_get_section (abfd, tsection, & tdata))
187             {
188               int xx = (begin_addr - 8) - tsection->vma;
189
190               tdata = bfd_malloc (8);
191               if (bfd_get_section_contents (abfd, tsection, tdata, (bfd_vma) xx, 8))
192                 {
193                   bfd_vma eh, eh_data;
194
195                   eh = bfd_get_32 (abfd, tdata);
196                   eh_data = bfd_get_32 (abfd, tdata + 4);
197                   fprintf (file, "%08x  ", (unsigned int) eh);
198                   fprintf (file, "%08x", (unsigned int) eh_data);
199                   if (eh != 0)
200                     {
201                       const char *s = my_symbol_for_address (abfd, eh, &sym_cache);
202
203                       if (s)
204                         fprintf (file, " (%s) ", s);
205                     }
206                 }
207               free (tdata);
208             }
209           else
210             {
211               if (tdata)
212                 free (tdata);
213             }
214         }
215
216       fprintf (file, "\n");
217     }
218
219   free (data);
220
221   cleanup_syms (& sym_cache);
222
223   return TRUE;
224 #undef PDATA_ROW_SIZE
225 }