blob: 876c834bd44b94778c36fbc5407937ae00fb5b3c [file] [log] [blame]
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +02001/*
2 *
3 * honggfuzz - sanitizer coverage feedback parsing
4 * -----------------------------------------------
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License"); you may
7 * not use this file except in compliance with the License. You may obtain
8 * a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
15 * implied. See the License for the specific language governing
16 * permissions and limitations under the License.
17 *
18 */
19
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020020/*
21 * Clang sanitizer coverage (sancov) data parsing functions. Supported methods:
22 * - raw unified data (preferred method)
23 * - individual data per executable/DSO (not preferred since lots of data lost if instrumented
24 * code exits abnormally or with sanitizer unhandled signal (common in Android OS)
Robert Swiecki72d2bef2016-01-19 14:39:26 +010025 *
26 * For raw-unpack method a global (shared across workers) Trie is created for the chosen
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020027 * initial seed and maintained until seed is replaced. Trie nodes store the loaded (as exposed
28 * from *.sancov.map file) execs/DSOs from target application using the map name as key. Trie node
29 * data struct (trieData_t) maintains information for each instrumented map including a bitmap with
Robert Swiecki0b566112017-10-17 17:39:07 +020030 * all hit relative BB addresses (realBBAddr - baseAddr to circumvent ASLR). Map's bitmap is updated
31 * while new areas on target application are discovered based on absolute elitism implemented at
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020032 * fuzz_sanCovFeedback().
Robert Swiecki72d2bef2016-01-19 14:39:26 +010033 *
Robert Swiecki0b566112017-10-17 17:39:07 +020034 * For individual data files a pid (fuzzer's thread or remote process) based filename search is
35 * performed to identify all files belonging to examined execution. This method doesn't implement
36 * yet bitmap runtime data to detect newly discovered areas. It's mainly used so far as a comparison
37 * metric for raw-unpack method and stability check for sancov experimental features such as
38 * coverage counters: http://clang.llvm.org/docs/SanitizerCoverage.html
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020039 */
40
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020041#include "sancov.h"
42
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020043#include <ctype.h>
Jagger00265602016-03-10 02:36:27 +010044#include <dirent.h>
45#include <inttypes.h>
46#include <stdio.h>
47#include <stdlib.h>
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020048#include <string.h>
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020049#include <sys/mman.h>
Jagger00265602016-03-10 02:36:27 +010050#include <sys/stat.h>
51#include <sys/types.h>
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020052
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020053#include "libcommon/common.h"
Robert Swieckiec7b8452017-06-01 13:25:56 +020054#include "libcommon/files.h"
55#include "libcommon/log.h"
56#include "libcommon/util.h"
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020057#include "sanitizers.h"
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020058
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020059/* sancov files magic values */
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +020060#define kMagic32 0xC0BFFFFFFFFFFF32
61#define kMagic64 0xC0BFFFFFFFFFFF64
62
Robert Swiecki72d2bef2016-01-19 14:39:26 +010063/*
Anestis Bechtsoudis0ddd0782016-12-28 18:33:28 +020064 * Each DSO/executable that has been compiled with enabled coverage instrumentation
65 * is detected from compiler_rt runtime library when loaded. When coverage_direct
66 * method is selected, runtime library is pre-allocating kPcArrayMmapSize [1] byte
67 * chunks until the total size of chunks is greater than the number of inserted
68 * guards. This effectively means that we might have a large unused (zero-filled)
69 * area that we can't identify at runtime (we need to do binary inspection).
70 *
71 * Runtime maintained data structs size overhead is not affected since fixed-size
72 * bitmap is used. However, the way the display coverage statistics are generated
73 * is not very accurate because:
74 * a) ASan compiled DSO might get loaded although not followed from monitoring
75 execution affecting the counters
76 * b) Not all zero-fill chunks translate into non-hit basic block as they might
77 * be the chunk padding
78 *
79 * Probably there aren't many we can do to deal with this issue without introducing
80 * a huge performance overhead at an already costly feedback method.
81 *
Robert Swiecki0b566112017-10-17 17:39:07 +020082 * [1]
83 'https://llvm.org/svn/llvm-project/compiler-rt/branches/release_38/lib/sanitizer_common/sanitizer_coverage_libcdep.cc'
Anestis Bechtsoudis0ddd0782016-12-28 18:33:28 +020084 */
85#define kPcArrayMmapSize (64 * 1024)
86
87/*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020088 * bitmap implementation
89 */
Robert Swieckid50ed422017-11-13 23:32:26 +010090static bitmap_t* sancov_newBitmap(uint32_t capacity) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +020091 bitmap_t* pBM = util_Malloc(sizeof(bitmap_t));
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020092 pBM->capacity = capacity;
93 pBM->nChunks = (capacity + 31) / 32;
Jagger74d0d102016-03-18 22:55:59 +010094 pBM->pChunks = util_Calloc(pBM->nChunks * sizeof(uint32_t));
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +020095 return pBM;
96}
97
Robert Swieckid50ed422017-11-13 23:32:26 +010098static inline bool sancov_queryBitmap(bitmap_t* pBM, uint32_t index) {
Anestis Bechtsoudis58c45d22016-01-10 15:05:39 +020099 if (index > pBM->capacity) {
100 LOG_E("bitmap overflow (%u)", index);
101 return false;
102 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200103 if (pBM->pChunks[index / 32] & (1 << (index % 32))) {
104 return true;
105 }
106 return false;
107}
108
Robert Swieckid50ed422017-11-13 23:32:26 +0100109static inline void sancov_setBitmap(bitmap_t* pBM, uint32_t index) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200110 /* This will be removed. So far checks only to verify accepted ranges. */
111 if (index >= pBM->capacity) {
112 LOG_E("Out of range index (%u > %u)", index, pBM->capacity);
113 }
114 pBM->pChunks[index / 32] |= (1 << (index % 32));
115}
116
Robert Swieckid50ed422017-11-13 23:32:26 +0100117static inline void sancov_destroyBitmap(bitmap_t* pBM) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200118 free(pBM->pChunks);
119 free(pBM);
120}
121
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100122/*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200123 * Trie implementation
124 */
Robert Swieckid50ed422017-11-13 23:32:26 +0100125static node_t* sancov_trieCreateNode(char key) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200126 node_t* node = (node_t*)util_Malloc(sizeof(node_t));
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200127 node->key = key;
128 node->next = NULL;
129 node->children = NULL;
130 node->parent = NULL;
131 node->prev = NULL;
132
133 /* Zero init node's data struct */
134 memset(&node->data, 0, sizeof(trieData_t));
135 return node;
136}
137
Robert Swieckid50ed422017-11-13 23:32:26 +0100138static node_t* sancov_trieSearch(node_t* root, const char* key) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200139 node_t *pNodeLevel = root, *pNodePtr = NULL;
140 int nodeLevelId = 0;
141 while (1) {
142 node_t *pNodeFound = NULL, *pCurNode = NULL;
143 for (pCurNode = pNodeLevel; pCurNode != NULL; pCurNode = pCurNode->next) {
144 if (pCurNode->key == *key) {
145 pNodeFound = pCurNode;
146 nodeLevelId++;
147 break;
148 }
149 }
150 if (pNodeFound == NULL) {
151 return NULL;
152 }
153 if (*key == '\0') {
154 pNodePtr = pCurNode;
155 return pNodePtr;
156 }
157 pNodeLevel = pNodeFound->children;
158 key++;
159 }
160}
161
Robert Swieckid50ed422017-11-13 23:32:26 +0100162static void sancov_trieAdd(node_t** root, const char* key) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200163 if (*root == NULL) {
164 LOG_E("Invalid Trie (NULL root node)");
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200165 return;
166 }
167
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200168 /* Traverse Trie */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200169 node_t* pTravNode = (*root)->children;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200170 if (pTravNode == NULL) {
171 /* First node */
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200172 for (pTravNode = *root; *key != '\0'; pTravNode = pTravNode->children) {
Jagger3db1d952016-03-10 02:02:46 +0100173 pTravNode->children = sancov_trieCreateNode(*key);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200174 pTravNode->children->parent = pTravNode;
175 key++;
176 }
Jagger3db1d952016-03-10 02:02:46 +0100177 pTravNode->children = sancov_trieCreateNode('\0');
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200178 pTravNode->children->parent = pTravNode;
179 return;
180 }
181
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200182 while (*key != '\0') {
183 if (*key == pTravNode->key) {
184 key++;
185 pTravNode = pTravNode->children;
186 } else {
187 break;
188 }
189 }
190 while (pTravNode->next) {
191 if (*key == pTravNode->next->key) {
192 key++;
Robert Swiecki40ef8402016-03-10 15:14:13 +0100193 sancov_trieAdd(&(pTravNode->next), key);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200194 return;
195 }
196 pTravNode = pTravNode->next;
197 }
198 if (*key) {
Jagger3db1d952016-03-10 02:02:46 +0100199 pTravNode->next = sancov_trieCreateNode(*key);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200200 } else {
Jagger3db1d952016-03-10 02:02:46 +0100201 pTravNode->next = sancov_trieCreateNode(*key);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200202 }
203 pTravNode->next->parent = pTravNode->parent;
204 pTravNode->next->prev = pTravNode;
205 if (!*key) {
206 return;
207 }
208 key++;
209 for (pTravNode = pTravNode->next; *key; pTravNode = pTravNode->children) {
Jagger3db1d952016-03-10 02:02:46 +0100210 pTravNode->children = sancov_trieCreateNode(*key);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200211 pTravNode->children->parent = pTravNode;
212 key++;
213 }
Jagger3db1d952016-03-10 02:02:46 +0100214 pTravNode->children = sancov_trieCreateNode('\0');
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200215 pTravNode->children->parent = pTravNode;
216
217 return;
218}
219
Robert Swieckid50ed422017-11-13 23:32:26 +0100220static inline void sancov_trieFreeNode(node_t* node) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200221 /* First destroy bitmap heap buffers allocated for instrumented maps */
222 if (node->data.pBM) {
Jagger3db1d952016-03-10 02:02:46 +0100223 sancov_destroyBitmap(node->data.pBM);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200224 }
225 free(node);
226}
227
Robert Swieckid50ed422017-11-13 23:32:26 +0100228static inline void sancov_trieCreate(node_t** root) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200229 /* Create root node if new Trie */
Jagger3db1d952016-03-10 02:02:46 +0100230 *root = sancov_trieCreateNode('\0');
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200231}
232
233/* Destroy Trie - iterate nodes and free memory */
Robert Swieckid50ed422017-11-13 23:32:26 +0100234UNUSED static void sancov_trieDestroy(node_t* root) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200235 node_t* pNode = root;
236 node_t* pNodeTmp = root;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200237 while (pNode) {
238 while (pNode->children) {
239 pNode = pNode->children;
240 }
241
242 if (pNode->prev && pNode->next) {
243 pNodeTmp = pNode;
244 pNode->next->prev = pNode->prev;
245 pNode->prev->next = pNode->next;
Jagger3db1d952016-03-10 02:02:46 +0100246 sancov_trieFreeNode(pNodeTmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200247 } else if (pNode->prev && !pNode->next) {
248 pNodeTmp = pNode;
249 pNode->prev->next = NULL;
Jagger3db1d952016-03-10 02:02:46 +0100250 sancov_trieFreeNode(pNodeTmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200251 } else if (!pNode->prev && pNode->next) {
252 pNodeTmp = pNode;
253 pNode->parent->children = pNode->next;
254 pNode->next->prev = NULL;
255 pNode = pNode->next;
Jagger3db1d952016-03-10 02:02:46 +0100256 sancov_trieFreeNode(pNodeTmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200257 } else {
258 pNodeTmp = pNode;
259 if (pNode->parent == NULL) {
260 /* Root */
Jagger3db1d952016-03-10 02:02:46 +0100261 sancov_trieFreeNode(pNodeTmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200262 return;
263 }
264 pNode = pNode->parent;
265 pNode->children = NULL;
Jagger3db1d952016-03-10 02:02:46 +0100266 sancov_trieFreeNode(pNodeTmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200267 }
268 }
269}
270
271/* Modified interpolation search algorithm to search for nearest address fit */
Robert Swieckid50ed422017-11-13 23:32:26 +0100272static inline uint64_t sancov_interpSearch(uint64_t* buf, uint64_t size, uint64_t key) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200273 /* Avoid extra checks assuming caller always provides non-zero array size */
274 uint64_t low = 0;
275 uint64_t high = size - 1;
276 uint64_t mid = high;
277
278 while (buf[high] != buf[low] && key >= buf[low] && key <= buf[high]) {
279 mid = low + (key - buf[low]) * ((high - low) / (buf[high] - buf[low]));
280 if (buf[mid] < key) {
281 low = mid + 1;
282 } else if (key < buf[mid]) {
283 high = mid - 1;
284 } else {
285 return mid;
286 }
287 }
288 return mid;
289}
290
291/* qsort struct comparison function (memMap_t struct start addr field) */
Robert Swieckid50ed422017-11-13 23:32:26 +0100292static int sancov_qsortCmp(const void* a, const void* b) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200293 memMap_t* pA = (memMap_t*)a;
294 memMap_t* pB = (memMap_t*)b;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200295 if (pA->start < pB->start) {
296 return -1;
297 } else if (pA->start > pB->start) {
298 return 1;
299 } else {
300 /* Normally we should never hit that case */
301 LOG_W("Duplicate map start addr detected");
302 return 0;
303 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200304}
305
Robert Swieckid50ed422017-11-13 23:32:26 +0100306static bool sancov_sanCovParseRaw(run_t* run) {
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200307 int dataFd = -1;
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200308 uint8_t* dataBuf = NULL;
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200309 off_t dataFileSz = 0, pos = 0;
Jaggerf26b1b62016-03-19 01:59:30 +0100310 bool is32bit = true;
Robert Swieckid50ed422017-11-13 23:32:26 +0100311 char covFile[PATH_MAX] = {0};
Robert Swiecki78633d12017-11-13 23:24:55 +0100312 pid_t targetPid = (run->global->linux.pid > 0) ? run->global->linux.pid : run->pid;
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200313
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200314 /* Fuzzer local runtime data structs - need free() before exit */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200315 uint64_t* startMapsIndex = NULL;
316 memMap_t* mapsBuf = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200317
318 /* Local counters */
Robert Swieckid50ed422017-11-13 23:32:26 +0100319 uint64_t nBBs = 0; /* Total BB hits found in raw file */
320 uint64_t nZeroBBs = 0; /* Number of non-hit instrumented BBs */
321 uint64_t mapsNum = 0; /* Total number of entries in map file */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200322 uint64_t noCovMapsNum = 0; /* Loaded DSOs not compiled with coverage */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200323
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200324 /* File line-by-line read help buffers */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200325 __block char* pLine = NULL;
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200326 size_t lineSz = 0;
327
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200328 /* Coverage data analysis starts by parsing map file listing */
Robert Swiecki82c707c2017-11-14 16:36:23 +0100329 snprintf(covFile, sizeof(covFile), "%s/%s/%d.sancov.map", run->global->io.workDir,
330 _HF_SANCOV_DIR, targetPid);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200331 if (!files_exists(covFile)) {
332 LOG_D("sancov map file not found");
333 return false;
334 }
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200335 FILE* fCovMap = fopen(covFile, "rb");
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200336 if (fCovMap == NULL) {
337 PLOG_E("Couldn't open '%s' - R/O mode", covFile);
Jaggerf26b1b62016-03-19 01:59:30 +0100338 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200339 }
Robert Swiecki0b566112017-10-17 17:39:07 +0200340 defer { fclose(fCovMap); };
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200341
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200342 /* First line contains PC length (32/64-bit) */
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200343 if (getline(&pLine, &lineSz, fCovMap) == -1) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200344 LOG_E("Invalid map file '%s'", covFile);
Jaggerf26b1b62016-03-19 01:59:30 +0100345 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200346 }
Robert Swieckid50ed422017-11-13 23:32:26 +0100347 defer {
Jagger4fe18692016-04-22 23:15:07 +0200348 free(pLine);
349 pLine = NULL;
350 };
Jaggerf26b1b62016-03-19 01:59:30 +0100351
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200352 int pcLen = atoi(pLine);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200353 if (pcLen == 32) {
354 is32bit = true;
355 } else if (pcLen == 64) {
356 is32bit = false;
357 } else {
358 LOG_E("Invalid PC length (%d) in map file '%s'", pcLen, covFile);
359 }
Anestis Bechtsoudis1fc7cd42015-12-26 17:54:15 +0200360
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200361 /* See if #maps is available from previous run to avoid realloc inside loop */
Robert Swiecki78633d12017-11-13 23:24:55 +0100362 uint64_t prevMapsNum = ATOMIC_GET(run->global->sanCovCnts.dsoCnt);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200363 if (prevMapsNum > 0) {
Jagger679c2052016-03-18 22:53:53 +0100364 mapsBuf = util_Malloc(prevMapsNum * sizeof(memMap_t));
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200365 }
Jaggerf26b1b62016-03-19 01:59:30 +0100366 /* It's OK to free(NULL) */
Robert Swiecki0b566112017-10-17 17:39:07 +0200367 defer { free(mapsBuf); };
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200368
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200369 /* Iterate map entries */
370 for (;;) {
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200371 if (getline(&pLine, &lineSz, fCovMap) == -1) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200372 break;
373 }
374
375 /* Trim trailing whitespaces, not sure if needed copied from upstream sancov.py */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200376 char* lineEnd = pLine + strlen(pLine) - 1;
Jagger43c33e52016-03-11 22:16:26 +0100377 while (lineEnd > pLine && isspace((int)*lineEnd)) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200378 lineEnd--;
379 }
380 *(lineEnd + 1) = 0;
381
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100382 /*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200383 * Each line has following format:
384 * Start End Base bin/DSO name
385 * b5843000 b584e6ac b5843000 liblog.so
386 */
Robert Swieckid50ed422017-11-13 23:32:26 +0100387 memMap_t mapData = {.start = 0};
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200388 char* savePtr = NULL;
Anestis Bechtsoudis267f0d82016-01-08 16:02:50 +0200389 mapData.start = strtoull(strtok_r(pLine, " ", &savePtr), NULL, 16);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200390 mapData.end = strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16);
391 mapData.base = strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16);
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200392 char* mapName = strtok_r(NULL, " ", &savePtr);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200393 memcpy(mapData.mapName, mapName, strlen(mapName));
394
395 /* Interaction with global Trie should mutex wrap to avoid threads races */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200396 {
Robert Swiecki78633d12017-11-13 23:24:55 +0100397 MX_SCOPED_LOCK(&run->global->sanCov_mutex);
Robert Swiecki5d6e7342016-03-16 15:36:11 +0100398
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200399 /* Add entry to Trie with zero data if not already */
Robert Swiecki78633d12017-11-13 23:24:55 +0100400 if (!sancov_trieSearch(run->global->covMetadata->children, mapData.mapName)) {
401 sancov_trieAdd(&run->global->covMetadata, mapData.mapName);
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200402 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200403 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200404
Robert Swiecki0b566112017-10-17 17:39:07 +0200405 /* If no DSO number history (first run) or new DSO loaded, realloc local maps metadata buf
406 */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200407 if (prevMapsNum == 0 || prevMapsNum < mapsNum) {
Robert Swieckid50ed422017-11-13 23:32:26 +0100408 if ((mapsBuf = util_Realloc(mapsBuf, (size_t)(mapsNum + 1) * sizeof(memMap_t))) ==
409 NULL) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200410 PLOG_E("realloc failed (sz=%" PRIu64 ")", (mapsNum + 1) * sizeof(memMap_t));
Jaggerf26b1b62016-03-19 01:59:30 +0100411 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200412 }
413 }
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200414
415 /* Add entry to local maps metadata array */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200416 memcpy(&mapsBuf[mapsNum], &mapData, sizeof(memMap_t));
417
418 /* Increase loaded maps counter (includes non-instrumented DSOs too) */
419 mapsNum++;
420 }
421
422 /* Delete .sancov.map file */
Robert Swiecki78633d12017-11-13 23:24:55 +0100423 if (run->global->linux.pid == 0 && run->global->persistent == false) {
Jagger1ebc6dc2016-03-12 01:39:09 +0100424 unlink(covFile);
425 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200426
427 /* Create a quick index array with maps start addresses */
Jagger679c2052016-03-18 22:53:53 +0100428 startMapsIndex = util_Malloc(mapsNum * sizeof(uint64_t));
Robert Swiecki0b566112017-10-17 17:39:07 +0200429 defer { free(startMapsIndex); };
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200430
431 /* Sort quick maps index */
Jagger3db1d952016-03-10 02:02:46 +0100432 qsort(mapsBuf, mapsNum, sizeof(memMap_t), sancov_qsortCmp);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200433 for (size_t i = 0; i < mapsNum; i++) {
434 startMapsIndex[i] = mapsBuf[i].start;
435 }
436
437 /* mmap() .sancov.raw file */
Robert Swiecki82c707c2017-11-14 16:36:23 +0100438 snprintf(covFile, sizeof(covFile), "%s/%s/%d.sancov.raw", run->global->io.workDir,
439 _HF_SANCOV_DIR, targetPid);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200440 dataBuf = files_mapFile(covFile, &dataFileSz, &dataFd, false);
441 if (dataBuf == NULL) {
442 LOG_E("Couldn't open and map '%s' in R/O mode", covFile);
Jaggerf26b1b62016-03-19 01:59:30 +0100443 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200444 }
Robert Swieckid50ed422017-11-13 23:32:26 +0100445 defer {
Jagger4fe18692016-04-22 23:15:07 +0200446 munmap(dataBuf, dataFileSz);
447 close(dataFd);
448 };
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200449
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100450 /*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200451 * Avoid cost of size checks inside raw data read loop by defining the read function
452 * & pivot size based on PC length.
453 */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200454 uint64_t (*pReadRawBBAddrFunc)(const uint8_t*) = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200455 uint8_t pivot = 0;
456 if (is32bit) {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200457 pReadRawBBAddrFunc = &util_getUINT32;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200458 pivot = 4;
459 } else {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200460 pReadRawBBAddrFunc = &util_getUINT64;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200461 pivot = 8;
462 }
463
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100464 /*
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200465 * Take advantage of data locality (next processed addr is very likely to belong
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200466 * to same map) to avoid Trie node search for each read entry.
467 */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200468 node_t* curMap = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200469 uint64_t prevIndex = 0;
470
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200471 /* Iterate over data buffer containing list of hit BB addresses */
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200472 while (pos < dataFileSz) {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200473 uint64_t bbAddr = pReadRawBBAddrFunc(dataBuf + pos);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200474 pos += pivot;
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200475 /* Don't bother for zero BB addr (inserted checks without hit) */
476 if (bbAddr == 0x0) {
477 nZeroBBs++;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200478 continue;
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200479 } else {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200480 /* Find best hit based on start addr & verify range for errors */
Jagger3db1d952016-03-10 02:02:46 +0100481 uint64_t bestFit = sancov_interpSearch(startMapsIndex, mapsNum, bbAddr);
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200482 if (bbAddr >= mapsBuf[bestFit].start && bbAddr < mapsBuf[bestFit].end) {
483 /* Increase exe/DSO total BB counter */
484 mapsBuf[bestFit].bbCnt++;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200485
486 /* Update current Trie node if map changed */
487 if (curMap == NULL || (prevIndex != bestFit)) {
488 prevIndex = bestFit;
489
490 /* Interaction with global Trie should mutex wrap to avoid threads races */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200491 {
Robert Swiecki78633d12017-11-13 23:24:55 +0100492 MX_SCOPED_LOCK(&run->global->sanCov_mutex);
Robert Swiecki5d6e7342016-03-16 15:36:11 +0100493
Robert Swiecki0b566112017-10-17 17:39:07 +0200494 curMap = sancov_trieSearch(
Robert Swiecki78633d12017-11-13 23:24:55 +0100495 run->global->covMetadata->children, mapsBuf[bestFit].mapName);
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200496 if (curMap == NULL) {
497 LOG_E("Corrupted Trie - '%s' not found", mapsBuf[bestFit].mapName);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200498 continue;
499 }
500
Robert Swiecki0b566112017-10-17 17:39:07 +0200501 /* Maintain bitmaps only for exec/DSOs with coverage enabled - allocate on
502 * first use */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200503 if (curMap->data.pBM == NULL) {
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200504 LOG_D("Allocating bitmap for map '%s'", mapsBuf[bestFit].mapName);
Jagger3d977522016-08-21 19:15:59 +0200505 curMap->data.pBM = sancov_newBitmap(_HF_SANCOV_BITMAP_SIZE);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200506
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100507 /*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200508 * If bitmap allocation failed, unset cached Trie node ptr
509 * to execute this selection branch again.
510 */
511 if (curMap->data.pBM == NULL) {
512 curMap = NULL;
Anestis Bechtsoudis1fd10c72016-01-07 12:38:45 +0200513 continue;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200514 }
515 }
516 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200517 }
518
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200519 /* If new relative BB addr update DSO's bitmap */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200520 uint32_t relAddr = (uint32_t)(bbAddr - mapsBuf[bestFit].base);
Jagger3db1d952016-03-10 02:02:46 +0100521 if (!sancov_queryBitmap(curMap->data.pBM, relAddr)) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200522 /* Interaction with global Trie should mutex wrap to avoid threads races */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200523 {
Robert Swiecki78633d12017-11-13 23:24:55 +0100524 MX_SCOPED_LOCK(&run->global->sanCov_mutex);
Robert Swiecki5d6e7342016-03-16 15:36:11 +0100525
Jagger3db1d952016-03-10 02:02:46 +0100526 sancov_setBitmap(curMap->data.pBM, relAddr);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200527 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200528
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200529 /* Also increase new BBs counter at worker's thread runtime data */
530 mapsBuf[bestFit].newBBCnt++;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200531 }
532 } else {
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100533 /*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200534 * Normally this should never get executed. If hit, sanitizer
535 * coverage data collection come across some kind of bug.
536 */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200537 LOG_E("Invalid BB addr (%#" PRIx64 ") at offset %" PRId64, bbAddr, (uint64_t)pos);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200538 }
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200539 }
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200540 nBBs++;
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200541 }
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200542
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200543 /* Finally iterate over all instrumented maps to sum-up the number of newly met BB addresses */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200544 for (uint64_t i = 0; i < mapsNum; i++) {
Robert Swiecki142f9412016-03-14 19:22:01 +0100545 if (mapsBuf[i].bbCnt > 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100546 run->sanCovCnts.newBBCnt += mapsBuf[i].newBBCnt;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200547 } else {
548 noCovMapsNum++;
549 }
550 }
551
552 /* Successful parsing - update fuzzer worker's counters */
Robert Swieckie7294ca2017-11-11 02:46:32 +0100553 run->sanCovCnts.hitBBCnt = nBBs;
554 run->sanCovCnts.totalBBCnt = nBBs + nZeroBBs;
555 run->sanCovCnts.dsoCnt = mapsNum;
556 run->sanCovCnts.iDsoCnt = mapsNum - noCovMapsNum; /* Instrumented DSOs */
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200557
Robert Swiecki78633d12017-11-13 23:24:55 +0100558 if (run->global->linux.pid == 0 && run->global->persistent == false) {
Jagger1ebc6dc2016-03-12 01:39:09 +0100559 unlink(covFile);
560 }
Jaggerf26b1b62016-03-19 01:59:30 +0100561 return true;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200562}
563
Robert Swieckid50ed422017-11-13 23:32:26 +0100564static bool sancov_sanCovParse(run_t* run) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200565 int dataFd = -1;
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200566 uint8_t* dataBuf = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200567 off_t dataFileSz = 0, pos = 0;
568 bool is32bit = true;
Robert Swieckid50ed422017-11-13 23:32:26 +0100569 char covFile[PATH_MAX] = {0};
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200570 DIR* pSanCovDir = NULL;
Robert Swiecki78633d12017-11-13 23:24:55 +0100571 pid_t targetPid = (run->global->linux.pid > 0) ? run->global->linux.pid : run->pid;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200572
Robert Swiecki82c707c2017-11-14 16:36:23 +0100573 snprintf(covFile, sizeof(covFile), "%s/%s/%s.%d.sancov", run->global->io.workDir,
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100574 _HF_SANCOV_DIR, files_basename(run->global->exe.cmdline[0]), targetPid);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200575 if (!files_exists(covFile)) {
576 LOG_D("Target sancov file not found");
577 return false;
578 }
579
Anestis Bechtsoudisa7c56ce2016-02-07 12:53:20 +0200580 /* Local cache file suffix to use for file search of target pid data */
Robert Swieckid50ed422017-11-13 23:32:26 +0100581 char pidFSuffix[13] = {0};
Anestis Bechtsoudisa7c56ce2016-02-07 12:53:20 +0200582 snprintf(pidFSuffix, sizeof(pidFSuffix), "%d.sancov", targetPid);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200583
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200584 /* Total BBs counter summarizes all DSOs */
585 uint64_t nBBs = 0;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200586
Anestis Bechtsoudisa7c56ce2016-02-07 12:53:20 +0200587 /* Iterate sancov dir for files generated against target pid */
Robert Swiecki82c707c2017-11-14 16:36:23 +0100588 snprintf(covFile, sizeof(covFile), "%s/%s", run->global->io.workDir, _HF_SANCOV_DIR);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200589 pSanCovDir = opendir(covFile);
Jaggerf26b1b62016-03-19 01:59:30 +0100590 if (pSanCovDir == NULL) {
591 PLOG_E("opendir('%s')", covFile);
592 return false;
593 }
Robert Swiecki0b566112017-10-17 17:39:07 +0200594 defer { closedir(pSanCovDir); };
Jaggerf26b1b62016-03-19 01:59:30 +0100595
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200596 struct dirent* pDir = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200597 while ((pDir = readdir(pSanCovDir)) != NULL) {
Anestis Bechtsoudisa7c56ce2016-02-07 12:53:20 +0200598 /* Parse files with target's pid */
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200599 if (strstr(pDir->d_name, pidFSuffix)) {
Robert Swiecki82c707c2017-11-14 16:36:23 +0100600 snprintf(covFile, sizeof(covFile), "%s/%s/%s", run->global->io.workDir, _HF_SANCOV_DIR,
Robert Swiecki78633d12017-11-13 23:24:55 +0100601 pDir->d_name);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200602 dataBuf = files_mapFile(covFile, &dataFileSz, &dataFd, false);
603 if (dataBuf == NULL) {
604 LOG_E("Couldn't open and map '%s' in R/O mode", covFile);
Jaggerf26b1b62016-03-19 01:59:30 +0100605 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200606 }
Robert Swieckid50ed422017-11-13 23:32:26 +0100607 defer {
Jagger4fe18692016-04-22 23:15:07 +0200608 munmap(dataBuf, dataFileSz);
609 close(dataFd);
610 };
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200611
612 if (dataFileSz < 8) {
613 LOG_E("Coverage data file too short");
Jaggerf26b1b62016-03-19 01:59:30 +0100614 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200615 }
616
617 /* Check magic values & derive PC length */
618 uint64_t magic = util_getUINT64(dataBuf);
619 if (magic == kMagic32) {
620 is32bit = true;
621 } else if (magic == kMagic64) {
622 is32bit = false;
623 } else {
624 LOG_E("Invalid coverage data file");
Jaggerf26b1b62016-03-19 01:59:30 +0100625 return false;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200626 }
627 pos += 8;
628
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100629 /*
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200630 * Avoid cost of size checks inside raw data read loop by defining the read function
631 * & pivot size based on PC length.
632 */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200633 uint64_t (*pReadRawBBAddrFunc)(const uint8_t*) = NULL;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200634 uint8_t pivot = 0;
635 if (is32bit) {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200636 pReadRawBBAddrFunc = &util_getUINT32;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200637 pivot = 4;
638 } else {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200639 pReadRawBBAddrFunc = &util_getUINT64;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200640 pivot = 8;
641 }
642
643 while (pos < dataFileSz) {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200644 uint32_t bbAddr = pReadRawBBAddrFunc(dataBuf + pos);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200645 pos += pivot;
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200646 if (bbAddr == 0x0) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200647 continue;
648 }
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200649 nBBs++;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200650 }
651 }
652 }
653
654 /* Successful parsing - update fuzzer worker counters */
Robert Swieckie7294ca2017-11-11 02:46:32 +0100655 run->sanCovCnts.hitBBCnt = nBBs;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200656
Robert Swiecki78633d12017-11-13 23:24:55 +0100657 if (run->global->linux.pid == 0 && run->global->persistent == false) {
Jagger1ebc6dc2016-03-12 01:39:09 +0100658 unlink(covFile);
659 }
Jaggerf26b1b62016-03-19 01:59:30 +0100660 return true;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200661}
662
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100663/*
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200664 * Sanitizer coverage data are stored in FS can be parsed via two methods:
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100665 * raw unpack & separate bin/DSO sancov file. Separate bin/DSO sancov file
666 * method is usually avoided since coverage data are lost if sanitizer unhandled
667 * signal. Additionally, the FS I/O overhead is bigger compared to raw unpack
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200668 * method which uses runtime data structures.
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100669 *
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200670 * Enabled methods are controlled from sanitizer flags in arch.c
671 */
Robert Swieckid50ed422017-11-13 23:32:26 +0100672void sancov_Analyze(run_t* run) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100673 if (!run->global->useSanCov) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200674 return;
675 }
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100676 /*
Anestis Bechtsoudis97633cc2016-01-13 16:25:57 +0200677 * For now supported methods are implemented in fail-over nature. This will
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200678 * change in the future when best method is concluded.
679 */
Robert Swiecki78633d12017-11-13 23:24:55 +0100680 if (sancov_sanCovParseRaw(run) == false) {
681 sancov_sanCovParse(run);
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200682 }
Anestis Bechtsoudisd76c3b82015-12-26 17:35:25 +0200683}
Jagger00265602016-03-10 02:36:27 +0100684
Robert Swieckid50ed422017-11-13 23:32:26 +0100685bool sancov_Init(honggfuzz_t* hfuzz) {
Jagger9e7ccc12016-09-26 00:47:52 +0200686 if (hfuzz->useSanCov == false) {
687 return true;
688 }
689 sancov_trieCreate(&hfuzz->covMetadata);
690
Robert Swieckid50ed422017-11-13 23:32:26 +0100691 char sanCovOutDir[PATH_MAX] = {0};
Robert Swiecki82c707c2017-11-14 16:36:23 +0100692 snprintf(sanCovOutDir, sizeof(sanCovOutDir), "%s/%s", hfuzz->io.workDir, _HF_SANCOV_DIR);
Jagger99626d32016-09-26 00:50:14 +0200693 if (!files_exists(sanCovOutDir)) {
694 if (mkdir(sanCovOutDir, S_IRWXU | S_IXGRP | S_IXOTH) != 0) {
695 PLOG_E("mkdir() '%s' failed", sanCovOutDir);
696 }
697 }
698
Jagger00265602016-03-10 02:36:27 +0100699 return true;
700}