VG_REGPARM(3) void assertDynamicSize(const char* label, ShadowTemp* temp, FloatBlocks num_blocks){ if (temp == NULL) return; tl_assert2(INT(temp->num_blocks) == INT(num_blocks), "%s: Expected %d vals in %p, got %d", label, INT(num_blocks), temp, INT(temp->num_blocks)); for(int i = 1; i < INT(temp->num_blocks); ++i){ tl_assert2(temp->values[i]->type == temp->values[0]->type, "%s: Value %d in %p is not a %s, but value 0 is!", label, i, temp, typeName(temp->values[0]->type)); } }
VG_REGPARM(3) void assertNumBlocksNot(const char* label, ShadowTemp* temp, FloatBlocks num_blocks){ tl_assert2(INT(temp->num_blocks) != INT(num_blocks), "%s: Expected not %d vals in %p, got %d\n", label, INT(num_blocks), temp, INT(temp->num_blocks)); }
VG_REGPARM(3) void assertTempType(const char* label, ShadowTemp* temp, ValueType type){ for(int i = 0; i < INT(temp->num_blocks); i += temp->values[i]->type == Vt_Double ? 2 : 1){ tl_assert2(temp->values[i]->type == type, "%s: Expected type %d for %p, got %d\n", label, type, temp->values[i], temp->values[i]->type); } }
VG_REGPARM(2) void assertTempValid(const char* label, ShadowTemp* temp){ for(int i = 0; i < INT(temp->num_blocks); i += temp->values[i]->type == Vt_Double ? 2 : 1){ tl_assert2(temp->values[i] != NULL, "%s: Value %d of temp %p is NULL!", label, i, temp); assertValValid(label, temp->values[i]); } }
void printReal(Real real){ #ifdef USE_MPFR char* shadowValStr; mpfr_exp_t shadowValExpt; shadowValStr = mpfr_get_str(NULL, &shadowValExpt, 10, longprint_len, real->mpfr_val, MPFR_RNDN); VG_(printf)("%c.%se%ld", shadowValStr[0], shadowValStr+1, shadowValExpt-1); mpfr_free_str(shadowValStr); #else tl_assert2(0, "Can't print GMP vals!\n"); #endif }
static Char* parse_extra_rule(Char* read_ptr, Trace_Block* block) { Char* name; tl_assert2(block, "the first group cannot be started by {"); read_ptr++; name = read_ptr; while (*read_ptr != '}') { tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r', "unterminated {"); read_ptr++; } tl_assert2(name != read_ptr, "node has no name"); search_rule(block, name, read_ptr - name); read_ptr++; while (*read_ptr == ' ') read_ptr++; tl_assert2(*read_ptr == '\n' || *read_ptr == '\r' || !*read_ptr, "Garbage at the end of the line"); return read_ptr; }
static void search_rule(Trace_Block* block, Char* name, SizeT name_len) { Rule_List* rule_ptr; rule_ptr = rule_head; while (rule_ptr) { if (rule_ptr->name_len == name_len && rule_ptr->name[0] == name[0] && VG_(memcmp)(rule_ptr->name, name, name_len * sizeof(Char)) == 0) { tl_assert2(!rule_ptr->parent, "Rule is already assigned"); rule_ptr->parent = block; return; } rule_ptr = rule_ptr->next; } VG_(printf)("Rule '%s' not found\n", name); tl_assert(0); }
void CheckAssert(int x) { tl_assert(x); tl_assert2(x, "fail"); }
VG_REGPARM(3) void assertValType(const char* label, ShadowValue* val, ValueType type){ tl_assert2(val->type == type, "%s: Expected type %s for %p, got %s\n", label, typeName(type), val, typeName(val->type)); }
VG_REGPARM(2) void assertValValid(const char* label, ShadowValue* val){ tl_assert2(val->real != NULL, "%s: value is %p", label, val); }
static void fr_post_clo_init(void) { Rule_List* last_rule_ptr = NULL; Char* read_ptr; Trace_Block* block = NULL; Trace_Block* parent = NULL; Int* indents = (int*)dir_buffer; Int indent; Int depth = -1; Bool is_group; SysRes sres; Int fd; OffT file_size; if (clo_mmap) { #if VG_WORDSIZE == 4 mmap_section.next = NULL; mmap_section.page_addr = 0; mmap_section.trace_blocks = VG_(calloc)("freya.fr_post_clo_init.2", PAGE_NUMBER, sizeof(Trace_Block*)); mmap_section.used_blocks = VG_(calloc)("freya.fr_post_clo_init.3", PAGE_NUMBER, sizeof(Char)); #else mmap_sections = VG_(calloc)("freya.fr_post_clo_init.1", 1, sizeof(Mmap_Section)); mmap_sections->next = NULL; mmap_sections->page_addr = 0; mmap_sections->trace_blocks = VG_(calloc)("freya.fr_post_clo_init.2", PAGE_NUMBER, sizeof(Trace_Block*)); mmap_sections->used_blocks = VG_(calloc)("freya.fr_post_clo_init.3", PAGE_NUMBER, sizeof(Char)); mmap_section_cache = mmap_sections; #endif } read_ptr = NULL; if (clo_config) { sres = VG_(open)(clo_config, VKI_O_RDONLY, 0); if (!sr_isError(sres)) { fd = (Int) sr_Res(sres); file_size = VG_(lseek)(fd, 0, VKI_SEEK_END); VG_(lseek)(fd, 0, VKI_SEEK_SET); if (clo_fr_verb) VG_(printf)("File '%s' (size: %ld bytes) is successfully opened.\n", clo_config, file_size); read_ptr = VG_(malloc)("freya.fr_post_clo_init.3", (file_size + 1) * sizeof(Char)); VG_(read)(fd, read_ptr, file_size); read_ptr[file_size] = '\0'; VG_(close) (fd); } else if (clo_fr_verb) VG_(printf)("Cannot open '%s'. (Fallback to default config)\n", clo_config); } else if (clo_fr_verb) VG_(printf)("No config file provided. (Fallback to default config)\n"); if (!read_ptr) { // Duplicate read_ptr = VG_(malloc)("freya.fr_post_clo_init.4", (VG_(strlen)(default_rule) + 1) * sizeof(Char)); VG_(strcpy)(read_ptr, default_rule); } while (*read_ptr) { // Parsing the next line, first skip spaces indent = 0; while (*read_ptr == ' ') { indent++; read_ptr++; } // Skip comments and empty lines if (*read_ptr == '#' || *read_ptr == '\r' || *read_ptr == '\n') { while (*read_ptr != '\0' && *read_ptr != '\r' && *read_ptr != '\n') read_ptr++; if (*read_ptr) { read_ptr++; continue; } } if (*read_ptr == '{') { read_ptr = parse_extra_rule(read_ptr, block); continue; } else if (*read_ptr != '[' && *read_ptr != '(') { read_ptr = parse_rule(read_ptr, &last_rule_ptr); continue; } is_group = *read_ptr == '['; block = VG_(malloc)("freya.fr_post_clo_init.4", sizeof(Trace_Block)); read_ptr++; block->name = read_ptr; while (!(!is_group && *read_ptr == ')') && !(is_group && *read_ptr == ']')) { tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r', "unterminated ( or ["); read_ptr++; } tl_assert2(block->name != read_ptr, "node has no name"); *read_ptr = '\0'; if (!is_group) search_rule(block, block->name, read_ptr - block->name); read_ptr++; if (*read_ptr == '+') { tl_assert2(default_parent == NULL, "Only one default node is allowed"); default_parent = block; read_ptr++; } while (*read_ptr == ' ') read_ptr++; tl_assert2(*read_ptr == '\n' || *read_ptr == '\r' || !*read_ptr, "Garbage at the end of the line"); if (clo_fr_verb) VG_(printf)("%s '%s' %s\n", is_group ? "Group:" : "Group & Attach:", block->name, default_parent == block ? "(Default)" : ""); if (depth >= 0) { if (indents[depth] != indent) { if (indent > indents[depth]) { tl_assert2(depth < 63, "Maximum allowed depth is 63 for the tree"); depth++; indents[depth] = indent; if (parent) parent = parent->first; else parent = trace_head; } else { do { tl_assert2(depth != 0, "Wrong tree indentation"); depth--; tl_assert(parent); parent = parent->parent; } while (indent != indents[depth]); tl_assert((depth == 0 && !parent) || (depth > 0 && parent)); } } } else { // The indentation of the top element tl_assert(!parent); indents[0] = indent; depth = 0; } block->parent = parent; if (parent) { block->next = parent->first; parent->first = block; } else { block->next = trace_head; trace_head = block; } block->first = NULL; block->hash_next = NULL; block->allocs = 0; block->total = 0; block->current = 0; block->peak = 0; block->ips = 0; } remove_unused_rules(); }
static Char* parse_rule(Char* read_ptr, Rule_List** last_rule_ptr) { Rule_List* rule; Rule_List* rule_ptr; rule = VG_(malloc)("freya.parse_rule.1", sizeof(Rule_List)); rule->next = NULL; rule->parent = NULL; if (*read_ptr != '-') { rule->name = read_ptr; while (*read_ptr != ' ') { tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r' && *read_ptr != ')', "Rule must start with hypen or a name followed by a space"); read_ptr++; } rule->name_len = read_ptr - rule->name; *read_ptr = '\0'; // Must have a unique name rule_ptr = rule_head; while (rule_ptr) { if (rule_ptr->name_len == rule->name_len && VG_(memcmp)(rule->name, rule_ptr->name, rule->name_len * sizeof(Char)) == 0) { VG_(printf)("Redefined rule %s. Rule names must be unique!\n", rule->name); tl_assert(0); } rule_ptr = rule_ptr->next; } } else { rule->name = NULL; rule->name_len = 0; } read_ptr++; // Enque this new rule if (*last_rule_ptr) (*last_rule_ptr)->next = rule; else rule_head = rule; *last_rule_ptr = rule; while (*read_ptr == ' ') read_ptr++; if (*read_ptr == '(' || *read_ptr == '{') { rule->is_namespace = *read_ptr == '{'; read_ptr++; rule->func_name = read_ptr; while (!(!rule->is_namespace && *read_ptr == ')') && !(rule->is_namespace && *read_ptr == '}')) { tl_assert2(*read_ptr && *read_ptr != '\n' && *read_ptr != '\r', "unterminated ( or {"); read_ptr++; } rule->func_name_len = read_ptr - rule->func_name; tl_assert2(rule->func_name_len > 0, "missing function or namespace name"); *read_ptr = '\0'; read_ptr++; while (*read_ptr == ' ') read_ptr++; } else { rule->func_name = NULL; rule->func_name_len = 0; rule->is_namespace = False; } rule->path = read_ptr; while (*read_ptr && *read_ptr != '\n' && *read_ptr != '\r') read_ptr++; rule->path_len = read_ptr - rule->path; if (rule->path_len == 0) rule->path = NULL; else if (*read_ptr) { *read_ptr = '\0'; read_ptr++; } if (clo_fr_verb) VG_(printf)("Rule: '%s' (%ld) %s: '%s' (%ld) Path: '%s' (%ld)\n", rule->name, rule->name_len, rule->is_namespace ? "Namesp" : "Func", rule->func_name, rule->func_name_len, rule->path, rule->path_len); return read_ptr; }