1bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov/* Copyright (c) 2008-2010, Google Inc. 2bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * All rights reserved. 3bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 4bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * Redistribution and use in source and binary forms, with or without 5bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * modification, are permitted provided that the following conditions are 6bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * met: 7bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 8bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Redistributions of source code must retain the above copyright 9bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * notice, this list of conditions and the following disclaimer. 10bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * * Neither the name of Google Inc. nor the names of its 11bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * contributors may be used to endorse or promote products derived from 12bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * this software without specific prior written permission. 13bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * 14bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 15bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 16bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 17bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 18bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 19bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 20bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov */ 26bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 27bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// This file is part of ThreadSanitizer, a dynamic data race detector. 28bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Author: Konstantin Serebryany. 29bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Author: Timur Iskhodzhanov. 30bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 31bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Experimental off-line race detector. 32bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Reads program events from a file and detects races. 33bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// See http://code.google.com/p/data-race-test 34bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 35bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// ------------- Includes ------------- {{{1 36bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "thread_sanitizer.h" 37bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include "ts_events.h" 38bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 39bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include <stdio.h> 40bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include <stdarg.h> 41bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include <ctype.h> 42bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov#include <time.h> 43bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 44bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// ------------- Globals ------------- {{{1 45bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic map<string, int> *g_event_type_map; 46bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstruct PcInfo { 47bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string img_name; 48bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string file_name; 49bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string rtn_name; 50bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int line; 51bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov}; 52bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 53bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic map<uintptr_t, PcInfo> *g_pc_info_map; 54bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 55bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovunsigned long offline_line_n; 56bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//------------- Read binary file Utils ------------ {{{1 57bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic const int kBufSize = 65536; 58bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 59bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovtemplate<typename T> 60bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic bool Read(FILE *fp, T *res) { 61bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned char buf[16]; 62bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int size = fread(buf, sizeof(T), 1, fp); 63bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *res = 0; 64bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (unsigned int i=0; i<sizeof(T); i++) { 65bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *res <<= 8; 66bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *res += buf[i]; 67bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 68bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return size == 1; 69bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 70bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 71bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 72bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic bool ReadANSI(FILE *file, string *res) { 73bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char buf[kBufSize]; 74bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned short length; 75bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (!Read<unsigned short>(file, &length)) { 76bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return false; 77bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 78bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int size = fread(buf, 1, (int)length, file); 79bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov buf[length] = 0; 80bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *res = (char *)buf; 81bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return size == length; 82bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 83bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//------------- Utils ------------------- {{{1 84bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic EventType EventNameToEventType(const char *name) { 85bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov map<string, int>::iterator it = g_event_type_map->find(name); 86bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (it == g_event_type_map->end()) { 87bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("Unknown event type: %s\n", name); 88bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 89bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(it != g_event_type_map->end()); 90bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return (EventType)it->second; 91bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 92bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 93bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void InitEventTypeMap() { 94bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov g_event_type_map = new map<string, int>; 95bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov for (int i = 0; i < LAST_EVENT; i++) { 96bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (*g_event_type_map)[kEventNames[i]] = i; 97bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 98bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 99bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 100bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void SkipCommentText(FILE *file) { 101bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char buff[kBufSize]; 102bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int i = 0; 103bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (true) { 104bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int c = fgetc(file); 105bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (c == EOF) break; 106bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (c == '\n') { 107bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n++; 108bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 109bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 110bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (i < kBufSize - 1) 111bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov buff[i++] = c; 112bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 113bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov buff[i] = 0; 114bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (buff[0] == 'P' && buff[1] == 'C') { 115bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char img[kBufSize]; 116bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char rtn[kBufSize]; 117bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char file[kBufSize]; 118bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int line = 0; 119bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned long pc = 0; 120bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (sscanf(buff, "PC %lx %s %s %s %d", (unsigned long*)&pc, 121bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov img, rtn, file, &line) == 5 && 122bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc != 0) { 123bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(g_pc_info_map); 124bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PcInfo pc_info; 125bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.img_name = img; 126bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.rtn_name = rtn; 127bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.file_name = file; 128bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.line = line; 129bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (*g_pc_info_map)[pc] = pc_info; 130bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // Printf("***** PC %lx %s\n", pc, rtn); 131bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 132bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 133bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (buff[0] == '>') { 134bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // Just print the rest of comment. 135bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("%s\n", buff + 2); 136bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 137bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 138bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 139bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic void SkipWhiteSpaceAndComments(FILE *file) { 140bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int c = 0; 141bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (true) { 142bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov c = fgetc(file); 143bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (c == EOF) return; 144bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (c == '#' || c == '=') { 145bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov SkipCommentText(file); 146bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov continue; 147bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 148bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (isspace(c)) continue; 149bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 150bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 151bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ungetc(c, file); 152bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 153bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 154bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovtypedef bool (*EventReader)(FILE *, Event *); 155bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 156bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool ReadOneStrEventFromFile(FILE *file, Event *event) { 157bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(event); 158bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char name[1024]; 159bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uint32_t tid; 160bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned long pc, a, info; 161bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov SkipWhiteSpaceAndComments(file); 162bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n++; 163bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (5 == fscanf(file, "%s%x%lx%lx%lx", name, &tid, &pc, &a, &info)) { 164bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov event->Init(EventNameToEventType(name), tid, pc, a, info); 165bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return true; 166bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 167bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return false; 168bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 169bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 170bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool ProcessCodePosition(FILE *input, int *pc, string *str) { 171bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool ok = Read<int>(input, pc); 172bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ReadANSI(input, str); 173bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return ok; 174bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 175bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 176bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool ProcessMessage(FILE *input, string *str) { 177bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return ReadANSI(input, str); 178bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 179bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 180bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// Read information about event in format: [[[info] address] pc] tid. 181bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool ProcessEvent(FILE *input, EventType type, Event *event) { 182bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool ok = true; 183bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned short tid = 0; 184bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int pc = 0; 185bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int64_t address = 0; 186bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned short extra = 0; 187bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // It's tricky switch without breaks. 188bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov switch (type) { 189bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case THR_START: 190bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<unsigned short>(input, &extra); 191bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // fallthrough. 192bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case READ: 193bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case READER_LOCK: 194bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case SIGNAL: 195bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case THR_JOIN_AFTER: 196bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case UNLOCK: 197bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case WAIT: 198bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case WRITE: 199bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case WRITER_LOCK: 200bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<int64_t>(input, &address); 201bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // fallthrough. 202bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case EXPECT_RACE_BEGIN: 203bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case EXPECT_RACE_END: 204bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case RTN_EXIT: 205bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case SBLOCK_ENTER: 206bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case STACK_TRACE: 207bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case THR_END: 208bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case THR_FIRST_INSN: 209bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<int>(input, &pc); 210bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // fallthrough. 211bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case RTN_CALL: 212bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<unsigned short>(input, &tid); 213bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 214bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov default: 215bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // read unsupported EventType. 216bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("Unsupported EventType %s %d\n", type, (int)type); 217bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(false); 218bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 219bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (type == READ || type == WRITE) { 220bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov extra = 1; 221bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 222bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov event->Init(type, (int)tid, pc, address, (int)extra); 223bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return ok; 224bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 225bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 226bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovbool ReadOneBinEventFromFile(FILE *input, Event *event) { 227bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(event); 228bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool ok = true; 229bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov EventType type; 230bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned char typeOrd; 231bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int pc; 232bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int line; 233bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char rtn[kBufSize]; 234bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov char file[kBufSize]; 235bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string str; 236bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (ok) { 237bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n++; 238bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<unsigned char>(input, &typeOrd); 239bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (!ok) break; 240bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov type = (EventType)typeOrd; 241bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov switch (type) { 242bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case PC_DESCRIPTION: 243bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessCodePosition(input, &pc, &str); 244bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (sscanf(str.c_str(), "%s %s %d", rtn, file, &line) == 3 && pc != 0) { 245bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(g_pc_info_map); 246bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PcInfo pc_info; 247bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.img_name = "java"; 248bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.rtn_name = rtn; 249bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.file_name = file; 250bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov pc_info.line = line; 251bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (*g_pc_info_map)[pc] = pc_info; 252bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 253bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 254bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case PRINT_MESSAGE: 255bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessMessage(input, &str); 256bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov // Just print the rest of comment. 257bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("%s\n", str.c_str()); 258bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 259bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov default: 260bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessEvent(input, type, event); 261bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return ok; 262bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 263bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 264bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return false; 265bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 266bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 267bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid DecodeEventsFromFile(FILE *input, FILE *output) { 268bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n = 0; 269bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov bool ok = true; 270bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov EventType type; 271bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov unsigned char typeOrd; 272bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int pc; 273bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string str; 274bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Event event; 275bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (ok) { 276bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= Read<unsigned char>(input, &typeOrd); 277bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (!ok) break; 278bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov type = (EventType)typeOrd; 279bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov switch (type) { 280bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case PC_DESCRIPTION: 281bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessCodePosition(input, &pc, &str); 282bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov fprintf(output, "#PC %x java %s\n", pc, str.c_str()); 283bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 284bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov case PRINT_MESSAGE: 285bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessMessage(input, &str); 286bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov fprintf(output, "#> %s\n", str.c_str()); 287bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 288bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov default: 289bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ok &= ProcessEvent(input, type, &event); 290bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov fprintf(output, "%s %x %x %lx %lx\n", kEventNames[event.type()], 291bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov event.tid(), (unsigned int)event.pc(), 292bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov (long unsigned int)event.a(), (long unsigned int)event.info()); 293bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov break; 294bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 295bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n++; 296bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 297bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("INFO: ThreadSanitizer write %ld lines.\n", offline_line_n); 298bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 299bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 300bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic const uint32_t max_unknown_thread = 10000; 301bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 302bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstatic bool known_threads[max_unknown_thread] = {}; 303bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 304bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy StepanovINLINE void ReadEventsFromFile(FILE *file, EventReader event_reader_cb) { 305bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Event event; 306bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uint64_t n_events = 0; 307bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov offline_line_n = 0; 308bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov while (event_reader_cb(file, &event)) { 309bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov //event.Print(); 310bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov n_events++; 311bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov uint32_t tid = event.tid(); 312bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (event.type() == THR_START && tid < max_unknown_thread) { 313bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov known_threads[tid] = true; 314bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 315bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (tid >= max_unknown_thread || known_threads[tid]) { 316bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ThreadSanitizerHandleOneEvent(&event); 317bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 318bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 319bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("INFO: ThreadSanitizerOffline: %ld events read\n", n_events); 320bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 321bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//------------- ThreadSanitizer exports ------------ {{{1 322bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 323bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovvoid PcToStrings(uintptr_t pc, bool demangle, 324bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string *img_name, string *rtn_name, 325bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string *file_name, int *line_no) { 326bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (g_pc_info_map->count(pc) == 0) { 327bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *img_name = ""; 328bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *rtn_name = ""; 329bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *file_name = ""; 330bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *line_no = 0; 331bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return; 332bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 333bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PcInfo &info = (*g_pc_info_map)[pc]; 334bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *img_name = info.img_name; 335bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *rtn_name = info.rtn_name; 336bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *file_name = info.file_name; 337bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *line_no = info.line; 338bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (*file_name == "unknown") 339bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov *file_name = ""; 340bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 341bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 342bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovstring PcToRtnName(uintptr_t pc, bool demangle) { 343bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov string img, rtn, file; 344bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov int line; 345bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov PcToStrings(pc, demangle, &img, &rtn, &file, &line); 346bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return rtn; 347bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 348bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov//------------- main ---------------------------- {{{1 349bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanovint main(int argc, char *argv[]) { 350bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("INFO: ThreadSanitizerOffline r%s\n", TS_VERSION); 351bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 352bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov InitEventTypeMap(); 353bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov g_pc_info_map = new map<uintptr_t, PcInfo>; 354bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov G_flags = new FLAGS; 355bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 356bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov vector<string> args(argv + 1, argv + argc); 357bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ThreadSanitizerParseFlags(&args); 358bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ThreadSanitizerInit(); 359bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 360bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov CHECK(G_flags); 361bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (G_flags->input_type == "bin") { 362bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReadEventsFromFile(stdin, ReadOneBinEventFromFile); 363bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else if (G_flags->input_type == "decode") { 364bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov FILE* output; 365bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (G_flags->log_file.size() > 0) { 366bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov output = fopen(G_flags->log_file.c_str(), "w"); 367bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else { 368bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov output = stdout; 369bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 370bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov DecodeEventsFromFile(stdin, output); 371bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else if (G_flags->input_type == "str") { 372bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ReadEventsFromFile(stdin, ReadOneStrEventFromFile); 373bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } else { 374bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov Printf("Error: Unknown input_type value %s\n", G_flags->input_type.c_str()); 375bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov exit(5); 376bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 377bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 378bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov ThreadSanitizerFini(); 379bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov if (G_flags->error_exitcode && GetNumberOfFoundErrors() > 0) { 380bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov return G_flags->error_exitcode; 381bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov } 382bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov} 383bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov 384bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// end. {{{1 385bec2f0e0495e343f55908a6f0cc4bd8dd27b27d1Evgeniy Stepanov// vim:shiftwidth=2:softtabstop=2:expandtab:tw=80 386