📄 range.c
字号:
/* range.c - program execution range routines *//* SimpleScalar(TM) Tool Suite * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. * All Rights Reserved. * * THIS IS A LEGAL DOCUMENT, BY USING SIMPLESCALAR, * YOU ARE AGREEING TO THESE TERMS AND CONDITIONS. * * No portion of this work may be used by any commercial entity, or for any * commercial purpose, without the prior, written permission of SimpleScalar, * LLC (info@simplescalar.com). Nonprofit and noncommercial use is permitted * as described below. * * 1. SimpleScalar is provided AS IS, with no warranty of any kind, express * or implied. The user of the program accepts full responsibility for the * application of the program and the use of any results. * * 2. Nonprofit and noncommercial use is encouraged. SimpleScalar may be * downloaded, compiled, executed, copied, and modified solely for nonprofit, * educational, noncommercial research, and noncommercial scholarship * purposes provided that this notice in its entirety accompanies all copies. * Copies of the modified software can be delivered to persons who use it * solely for nonprofit, educational, noncommercial research, and * noncommercial scholarship purposes provided that this notice in its * entirety accompanies all copies. * * 3. ALL COMMERCIAL USE, AND ALL USE BY FOR PROFIT ENTITIES, IS EXPRESSLY * PROHIBITED WITHOUT A LICENSE FROM SIMPLESCALAR, LLC (info@simplescalar.com). * * 4. No nonprofit user may place any restrictions on the use of this software, * including as modified by the user, by any other authorized user. * * 5. Noncommercial and nonprofit users may distribute copies of SimpleScalar * in compiled or executable form as set forth in Section 2, provided that * either: (A) it is accompanied by the corresponding machine-readable source * code, or (B) it is accompanied by a written offer, with no time limit, to * give anyone a machine-readable copy of the corresponding source code in * return for reimbursement of the cost of distribution. This written offer * must permit verbatim duplication by anyone, or (C) it is distributed by * someone who received only the executable form, and is accompanied by a * copy of the written offer of source code. * * 6. SimpleScalar was developed by Todd M. Austin, Ph.D. The tool suite is * currently maintained by SimpleScalar LLC (info@simplescalar.com). US Mail: * 2395 Timbercrest Court, Ann Arbor, MI 48105. * * Copyright (C) 1994-2003 by Todd M. Austin, Ph.D. and SimpleScalar, LLC. */#include <stdio.h>#include <stdlib.h>#include <string.h>#include <errno.h>#include "host.h"#include "misc.h"#include "machine.h"#include "symbol.h"#include "loader.h"#include "range.h"/* parse execution position *PSTR to *POS */char * /* error string, or NULL */range_parse_pos(char *pstr, /* execution position string */ struct range_pos_t *pos) /* position return buffer */{ char *s, *endp; struct sym_sym_t *sym; /* determine position type */ if (pstr[0] == '@') { /* address position */ pos->ptype = pt_addr; s = pstr + 1; } else if (pstr[0] == '#') { /* cycle count position */ pos->ptype = pt_cycle; s = pstr + 1; } else { /* inst count position */ pos->ptype = pt_inst; s = pstr; } /* get position value */ errno = 0; pos->pos = (counter_t)strtoul(s, &endp, /* parse base */0); if (!errno && !*endp) { /* good conversion */ return NULL; } /* else, not an integer, attempt double conversion */ errno = 0; pos->pos = (counter_t)strtod(s, &endp); if (!errno && !*endp) { /* good conversion */ /* FIXME: ignoring decimal point!! */ return NULL; } /* else, attempt symbol lookup */ sym_loadsyms(ld_prog_fname, /* !locals */FALSE); sym = sym_bind_name(s, NULL, sdb_any); if (sym != NULL) { pos->pos = (counter_t)sym->addr; return NULL; } /* else, no binding made */ return "cannot bind execution position to a value";}/* print execution position *POS */voidrange_print_pos(struct range_pos_t *pos, /* execution position */ FILE *stream) /* output stream */{ switch (pos->ptype) { case pt_addr: myfprintf(stream, "@0x%08p", (md_addr_t)pos->pos); break; case pt_inst: fprintf(stream, "%.0f", (double)pos->pos); break; case pt_cycle: fprintf(stream, "#%.0f", (double)pos->pos); break; default: panic("bogus execution position type"); }}/* parse execution range *RSTR to *RANGE */char * /* error string, or NULL */range_parse_range(char *rstr, /* execution range string */ struct range_range_t *range) /* range return buffer */{ char *pos1, *pos2, *p, buf[512], *errstr; /* make a copy of the execution range */ strcpy(buf, rstr); pos1 = buf; /* find mid-point */ p = buf; while (*p != ':' && *p != '\0') { p++; } if (*p != ':') return "badly formed execution range"; *p = '\0'; /* this is where the second position will start */ pos2 = p + 1; /* parse start position */ if (*pos1 && *pos1 != ':') { errstr = range_parse_pos(pos1, &range->start); if (errstr) return errstr; } else { /* default start range */ range->start.ptype = pt_inst; range->start.pos = 0; } /* parse end position */ if (*pos2) { if (*pos2 == '+') { int delta; char *endp; /* get delta value */ errno = 0; delta = strtol(pos2 + 1, &endp, /* parse base */0); if (!errno && !*endp) { /* good conversion */ range->end.ptype = range->start.ptype; range->end.pos = range->start.pos + delta; } else { /* bad conversion */ return "badly formed execution range delta"; } } else { errstr = range_parse_pos(pos2, &range->end); if (errstr) return errstr; } } else { /* default end range */ range->end.ptype = range->start.ptype;#ifdef HOST_HAS_QWORD range->end.pos = ULL(0x7fffffffffffffff);#else /* !__GNUC__ */ range->end.pos = 281474976645120.0;#endif /* __GNUC__ */ } /* no error */ return NULL;}/* print execution range *RANGE */voidrange_print_range(struct range_range_t *range, /* execution range */ FILE *stream) /* output stream */{ range_print_pos(&range->start, stream); fprintf(stream, ":"); range_print_pos(&range->end, stream);}/* determine if inputs match execution position */int /* relation to position */range_cmp_pos(struct range_pos_t *pos, /* execution position */ counter_t val) /* position value */{ if (val < pos->pos) return /* before */-1; else if (val == pos->pos) return /* equal */0; else /* if (pos->pos < val) */ return /* after */1;}/* determine if inputs are in range */int /* relation to range */range_cmp_range(struct range_range_t *range, /* execution range */ counter_t val) /* position value */{ if (range->start.ptype != range->end.ptype) panic("invalid range"); if (val < range->start.pos) return /* before */-1; else if (range->start.pos <= val && val <= range->end.pos) return /* inside */0; else /* if (range->end.pos < val) */ return /* after */1;}/* determine if inputs are in range, passes all possible info needed */int /* relation to range */range_cmp_range1(struct range_range_t *range, /* execution range */ md_addr_t addr, /* address value */ counter_t icount, /* instruction count */ counter_t cycle) /* cycle count */{ if (range->start.ptype != range->end.ptype) panic("invalid range"); switch (range->start.ptype) { case pt_addr: if (addr < (md_addr_t)range->start.pos) return /* before */-1; else if ((md_addr_t)range->start.pos <= addr && addr <= (md_addr_t)range->end.pos) return /* inside */0; else /* if (range->end.pos < addr) */ return /* after */1; break; case pt_inst: if (icount < range->start.pos) return /* before */-1; else if (range->start.pos <= icount && icount <= range->end.pos) return /* inside */0; else /* if (range->end.pos < icount) */ return /* after */1; break; case pt_cycle: if (cycle < range->start.pos) return /* before */-1; else if (range->start.pos <= cycle && cycle <= range->end.pos) return /* inside */0; else /* if (range->end.pos < cycle) */ return /* after */1; break; default: panic("bogus range type"); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -