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