static bfd_boolean pex64_bfd_print_pdata (bfd *abfd, void *vfile) { FILE *file = (FILE *) vfile; bfd_byte *data = NULL; asection *section = bfd_get_section_by_name (abfd, ".pdata"); bfd_size_type datasize = 0; bfd_size_type i; bfd_size_type start, stop; int onaline = PDATA_ROW_SIZE; if (section == NULL || coff_section_data (abfd, section) == NULL || pei_section_data (abfd, section) == NULL) return TRUE; stop = pei_section_data (abfd, section)->virt_size; if ((stop % onaline) != 0) fprintf (file, _("warning: .pdata section size (%ld) is not a multiple of %d\n"), (long) stop, onaline); fprintf (file, _("\nThe Function Table (interpreted .pdata section contents)\n")); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); datasize = section->size; if (datasize == 0) return TRUE; if (!bfd_malloc_and_get_section (abfd, section, &data)) { if (data != NULL) free (data); return FALSE; } start = 0; for (i = start; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &data[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; fputc (' ', file); fprintf_vma (file, i + section->vma); fprintf (file, ":\t"); rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase; fprintf_vma (file, rf.rva_BeginAddress); fputc (' ', file); rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase; fprintf_vma (file, rf.rva_EndAddress); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData); fprintf (file, "\n"); if (rf.rva_UnwindData != 0) { if (rf.isChained) { fprintf (file, "\t shares information with pdata element at 0x"); fprintf_vma (file, rf.rva_UnwindData + pe_data (abfd)->pe_opthdr.ImageBase); fprintf (file, ".\n"); } else pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress); } } free (data); return TRUE; }
static bfd_boolean pex64_bfd_print_pdata_section (bfd *abfd, void *vfile, asection *pdata_section) { FILE *file = (FILE *) vfile; bfd_byte *pdata = NULL; bfd_byte *xdata = NULL; asection *xdata_section = NULL; bfd_vma xdata_base; bfd_size_type i; bfd_size_type datasize; bfd_size_type stop; bfd_vma prev_beginaddress = (bfd_vma) -1; bfd_vma prev_unwinddata_rva = (bfd_vma) -1; bfd_vma imagebase; int onaline = PDATA_ROW_SIZE; int seen_error = 0; bfd_vma *xdata_arr = NULL; int xdata_arr_cnt; bfd_boolean virt_size_is_zero = FALSE; /* Sanity checks. */ if (pdata_section == NULL || coff_section_data (abfd, pdata_section) == NULL || pei_section_data (abfd, pdata_section) == NULL) return TRUE; stop = pei_section_data (abfd, pdata_section)->virt_size; if ((stop % onaline) != 0) fprintf (file, _("Warning: %s section size (%ld) is not a multiple of %d\n"), pdata_section->name, (long) stop, onaline); datasize = pdata_section->size; if (datasize == 0) { if (stop) fprintf (file, _("Warning: %s section size is zero\n"), pdata_section->name); return TRUE; } /* virt_size might be zero for objects. */ if (stop == 0 && strcmp (abfd->xvec->name, "pe-x86-64") == 0) { stop = (datasize / onaline) * onaline; virt_size_is_zero = TRUE; } else if (datasize < stop) { fprintf (file, _("Warning: %s section size (%ld) is smaller than virtual size (%ld)\n"), pdata_section->name, (unsigned long) datasize, (unsigned long) stop); /* Be sure not to read passed datasize. */ stop = datasize / onaline; } /* Display functions table. */ fprintf (file, _("\nThe Function Table (interpreted %s section contents)\n"), pdata_section->name); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata)) goto done; /* Table of xdata entries. */ xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); xdata_arr_cnt = 0; if (strcmp (abfd->xvec->name, "pei-x86-64") == 0) imagebase = pe_data (abfd)->pe_opthdr.ImageBase; else imagebase = 0; for (i = 0; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; fputc (' ', file); fprintf_vma (file, i + pdata_section->vma); fprintf (file, ":\t"); fprintf_vma (file, imagebase + rf.rva_BeginAddress); fprintf (file, " "); fprintf_vma (file, imagebase + rf.rva_EndAddress); fprintf (file, " "); fprintf_vma (file, imagebase + rf.rva_UnwindData); fprintf (file, "\n"); if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress) { seen_error = 1; fprintf (file, " has %s begin address as predecessor\n", (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same")); } prev_beginaddress = rf.rva_BeginAddress; /* Now we check for negative addresses. */ if ((prev_beginaddress & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative begin address\n"); } if ((rf.rva_EndAddress & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative end address\n"); } if ((rf.rva_UnwindData & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative unwind address\n"); } else if ((rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) || virt_size_is_zero) xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; } if (seen_error) goto done; /* Add end of list marker. */ xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0); /* Sort start RVAs of xdata. */ if (xdata_arr_cnt > 1) qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma), sort_xdata_arr); /* Find the section containing the unwind data (.xdata). */ xdata_base = xdata_arr[0]; /* For sections with long names, first look for the same section name, replacing .pdata by .xdata prefix. */ if (strcmp (pdata_section->name, ".pdata") != 0) { size_t len = strlen (pdata_section->name); char *xdata_name = alloca (len + 1); xdata_name = memcpy (xdata_name, pdata_section->name, len + 1); /* Transform .pdata prefix into .xdata prefix. */ if (len > 1) xdata_name [1] = 'x'; xdata_section = pex64_get_section_by_rva (abfd, xdata_base, xdata_name); } /* Second, try the .xdata section itself. */ if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata"); /* Otherwise, if xdata_base is non zero, search also inside other standard sections. */ if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata"); if (!xdata_section && xdata_base) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text"); /* Transfer xdata section into xdata array. */ if (!xdata_section || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata)) goto done; /* Avoid "also used "... ouput for single unwind info in object file. */ prev_unwinddata_rva = (bfd_vma) -1; /* Do dump of pdata related xdata. */ for (i = 0; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; if (i == 0) fprintf (file, _("\nDump of %s\n"), xdata_section->name); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData + imagebase); if (prev_unwinddata_rva == rf.rva_UnwindData) { /* Do not dump again the xdata for the same entry. */ fprintf (file, " also used for function at "); fprintf_vma (file, rf.rva_BeginAddress + imagebase); fputc ('\n', file); continue; } else prev_unwinddata_rva = rf.rva_UnwindData; fprintf (file, " (rva: %08x): ", (unsigned int) rf.rva_UnwindData); fprintf_vma (file, rf.rva_BeginAddress + imagebase); fprintf (file, " - "); fprintf_vma (file, rf.rva_EndAddress + imagebase); fputc ('\n', file); if (rf.rva_UnwindData != 0 || virt_size_is_zero) { if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) { bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf); bfd_vma pdata_vma = bfd_get_section_vma (abfd, pdata_section); struct pex64_runtime_function arf; fprintf (file, "\t shares information with "); altent += imagebase; if (altent >= pdata_vma && (altent + PDATA_ROW_SIZE <= pdata_vma + pei_section_data (abfd, pdata_section)->virt_size)) { pex64_get_runtime_function (abfd, &arf, &pdata[altent - pdata_vma]); fprintf (file, "pdata element at 0x"); fprintf_vma (file, arf.rva_UnwindData); } else fprintf (file, "unknown pdata element"); fprintf (file, ".\n"); } else { bfd_vma *p; /* Search for the current entry in the sorted array. */ p = (bfd_vma *) bsearch (&rf.rva_UnwindData, xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma), sort_xdata_arr); /* Advance to the next pointer into the xdata section. We may have shared xdata entries, which will result in a string of identical pointers in the array; advance past all of them. */ while (p[0] <= rf.rva_UnwindData) ++p; if (p[0] == ~((bfd_vma) 0)) p = NULL; pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf); } } } done: free (pdata); free (xdata_arr); free (xdata); return TRUE; }
static bfd_boolean pex64_bfd_print_pdata (bfd *abfd, void *vfile) { FILE *file = (FILE *) vfile; bfd_byte *pdata = NULL; bfd_byte *xdata = NULL; asection *pdata_section = bfd_get_section_by_name (abfd, ".pdata"); asection *xdata_section; bfd_vma xdata_base; bfd_size_type i; bfd_size_type stop; bfd_vma prev_beginaddress = 0; bfd_vma prev_unwinddata_rva = 0; bfd_vma imagebase; int onaline = PDATA_ROW_SIZE; int seen_error = 0; bfd_vma *xdata_arr = NULL; int xdata_arr_cnt; /* Sanity checks. */ if (pdata_section == NULL || coff_section_data (abfd, pdata_section) == NULL || pei_section_data (abfd, pdata_section) == NULL) return TRUE; stop = pei_section_data (abfd, pdata_section)->virt_size; /* PR 17512: file: 005-181405-0.004. */ if (stop == 0 || pdata_section->size == 0) { fprintf (file, _("No unwind data in .pdata section\n")); return TRUE; } if ((stop % onaline) != 0) fprintf (file, _("warning: .pdata section size (%ld) is not a multiple of %d\n"), (long) stop, onaline); /* Display functions table. */ fprintf (file, _("\nThe Function Table (interpreted .pdata section contents)\n")); fprintf (file, _("vma:\t\t\tBeginAddress\t EndAddress\t UnwindData\n")); if (!bfd_malloc_and_get_section (abfd, pdata_section, &pdata)) goto done; /* Table of xdata entries. */ xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); xdata_arr_cnt = 0; imagebase = pe_data (abfd)->pe_opthdr.ImageBase; for (i = 0; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; fputc (' ', file); fprintf_vma (file, i + pdata_section->vma); fprintf (file, ":\t"); fprintf_vma (file, imagebase + rf.rva_BeginAddress); fprintf (file, " "); fprintf_vma (file, imagebase + rf.rva_EndAddress); fprintf (file, " "); fprintf_vma (file, imagebase + rf.rva_UnwindData); fprintf (file, "\n"); if (i != 0 && rf.rva_BeginAddress <= prev_beginaddress) { seen_error = 1; fprintf (file, " has %s begin address as predecessor\n", (rf.rva_BeginAddress < prev_beginaddress ? "smaller" : "same")); } prev_beginaddress = rf.rva_BeginAddress; /* Now we check for negative addresses. */ if ((prev_beginaddress & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative begin address\n"); } if ((rf.rva_EndAddress & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative end address\n"); } if ((rf.rva_UnwindData & 0x80000000) != 0) { seen_error = 1; fprintf (file, " has negative unwind address\n"); } if (rf.rva_UnwindData && !PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; } if (seen_error) goto done; /* Add end of list marker. */ xdata_arr[xdata_arr_cnt++] = ~((bfd_vma) 0); /* Sort start RVAs of xdata. */ if (xdata_arr_cnt > 1) qsort (xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma), sort_xdata_arr); /* Find the section containing the unwind data (.xdata). */ xdata_base = xdata_arr[0]; xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".rdata"); if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".data"); if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".xdata"); if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".pdata"); if (!xdata_section) xdata_section = pex64_get_section_by_rva (abfd, xdata_base, ".text"); if (!xdata_section || !bfd_malloc_and_get_section (abfd, xdata_section, &xdata)) goto done; /* Do dump of pdata related xdata. */ for (i = 0; i < stop; i += onaline) { struct pex64_runtime_function rf; if (i + PDATA_ROW_SIZE > stop) break; pex64_get_runtime_function (abfd, &rf, &pdata[i]); if (rf.rva_BeginAddress == 0 && rf.rva_EndAddress == 0 && rf.rva_UnwindData == 0) /* We are probably into the padding of the section now. */ break; if (i == 0) fprintf (file, "\nDump of .xdata\n"); fputc (' ', file); fprintf_vma (file, rf.rva_UnwindData + imagebase); if (prev_unwinddata_rva == rf.rva_UnwindData) { /* Do not dump again the xdata for the same entry. */ fprintf (file, " also used for function at "); fprintf_vma (file, rf.rva_BeginAddress + imagebase); fputc ('\n', file); continue; } else prev_unwinddata_rva = rf.rva_UnwindData; fprintf (file, " (rva: %08x): ", (unsigned int) rf.rva_UnwindData); fprintf_vma (file, rf.rva_BeginAddress + imagebase); fprintf (file, " - "); fprintf_vma (file, rf.rva_EndAddress + imagebase); fputc ('\n', file); if (rf.rva_UnwindData != 0) { if (PEX64_IS_RUNTIME_FUNCTION_CHAINED (&rf)) { bfd_vma altent = PEX64_GET_UNWINDDATA_UNIFIED_RVA (&rf); bfd_vma pdata_vma = bfd_get_section_vma (abfd, pdata_section); struct pex64_runtime_function arf; fprintf (file, "\t shares information with "); altent += imagebase; if (altent >= pdata_vma && (altent + PDATA_ROW_SIZE <= pdata_vma + pei_section_data (abfd, pdata_section)->virt_size)) { pex64_get_runtime_function (abfd, &arf, &pdata[altent - pdata_vma]); fprintf (file, "pdata element at 0x"); fprintf_vma (file, arf.rva_UnwindData); } else fprintf (file, "unknown pdata element"); fprintf (file, ".\n"); } else { bfd_vma *p; /* Search for the current entry in the sorted array. */ p = (bfd_vma *) bsearch (&rf.rva_UnwindData, xdata_arr, (size_t) xdata_arr_cnt, sizeof (bfd_vma), sort_xdata_arr); /* Advance to the next pointer into the xdata section. We may have shared xdata entries, which will result in a string of identical pointers in the array; advance past all of them. */ while (p[0] <= rf.rva_UnwindData) ++p; if (p[0] == ~((bfd_vma) 0)) p = NULL; pex64_dump_xdata (file, abfd, xdata_section, xdata, p, &rf); } } } done: free (pdata); free (xdata_arr); free (xdata); return TRUE; }