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;
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
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");
}
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;
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);
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
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;
&& 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);
}
}