/*
 * Use this when both arc.angle and anext are multiples of 90 degrees,
 * and anext = arc.angle +/- 90.
 */
static int
next_arc_quadrant(arc_curve_params_t * arc, double anext)
{
    double x0 = arc->p0.x = arc->p3.x;
    double y0 = arc->p0.y = arc->p3.y;

    if (!arc->fast_quadrant) {
	/*
	 * If the CTM is well-behaved, we can pre-calculate the delta
	 * from the arc points to the control points.
	 */
	const gs_imager_state *pis = arc->pis;
	double scale = 0; /* Quiet gcc warning. */

	if (is_fzero2(pis->ctm.xy, pis->ctm.yx) ?
	    (scale = fabs(pis->ctm.xx)) == fabs(pis->ctm.yy) :
	    is_fzero2(pis->ctm.xx, pis->ctm.yy) ?
	    (scale = fabs(pis->ctm.xy)) == fabs(pis->ctm.yx) :
	    0
	    ) {
	    double scaled_radius = arc->radius * scale;

	    arc->scaled_radius = float2fixed(scaled_radius);
	    arc->quadrant_delta =
		float2fixed(scaled_radius * quarter_arc_fraction);
	    arc->fast_quadrant = 1;
	} else {
	    arc->fast_quadrant = -1;
	}
    }
    /*
     * We know that anext is a multiple of 90 (as a fixed); we want
     * (anext / 90) & 3.  The following is much faster than a division.
     */
    switch (((int)anext >> 1) & 3) {
    case 0:
	arc->sincos.sin = 0, arc->sincos.cos = 1;
	arc->p3.x = x0 = arc->center.x + arc->radius;
	arc->p3.y = arc->center.y;
	break;
    case 1:
	arc->sincos.sin = 1, arc->sincos.cos = 0;
	arc->p3.x = arc->center.x;
	arc->p3.y = y0 = arc->center.y + arc->radius;
	break;
    case 2:
	arc->sincos.sin = 0, arc->sincos.cos = -1;
	arc->p3.x = x0 = arc->center.x - arc->radius;
	arc->p3.y = arc->center.y;
	break;
    case 3:
	arc->sincos.sin = -1, arc->sincos.cos = 0;
	arc->p3.x = arc->center.x;
	arc->p3.y = y0 = arc->center.y - arc->radius;
	break;
    }
    arc->pt.x = x0, arc->pt.y = y0;
    arc->angle = anext;
    return arc_add(arc, true);
}
void
aarch64_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
{
  bfd_vma pc, dest_pc, offset;
  unsigned int insn;
  Sym *child;

  DBG (CALLDEBUG, printf ("[find_call] %s: 0x%lx to 0x%lx\n",
			  parent->name, (unsigned long) p_lowpc,
			  (unsigned long) p_highpc));

  for (pc = p_lowpc; pc < p_highpc; pc += 4)
    {

      insn = bfd_get_32 (core_bfd, ((unsigned char *) core_text_space
				    + pc - core_text_sect->vma));

      if ((insn & BRANCH_MASK) == BRANCH_PATTERN)
	{
	  DBG (CALLDEBUG,
	       printf ("[find_call] 0x%lx: bl", (unsigned long) pc));

	  /* Regular pc relative addressing check that this is the
	     address of a function.  */
	  offset = ((((bfd_vma) insn & 0x3ffffff) ^ 0x2000000) - 0x2000000) << 2;

	  dest_pc = pc + offset;

	  if (hist_check_address (dest_pc))
	    {
	      child = sym_lookup (&symtab, dest_pc);

	      if (child)
		{
		  DBG (CALLDEBUG,
		       printf ("\tdest_pc=0x%lx, (name=%s, addr=0x%lx)\n",
			       (unsigned long) dest_pc, child->name,
			       (unsigned long) child->addr));

		  if (child->addr == dest_pc)
		    {
		      /* a hit.  */
		      arc_add (parent, child, (unsigned long) 0);
		      continue;
		    }
		}
	    }

	  /* Something funny going on.  */
	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
	}
    }
}
Exemple #3
0
void
i386_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
{
  unsigned char *instructp;
  Sym *child;
  bfd_vma pc, destpc;

  DBG (CALLDEBUG, printf ("[findcall] %s: 0x%lx to 0x%lx\n",
			  parent->name, (unsigned long) p_lowpc,
			  (unsigned long) p_highpc));

  for (pc = p_lowpc; pc < p_highpc; ++pc)
    {
      instructp = (unsigned char *) core_text_space + pc - core_text_sect->vma;
      if (i386_iscall (instructp))
	{
	  DBG (CALLDEBUG,
	       printf ("[findcall]\t0x%lx:call", (unsigned long) pc));
	  /*
	   *  regular pc relative addressing
	   *    check that this is the address of
	   *    a function.
	   */

	  destpc = bfd_get_32 (core_bfd[0], instructp + 1) + pc + 5;
	  if (hist_check_address (destpc))
	    {
	      child = sym_lookup (&symtab, destpc);
	      if (child && child->addr == destpc)
		{
		  /*
		   *      a hit
		   */
		  DBG (CALLDEBUG,
		       printf ("\tdestpc 0x%lx (%s)\n",
			       (unsigned long) destpc, child->name));
		  arc_add (parent, child, (unsigned long) 0);
		  instructp += 4;	/* call is a 5 byte instruction */
		  continue;
		}
	    }
	  /*
	   *  else:
	   *    it looked like a callf, but it:
	   *      a) wasn't actually a callf, or
	   *      b) didn't point to a known function in the symtab, or
	   *      c) something funny is going on.
	   */
	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
	}
    }
}
Exemple #4
0
int
parse_cmd (char *line, arc_t *arc)
{
	char		*p, *q;
	unsigned long	id;
	char		*name;
	int		len, rc;

	if ((line == NULL) || (arc == NULL)) abort();

	p = line; while (isspace (*p)) p++;
	if (!isdigit (*p)) return (0);

	/* use strtoul side-effect to get to next field on line */
	errno = 0; id = strtoul (p, &q, 0);
	if (errno || !isspace (*q)) return (0);

	/* skip whitespace */
	p = q; while (isspace (*p)) p++;
	if (*p != '"') return (0);

	/* extract filename */
	p++; q = p; while ((*p != '\0') && (*p != '"')) p++;
	if (*p != '"') return (0);
	*p = '\0';
	name = strdup (q);

	/* fix backslashes in filename */
	p = name; len = strlen (p);
	while (*p != '\0') {
		if (*p == '\\') {
			*p = '/'; p++;
			/* calc len - offset, offset == p - item->name, because we shift p
			 * with 1 char we lose the extra '\' and include the trailing '\0'! */
			memmove (p, p+1, len - (p - name));
			/* length is reduced by 1! */
			len--;
		} else p++;
	}

	rc = arc_add (arc, id, name);

	if (rc) printf ("%lu\t%s\n", id, name);

	free (name);
	return (rc);
}
/* Compute the next curve as part of an arc. */
static int
next_arc_curve(arc_curve_params_t * arc, double anext)
{
    double x0 = arc->p0.x = arc->p3.x;
    double y0 = arc->p0.y = arc->p3.y;
    double trad = arc->radius *
	tan((anext - arc->angle) *
	    (degrees_to_radians / 2));

    arc->pt.x = x0 - trad * arc->sincos.sin;
    arc->pt.y = y0 + trad * arc->sincos.cos;
    gs_sincos_degrees(anext, &arc->sincos);
    arc->p3.x = arc->center.x + arc->radius * arc->sincos.cos;
    arc->p3.y = arc->center.y + arc->radius * arc->sincos.sin;
    arc->angle = anext;
    return arc_add(arc, false);
}
int
gs_arcto(gs_state * pgs,
floatp ax1, floatp ay1, floatp ax2, floatp ay2, floatp arad, float retxy[4])
{
    double xt0, yt0, xt2, yt2;
    gs_point up0;

#define ax0 up0.x
#define ay0 up0.y
    /* Transform the current point back into user coordinates. */
    int code = gs_currentpoint(pgs, &up0);

    if (code < 0)
	return code;
    {	
        double dx0, dy0, dx2, dy2, sql0, sql2;
        
        /* Now we have to compute the tangent points. */
	/* Basically, the idea is to compute the tangent */
	/* of the bisector by using tan(x+y) and tan(z/2) */
	/* formulas, without ever using any trig. */
	dx0 = ax0 - ax1; dy0 = ay0 - ay1;
	dx2 = ax2 - ax1; dy2 = ay2 - ay1;

	/* Compute the squared lengths from p1 to p0 and p2. */
	sql0 = dx0 * dx0 + dy0 * dy0;
	sql2 = dx2 * dx2 + dy2 * dy2;

        if (sql0 == 0. || sql2 == 0.)
            return_error(gs_error_undefinedresult); /* for CET 11-04 */

	/* Check for collinear points. */
	if (dx0*dy2 == dy0*dx2) {
	    code = gs_lineto(pgs, ax1, ay1);
	    xt0 = xt2 = ax1;
	    yt0 = yt2 = ay1;
	} else {		/* not collinear */
	    /* Compute the distance from p1 to the tangent points. */
	    /* This is the only messy part. */
	    double num = dy0 * dx2 - dy2 * dx0;
	    double denom = sqrt(sql0 * sql2) - (dx0 * dx2 + dy0 * dy2);

	    double dist = fabs(arad * num / denom);
	    double l0 = dist / sqrt(sql0), l2 = dist / sqrt(sql2);
	    arc_curve_params_t arc;

	    arc.ppath = pgs->path;
	    arc.pis = (gs_imager_state *) pgs;
	    arc.radius = arad;
	    arc.action = arc_lineto;
	    arc.notes = sn_none;
	    if (arad < 0)
		l0 = -l0, l2 = -l2;
	    arc.p0.x = xt0 = ax1 + dx0 * l0;
	    arc.p0.y = yt0 = ay1 + dy0 * l0;
	    arc.p3.x = xt2 = ax1 + dx2 * l2;
	    arc.p3.y = yt2 = ay1 + dy2 * l2;
	    arc.pt.x = ax1;
	    arc.pt.y = ay1;
	    code = arc_add(&arc, false);
	    if (code == 0)
		code = gx_setcurrentpoint_from_path((gs_imager_state *)pgs, pgs->path);
	}
    }
    if (retxy != 0) {
	retxy[0] = xt0;
	retxy[1] = yt0;
	retxy[2] = xt2;
	retxy[3] = yt2;
    }
    return code;
}
Exemple #7
0
void
sym_id_parse (void)
{
  Sym *sym, *left, *right;
  struct sym_id *id;
  Sym_Table *tab;

  /* Convert symbol ids into Syms, so we can deal with them more easily.  */
  for (id = id_list; id; id = id->next)
    parse_id (id);

  /* First determine size of each table.  */
  for (sym = symtab.base; sym < symtab.limit; ++sym)
    {
      for (id = id_list; id; id = id->next)
	{
	  if (match (&id->left.sym, sym))
	    extend_match (&id->left, sym, &syms[id->which_table], FALSE);

	  if (id->has_right && match (&id->right.sym, sym))
	    extend_match (&id->right, sym, &right_ids, FALSE);
	}
    }

  /* Create tables of appropriate size and reset lengths.  */
  for (tab = syms; tab < &syms[NUM_TABLES]; ++tab)
    {
      if (tab->len)
	{
	  tab->base = (Sym *) xmalloc (tab->len * sizeof (Sym));
	  tab->limit = tab->base + tab->len;
	  tab->len = 0;
	}
    }

  if (right_ids.len)
    {
      right_ids.base = (Sym *) xmalloc (right_ids.len * sizeof (Sym));
      right_ids.limit = right_ids.base + right_ids.len;
      right_ids.len = 0;
    }

  /* Make a second pass through symtab, creating syms as necessary.  */
  for (sym = symtab.base; sym < symtab.limit; ++sym)
    {
      for (id = id_list; id; id = id->next)
	{
	  if (match (&id->left.sym, sym))
	    extend_match (&id->left, sym, &syms[id->which_table], TRUE);

	  if (id->has_right && match (&id->right.sym, sym))
	    extend_match (&id->right, sym, &right_ids, TRUE);
	}
    }

  /* Go through ids creating arcs as needed.  */
  for (id = id_list; id; id = id->next)
    {
      if (id->has_right)
	{
	  for (left = id->left.first_match; left; left = left->next)
	    {
	      for (right = id->right.first_match; right; right = right->next)
		{
		  DBG (IDDEBUG,
		       printf (
				"[sym_id_parse]: arc %s:%s(%lx-%lx) -> %s:%s(%lx-%lx) to %s\n",
				left->file ? left->file->name : "*",
				left->name ? left->name : "*",
				(unsigned long) left->addr,
				(unsigned long) left->end_addr,
				right->file ? right->file->name : "*",
				right->name ? right->name : "*",
				(unsigned long) right->addr,
				(unsigned long) right->end_addr,
				table_name[id->which_table]));

		  arc_add (left, right, (unsigned long) 0);
		}
	    }
	}
    }

  /* Finally, we can sort the tables and we're done.  */
  for (tab = &syms[0]; tab < &syms[NUM_TABLES]; ++tab)
    {
      DBG (IDDEBUG, printf ("[sym_id_parse] syms[%s]:\n",
			    table_name[tab - &syms[0]]));
      symtab_finalize (tab);
    }
}
Exemple #8
0
/*
 * On the Alpha we can only detect PC relative calls, which are
 * usually generated for calls to functions within the same
 * object file only.  This is still better than nothing, however.
 * (In particular it should be possible to find functions that
 *  potentially call integer division routines, for example.)
 */
void
alpha_find_call (Sym *parent, bfd_vma p_lowpc, bfd_vma p_highpc)
{
  bfd_vma pc, dest_pc;
  unsigned int insn;
  Sym *child;

  if (indirect_child.name == NULL)
    {
      sym_init (&indirect_child);
      indirect_child.name = _("<indirect child>");
      indirect_child.cg.prop.fract = 1.0;
      indirect_child.cg.cyc.head = &indirect_child;
    }

  DBG (CALLDEBUG, printf (_("[find_call] %s: 0x%lx to 0x%lx\n"),
			  parent->name, (unsigned long) p_lowpc,
			  (unsigned long) p_highpc));
  for (pc = (p_lowpc + 3) & ~(bfd_vma) 3; pc < p_highpc; pc += 4)
    {
      insn = bfd_get_32 (core_bfd[0], ((unsigned char *) core_text_space
				    + pc - core_text_sect->vma));
      switch (insn & (0x3f << 26))
	{
	case OP_Jxx << 26:
	  /*
	   * There is no simple and reliable way to determine the
	   * target of a jsr (the hint bits help, but there aren't
	   * enough bits to get a satisfactory hit rate).  Instead,
	   * for any indirect jump we simply add an arc from PARENT
	   * to INDIRECT_CHILD---that way the user it at least able
	   * to see that there are other calls as well.
	   */
	  if ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
	      || (insn & (3 << 14)) == Jxx_FUNC_JSR_COROUTINE << 14)
	    {
	      DBG (CALLDEBUG,
		   printf (_("[find_call] 0x%lx: jsr%s <indirect_child>\n"),
			   (unsigned long) pc,
			   ((insn & (3 << 14)) == Jxx_FUNC_JSR << 14
			    ? "" : "_coroutine")));
	      arc_add (parent, &indirect_child, (unsigned long) 0);
	    }
	  break;

	case OP_BSR << 26:
	  DBG (CALLDEBUG,
	       printf (_("[find_call] 0x%lx: bsr"), (unsigned long) pc));
	  /*
	   * Regular PC relative addressing.  Check that this is the
	   * address of a function.  The linker sometimes redirects
	   * the entry point by 8 bytes to skip loading the global
	   * pointer, so we allow for either address:
	   */
	  dest_pc = pc + 4 + (((bfd_signed_vma) (insn & 0x1fffff)
			       ^ 0x100000) - 0x100000);
	  if (hist_check_address (dest_pc))
	    {
	      child = sym_lookup (&symtab, dest_pc);
              if (child)
                {
	          DBG (CALLDEBUG,
		       printf (" 0x%lx\t; name=%s, addr=0x%lx",
			       (unsigned long) dest_pc, child->name,
			       (unsigned long) child->addr));
	          if (child->addr == dest_pc || child->addr == dest_pc - 8)
		    {
		      DBG (CALLDEBUG, printf ("\n"));
		      /* a hit:  */
		      arc_add (parent, child, (unsigned long) 0);
		      continue;
		    }
                }
	    }
	  /*
	   * Something funny going on.
	   */
	  DBG (CALLDEBUG, printf ("\tbut it's a botch\n"));
	  break;

	default:
	  break;
	}
    }
}