diff options
-rw-r--r-- | bfd/ChangeLog | 10 | ||||
-rw-r--r-- | bfd/pei-x86_64.c | 93 |
2 files changed, 64 insertions, 39 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 39a5c98..6e32abb 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2010-10-08 Kai Tietz <kai.tietz@onevision.com> + + * pei-x86_64.c (find_next_xdata_or_end): Removed. + (pex64_dump_xdata): Remove arguments stop, onaline, + and pdata. New argument endx. Print term "none" + instead of misleading "CFA". + (sort_xdata_arr): New function. + (pex64_bfd_print_pdata): Use binary search/sort for unwind-RVAs + instead of searching quadratic. + 2010-10-08 Pierre Muller <muller@ics.u-strasbg.fr> Alan Modra <amodra@gmail.com> diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c index 76009f3..fdc6205 100644 --- a/bfd/pei-x86_64.c +++ b/bfd/pei-x86_64.c @@ -303,41 +303,9 @@ pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name) return section; } -static bfd_vma -find_next_xdata_or_end (bfd *abfd, bfd_byte *pdata, bfd_size_type stop, - int onaline, bfd_vma cur_address, bfd_vma max_size) -{ - bfd_size_type i; - bfd_vma ret = 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; - if (rf.rva_UnwindData != 0 && !rf.isChained) - { - if (!ret && rf.rva_UnwindData > cur_address) - ret = rf.rva_UnwindData; - else if (rf.rva_UnwindData > cur_address && ret > rf.rva_UnwindData) - ret = rf.rva_UnwindData; - } - } - if (!ret) - return max_size; - return ret; -} - static void pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr, - bfd_size_type stop, int onaline, bfd_byte *pdata) + bfd_vma *endx) { asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata"); bfd_vma vsize; @@ -364,10 +332,11 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr, vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase; addr -= vsize; - end_addr = find_next_xdata_or_end (abfd, pdata, stop, onaline, addr + vsize, - vsize + (section->rawsize != 0 ? section->rawsize : section->size)); + if (endx) + end_addr = endx[0] - vsize; + else + end_addr = (section->rawsize != 0 ? section->rawsize : section->size); - end_addr -= vsize; if (bfd_malloc_and_get_section (abfd, section, &data)) { struct pex64_unwind_info ui; @@ -411,7 +380,7 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr, fprintf (file, "\tPrologue size: %u, Frame offset = 0x%x.\n", (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset); fprintf (file, "\tFrame register is %s.\n", - ui.FrameRegister == 0 ? "CFA" + ui.FrameRegister == 0 ? "none" : pex_regs[(unsigned int) ui.FrameRegister]); pex64_xdata_print_uwd_codes (file, &ui, pc_addr); @@ -438,6 +407,17 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr, free (data); } +static int +sort_xdata_arr (const void *l, const void *r) +{ + const bfd_vma *lp = (const bfd_vma *) l; + const bfd_vma *rp = (const bfd_vma *) r; + + if (*lp == *rp) + return 0; + return (*lp < *rp ? -1 : 1); +} + static bfd_boolean pex64_bfd_print_pdata (bfd *abfd, void *vfile) { @@ -450,6 +430,8 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) bfd_vma prev_beginaddress = 0; int onaline = PDATA_ROW_SIZE; int seen_error = 0; + bfd_vma *xdata_arr; + int xdata_arr_cnt; if (section == NULL || coff_section_data (abfd, section) == NULL @@ -478,6 +460,8 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) return FALSE; } + xdata_arr = (bfd_vma *) xmalloc (sizeof (bfd_vma) * ((stop / onaline) + 1)); + xdata_arr_cnt = 0; /* Do sanity check of pdata. */ for (i = 0; i < stop; i += onaline) { @@ -523,14 +507,26 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) seen_error = 1; fprintf (file, " has negative unwind address\n"); } + if (rf.rva_UnwindData && !rf.isChained) + xdata_arr[xdata_arr_cnt++] = rf.rva_UnwindData; } if (seen_error) { free (data); + free (xdata_arr); return TRUE; } + + /* 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); + /* Do dump of pdata related xdata. */ for (i = 0; i < stop; i += onaline) @@ -563,12 +559,31 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) fprintf (file, ".\n"); } else - pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress, - stop, onaline, data); + { + 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, rf.rva_UnwindData, + rf.rva_BeginAddress, p); + } } } free (data); + free (xdata_arr); return TRUE; } |