11cb0ef41Sopenharmony_ci// Copyright 2020 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/d8/cov.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <fcntl.h> 81cb0ef41Sopenharmony_ci#include <inttypes.h> 91cb0ef41Sopenharmony_ci#include <stdio.h> 101cb0ef41Sopenharmony_ci#include <stdlib.h> 111cb0ef41Sopenharmony_ci#include <string.h> 121cb0ef41Sopenharmony_ci#include <sys/mman.h> 131cb0ef41Sopenharmony_ci#include <sys/stat.h> 141cb0ef41Sopenharmony_ci#include <sys/wait.h> 151cb0ef41Sopenharmony_ci#include <unistd.h> 161cb0ef41Sopenharmony_ci 171cb0ef41Sopenharmony_ci#include "src/base/platform/wrappers.h" 181cb0ef41Sopenharmony_ci 191cb0ef41Sopenharmony_ci#define SHM_SIZE 0x100000 201cb0ef41Sopenharmony_ci#define MAX_EDGES ((SHM_SIZE - 4) * 8) 211cb0ef41Sopenharmony_ci 221cb0ef41Sopenharmony_cistruct shmem_data { 231cb0ef41Sopenharmony_ci uint32_t num_edges; 241cb0ef41Sopenharmony_ci unsigned char edges[]; 251cb0ef41Sopenharmony_ci}; 261cb0ef41Sopenharmony_ci 271cb0ef41Sopenharmony_cistruct shmem_data* shmem; 281cb0ef41Sopenharmony_ci 291cb0ef41Sopenharmony_ciuint32_t *edges_start, *edges_stop; 301cb0ef41Sopenharmony_ciuint32_t builtins_start; 311cb0ef41Sopenharmony_ciuint32_t builtins_edge_count; 321cb0ef41Sopenharmony_ci 331cb0ef41Sopenharmony_civoid sanitizer_cov_reset_edgeguards() { 341cb0ef41Sopenharmony_ci uint32_t N = 0; 351cb0ef41Sopenharmony_ci for (uint32_t* x = edges_start; x < edges_stop && N < MAX_EDGES; x++) 361cb0ef41Sopenharmony_ci *x = ++N; 371cb0ef41Sopenharmony_ci} 381cb0ef41Sopenharmony_ci 391cb0ef41Sopenharmony_ciextern "C" void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, 401cb0ef41Sopenharmony_ci uint32_t* stop) { 411cb0ef41Sopenharmony_ci // Map the shared memory region 421cb0ef41Sopenharmony_ci const char* shm_key = getenv("SHM_ID"); 431cb0ef41Sopenharmony_ci if (!shm_key) { 441cb0ef41Sopenharmony_ci puts("[COV] no shared memory bitmap available, skipping"); 451cb0ef41Sopenharmony_ci shmem = (struct shmem_data*)v8::base::Malloc(SHM_SIZE); 461cb0ef41Sopenharmony_ci } else { 471cb0ef41Sopenharmony_ci int fd = shm_open(shm_key, O_RDWR, S_IREAD | S_IWRITE); 481cb0ef41Sopenharmony_ci if (fd <= -1) { 491cb0ef41Sopenharmony_ci fprintf(stderr, "[COV] Failed to open shared memory region\n"); 501cb0ef41Sopenharmony_ci _exit(-1); 511cb0ef41Sopenharmony_ci } 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ci shmem = (struct shmem_data*)mmap(0, SHM_SIZE, PROT_READ | PROT_WRITE, 541cb0ef41Sopenharmony_ci MAP_SHARED, fd, 0); 551cb0ef41Sopenharmony_ci if (shmem == MAP_FAILED) { 561cb0ef41Sopenharmony_ci fprintf(stderr, "[COV] Failed to mmap shared memory region\n"); 571cb0ef41Sopenharmony_ci _exit(-1); 581cb0ef41Sopenharmony_ci } 591cb0ef41Sopenharmony_ci } 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_ci edges_start = start; 621cb0ef41Sopenharmony_ci edges_stop = stop; 631cb0ef41Sopenharmony_ci sanitizer_cov_reset_edgeguards(); 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci shmem->num_edges = static_cast<uint32_t>(stop - start); 661cb0ef41Sopenharmony_ci builtins_start = 1 + shmem->num_edges; 671cb0ef41Sopenharmony_ci printf("[COV] edge counters initialized. Shared memory: %s with %u edges\n", 681cb0ef41Sopenharmony_ci shm_key, shmem->num_edges); 691cb0ef41Sopenharmony_ci} 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_ciuint32_t sanitizer_cov_count_discovered_edges() { 721cb0ef41Sopenharmony_ci uint32_t on_edges_counter = 0; 731cb0ef41Sopenharmony_ci for (uint32_t i = 1; i < builtins_start; ++i) { 741cb0ef41Sopenharmony_ci // TODO(ralbovsky): Can be optimized for fewer divisions. 751cb0ef41Sopenharmony_ci if (shmem->edges[i / 8] & (1 << (i % 8))) { 761cb0ef41Sopenharmony_ci ++on_edges_counter; 771cb0ef41Sopenharmony_ci } 781cb0ef41Sopenharmony_ci } 791cb0ef41Sopenharmony_ci return on_edges_counter; 801cb0ef41Sopenharmony_ci} 811cb0ef41Sopenharmony_ci 821cb0ef41Sopenharmony_ciextern "C" void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { 831cb0ef41Sopenharmony_ci // There's a small race condition here: if this function executes in two 841cb0ef41Sopenharmony_ci // threads for the same edge at the same time, the first thread might disable 851cb0ef41Sopenharmony_ci // the edge (by setting the guard to zero) before the second thread fetches 861cb0ef41Sopenharmony_ci // the guard value (and thus the index). However, our instrumentation ignores 871cb0ef41Sopenharmony_ci // the first edge (see libcoverage.c) and so the race is unproblematic. 881cb0ef41Sopenharmony_ci uint32_t index = *guard; 891cb0ef41Sopenharmony_ci shmem->edges[index / 8] |= 1 << (index % 8); 901cb0ef41Sopenharmony_ci *guard = 0; 911cb0ef41Sopenharmony_ci} 921cb0ef41Sopenharmony_ci 931cb0ef41Sopenharmony_civoid cov_init_builtins_edges(uint32_t num_edges) { 941cb0ef41Sopenharmony_ci if (num_edges + shmem->num_edges > MAX_EDGES) { 951cb0ef41Sopenharmony_ci printf( 961cb0ef41Sopenharmony_ci "[COV] Error: Insufficient amount of edges left for builtins " 971cb0ef41Sopenharmony_ci "coverage.\n"); 981cb0ef41Sopenharmony_ci exit(-1); 991cb0ef41Sopenharmony_ci } 1001cb0ef41Sopenharmony_ci builtins_edge_count = num_edges; 1011cb0ef41Sopenharmony_ci builtins_start = 1 + shmem->num_edges; 1021cb0ef41Sopenharmony_ci shmem->num_edges += builtins_edge_count; 1031cb0ef41Sopenharmony_ci printf("[COV] Additional %d edges for builtins initialized.\n", num_edges); 1041cb0ef41Sopenharmony_ci} 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_ci// This function is ran once per REPRL loop. In case of crash the coverage of 1071cb0ef41Sopenharmony_ci// crash will not be stored in shared memory. Therefore, it would be useful, if 1081cb0ef41Sopenharmony_ci// we could store these coverage information into shared memory in real time. 1091cb0ef41Sopenharmony_civoid cov_update_builtins_basic_block_coverage( 1101cb0ef41Sopenharmony_ci const std::vector<bool>& cov_map) { 1111cb0ef41Sopenharmony_ci if (cov_map.size() != builtins_edge_count) { 1121cb0ef41Sopenharmony_ci printf("[COV] Error: Size of builtins cov map changed.\n"); 1131cb0ef41Sopenharmony_ci exit(-1); 1141cb0ef41Sopenharmony_ci } 1151cb0ef41Sopenharmony_ci for (uint32_t i = 0; i < cov_map.size(); ++i) { 1161cb0ef41Sopenharmony_ci if (cov_map[i]) { 1171cb0ef41Sopenharmony_ci // TODO(ralbovsky): Can be optimized for fewer divisions. 1181cb0ef41Sopenharmony_ci shmem->edges[(i + builtins_start) / 8] |= 1191cb0ef41Sopenharmony_ci (1 << ((i + builtins_start) % 8)); 1201cb0ef41Sopenharmony_ci } 1211cb0ef41Sopenharmony_ci } 1221cb0ef41Sopenharmony_ci} 123