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