Пример #1
0
/* Add an entry to the base file: */
static void
mcore_emit_base_file_entry(struct bfd_link_info *info, bfd *output_bfd,
                           asection *input_section, bfd_vma reloc_offset)
{
  bfd_vma addr = (reloc_offset - input_section->vma
                  + input_section->output_offset
                  + input_section->output_section->vma);

  if (coff_data(output_bfd)->pe) {
     addr -= pe_data(output_bfd)->pe_opthdr.ImageBase;
  }

  fwrite(&addr, (size_t)1UL, sizeof(addr), (FILE *)info->base_file);
}
Пример #2
0
static asection *
pex64_get_section_by_rva (bfd *abfd, bfd_vma addr, const char *sec_name)
{
  asection *section = bfd_get_section_by_name (abfd, sec_name);
  bfd_vma vsize;
  bfd_size_type datasize = 0;

  if (section == NULL
      || coff_section_data (abfd, section) == NULL
      || pei_section_data (abfd, section) == NULL)
    return NULL;
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
  datasize = section->size;
  if (!datasize || vsize > addr || (vsize + datasize) < addr)
    return NULL;
  return section;
}
Пример #3
0
static bfd_boolean
mcore_emit_base_file_entry (struct bfd_link_info *info,
			    bfd *output_bfd,
			    asection *input_section,
			    bfd_vma reloc_offset)
{
  bfd_vma addr = reloc_offset
                 - input_section->vma
                 + input_section->output_offset
                 + input_section->output_section->vma;

  if (coff_data (output_bfd)->pe)
     addr -= pe_data (output_bfd)->pe_opthdr.ImageBase;

  if (fwrite (&addr, sizeof (addr), 1, (FILE *) info->base_file) == 1)
    return TRUE;

  bfd_set_error (bfd_error_system_call);
  return FALSE;
}
Пример #4
0
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;
}
Пример #5
0
static void
pex64_dump_xdata (FILE *file, bfd *abfd,
		  asection *xdata_section, bfd_byte *xdata, bfd_vma *endx,
		  struct pex64_runtime_function *rf)
{
  bfd_vma vaddr;
  bfd_vma end_addr;
  bfd_vma addr = rf->rva_UnwindData;
  bfd_size_type sec_size = xdata_section->rawsize > 0 ? xdata_section->rawsize : xdata_section->size;
  struct pex64_unwind_info ui;

  vaddr = xdata_section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
  addr -= vaddr;

  /* PR 17512: file: 2245-7442-0.004.  */
  if (addr >= sec_size)
    {
      fprintf (file, _("warning: xdata section corrupt\n"));
      return;
    }

  if (endx)
    {
      end_addr = endx[0] - vaddr;
      /* PR 17512: file: 2245-7442-0.004.  */
      if (end_addr > sec_size)
	{
	  fprintf (file, _("warning: xdata section corrupt"));
	  end_addr = sec_size;
	}
    }
  else
    end_addr = sec_size;

  pex64_get_unwind_info (abfd, &ui, &xdata[addr]);

  if (ui.Version != 1 && ui.Version != 2)
    {
      unsigned int i;
      fprintf (file, "\tVersion %u (unknown).\n",
	       (unsigned int) ui.Version);
      for (i = 0; addr < end_addr; addr += 1, i++)
	{
	  if ((i & 15) == 0)
	    fprintf (file, "\t  %03x:", i);
	  fprintf (file, " %02x", xdata[addr]);
	  if ((i & 15) == 15)
	    fprintf (file, "\n");
	}
      if ((i & 15) != 0)
	fprintf (file, "\n");
      return;
    }

  fprintf (file, "\tVersion: %d, Flags: ", ui.Version);
  switch (ui.Flags)
    {
    case UNW_FLAG_NHANDLER:
      fprintf (file, "none");
      break;
    case UNW_FLAG_EHANDLER:
      fprintf (file, "UNW_FLAG_EHANDLER");
      break;
    case UNW_FLAG_UHANDLER:
      fprintf (file, "UNW_FLAG_UHANDLER");
      break;
    case UNW_FLAG_FHANDLER:
      fprintf
	(file, "UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER");
      break;
    case UNW_FLAG_CHAININFO:
      fprintf (file, "UNW_FLAG_CHAININFO");
      break;
    default:
      fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
      break;
    }
  fputc ('\n', file);
  fprintf (file, "\tNbr codes: %u, ", (unsigned int) ui.CountOfCodes);
  fprintf (file, "Prologue size: 0x%02x, Frame offset: 0x%x, ",
	   (unsigned int) ui.SizeOfPrologue, (unsigned int) ui.FrameOffset);
  fprintf (file, "Frame reg: %s\n",
	   ui.FrameRegister == 0 ? "none"
	   : pex_regs[(unsigned int) ui.FrameRegister]);

  /* PR 17512: file: 2245-7442-0.004.  */
  if (ui.CountOfCodes * 2 + ui.rawUnwindCodes > xdata + xdata_section->size)
    fprintf (file, _("Too many unwind codes (%ld)\n"), (long) ui.CountOfCodes);
  else
    pex64_xdata_print_uwd_codes (file, abfd, &ui, rf);

  switch (ui.Flags)
    {
    case UNW_FLAG_EHANDLER:
    case UNW_FLAG_UHANDLER:
    case UNW_FLAG_FHANDLER:
      fprintf (file, "\tHandler: ");
      fprintf_vma (file, (ui.rva_ExceptionHandler
			  + pe_data (abfd)->pe_opthdr.ImageBase));
      fprintf (file, ".\n");
      break;
    case UNW_FLAG_CHAININFO:
      fprintf (file, "\tChain: start: ");
      fprintf_vma (file, ui.rva_BeginAddress);
      fprintf (file, ", end: ");
      fprintf_vma (file, ui.rva_EndAddress);
      fprintf (file, "\n\t unwind data: ");
      fprintf_vma (file, ui.rva_UnwindData);
      fprintf (file, ".\n");
      break;
    }

  /* 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", xdata[addr]);
	  if ((i & 15) == 15)
	    fprintf (file, "\n");
	}
      if ((i & 15) != 0)
	fprintf (file, "\n");
    }
}
Пример #6
0
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;
}
Пример #7
0
static void
pex64_dump_xdata (FILE *file, bfd *abfd, bfd_vma addr, bfd_vma pc_addr)
{
  asection *section = pex64_get_section_by_rva (abfd, addr, ".rdata");
  bfd_vma vsize;
  bfd_byte *data = NULL;
  bfd_vma i;

  if (!section)
    section = pex64_get_section_by_rva (abfd, addr, ".data");
  if (!section)
    section = pex64_get_section_by_rva (abfd, addr, ".xdata");
  if (!section)
    {
      section = pex64_get_section_by_rva (abfd, addr, ".pdata");
      if (section)
	{
	  fprintf (file, "\t Shares information with pdata element at 0x");
	  fprintf_vma (file, addr + pe_data (abfd)->pe_opthdr.ImageBase);
	  fprintf (file, ".\n");
	}
    }
  if (!section)
    return;
  vsize = section->vma - pe_data (abfd)->pe_opthdr.ImageBase;
  addr -= vsize;
  if (bfd_malloc_and_get_section (abfd, section, &data))
    {
      struct pex64_unwind_info ui;

      if (!data)
	return;

      pex64_get_unwind_info (abfd, &ui, &data[addr]);

      if (ui.Version != 1)
	{
	  fprintf (file, "\tVersion %u (unknown).\n", (unsigned int) ui.Version);
	  return;
	}

      fprintf (file, "\tFlags: ");
      switch (ui.Flags)
	{
	case UNW_FLAG_NHANDLER:
	  fprintf (file, "UNW_FLAG_NHANDLER");
	  break;
	case UNW_FLAG_EHANDLER:
	  fprintf (file, "UNW_FLAG_EHANDLER");
	  break;
	case UNW_FLAG_UHANDLER:
	  fprintf (file, "UNW_FLAG_UHANDLER");
	  break;
	case UNW_FLAG_FHANDLER:
	  fprintf (file, "UNW_FLAG_FHANDLER = (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER)");
	  break;
	case UNW_FLAG_CHAININFO:
	  fprintf (file, "UNW_FLAG_CHAININFO");
	  break;
	default:
	  fprintf (file, "unknown flags value 0x%x", (unsigned int) ui.Flags);
	  break;
	}
      fprintf (file, ".\n");
      if (ui.CountOfCodes != 0)
	fprintf (file, "\tEntry has %u codes.", (unsigned int) ui.CountOfCodes);
      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"
			      : pex_regs[(unsigned int) ui.FrameRegister]);

      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);
	}
    }
  if (data != NULL)
    free (data);
}
Пример #8
0
static
BOOL StackBackTrace(HANDLE hProcess, HANDLE hThread, PCONTEXT pContext)
{
	STACKFRAME StackFrame;

	HMODULE hModule = NULL;
	TCHAR szModule[MAX_PATH];

#ifdef HAVE_BFD
	bfd *abfd = NULL;
	asymbol **syms = NULL;	// The symbol table.
	long symcount = 0;	// Number of symbols in `syms'.
#endif /* HAVE_BFD */

	assert(!bSymInitialized);

	j_SymSetOptions(/* SYMOPT_UNDNAME | */ SYMOPT_LOAD_LINES);
	if(j_SymInitialize(hProcess, NULL, TRUE))
		bSymInitialized = TRUE;

	memset( &StackFrame, 0, sizeof(StackFrame) );

	// Initialize the STACKFRAME structure for the first call.  This is only
	// necessary for Intel CPUs, and isn't mentioned in the documentation.
	StackFrame.AddrPC.Offset = pContext->Eip;
	StackFrame.AddrPC.Mode = AddrModeFlat;
	StackFrame.AddrStack.Offset = pContext->Esp;
	StackFrame.AddrStack.Mode = AddrModeFlat;
	StackFrame.AddrFrame.Offset = pContext->Ebp;
	StackFrame.AddrFrame.Mode = AddrModeFlat;

	rprintf( _T("Call stack:\r\n") );

	if(0)
		rprintf( _T("AddrPC     AddrReturn AddrFrame  AddrStack\r\n") );

	while ( 1 )
	{
		BOOL bSuccess = FALSE;
#ifdef HAVE_BFD
		const HMODULE hPrevModule = hModule;
#endif /* HAVE_BFD */
		TCHAR szSymName[512] = _T("");
		TCHAR szFileName[MAX_PATH] = _T("");
		DWORD LineNumber = 0;

		if(bSymInitialized)
		{
			if(!j_StackWalk(
					IMAGE_FILE_MACHINE_I386,
					hProcess,
					hThread,
					&StackFrame,
					pContext,
					NULL,
					j_SymFunctionTableAccess,
					j_SymGetModuleBase,
					NULL
				)
			)
				break;
		}
		else
		{
			if(!IntelStackWalk(
					IMAGE_FILE_MACHINE_I386,
					hProcess,
					hThread,
					&StackFrame,
					pContext,
					NULL,
					NULL,
					NULL,
					NULL
				)
			)
				break;
		}

		// Basic sanity check to make sure  the frame is OK.  Bail if not.
		if ( 0 == StackFrame.AddrFrame.Offset )
			break;

		if(0)
		{
			rprintf(
				_T("%08lX   %08lX   %08lX   %08lX\r\n"),
				StackFrame.AddrPC.Offset,
				StackFrame.AddrReturn.Offset,
				StackFrame.AddrFrame.Offset,
				StackFrame.AddrStack.Offset
			);
			rprintf(
				_T("%08lX   %08lX   %08lX   %08lX\r\n"),
				StackFrame.Params[0],
				StackFrame.Params[1],
				StackFrame.Params[2],
				StackFrame.Params[3]
			);
		}

		rprintf( _T("%08lX"), StackFrame.AddrPC.Offset);

		if((hModule = (HMODULE) GetModuleBase(StackFrame.AddrPC.Offset)) && GetModuleFileName(hModule, szModule, sizeof(szModule)))
		{
#ifndef HAVE_BFD
			rprintf( _T("  %s:ModulBase %08lX"), szModule, hModule);
#else /* HAVE_BFD */
			rprintf( _T("  %s:%08lX"), szModule, StackFrame.AddrPC.Offset);

			if(hModule != hPrevModule)
			{
				if(syms)
				{
					GlobalFree(syms);
					syms = NULL;
					symcount = 0;
				}

				if(abfd)
					bfd_close(abfd);

				if((abfd = bfd_openr (szModule, NULL)))
					if(bfd_check_format(abfd, bfd_object))
					{
						bfd_vma adjust_section_vma = 0;

						/* If we are adjusting section VMA's, change them all now.  Changing
						the BFD information is a hack.  However, we must do it, or
						bfd_find_nearest_line will not do the right thing.  */
						if ((adjust_section_vma = (bfd_vma) hModule - pe_data(abfd)->pe_opthdr.ImageBase))
						{
							asection *s;

							for (s = abfd->sections; s != NULL; s = s->next)
							{
								s->vma += adjust_section_vma;
								s->lma += adjust_section_vma;
							}
						}

						if(bfd_get_file_flags(abfd) & HAS_SYMS)
							/* Read in the symbol table.  */
							slurp_symtab(abfd, &syms, &symcount);
					}
			}

			if(!bSuccess && abfd && syms && symcount)
				if((bSuccess = BfdGetSymFromAddr(abfd, syms, symcount, StackFrame.AddrPC.Offset, szSymName, 512)))
				{
					/*
					framepointer = StackFrame.AddrFrame.Offset;
					hprocess = hProcess;
					*/

					BfdDemangleSymName(szSymName, szSymName, 512);

					rprintf( _T("  %s"), szSymName);

					if(BfdGetLineFromAddr(abfd, syms, symcount, StackFrame.AddrPC.Offset, szFileName, MAX_PATH, &LineNumber))
						rprintf( _T("  %s:%ld"), szFileName, LineNumber);
				}
#endif /* HAVE_BFD */

			if(!bSuccess && bSymInitialized)
				if((bSuccess = ImagehlpGetSymFromAddr(hProcess, StackFrame.AddrPC.Offset, szSymName, 512)))
				{
					rprintf( _T("  %s"), szSymName);

					ImagehlpDemangleSymName(szSymName, szSymName, 512);

					if(ImagehlpGetLineFromAddr(hProcess, StackFrame.AddrPC.Offset, szFileName, MAX_PATH, &LineNumber))
						rprintf( _T("  %s:%ld"), szFileName, LineNumber);
				}

			if(!bSuccess)
				if((bSuccess = PEGetSymFromAddr(hProcess, StackFrame.AddrPC.Offset, szSymName, 512)))
					rprintf( _T("  %s"), szSymName);
		}

		rprintf(_T("\r\n"));
	}

#ifdef HAVE_BFD
	if(syms)
	{
		GlobalFree(syms);
		syms = NULL;
		symcount = 0;
	}

	if(abfd)
		bfd_close(abfd);
#endif /* HAVE_BFD */

	if(bSymInitialized)
	{
		if(!j_SymCleanup(hProcess))
			assert(0);

		bSymInitialized = FALSE;
	}

	return TRUE;
}
Пример #9
0
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;
}
Пример #10
0
static int
amd64_windows_find_unwind_info (struct gdbarch *gdbarch, CORE_ADDR pc,
				CORE_ADDR *unwind_info,
				CORE_ADDR *image_base,
				CORE_ADDR *start_rva,
				CORE_ADDR *end_rva)
{
  struct obj_section *sec;
  pe_data_type *pe;
  IMAGE_DATA_DIRECTORY *dir;
  struct objfile *objfile;
  unsigned long lo, hi;
  CORE_ADDR base;
  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

  /* Get the corresponding exception directory.  */
  sec = find_pc_section (pc);
  if (sec == NULL)
    return -1;
  objfile = sec->objfile;
  pe = pe_data (sec->objfile->obfd);
  dir = &pe->pe_opthdr.DataDirectory[PE_EXCEPTION_TABLE];

  base = pe->pe_opthdr.ImageBase
    + ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
  *image_base = base;

  /* Find the entry.

     Note: This does not handle dynamically added entries (for JIT
     engines).  For this, we would need to ask the kernel directly,
     which means getting some info from the native layer.  For the
     rest of the code, however, it's probably faster to search
     the entry ourselves.  */
  lo = 0;
  hi = dir->Size / sizeof (struct external_pex64_runtime_function);
  *unwind_info = 0;
  while (lo <= hi)
    {
      unsigned long mid = lo + (hi - lo) / 2;
      struct external_pex64_runtime_function d;
      CORE_ADDR sa, ea;

      if (target_read_memory (base + dir->VirtualAddress + mid * sizeof (d),
			      (gdb_byte *) &d, sizeof (d)) != 0)
	return -1;

      sa = extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
      ea = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
      if (pc < base + sa)
	hi = mid - 1;
      else if (pc >= base + ea)
	lo = mid + 1;
      else if (pc >= base + sa && pc < base + ea)
	{
	  /* Got it.  */
	  *start_rva = sa;
	  *end_rva = ea;
	  *unwind_info =
	    extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);
	  break;
	}
      else
	break;
    }

  if (frame_debug)
    fprintf_unfiltered
      (gdb_stdlog,
       "amd64_windows_find_unwind_data:  image_base=%s, unwind_data=%s\n",
       paddress (gdbarch, base), paddress (gdbarch, *unwind_info));

  if (*unwind_info & 1)
    {
      /* Unofficially documented unwind info redirection, when UNWIND_INFO
	 address is odd (http://www.codemachine.com/article_x64deepdive.html).
      */
      struct external_pex64_runtime_function d;
      CORE_ADDR sa, ea;

      if (target_read_memory (base + (*unwind_info & ~1),
			      (gdb_byte *) &d, sizeof (d)) != 0)
	return -1;

      *start_rva =
	extract_unsigned_integer (d.rva_BeginAddress, 4, byte_order);
      *end_rva = extract_unsigned_integer (d.rva_EndAddress, 4, byte_order);
      *unwind_info =
	extract_unsigned_integer (d.rva_UnwindData, 4, byte_order);

    }
  return 0;
}