From 2eb039095279c4d398fdc04652879a8b0b9f7562 Mon Sep 17 00:00:00 2001 From: Kai Tietz Date: Wed, 15 Sep 2010 17:27:30 +0000 Subject: [PATCH] 2010-09-15 Kai Tietz * pei-x86_64.c (pex64_get_unwind_info): Reorgnized. (pex64_get_scope_entry): Removed. (find_next_xdata_or_end): New helper. (pex64_dump_xdata): Reworked. (pex64_bfd_print_pdata): Add checking for valid pdata sorting and values. Reworked output. --- bfd/ChangeLog | 10 +++ bfd/pei-x86_64.c | 195 +++++++++++++++++++++++++++++------------------ 2 files changed, 129 insertions(+), 76 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 84b6be633a4..f5f69258f3d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,13 @@ +2010-09-15 Kai Tietz + + * pei-x86_64.c (pex64_get_unwind_info): Reorgnized. + (pex64_get_scope_entry): Removed. + (find_next_xdata_or_end): New helper. + (pex64_dump_xdata): Reworked. + (pex64_bfd_print_pdata): Add checking for + valid pdata sorting and values. Reworked + output. + 2010-09-15 H.J. Lu PR binutils/12004 diff --git a/bfd/pei-x86_64.c b/bfd/pei-x86_64.c index f5070049b3c..76009f39155 100644 --- a/bfd/pei-x86_64.c +++ b/bfd/pei-x86_64.c @@ -114,17 +114,6 @@ pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data) ex_dta += ui->SizeOfBlock; switch (ui->Flags) { - case UNW_FLAG_EHANDLER: - ui->rva_ExceptionHandler = bfd_get_32 (abfd, ex_dta); - break; - case UNW_FLAG_UHANDLER: - ui->rva_TerminationHandler = bfd_get_32 (abfd, ex_dta); - break; - case UNW_FLAG_FHANDLER: - ui->rva_FrameHandler = bfd_get_32 (abfd, ex_dta); - ui->FrameHandlerArgument = bfd_get_32 (abfd, ex_dta + 4); - ui->SizeOfBlock += 8; - return; case UNW_FLAG_CHAININFO: ui->rva_FunctionEntry = bfd_get_32 (abfd, ex_dta); ui->SizeOfBlock += 4; @@ -132,26 +121,6 @@ pex64_get_unwind_info (bfd *abfd, struct pex64_unwind_info *ui, void *data) default: return; } - ex_dta += 4; - ui->SizeOfBlock += 8; - ui->CountOfScopes = bfd_get_32 (abfd, ex_dta); - ex_dta += 4; - ui->rawScopeEntries = ex_dta; - ui->SizeOfBlock += (ui->CountOfScopes * PEX64_SCOPE_ENTRY_SIZE); -} - -static void -pex64_get_scope_entry (bfd *abfd, struct pex64_scope_entry *se, - bfd_vma idx, const bfd_byte *x) -{ - const struct external_pex64_scope_entry *ex_se; - x += (idx * PEX64_SCOPE_ENTRY_SIZE); - ex_se = (const struct external_pex64_scope_entry *) x; - memset (se, 0, sizeof (struct pex64_scope_entry)); - se->rva_BeginAddress = bfd_get_32 (abfd, ex_se->rva_BeginAddress); - se->rva_EndAddress = bfd_get_32 (abfd, ex_se->rva_EndAddress); - se->rva_HandlerAddress = bfd_get_32 (abfd, ex_se->rva_HandlerAddress); - se->rva_JumpAddress = bfd_get_32 (abfd, ex_se->rva_JumpAddress); } static void @@ -334,13 +303,46 @@ 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) +pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr, + bfd_size_type stop, int onaline, bfd_byte *pdata) { asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata"); bfd_vma vsize; bfd_byte *data = NULL; - bfd_vma i; + bfd_vma end_addr; if (!section) section = pex64_get_section_by_rva (abfd, addr, ".data"); @@ -358,8 +360,14 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr) } if (!section) return; + 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)); + + end_addr -= vsize; if (bfd_malloc_and_get_section (abfd, section, &data)) { struct pex64_unwind_info ui; @@ -408,40 +416,23 @@ pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr) pex64_xdata_print_uwd_codes (file, &ui, pc_addr); - switch (ui.Flags) - { - case UNW_FLAG_NHANDLER: - return; - case UNW_FLAG_EHANDLER: - fprintf (file, "\texception_handler at 0x%x.\n", (unsigned int) ui.rva_ExceptionHandler); - break; - case UNW_FLAG_UHANDLER: - fprintf (file, "\ttermination_handler at 0x%x.\n", (unsigned int) ui.rva_TerminationHandler); - case UNW_FLAG_FHANDLER: - fprintf (file, "\tframe_handler at 0x%x.\n", (unsigned int) ui.rva_FrameHandler); - fprintf (file, "\t Argument for FrameHandler: 0x%x.\n", - (unsigned int) ui.FrameHandlerArgument); - return; - case UNW_FLAG_CHAININFO: - fprintf (file, "\t Function Entry: 0x%x\n", (unsigned int) ui.rva_FunctionEntry); - return; - default: - fprintf (file, "\t Unknown flag value of 0x%x\n", (unsigned int) ui.Flags); - return; - } - fprintf (file, "\t 0x%x # of scope(s)\n", (unsigned int) ui.CountOfScopes); - for (i = 0; i < ui.CountOfScopes; i++) - { - struct pex64_scope_entry se; - pex64_get_scope_entry (abfd, &se, i, ui.rawScopeEntries); - fprintf (file, "\t scope #%u: BeginAddress: 0x%x, EndAddress: 0x%x," - "\n\t\tHandlerAddress:0x%x, JumpTarget:0x%x\n", - (unsigned int) (i + 1), - (unsigned int) se.rva_BeginAddress, - (unsigned int) se.rva_EndAddress, - (unsigned int) se.rva_HandlerAddress, - (unsigned int) se.rva_JumpAddress); - } + /* Now we need end of this xdata block. */ + addr += ui.SizeOfBlock; + if (addr < end_addr) + { + unsigned int i; + fprintf (file,"\tUser data:\n"); + for (i = 0; addr < end_addr; addr += 1, i++) + { + if ((i & 15) == 0) + fprintf (file, "\t %03x:", i); + fprintf (file, " %02x", data[addr]); + if ((i & 15) == 15) + fprintf (file, "\n"); + } + if ((i & 15) != 0) + fprintf (file, "\n"); + } } if (data != NULL) free (data); @@ -455,8 +446,10 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) asection *section = bfd_get_section_by_name (abfd, ".pdata"); bfd_size_type datasize = 0; bfd_size_type i; - bfd_size_type start, stop; + bfd_size_type stop; + bfd_vma prev_beginaddress = 0; int onaline = PDATA_ROW_SIZE; + int seen_error = 0; if (section == NULL || coff_section_data (abfd, section) == NULL @@ -485,9 +478,8 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) return FALSE; } - start = 0; - - for (i = start; i < stop; i += onaline) + /* Do sanity check of pdata. */ + for (i = 0; i < stop; i += onaline) { struct pex64_runtime_function rf; @@ -499,29 +491,80 @@ pex64_bfd_print_pdata (bfd *abfd, void *vfile) && 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 (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 (seen_error) + { + free (data); + + return TRUE; + } + /* 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, &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; + if (i == 0) + fprintf (file, "\nDump of .xdata\n"); + fputc (' ', file); + fprintf_vma (file, rf.rva_UnwindData); + fprintf (file, ":\n"); + + rf.rva_BeginAddress += pe_data (abfd)->pe_opthdr.ImageBase; + rf.rva_EndAddress += pe_data (abfd)->pe_opthdr.ImageBase; 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_vma (file, rf.rva_UnwindData); fprintf (file, ".\n"); } else - pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress); + pex64_dump_xdata (file, abfd, rf.rva_UnwindData, rf.rva_BeginAddress, + stop, onaline, data); } } -- 2.30.2