]>
Commit | Line | Data |
---|---|---|
99ad8390 | 1 | /* BFD back-end for Intel 386 PE IMAGE COFF files. |
88183869 | 2 | Copyright 2006, 2007, 2009 Free Software Foundation, Inc. |
99ad8390 NC |
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 | |
cd123cb7 | 8 | the Free Software Foundation; either version 3 of the License, or |
99ad8390 NC |
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 | |
cd123cb7 NC |
18 | Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, |
19 | MA 02110-1301, USA. | |
99ad8390 NC |
20 | |
21 | Written by Kai Tietz, OneVision Software GmbH&CoKg. */ | |
22 | ||
99ad8390 | 23 | #include "sysdep.h" |
3db64b00 | 24 | #include "bfd.h" |
99ad8390 NC |
25 | |
26 | #define TARGET_SYM x86_64pei_vec | |
27 | #define TARGET_NAME "pei-x86-64" | |
28 | #define COFF_IMAGE_WITH_PE | |
29 | #define COFF_WITH_PE | |
30 | #define COFF_WITH_pex64 | |
31 | #define PCRELOFFSET TRUE | |
32 | #define TARGET_UNDERSCORE '_' | |
88183869 DK |
33 | /* Long section names not allowed in executable images, only object files. */ |
34 | #define COFF_LONG_SECTION_NAMES 0 | |
99ad8390 NC |
35 | #define COFF_SUPPORT_GNU_LINKONCE |
36 | #define COFF_LONG_FILENAMES | |
e48570bb | 37 | #define PDATA_ROW_SIZE (3 * 4) |
99ad8390 NC |
38 | |
39 | #define COFF_SECTION_ALIGNMENT_ENTRIES \ | |
40 | { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \ | |
41 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ | |
42 | { COFF_SECTION_NAME_EXACT_MATCH (".data"), \ | |
43 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ | |
44 | { COFF_SECTION_NAME_EXACT_MATCH (".rdata"), \ | |
45 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ | |
46 | { COFF_SECTION_NAME_EXACT_MATCH (".text"), \ | |
47 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \ | |
48 | { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \ | |
49 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ | |
50 | { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \ | |
51 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \ | |
52 | { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \ | |
53 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \ | |
54 | { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \ | |
55 | COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 } | |
56 | ||
e48570bb DK |
57 | /* Note we have to make sure not to include headers twice. |
58 | Not all headers are wrapped in #ifdef guards, so we define | |
59 | PEI_HEADERS to prevent double including in coff-x86_64.c */ | |
60 | #define PEI_HEADERS | |
61 | #include "sysdep.h" | |
62 | #include "bfd.h" | |
63 | #include "libbfd.h" | |
64 | #include "coff/x86_64.h" | |
65 | #include "coff/internal.h" | |
66 | #include "coff/pe.h" | |
67 | #include "libcoff.h" | |
68 | #include "libpei.h" | |
69 | #include "libiberty.h" | |
70 | ||
71 | #undef AOUTSZ | |
72 | #define AOUTSZ PEPAOUTSZ | |
73 | #define PEAOUTHDR PEPAOUTHDR | |
74 | ||
75 | static const char *pex_regs[16] = { | |
76 | "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", | |
77 | "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" | |
78 | }; | |
79 | ||
80 | static void | |
81 | pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf, | |
82 | const void *data) | |
83 | { | |
84 | const struct external_pex64_runtime_function *ex_rf = | |
85 | (const struct external_pex64_runtime_function *) data; | |
86 | rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress); | |
87 | rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress); | |
88 | rf->rva_UnwindData = bfd_get_32 (abfd, ex_rf->rva_UnwindData); | |
89 | rf->isChained = PEX64_IS_RUNTIME_FUNCTION_CHAINED (rf); | |
90 | rf->rva_UnwindData = PEX64_GET_UNWINDDATA_UNIFIED_RVA (rf); | |
91 | } | |
92 | ||
93 | static void | |
94 | pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data) | |
95 | { | |
96 | struct external_pex64_unwind_info *ex_ui = | |
97 | (struct external_pex64_unwind_info *) data; | |
98 | bfd_byte *ex_dta = (bfd_byte *) data; | |
99 | ||
100 | memset (ui, 0, sizeof (struct pex64_unwind_info)); | |
101 | ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags); | |
102 | ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags); | |
103 | ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue; | |
104 | ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes; | |
105 | ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset); | |
106 | ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset); | |
107 | ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes); | |
108 | ui->SizeOfBlock = ui->sizeofUnwindCodes + 4; | |
109 | ui->rawUnwindCodes = &ex_dta[4]; | |
110 | ex_dta += ui->SizeOfBlock; | |
111 | switch (ui->Flags) | |
112 | { | |
113 | case UNW_FLAG_EHANDLER: | |
114 | ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta); | |
115 | break; | |
116 | case UNW_FLAG_UHANDLER: | |
117 | ui->rva_TerminationHandler = bfd_get_32 (abfd, ex_dta); | |
118 | break; | |
119 | case UNW_FLAG_FHANDLER: | |
120 | ui->rva_FrameHandler = bfd_get_32 (abfd, ex_dta); | |
121 | ui->FrameHandlerArgument = bfd_get_32 (abfd, ex_dta + 4); | |
122 | ui->SizeOfBlock += 8; | |
123 | return; | |
124 | case UNW_FLAG_CHAININFO: | |
125 | ui->rva_FunctionEntry = bfd_get_32 (abfd, ex_dta); | |
126 | ui->SizeOfBlock += 4; | |
127 | return; | |
128 | default: | |
129 | return; | |
130 | } | |
131 | ex_dta += 4; | |
132 | ui->SizeOfBlock += 8; | |
133 | ui->CountOfScopes = bfd_get_32 (abfd, ex_dta); | |
134 | ex_dta += 4; | |
135 | ui->rawScopeEntries = ex_dta; | |
136 | ui->SizeOfBlock += (ui->CountOfScopes * PEX64_SCOPE_ENTRY_SIZE); | |
137 | } | |
138 | ||
139 | static void | |
140 | pex64_get_scope_entry (bfd *abfd, struct pex64_scope_entry *se, | |
141 | bfd_vma idx, const bfd_byte *x) | |
142 | { | |
143 | const struct external_pex64_scope_entry *ex_se; | |
144 | x += (idx * PEX64_SCOPE_ENTRY_SIZE); | |
145 | ex_se = (const struct external_pex64_scope_entry *) x; | |
146 | memset (se, 0, sizeof (struct pex64_scope_entry)); | |
147 | se->rva_BeginAddress = bfd_get_32 (abfd, ex_se->rva_BeginAddress); | |
148 | se->rva_EndAddress = bfd_get_32 (abfd, ex_se->rva_EndAddress); | |
149 | se->rva_HandlerAddress = bfd_get_32 (abfd, ex_se->rva_HandlerAddress); | |
150 | se->rva_JumpAddress = bfd_get_32 (abfd, ex_se->rva_JumpAddress); | |
151 | } | |
152 | ||
153 | static void | |
154 | pex64_xdata_print_uwd_codes (FILE *file, struct pex64_unwind_info *ui, | |
155 | bfd_vma pc_addr) | |
156 | { | |
157 | bfd_vma i; | |
158 | bfd_vma tmp = 0; | |
159 | const bfd_byte *insns[256]; | |
160 | bfd_vma insns_count = 0; | |
161 | const bfd_byte *dta = ui->rawUnwindCodes; | |
162 | ||
163 | if (ui->CountOfCodes == 0 || !dta) | |
164 | return; | |
165 | ||
166 | /* Sort array ascending. Note: it is stored in reversed order. */ | |
167 | for (i = 0; i < ui->CountOfCodes; i++) | |
168 | { | |
169 | const bfd_byte *t; | |
170 | ||
171 | t = insns[insns_count++] = &dta[i * 2]; | |
172 | switch (PEX64_UNWCODE_CODE (t[1])) | |
173 | { | |
174 | case UWOP_PUSH_NONVOL: | |
175 | case UWOP_ALLOC_SMALL: | |
176 | case UWOP_SET_FPREG: | |
177 | case UWOP_PUSH_MACHFRAME: | |
178 | break; | |
179 | case UWOP_ALLOC_LARGE: | |
180 | if (PEX64_UNWCODE_INFO (t[1]) == 0) | |
181 | { | |
182 | i += 1; | |
183 | break; | |
184 | } | |
185 | else if (PEX64_UNWCODE_INFO (t[1]) == 1) | |
186 | { | |
187 | i += 2; | |
188 | break; | |
189 | } | |
190 | /* fall through. */ | |
191 | default: | |
192 | fprintf (file, "\t contains unknown code (%u).\n", | |
193 | (unsigned int) PEX64_UNWCODE_CODE (t[1])); | |
194 | return; | |
195 | case UWOP_SAVE_NONVOL: | |
196 | case UWOP_SAVE_XMM: | |
197 | case UWOP_SAVE_XMM128: | |
198 | i++; | |
199 | break; | |
200 | case UWOP_SAVE_NONVOL_FAR: | |
201 | case UWOP_SAVE_XMM_FAR: | |
202 | case UWOP_SAVE_XMM128_FAR: | |
203 | i += 2; | |
204 | break; | |
205 | } | |
206 | } | |
207 | fprintf (file, "\t At pc 0x"); | |
208 | fprintf_vma (file, pc_addr); | |
209 | fprintf (file, " there are the following saves (in logical order).\n"); | |
210 | for (i = insns_count; i > 0;) | |
211 | { | |
212 | --i; | |
213 | dta = insns[i]; | |
214 | fprintf (file, "\t insn ends at pc+0x%02x: ", (unsigned int) dta[0]); | |
215 | switch (PEX64_UNWCODE_CODE (dta[1])) | |
216 | { | |
217 | case UWOP_PUSH_NONVOL: | |
218 | fprintf (file, "push %s.\n", pex_regs[PEX64_UNWCODE_INFO (dta[1])]); | |
219 | break; | |
220 | case UWOP_ALLOC_LARGE: | |
221 | if (PEX64_UNWCODE_INFO (dta[1]) == 0) | |
222 | { | |
223 | tmp = (bfd_vma) (*((unsigned short *) &dta[2])); | |
224 | tmp *= 8; | |
225 | } | |
226 | else | |
227 | tmp = (bfd_vma) (*((unsigned int *)&dta[2])); | |
228 | fprintf (file, "save stack region of size 0x"); | |
229 | fprintf_vma (file, tmp); | |
230 | fprintf (file,".\n"); | |
231 | break; | |
232 | case UWOP_ALLOC_SMALL: | |
233 | tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]); | |
234 | tmp += 1; | |
235 | tmp *= 8; | |
236 | fprintf (file, "save stack region of size 0x"); | |
237 | fprintf_vma (file, tmp); | |
238 | fprintf (file,".\n"); | |
239 | break; | |
240 | case UWOP_SET_FPREG: | |
241 | tmp = (bfd_vma) PEX64_UNWCODE_INFO (dta[1]); | |
242 | tmp *= 16; | |
243 | fprintf (file, "FPReg = (FrameReg) + 0x"); | |
244 | fprintf_vma (file, tmp); | |
245 | fprintf (file, ".\n"); | |
246 | break; | |
247 | case UWOP_SAVE_NONVOL: | |
248 | fprintf (file, "mov %s at 0x", | |
249 | pex_regs[PEX64_UNWCODE_INFO (dta[1])]); | |
250 | tmp = (bfd_vma) (*((unsigned short *) &dta[2])); | |
251 | tmp *= 8; | |
252 | fprintf_vma (file, tmp); | |
253 | fprintf (file, ".\n"); | |
254 | break; | |
255 | case UWOP_SAVE_NONVOL_FAR: | |
256 | fprintf (file, "mov %s at 0x", | |
257 | pex_regs[PEX64_UNWCODE_INFO (dta[1])]); | |
258 | tmp = (bfd_vma) (*((unsigned int *) &dta[2])); | |
259 | fprintf_vma (file, tmp); | |
260 | fprintf (file, ".\n"); | |
261 | break; | |
262 | case UWOP_SAVE_XMM: | |
263 | tmp = (bfd_vma) (*((unsigned short *) &dta[2])); | |
264 | tmp *= 8; | |
265 | fprintf (file, "mov mm%u at 0x", | |
266 | (unsigned int) PEX64_UNWCODE_INFO (dta[1])); | |
267 | fprintf_vma (file, tmp); | |
268 | fprintf (file, ".\n"); | |
269 | break; | |
270 | case UWOP_SAVE_XMM_FAR: | |
271 | tmp = (bfd_vma) (*((unsigned int *) &dta[2])); | |
272 | fprintf (file, "mov mm%u at 0x", | |
273 | (unsigned int) PEX64_UNWCODE_INFO (dta[1])); | |
274 | fprintf_vma (file, tmp); | |
275 | fprintf (file, ".\n"); | |
276 | break; | |
277 | case UWOP_SAVE_XMM128: | |
278 | tmp = (bfd_vma) (*((unsigned short *) &dta[2])); | |
279 | tmp *= 16; | |
280 | fprintf (file, "mov xmm%u at 0x", | |
281 | (unsigned int) PEX64_UNWCODE_INFO ( dta[1])); | |
282 | fprintf_vma (file, tmp); | |
283 | fprintf (file, ".\n"); | |
284 | break; | |
285 | case UWOP_SAVE_XMM128_FAR: | |
286 | tmp = (bfd_vma) (*((unsigned int *) &dta[2])); | |
287 | fprintf (file, "mov xmm%u at 0x", | |
288 | (unsigned int) PEX64_UNWCODE_INFO (dta[1])); | |
289 | fprintf_vma (file, tmp); | |
290 | fprintf (file, ".\n"); | |
291 | break; | |
292 | case UWOP_PUSH_MACHFRAME: | |
293 | fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP"); | |
294 | if (PEX64_UNWCODE_INFO (dta[1]) == 0) | |
295 | { | |
296 | fprintf (file, ")"); | |
297 | } | |
298 | else if (PEX64_UNWCODE_INFO (dta[1]) == 1) | |
299 | { | |
300 | fprintf (file, ",ErrorCode)"); | |
301 | } | |
302 | else | |
303 | fprintf (file, ", unknown(%u))", | |
304 | (unsigned int) PEX64_UNWCODE_INFO (dta[1])); | |
305 | fprintf (file,".\n"); | |
306 | break; | |
307 | default: | |
308 | fprintf (file, "unknown code %u.\n", | |
309 | (unsigned int) PEX64_UNWCODE_INFO (dta[1])); | |
310 | break; | |
311 | } | |
312 | } | |
313 | } | |
314 | ||
315 | static asection * | |
316 | pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name) | |
317 | { | |
318 | asection *section = bfd_get_section_by_name (abfd, sec_name); | |
319 | bfd_vma vsize; | |
320 | bfd_size_type datasize = 0; | |
321 | ||
322 | if (section == NULL | |
323 | || coff_section_data (abfd, section) == NULL | |
324 | || pei_section_data (abfd, section) == NULL) | |
325 | return NULL; | |
326 | vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase; | |
327 | datasize = section->size; | |
328 | if (!datasize || vsize > addr || (vsize + datasize) < addr) | |
329 | return NULL; | |
330 | return section; | |
331 | } | |
332 | ||
333 | static void | |
334 | pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr) | |
335 | { | |
336 | asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata"); | |
337 | bfd_vma vsize; | |
338 | bfd_byte *data = NULL; | |
339 | bfd_vma i; | |
340 | ||
341 | if (!section) | |
342 | section = pex64_get_section_by_rva (abfd, addr, ".data"); | |
343 | if (!section) | |
344 | section = pex64_get_section_by_rva (abfd, addr, ".xdata"); | |
345 | if (!section) | |
346 | { | |
347 | section = pex64_get_section_by_rva (abfd, addr, ".pdata"); | |
348 | if (section) | |
349 | { | |
350 | fprintf (file, "\t Shares information with pdata element at 0x"); | |
351 | fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase); | |
352 | fprintf (file, ".\n"); | |
353 | } | |
354 | } | |
355 | if (!section) | |
356 | return; | |
357 | vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase; | |
358 | addr -= vsize; | |
359 | if (bfd_malloc_and_get_section (abfd, section, &data)) | |
360 | { | |
361 | struct pex64_unwind_info ui; | |
362 | ||
363 | if (!data) | |
364 | return; | |
365 | ||
366 | pex64_get_unwind_info (abfd, &ui, &data[addr]); | |
367 | ||
368 | if (ui.Version != 1) | |
369 | { | |
370 | fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) ui.Version); | |
371 | return; | |
372 | } | |
373 | ||
374 | fprintf (file, "\tFlags: "); | |
375 | switch (ui.Flags) | |
376 | { | |
377 | case UNW_FLAG_NHANDLER: | |
378 | fprintf (file, "UNW_FLAG_NHANDLER"); | |
379 | break; | |
380 | case UNW_FLAG_EHANDLER: | |
381 | fprintf (file, "UNW_FLAG_EHANDLER"); | |
382 | break; | |
383 | case UNW_FLAG_UHANDLER: | |
384 | fprintf (file, "UNW_FLAG_UHANDLER"); | |
385 | break; | |
386 | case UNW_FLAG_FHANDLER: | |
387 | fprintf (file, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)"); | |
388 | break; | |
389 | case UNW_FLAG_CHAININFO: | |
390 | fprintf (file, "UNW_FLAG_CHAININFO"); | |
391 | break; | |
392 | default: | |
393 | fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags); | |
394 | break; | |
395 | } | |
396 | fprintf (file, ".\n"); | |
397 | if (ui.CountOfCodes != 0) | |
398 | fprintf (file, "\tEntry has %u codes.", (unsigned int) ui.CountOfCodes); | |
399 | fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n", | |
400 | (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset); | |
401 | fprintf (file, "\tFrame register is %s.\n", | |
402 | ui.FrameRegister == 0 ? "CFA" | |
403 | : pex_regs[(unsigned int) ui.FrameRegister]); | |
404 | ||
405 | pex64_xdata_print_uwd_codes (file, &ui, pc_addr); | |
406 | ||
407 | switch (ui.Flags) | |
408 | { | |
409 | case UNW_FLAG_NHANDLER: | |
410 | return; | |
411 | case UNW_FLAG_EHANDLER: | |
412 | fprintf (file, "\texception_handler at 0x%x.\n", (unsigned int) ui.rva_ExceptionHandler); | |
413 | break; | |
414 | case UNW_FLAG_UHANDLER: | |
415 | fprintf (file, "\ttermination_handler at 0x%x.\n", (unsigned int) ui.rva_TerminationHandler); | |
416 | case UNW_FLAG_FHANDLER: | |
417 | fprintf (file, "\tframe_handler at 0x%x.\n", (unsigned int) ui.rva_FrameHandler); | |
418 | fprintf (file, "\t Argument for FrameHandler: 0x%x.\n", | |
419 | (unsigned int) ui.FrameHandlerArgument); | |
420 | return; | |
421 | case UNW_FLAG_CHAININFO: | |
422 | fprintf (file, "\t Function Entry: 0x%x\n", (unsigned int) ui.rva_FunctionEntry); | |
423 | return; | |
424 | default: | |
425 | fprintf (file, "\t Unknown flag value of 0x%x\n", (unsigned int) ui.Flags); | |
426 | return; | |
427 | } | |
428 | fprintf (file, "\t 0x%x # of scope(s)\n", (unsigned int) ui.CountOfScopes); | |
429 | for (i = 0; i < ui.CountOfScopes; i++) | |
430 | { | |
431 | struct pex64_scope_entry se; | |
432 | pex64_get_scope_entry (abfd, &se, i, ui.rawScopeEntries); | |
433 | fprintf (file, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x," | |
434 | "\n\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n", | |
435 | (unsigned int) (i + 1), | |
436 | (unsigned int) se.rva_BeginAddress, | |
437 | (unsigned int) se.rva_EndAddress, | |
438 | (unsigned int) se.rva_HandlerAddress, | |
439 | (unsigned int) se.rva_JumpAddress); | |
440 | } | |
441 | } | |
442 | if (data != NULL) | |
443 | free (data); | |
444 | } | |
445 | ||
446 | static bfd_boolean | |
447 | pex64_bfd_print_pdata (bfd *abfd, void *vfile) | |
448 | { | |
449 | FILE *file = (FILE *) vfile; | |
450 | bfd_byte *data = NULL; | |
451 | asection *section = bfd_get_section_by_name (abfd, ".pdata"); | |
452 | bfd_size_type datasize = 0; | |
453 | bfd_size_type i; | |
454 | bfd_size_type start, stop; | |
455 | int onaline = PDATA_ROW_SIZE; | |
456 | ||
457 | if (section == NULL | |
458 | || coff_section_data (abfd, section) == NULL | |
459 | || pei_section_data (abfd, section) == NULL) | |
460 | return TRUE; | |
461 | ||
462 | stop = pei_section_data (abfd, section)->virt_size; | |
463 | if ((stop % onaline) != 0) | |
464 | fprintf (file, | |
465 | _("warning: .pdata section size (%ld) is not a multiple of %d\n"), | |
466 | (long) stop, onaline); | |
467 | ||
468 | fprintf (file, | |
469 | _("\nThe Function Table (interpreted .pdata section contents)\n")); | |
470 | ||
471 | fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); | |
472 | ||
473 | datasize = section->size; | |
474 | if (datasize == 0) | |
475 | return TRUE; | |
476 | ||
477 | if (!bfd_malloc_and_get_section (abfd, section, &data)) | |
478 | { | |
479 | if (data != NULL) | |
480 | free (data); | |
481 | return FALSE; | |
482 | } | |
483 | ||
484 | start = 0; | |
485 | ||
486 | for (i = start; i < stop; i += onaline) | |
487 | { | |
488 | struct pex64_runtime_function rf; | |
489 | ||
490 | if (i + PDATA_ROW_SIZE > stop) | |
491 | break; | |
492 | pex64_get_runtime_function (abfd, &rf, &data[i]); | |
493 | ||
494 | if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 | |
495 | && rf.rva_UnwindData == 0) | |
496 | /* We are probably into the padding of the section now. */ | |
497 | break; | |
498 | ||
499 | fputc (' ', file); | |
500 | fprintf_vma (file, i + section->vma); | |
501 | fprintf (file, ":\t"); | |
502 | rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase; | |
503 | fprintf_vma (file, rf.rva_BeginAddress); | |
504 | fputc (' ', file); | |
505 | rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase; | |
506 | fprintf_vma (file, rf.rva_EndAddress); | |
507 | fputc (' ', file); | |
508 | fprintf_vma (file, rf.rva_UnwindData); | |
509 | fprintf (file, "\n"); | |
510 | ||
511 | if (rf.rva_UnwindData != 0) | |
512 | { | |
513 | if (rf.isChained) | |
514 | { | |
515 | fprintf (file, "\t shares information with pdata element at 0x"); | |
516 | fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase); | |
517 | fprintf (file, ".\n"); | |
518 | } | |
519 | else | |
520 | pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress); | |
521 | } | |
522 | } | |
523 | ||
524 | free (data); | |
525 | ||
526 | return TRUE; | |
527 | } | |
528 | ||
529 | #define bfd_pe_print_pdata pex64_bfd_print_pdata | |
530 | ||
99ad8390 | 531 | #include "coff-x86_64.c" |