]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/fuzzer/FuzzerShmemPosix.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / fuzzer / FuzzerShmemPosix.cpp
1 //===- FuzzerShmemPosix.cpp - Posix shared memory ---------------*- C++ -* ===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 // SharedMemoryRegion
10 //===----------------------------------------------------------------------===//
11 #include "FuzzerDefs.h"
12 #if LIBFUZZER_POSIX
13
14 #include "FuzzerIO.h"
15 #include "FuzzerShmem.h"
16
17 #include <errno.h>
18 #include <fcntl.h>
19 #include <semaphore.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <sys/mman.h>
23 #include <sys/stat.h>
24 #include <sys/types.h>
25 #include <unistd.h>
26
27 namespace fuzzer {
28
29 std::string SharedMemoryRegion::Path(const char *Name) {
30   return DirPlusFile(TmpDir(), Name);
31 }
32
33 std::string SharedMemoryRegion::SemName(const char *Name, int Idx) {
34   std::string Res(Name);
35   // When passing a name without a leading <slash> character to
36   // sem_open, the behaviour is unspecified in POSIX. Add a leading
37   // <slash> character for the name if there is no such one.
38   if (!Res.empty() && Res[0] != '/')
39     Res.insert(Res.begin(), '/');
40   return Res + (char)('0' + Idx);
41 }
42
43 bool SharedMemoryRegion::Map(int fd) {
44   Data =
45       (uint8_t *)mmap(0, kShmemSize, PROT_WRITE | PROT_READ, MAP_SHARED, fd, 0);
46   if (Data == (uint8_t*)-1)
47     return false;
48   return true;
49 }
50
51 bool SharedMemoryRegion::Create(const char *Name) {
52   int fd = open(Path(Name).c_str(), O_CREAT | O_RDWR, 0777);
53   if (fd < 0) return false;
54   if (ftruncate(fd, kShmemSize) < 0) return false;
55   if (!Map(fd))
56     return false;
57   for (int i = 0; i < 2; i++) {
58     sem_unlink(SemName(Name, i).c_str());
59     Semaphore[i] = sem_open(SemName(Name, i).c_str(), O_CREAT, 0644, 0);
60     if (Semaphore[i] == SEM_FAILED)
61       return false;
62   }
63   IAmServer = true;
64   return true;
65 }
66
67 bool SharedMemoryRegion::Open(const char *Name) {
68   int fd = open(Path(Name).c_str(), O_RDWR);
69   if (fd < 0) return false;
70   struct stat stat_res;
71   if (0 != fstat(fd, &stat_res))
72     return false;
73   assert(stat_res.st_size == kShmemSize);
74   if (!Map(fd))
75     return false;
76   for (int i = 0; i < 2; i++) {
77     Semaphore[i] = sem_open(SemName(Name, i).c_str(), 0);
78     if (Semaphore[i] == SEM_FAILED)
79       return false;
80   }
81   IAmServer = false;
82   return true;
83 }
84
85 bool SharedMemoryRegion::Destroy(const char *Name) {
86   return 0 == unlink(Path(Name).c_str());
87 }
88
89 void SharedMemoryRegion::Post(int Idx) {
90   assert(Idx == 0 || Idx == 1);
91   sem_post((sem_t*)Semaphore[Idx]);
92 }
93
94 void SharedMemoryRegion::Wait(int Idx) {
95   assert(Idx == 0 || Idx == 1);
96   for (int i = 0; i < 10 && sem_wait((sem_t*)Semaphore[Idx]); i++) {
97     // sem_wait may fail if interrupted by a signal.
98     sleep(i);
99     if (i)
100       Printf("%s: sem_wait[%d] failed %s\n", i < 9 ? "WARNING" : "ERROR", i,
101              strerror(errno));
102     if (i == 9) abort();
103   }
104 }
105
106 }  // namespace fuzzer
107
108 #endif  // LIBFUZZER_POSIX