pei-x86_64.c revision 1.8 1 1.1 christos /* BFD back-end for Intel 386 PE IMAGE COFF files.
2 1.8 christos Copyright (C) 2006-2022 Free Software Foundation, Inc.
3 1.1 christos
4 1.1 christos This file is part of BFD, the Binary File Descriptor library.
5 1.1 christos
6 1.1 christos This program is free software; you can redistribute it and/or modify
7 1.1 christos it under the terms of the GNU General Public License as published by
8 1.1 christos the Free Software Foundation; either version 3 of the License, or
9 1.1 christos (at your option) any later version.
10 1.1 christos
11 1.1 christos This program is distributed in the hope that it will be useful,
12 1.1 christos but WITHOUT ANY WARRANTY; without even the implied warranty of
13 1.1 christos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 1.1 christos GNU General Public License for more details.
15 1.1 christos
16 1.1 christos You should have received a copy of the GNU General Public License
17 1.1 christos along with this program; if not, write to the Free Software
18 1.1 christos Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19 1.1 christos MA 02110-1301, USA.
20 1.3 christos
21 1.1 christos Written by Kai Tietz, OneVision Software GmbH&CoKg. */
22 1.1 christos
23 1.1 christos #include "sysdep.h"
24 1.1 christos #include "bfd.h"
25 1.1 christos
26 1.6 christos #define TARGET_SYM x86_64_pei_vec
27 1.6 christos #define TARGET_NAME "pei-x86-64"
28 1.1 christos #define COFF_IMAGE_WITH_PE
29 1.1 christos #define COFF_WITH_PE
30 1.1 christos #define COFF_WITH_pex64
31 1.8 christos #define PCRELOFFSET true
32 1.1 christos #if defined (USE_MINGW64_LEADING_UNDERSCORES)
33 1.6 christos #define TARGET_UNDERSCORE '_'
34 1.1 christos #else
35 1.6 christos #define TARGET_UNDERSCORE 0
36 1.1 christos #endif
37 1.1 christos /* Long section names not allowed in executable images, only object files. */
38 1.1 christos #define COFF_LONG_SECTION_NAMES 0
39 1.1 christos #define COFF_SUPPORT_GNU_LINKONCE
40 1.1 christos #define COFF_LONG_FILENAMES
41 1.1 christos #define PDATA_ROW_SIZE (3 * 4)
42 1.1 christos
43 1.1 christos #define COFF_SECTION_ALIGNMENT_ENTRIES \
44 1.1 christos { COFF_SECTION_NAME_EXACT_MATCH (".bss"), \
45 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
46 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".data"), \
47 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
48 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".rdata"), \
49 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
50 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".text"), \
51 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 4 }, \
52 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".idata"), \
53 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
54 1.1 christos { COFF_SECTION_NAME_EXACT_MATCH (".pdata"), \
55 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 2 }, \
56 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".debug"), \
57 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }, \
58 1.1 christos { COFF_SECTION_NAME_PARTIAL_MATCH (".gnu.linkonce.wi."), \
59 1.1 christos COFF_ALIGNMENT_FIELD_EMPTY, COFF_ALIGNMENT_FIELD_EMPTY, 0 }
60 1.1 christos
61 1.1 christos /* Note we have to make sure not to include headers twice.
62 1.1 christos Not all headers are wrapped in #ifdef guards, so we define
63 1.1 christos PEI_HEADERS to prevent double including in coff-x86_64.c */
64 1.1 christos #define PEI_HEADERS
65 1.1 christos #include "sysdep.h"
66 1.1 christos #include "bfd.h"
67 1.1 christos #include "libbfd.h"
68 1.1 christos #include "coff/x86_64.h"
69 1.1 christos #include "coff/internal.h"
70 1.1 christos #include "coff/pe.h"
71 1.1 christos #include "libcoff.h"
72 1.1 christos #include "libpei.h"
73 1.1 christos #include "libiberty.h"
74 1.1 christos
75 1.1 christos #undef AOUTSZ
76 1.1 christos #define AOUTSZ PEPAOUTSZ
77 1.1 christos #define PEAOUTHDR PEPAOUTHDR
78 1.1 christos
79 1.3 christos /* Name of registers according to SEH conventions. */
80 1.3 christos
81 1.3 christos static const char * const pex_regs[16] = {
82 1.1 christos "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
83 1.1 christos "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15"
84 1.1 christos };
85 1.1 christos
86 1.3 christos /* Swap in a runtime function. */
87 1.3 christos
88 1.1 christos static void
89 1.1 christos pex64_get_runtime_function (bfd *abfd, struct pex64_runtime_function *rf,
90 1.1 christos const void *data)
91 1.1 christos {
92 1.1 christos const struct external_pex64_runtime_function *ex_rf =
93 1.1 christos (const struct external_pex64_runtime_function *) data;
94 1.1 christos rf->rva_BeginAddress = bfd_get_32 (abfd, ex_rf->rva_BeginAddress);
95 1.1 christos rf->rva_EndAddress = bfd_get_32 (abfd, ex_rf->rva_EndAddress);
96 1.1 christos rf->rva_UnwindData = bfd_get_32 (abfd, ex_rf->rva_UnwindData);
97 1.1 christos }
98 1.1 christos
99 1.3 christos /* Swap in unwind info header. */
100 1.3 christos
101 1.8 christos static bool
102 1.6 christos pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui,
103 1.6 christos void *data, void *data_end)
104 1.1 christos {
105 1.1 christos struct external_pex64_unwind_info *ex_ui =
106 1.1 christos (struct external_pex64_unwind_info *) data;
107 1.1 christos bfd_byte *ex_dta = (bfd_byte *) data;
108 1.6 christos bfd_byte *ex_dta_end = (bfd_byte *) data_end;
109 1.1 christos
110 1.1 christos memset (ui, 0, sizeof (struct pex64_unwind_info));
111 1.6 christos
112 1.6 christos if (ex_dta >= ex_dta_end || ex_dta + 4 >= ex_dta_end)
113 1.8 christos return false;
114 1.6 christos
115 1.1 christos ui->Version = PEX64_UWI_VERSION (ex_ui->Version_Flags);
116 1.1 christos ui->Flags = PEX64_UWI_FLAGS (ex_ui->Version_Flags);
117 1.1 christos ui->SizeOfPrologue = (bfd_vma) ex_ui->SizeOfPrologue;
118 1.1 christos ui->CountOfCodes = (bfd_vma) ex_ui->CountOfCodes;
119 1.1 christos ui->FrameRegister = PEX64_UWI_FRAMEREG (ex_ui->FrameRegisterOffset);
120 1.1 christos ui->FrameOffset = PEX64_UWI_FRAMEOFF (ex_ui->FrameRegisterOffset);
121 1.1 christos ui->sizeofUnwindCodes = PEX64_UWI_SIZEOF_UWCODE_ARRAY (ui->CountOfCodes);
122 1.1 christos ui->SizeOfBlock = ui->sizeofUnwindCodes + 4;
123 1.6 christos ui->rawUnwindCodes = ex_dta + 4;
124 1.6 christos ui->rawUnwindCodesEnd = ex_dta_end;
125 1.3 christos
126 1.1 christos ex_dta += ui->SizeOfBlock;
127 1.6 christos if (ex_dta >= ex_dta_end)
128 1.8 christos return false;
129 1.7 christos
130 1.1 christos switch (ui->Flags)
131 1.1 christos {
132 1.1 christos case UNW_FLAG_CHAININFO:
133 1.6 christos if (ex_dta + 12 >= ex_dta_end)
134 1.8 christos return false;
135 1.3 christos ui->rva_BeginAddress = bfd_get_32 (abfd, ex_dta + 0);
136 1.3 christos ui->rva_EndAddress = bfd_get_32 (abfd, ex_dta + 4);
137 1.3 christos ui->rva_UnwindData = bfd_get_32 (abfd, ex_dta + 8);
138 1.3 christos ui->SizeOfBlock += 12;
139 1.8 christos return true;
140 1.3 christos case UNW_FLAG_EHANDLER:
141 1.3 christos case UNW_FLAG_UHANDLER:
142 1.3 christos case UNW_FLAG_FHANDLER:
143 1.6 christos if (ex_dta + 4 >= ex_dta_end)
144 1.8 christos return false;
145 1.3 christos ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta);
146 1.1 christos ui->SizeOfBlock += 4;
147 1.8 christos return true;
148 1.1 christos default:
149 1.8 christos return true;
150 1.1 christos }
151 1.1 christos }
152 1.1 christos
153 1.3 christos /* Display unwind codes. */
154 1.3 christos
155 1.1 christos static void
156 1.3 christos pex64_xdata_print_uwd_codes (FILE *file, bfd *abfd,
157 1.3 christos struct pex64_unwind_info *ui,
158 1.3 christos struct pex64_runtime_function *rf)
159 1.1 christos {
160 1.3 christos unsigned int i;
161 1.3 christos unsigned int tmp; /* At least 32 bits. */
162 1.3 christos int save_allowed;
163 1.1 christos
164 1.3 christos if (ui->CountOfCodes == 0 || ui->rawUnwindCodes == NULL)
165 1.1 christos return;
166 1.1 christos
167 1.3 christos /* According to UNWIND_CODE documentation:
168 1.3 christos If an FP reg is used, the any unwind code taking an offset must only be
169 1.3 christos used after the FP reg is established in the prolog.
170 1.3 christos But there are counter examples of that in system dlls... */
171 1.8 christos save_allowed = true;
172 1.3 christos
173 1.3 christos i = 0;
174 1.3 christos
175 1.6 christos if (ui->rawUnwindCodes + 1 >= ui->rawUnwindCodesEnd)
176 1.6 christos {
177 1.6 christos fprintf (file, _("warning: corrupt unwind data\n"));
178 1.6 christos return;
179 1.6 christos }
180 1.6 christos
181 1.3 christos if (ui->Version == 2
182 1.3 christos && PEX64_UNWCODE_CODE (ui->rawUnwindCodes[1]) == UWOP_EPILOG)
183 1.1 christos {
184 1.3 christos /* Display epilog opcode (whose docoding is not fully documented).
185 1.6 christos Looks to be designed to speed-up unwinding, as there is no need
186 1.3 christos to decode instruction flow if outside an epilog. */
187 1.3 christos unsigned int func_size = rf->rva_EndAddress - rf->rva_BeginAddress;
188 1.3 christos
189 1.6 christos if (ui->rawUnwindCodes + 1 + (ui->CountOfCodes * 2) >= ui->rawUnwindCodesEnd)
190 1.6 christos {
191 1.6 christos fprintf (file, _("warning: corrupt unwind data\n"));
192 1.6 christos return;
193 1.6 christos }
194 1.7 christos
195 1.3 christos fprintf (file, "\tv2 epilog (length: %02x) at pc+:",
196 1.3 christos ui->rawUnwindCodes[0]);
197 1.6 christos
198 1.3 christos if (PEX64_UNWCODE_INFO (ui->rawUnwindCodes[1]))
199 1.3 christos fprintf (file, " 0x%x", func_size - ui->rawUnwindCodes[0]);
200 1.6 christos
201 1.3 christos i++;
202 1.3 christos for (; i < ui->CountOfCodes; i++)
203 1.3 christos {
204 1.3 christos const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
205 1.3 christos unsigned int off;
206 1.1 christos
207 1.3 christos if (PEX64_UNWCODE_CODE (dta[1]) != UWOP_EPILOG)
208 1.3 christos break;
209 1.3 christos off = dta[0] | (PEX64_UNWCODE_INFO (dta[1]) << 8);
210 1.3 christos if (off == 0)
211 1.3 christos fprintf (file, " [pad]");
212 1.3 christos else
213 1.3 christos fprintf (file, " 0x%x", func_size - off);
214 1.1 christos }
215 1.3 christos fputc ('\n', file);
216 1.1 christos }
217 1.3 christos
218 1.6 christos if (ui->rawUnwindCodes + 2 + (ui->CountOfCodes * 2) >= ui->rawUnwindCodesEnd)
219 1.6 christos {
220 1.6 christos fprintf (file, _("warning: corrupt unwind data\n"));
221 1.6 christos return;
222 1.6 christos }
223 1.7 christos
224 1.3 christos for (; i < ui->CountOfCodes; i++)
225 1.3 christos {
226 1.3 christos const bfd_byte *dta = ui->rawUnwindCodes + 2 * i;
227 1.3 christos unsigned int info = PEX64_UNWCODE_INFO (dta[1]);
228 1.8 christos int unexpected = false;
229 1.3 christos
230 1.3 christos fprintf (file, "\t pc+0x%02x: ", (unsigned int) dta[0]);
231 1.7 christos
232 1.1 christos switch (PEX64_UNWCODE_CODE (dta[1]))
233 1.1 christos {
234 1.1 christos case UWOP_PUSH_NONVOL:
235 1.3 christos fprintf (file, "push %s", pex_regs[info]);
236 1.1 christos break;
237 1.7 christos
238 1.1 christos case UWOP_ALLOC_LARGE:
239 1.3 christos if (info == 0)
240 1.1 christos {
241 1.7 christos if (dta + 4 > ui->rawUnwindCodesEnd)
242 1.7 christos {
243 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
244 1.7 christos return;
245 1.7 christos }
246 1.7 christos tmp = bfd_get_16 (abfd, dta + 2) * 8;
247 1.3 christos i++;
248 1.1 christos }
249 1.1 christos else
250 1.3 christos {
251 1.7 christos if (dta + 6 > ui->rawUnwindCodesEnd)
252 1.7 christos {
253 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
254 1.7 christos return;
255 1.7 christos }
256 1.7 christos tmp = bfd_get_32 (abfd, dta + 2);
257 1.3 christos i += 2;
258 1.3 christos }
259 1.3 christos fprintf (file, "alloc large area: rsp = rsp - 0x%x", tmp);
260 1.1 christos break;
261 1.7 christos
262 1.1 christos case UWOP_ALLOC_SMALL:
263 1.3 christos fprintf (file, "alloc small area: rsp = rsp - 0x%x", (info + 1) * 8);
264 1.1 christos break;
265 1.7 christos
266 1.1 christos case UWOP_SET_FPREG:
267 1.3 christos /* According to the documentation, info field is unused. */
268 1.3 christos fprintf (file, "FPReg: %s = rsp + 0x%x (info = 0x%x)",
269 1.3 christos pex_regs[ui->FrameRegister],
270 1.3 christos (unsigned int) ui->FrameOffset * 16, info);
271 1.3 christos unexpected = ui->FrameRegister == 0;
272 1.8 christos save_allowed = false;
273 1.1 christos break;
274 1.7 christos
275 1.1 christos case UWOP_SAVE_NONVOL:
276 1.7 christos if (dta + 4 > ui->rawUnwindCodesEnd)
277 1.7 christos {
278 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
279 1.7 christos return;
280 1.7 christos }
281 1.7 christos tmp = bfd_get_16 (abfd, dta + 2) * 8;
282 1.3 christos i++;
283 1.3 christos fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
284 1.3 christos unexpected = !save_allowed;
285 1.1 christos break;
286 1.7 christos
287 1.1 christos case UWOP_SAVE_NONVOL_FAR:
288 1.7 christos if (dta + 6 > ui->rawUnwindCodesEnd)
289 1.7 christos {
290 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
291 1.7 christos return;
292 1.7 christos }
293 1.7 christos tmp = bfd_get_32 (abfd, dta + 2);
294 1.3 christos i += 2;
295 1.3 christos fprintf (file, "save %s at rsp + 0x%x", pex_regs[info], tmp);
296 1.3 christos unexpected = !save_allowed;
297 1.1 christos break;
298 1.7 christos
299 1.1 christos case UWOP_SAVE_XMM:
300 1.3 christos if (ui->Version == 1)
301 1.3 christos {
302 1.7 christos if (dta + 4 > ui->rawUnwindCodesEnd)
303 1.7 christos {
304 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
305 1.7 christos return;
306 1.7 christos }
307 1.7 christos tmp = bfd_get_16 (abfd, dta + 2) * 8;
308 1.3 christos i++;
309 1.3 christos fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
310 1.3 christos unexpected = !save_allowed;
311 1.3 christos }
312 1.3 christos else if (ui->Version == 2)
313 1.3 christos {
314 1.3 christos fprintf (file, "epilog %02x %01x", dta[0], info);
315 1.8 christos unexpected = true;
316 1.3 christos }
317 1.1 christos break;
318 1.7 christos
319 1.1 christos case UWOP_SAVE_XMM_FAR:
320 1.7 christos if (dta + 6 > ui->rawUnwindCodesEnd)
321 1.7 christos {
322 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
323 1.7 christos return;
324 1.7 christos }
325 1.7 christos tmp = bfd_get_32 (abfd, dta + 2) * 8;
326 1.3 christos i += 2;
327 1.3 christos fprintf (file, "save mm%u at rsp + 0x%x", info, tmp);
328 1.3 christos unexpected = !save_allowed;
329 1.1 christos break;
330 1.7 christos
331 1.1 christos case UWOP_SAVE_XMM128:
332 1.7 christos if (dta + 4 > ui->rawUnwindCodesEnd)
333 1.7 christos {
334 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
335 1.7 christos return;
336 1.7 christos }
337 1.7 christos tmp = bfd_get_16 (abfd, dta + 2) * 16;
338 1.3 christos i++;
339 1.3 christos fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
340 1.3 christos unexpected = !save_allowed;
341 1.1 christos break;
342 1.7 christos
343 1.1 christos case UWOP_SAVE_XMM128_FAR:
344 1.7 christos if (dta + 6 > ui->rawUnwindCodesEnd)
345 1.7 christos {
346 1.7 christos fprintf (file, _("warning: corrupt unwind data\n"));
347 1.7 christos return;
348 1.7 christos }
349 1.7 christos tmp = bfd_get_32 (abfd, dta + 2) * 16;
350 1.3 christos i += 2;
351 1.3 christos fprintf (file, "save xmm%u at rsp + 0x%x", info, tmp);
352 1.3 christos unexpected = !save_allowed;
353 1.1 christos break;
354 1.7 christos
355 1.1 christos case UWOP_PUSH_MACHFRAME:
356 1.1 christos fprintf (file, "interrupt entry (SS, old RSP, EFLAGS, CS, RIP");
357 1.3 christos if (info == 0)
358 1.3 christos fprintf (file, ")");
359 1.3 christos else if (info == 1)
360 1.3 christos fprintf (file, ",ErrorCode)");
361 1.1 christos else
362 1.3 christos fprintf (file, ", unknown(%u))", info);
363 1.1 christos break;
364 1.7 christos
365 1.1 christos default:
366 1.3 christos /* PR 17512: file: 2245-7442-0.004. */
367 1.3 christos fprintf (file, _("Unknown: %x"), PEX64_UNWCODE_CODE (dta[1]));
368 1.1 christos break;
369 1.7 christos }
370 1.7 christos
371 1.3 christos if (unexpected)
372 1.3 christos fprintf (file, " [Unexpected!]");
373 1.3 christos fputc ('\n', file);
374 1.1 christos }
375 1.1 christos }
376 1.1 christos
377 1.3 christos /* Check wether section SEC_NAME contains the xdata at address ADDR. */
378 1.3 christos
379 1.1 christos static asection *
380 1.1 christos pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
381 1.1 christos {
382 1.1 christos asection *section = bfd_get_section_by_name (abfd, sec_name);
383 1.1 christos bfd_vma vsize;
384 1.1 christos bfd_size_type datasize = 0;
385 1.1 christos
386 1.1 christos if (section == NULL
387 1.1 christos || coff_section_data (abfd, section) == NULL
388 1.1 christos || pei_section_data (abfd, section) == NULL)
389 1.1 christos return NULL;
390 1.1 christos vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
391 1.1 christos datasize = section->size;
392 1.1 christos if (!datasize || vsize > addr || (vsize + datasize) < addr)
393 1.1 christos return NULL;
394 1.1 christos return section;
395 1.1 christos }
396 1.1 christos
397 1.3 christos /* Dump xdata at for function RF to FILE. The argument XDATA_SECTION
398 1.3 christos designate the bfd section containing the xdata, XDATA is its content,
399 1.3 christos and ENDX the size if known (or NULL). */
400 1.3 christos
401 1.1 christos static void
402 1.3 christos pex64_dump_xdata (FILE *file, bfd *abfd,
403 1.3 christos asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
404 1.3 christos struct pex64_runtime_function *rf)
405 1.1 christos {
406 1.3 christos bfd_vma vaddr;
407 1.1 christos bfd_vma end_addr;
408 1.3 christos bfd_vma addr = rf->rva_UnwindData;
409 1.3 christos bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
410 1.3 christos struct pex64_unwind_info ui;
411 1.3 christos
412 1.3 christos vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
413 1.3 christos addr -= vaddr;
414 1.1 christos
415 1.3 christos /* PR 17512: file: 2245-7442-0.004. */
416 1.3 christos if (addr >= sec_size)
417 1.3 christos {
418 1.3 christos fprintf (file, _("warning: xdata section corrupt\n"));
419 1.3 christos return;
420 1.1 christos }
421 1.1 christos
422 1.1 christos if (endx)
423 1.3 christos {
424 1.3 christos end_addr = endx[0] - vaddr;
425 1.3 christos /* PR 17512: file: 2245-7442-0.004. */
426 1.3 christos if (end_addr > sec_size)
427 1.3 christos {
428 1.6 christos fprintf (file, _("warning: xdata section corrupt\n"));
429 1.3 christos end_addr = sec_size;
430 1.3 christos }
431 1.3 christos }
432 1.1 christos else
433 1.3 christos end_addr = sec_size;
434 1.3 christos
435 1.6 christos if (! pex64_get_unwind_info (abfd, &ui, xdata + addr, xdata + end_addr))
436 1.6 christos {
437 1.6 christos fprintf (file, _("warning: xdata section corrupt\n"));
438 1.6 christos return;
439 1.6 christos }
440 1.1 christos
441 1.3 christos if (ui.Version != 1 && ui.Version != 2)
442 1.1 christos {
443 1.3 christos unsigned int i;
444 1.3 christos fprintf (file, "\tVersion %u (unknown).\n",
445 1.3 christos (unsigned int) ui.Version);
446 1.3 christos for (i = 0; addr < end_addr; addr += 1, i++)
447 1.3 christos {
448 1.3 christos if ((i & 15) == 0)
449 1.3 christos fprintf (file, "\t %03x:", i);
450 1.3 christos fprintf (file, " %02x", xdata[addr]);
451 1.3 christos if ((i & 15) == 15)
452 1.3 christos fprintf (file, "\n");
453 1.3 christos }
454 1.3 christos if ((i & 15) != 0)
455 1.3 christos fprintf (file, "\n");
456 1.3 christos return;
457 1.3 christos }
458 1.1 christos
459 1.3 christos fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
460 1.3 christos switch (ui.Flags)
461 1.3 christos {
462 1.3 christos case UNW_FLAG_NHANDLER:
463 1.3 christos fprintf (file, "none");
464 1.3 christos break;
465 1.3 christos case UNW_FLAG_EHANDLER:
466 1.3 christos fprintf (file, "UNW_FLAG_EHANDLER");
467 1.3 christos break;
468 1.3 christos case UNW_FLAG_UHANDLER:
469 1.3 christos fprintf (file, "UNW_FLAG_UHANDLER");
470 1.3 christos break;
471 1.3 christos case UNW_FLAG_FHANDLER:
472 1.3 christos fprintf
473 1.3 christos (file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
474 1.3 christos break;
475 1.3 christos case UNW_FLAG_CHAININFO:
476 1.3 christos fprintf (file, "UNW_FLAG_CHAININFO");
477 1.3 christos break;
478 1.3 christos default:
479 1.3 christos fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
480 1.3 christos break;
481 1.3 christos }
482 1.3 christos fputc ('\n', file);
483 1.3 christos fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
484 1.3 christos fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
485 1.3 christos (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
486 1.3 christos fprintf (file, "Frame reg: %s\n",
487 1.3 christos ui.FrameRegister == 0 ? "none"
488 1.3 christos : pex_regs[(unsigned int) ui.FrameRegister]);
489 1.3 christos
490 1.3 christos /* PR 17512: file: 2245-7442-0.004. */
491 1.3 christos if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
492 1.3 christos fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
493 1.3 christos else
494 1.3 christos pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);
495 1.1 christos
496 1.3 christos switch (ui.Flags)
497 1.3 christos {
498 1.3 christos case UNW_FLAG_EHANDLER:
499 1.3 christos case UNW_FLAG_UHANDLER:
500 1.3 christos case UNW_FLAG_FHANDLER:
501 1.3 christos fprintf (file, "\tHandler: ");
502 1.3 christos fprintf_vma (file, (ui.rva_ExceptionHandler
503 1.3 christos + pe_data (abfd)->pe_opthdr.ImageBase));
504 1.3 christos fprintf (file, ".\n");
505 1.3 christos break;
506 1.3 christos case UNW_FLAG_CHAININFO:
507 1.3 christos fprintf (file, "\tChain: start: ");
508 1.3 christos fprintf_vma (file, ui.rva_BeginAddress);
509 1.3 christos fprintf (file, ", end: ");
510 1.3 christos fprintf_vma (file, ui.rva_EndAddress);
511 1.3 christos fprintf (file, "\n\t unwind data: ");
512 1.3 christos fprintf_vma (file, ui.rva_UnwindData);
513 1.3 christos fprintf (file, ".\n");
514 1.3 christos break;
515 1.3 christos }
516 1.1 christos
517 1.3 christos /* Now we need end of this xdata block. */
518 1.3 christos addr += ui.SizeOfBlock;
519 1.3 christos if (addr < end_addr)
520 1.3 christos {
521 1.3 christos unsigned int i;
522 1.3 christos fprintf (file,"\tUser data:\n");
523 1.3 christos for (i = 0; addr < end_addr; addr += 1, i++)
524 1.1 christos {
525 1.3 christos if ((i & 15) == 0)
526 1.3 christos fprintf (file, "\t %03x:", i);
527 1.3 christos fprintf (file, " %02x", xdata[addr]);
528 1.3 christos if ((i & 15) == 15)
529 1.3 christos fprintf (file, "\n");
530 1.1 christos }
531 1.3 christos if ((i & 15) != 0)
532 1.3 christos fprintf (file, "\n");
533 1.1 christos }
534 1.1 christos }
535 1.1 christos
536 1.3 christos /* Helper function to sort xdata. The entries of xdata are sorted to know
537 1.3 christos the size of each entry. */
538 1.3 christos
539 1.1 christos static int
540 1.1 christos sort_xdata_arr (const void *l, const void *r)
541 1.1 christos {
542 1.1 christos const bfd_vma *lp = (const bfd_vma *) l;
543 1.1 christos const bfd_vma *rp = (const bfd_vma *) r;
544 1.1 christos
545 1.1 christos if (*lp == *rp)
546 1.1 christos return 0;
547 1.1 christos return (*lp < *rp ? -1 : 1);
548 1.1 christos }
549 1.1 christos
550 1.3 christos /* Display unwind tables for x86-64. */
551 1.3 christos
552 1.8 christos static bool
553 1.3 christos pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section)
554 1.1 christos {
555 1.1 christos FILE *file = (FILE *) vfile;
556 1.3 christos bfd_byte *pdata = NULL;
557 1.3 christos bfd_byte *xdata = NULL;
558 1.3 christos asection *xdata_section = NULL;
559 1.3 christos bfd_vma xdata_base;
560 1.1 christos bfd_size_type i;
561 1.3 christos bfd_size_type datasize;
562 1.1 christos bfd_size_type stop;
563 1.3 christos bfd_vma prev_beginaddress = (bfd_vma) -1;
564 1.3 christos bfd_vma prev_unwinddata_rva = (bfd_vma) -1;
565 1.3 christos bfd_vma imagebase;
566 1.1 christos int onaline = PDATA_ROW_SIZE;
567 1.1 christos int seen_error = 0;
568 1.3 christos bfd_vma *xdata_arr = NULL;
569 1.1 christos int xdata_arr_cnt;
570 1.8 christos bool virt_size_is_zero = false;
571 1.1 christos
572 1.3 christos /* Sanity checks. */
573 1.3 christos if (pdata_section == NULL
574 1.3 christos || coff_section_data (abfd, pdata_section) == NULL
575 1.3 christos || pei_section_data (abfd, pdata_section) == NULL)
576 1.8 christos return true;
577 1.1 christos
578 1.3 christos stop = pei_section_data (abfd, pdata_section)->virt_size;
579 1.1 christos if ((stop % onaline) != 0)
580 1.1 christos fprintf (file,
581 1.6 christos /* xgettext:c-format */
582 1.3 christos _("Warning: %s section size (%ld) is not a multiple of %d\n"),
583 1.3 christos pdata_section->name, (long) stop, onaline);
584 1.1 christos
585 1.3 christos datasize = pdata_section->size;
586 1.3 christos if (datasize == 0)
587 1.3 christos {
588 1.3 christos if (stop)
589 1.3 christos fprintf (file, _("Warning: %s section size is zero\n"),
590 1.3 christos pdata_section->name);
591 1.8 christos return true;
592 1.3 christos }
593 1.3 christos
594 1.3 christos /* virt_size might be zero for objects. */
595 1.3 christos if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0)
596 1.3 christos {
597 1.7 christos stop = datasize;
598 1.8 christos virt_size_is_zero = true;
599 1.3 christos }
600 1.3 christos else if (datasize < stop)
601 1.3 christos {
602 1.3 christos fprintf (file,
603 1.6 christos /* xgettext:c-format */
604 1.3 christos _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"),
605 1.3 christos pdata_section->name, (unsigned long) datasize,
606 1.3 christos (unsigned long) stop);
607 1.7 christos /* Be sure not to read past datasize. */
608 1.7 christos stop = datasize;
609 1.3 christos }
610 1.3 christos
611 1.3 christos /* Display functions table. */
612 1.1 christos fprintf (file,
613 1.3 christos _("\nThe Function Table (interpreted %s section contents)\n"),
614 1.3 christos pdata_section->name);
615 1.1 christos
616 1.1 christos fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n"));
617 1.1 christos
618 1.3 christos if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata))
619 1.3 christos goto done;
620 1.1 christos
621 1.3 christos /* Table of xdata entries. */
622 1.1 christos xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1));
623 1.1 christos xdata_arr_cnt = 0;
624 1.3 christos
625 1.3 christos if (strcmp (abfd->xvec->name, "pei-x86-64") == 0)
626 1.3 christos imagebase = pe_data (abfd)->pe_opthdr.ImageBase;
627 1.3 christos else
628 1.3 christos imagebase = 0;
629 1.3 christos
630 1.1 christos for (i = 0; i < stop; i += onaline)
631 1.1 christos {
632 1.1 christos struct pex64_runtime_function rf;
633 1.1 christos
634 1.1 christos if (i + PDATA_ROW_SIZE > stop)
635 1.1 christos break;
636 1.3 christos
637 1.3 christos pex64_get_runtime_function (abfd, &rf, &pdata[i]);
638 1.1 christos
639 1.1 christos if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
640 1.1 christos && rf.rva_UnwindData == 0)
641 1.1 christos /* We are probably into the padding of the section now. */
642 1.1 christos break;
643 1.1 christos fputc (' ', file);
644 1.3 christos fprintf_vma (file, i + pdata_section->vma);
645 1.1 christos fprintf (file, ":\t");
646 1.3 christos fprintf_vma (file, imagebase + rf.rva_BeginAddress);
647 1.3 christos fprintf (file, " ");
648 1.3 christos fprintf_vma (file, imagebase + rf.rva_EndAddress);
649 1.3 christos fprintf (file, " ");
650 1.3 christos fprintf_vma (file, imagebase + rf.rva_UnwindData);
651 1.1 christos fprintf (file, "\n");
652 1.1 christos if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress)
653 1.1 christos {
654 1.1 christos seen_error = 1;
655 1.1 christos fprintf (file, " has %s begin address as predecessor\n",
656 1.1 christos (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same"));
657 1.6 christos }
658 1.1 christos prev_beginaddress = rf.rva_BeginAddress;
659 1.1 christos /* Now we check for negative addresses. */
660 1.1 christos if ((prev_beginaddress & 0x80000000) != 0)
661 1.1 christos {
662 1.1 christos seen_error = 1;
663 1.1 christos fprintf (file, " has negative begin address\n");
664 1.1 christos }
665 1.1 christos if ((rf.rva_EndAddress & 0x80000000) != 0)
666 1.1 christos {
667 1.1 christos seen_error = 1;
668 1.1 christos fprintf (file, " has negative end address\n");
669 1.1 christos }
670 1.1 christos if ((rf.rva_UnwindData & 0x80000000) != 0)
671 1.1 christos {
672 1.1 christos seen_error = 1;
673 1.1 christos fprintf (file, " has negative unwind address\n");
674 1.1 christos }
675 1.3 christos else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
676 1.3 christos || virt_size_is_zero)
677 1.3 christos xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData;
678 1.1 christos }
679 1.1 christos
680 1.1 christos if (seen_error)
681 1.3 christos goto done;
682 1.1 christos
683 1.1 christos /* Add end of list marker. */
684 1.1 christos xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0);
685 1.1 christos
686 1.1 christos /* Sort start RVAs of xdata. */
687 1.1 christos if (xdata_arr_cnt > 1)
688 1.1 christos qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma),
689 1.1 christos sort_xdata_arr);
690 1.1 christos
691 1.3 christos /* Find the section containing the unwind data (.xdata). */
692 1.3 christos xdata_base = xdata_arr[0];
693 1.3 christos /* For sections with long names, first look for the same
694 1.3 christos section name, replacing .pdata by .xdata prefix. */
695 1.3 christos if (strcmp (pdata_section->name, ".pdata") != 0)
696 1.3 christos {
697 1.3 christos size_t len = strlen (pdata_section->name);
698 1.5 christos char *xdata_name = xmalloc (len + 1);
699 1.3 christos
700 1.3 christos xdata_name = memcpy (xdata_name, pdata_section->name, len + 1);
701 1.3 christos /* Transform .pdata prefix into .xdata prefix. */
702 1.3 christos if (len > 1)
703 1.3 christos xdata_name [1] = 'x';
704 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base,
705 1.3 christos xdata_name);
706 1.5 christos free (xdata_name);
707 1.3 christos }
708 1.3 christos /* Second, try the .xdata section itself. */
709 1.3 christos if (!xdata_section)
710 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata");
711 1.3 christos /* Otherwise, if xdata_base is non zero, search also inside
712 1.3 christos other standard sections. */
713 1.3 christos if (!xdata_section && xdata_base)
714 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata");
715 1.3 christos if (!xdata_section && xdata_base)
716 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data");
717 1.3 christos if (!xdata_section && xdata_base)
718 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata");
719 1.3 christos if (!xdata_section && xdata_base)
720 1.3 christos xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text");
721 1.3 christos /* Transfer xdata section into xdata array. */
722 1.3 christos if (!xdata_section
723 1.3 christos || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata))
724 1.3 christos goto done;
725 1.3 christos
726 1.3 christos /* Avoid "also used "... ouput for single unwind info
727 1.3 christos in object file. */
728 1.3 christos prev_unwinddata_rva = (bfd_vma) -1;
729 1.3 christos
730 1.1 christos /* Do dump of pdata related xdata. */
731 1.1 christos for (i = 0; i < stop; i += onaline)
732 1.1 christos {
733 1.1 christos struct pex64_runtime_function rf;
734 1.1 christos
735 1.1 christos if (i + PDATA_ROW_SIZE > stop)
736 1.1 christos break;
737 1.3 christos
738 1.3 christos pex64_get_runtime_function (abfd, &rf, &pdata[i]);
739 1.1 christos
740 1.1 christos if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0
741 1.1 christos && rf.rva_UnwindData == 0)
742 1.1 christos /* We are probably into the padding of the section now. */
743 1.1 christos break;
744 1.1 christos if (i == 0)
745 1.6 christos fprintf (file, _("\nDump of %s\n"), xdata_section->name);
746 1.3 christos
747 1.1 christos fputc (' ', file);
748 1.3 christos fprintf_vma (file, rf.rva_UnwindData + imagebase);
749 1.1 christos
750 1.3 christos if (prev_unwinddata_rva == rf.rva_UnwindData)
751 1.3 christos {
752 1.3 christos /* Do not dump again the xdata for the same entry. */
753 1.3 christos fprintf (file, " also used for function at ");
754 1.3 christos fprintf_vma (file, rf.rva_BeginAddress + imagebase);
755 1.3 christos fputc ('\n', file);
756 1.3 christos continue;
757 1.3 christos }
758 1.3 christos else
759 1.3 christos prev_unwinddata_rva = rf.rva_UnwindData;
760 1.1 christos
761 1.3 christos fprintf (file, " (rva: %08x): ",
762 1.3 christos (unsigned int) rf.rva_UnwindData);
763 1.3 christos fprintf_vma (file, rf.rva_BeginAddress + imagebase);
764 1.3 christos fprintf (file, " - ");
765 1.3 christos fprintf_vma (file, rf.rva_EndAddress + imagebase);
766 1.3 christos fputc ('\n', file);
767 1.3 christos
768 1.3 christos if (rf.rva_UnwindData != 0 || virt_size_is_zero)
769 1.1 christos {
770 1.3 christos if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf))
771 1.1 christos {
772 1.3 christos bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf);
773 1.7 christos bfd_vma pdata_vma = bfd_section_vma (pdata_section);
774 1.3 christos struct pex64_runtime_function arf;
775 1.3 christos
776 1.3 christos fprintf (file, "\t shares information with ");
777 1.3 christos altent += imagebase;
778 1.3 christos
779 1.3 christos if (altent >= pdata_vma
780 1.7 christos && altent - pdata_vma + PDATA_ROW_SIZE <= stop)
781 1.3 christos {
782 1.3 christos pex64_get_runtime_function
783 1.3 christos (abfd, &arf, &pdata[altent - pdata_vma]);
784 1.3 christos fprintf (file, "pdata element at 0x");
785 1.3 christos fprintf_vma (file, arf.rva_UnwindData);
786 1.3 christos }
787 1.3 christos else
788 1.3 christos fprintf (file, "unknown pdata element");
789 1.1 christos fprintf (file, ".\n");
790 1.1 christos }
791 1.1 christos else
792 1.1 christos {
793 1.1 christos bfd_vma *p;
794 1.1 christos
795 1.1 christos /* Search for the current entry in the sorted array. */
796 1.1 christos p = (bfd_vma *)
797 1.6 christos bsearch (&rf.rva_UnwindData, xdata_arr,
798 1.1 christos (size_t) xdata_arr_cnt, sizeof (bfd_vma),
799 1.1 christos sort_xdata_arr);
800 1.1 christos
801 1.1 christos /* Advance to the next pointer into the xdata section. We may
802 1.1 christos have shared xdata entries, which will result in a string of
803 1.1 christos identical pointers in the array; advance past all of them. */
804 1.1 christos while (p[0] <= rf.rva_UnwindData)
805 1.1 christos ++p;
806 1.3 christos
807 1.1 christos if (p[0] == ~((bfd_vma) 0))
808 1.1 christos p = NULL;
809 1.1 christos
810 1.3 christos pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf);
811 1.1 christos }
812 1.1 christos }
813 1.1 christos }
814 1.1 christos
815 1.3 christos done:
816 1.3 christos free (pdata);
817 1.1 christos free (xdata_arr);
818 1.3 christos free (xdata);
819 1.1 christos
820 1.8 christos return true;
821 1.1 christos }
822 1.1 christos
823 1.8 christos struct pex64_paps
824 1.8 christos {
825 1.8 christos void *obj;
826 1.8 christos /* Number of found pdata sections. */
827 1.8 christos unsigned int pdata_count;
828 1.8 christos };
829 1.3 christos
830 1.3 christos /* Functionn prototype. */
831 1.8 christos bool pex64_bfd_print_pdata (bfd *, void *);
832 1.3 christos
833 1.3 christos /* Helper function for bfd_map_over_section. */
834 1.3 christos static void
835 1.8 christos pex64_print_all_pdata_sections (bfd *abfd, asection *pdata, void *arg)
836 1.3 christos {
837 1.8 christos struct pex64_paps *paps = arg;
838 1.8 christos if (startswith (pdata->name, ".pdata"))
839 1.3 christos {
840 1.8 christos if (pex64_bfd_print_pdata_section (abfd, paps->obj, pdata))
841 1.8 christos paps->pdata_count++;
842 1.3 christos }
843 1.3 christos }
844 1.3 christos
845 1.8 christos bool
846 1.3 christos pex64_bfd_print_pdata (bfd *abfd, void *vfile)
847 1.3 christos {
848 1.3 christos asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata");
849 1.8 christos struct pex64_paps paps;
850 1.3 christos
851 1.3 christos if (pdata_section)
852 1.3 christos return pex64_bfd_print_pdata_section (abfd, vfile, pdata_section);
853 1.3 christos
854 1.8 christos paps.obj = vfile;
855 1.8 christos paps.pdata_count = 0;
856 1.8 christos bfd_map_over_sections (abfd, pex64_print_all_pdata_sections, &paps);
857 1.8 christos return paps.pdata_count != 0;
858 1.3 christos }
859 1.3 christos
860 1.1 christos #define bfd_pe_print_pdata pex64_bfd_print_pdata
861 1.3 christos #define bfd_coff_std_swap_table bfd_coff_pei_swap_table
862 1.1 christos
863 1.1 christos #include "coff-x86_64.c"
864