1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file.
4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A set of common helper functions used by crazy_linker tests.
6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// IMPORTANT: ALL FUNCTIONS HERE ARE INLINED. This avoids adding a
7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// dependency on another source file for all tests that include this
8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// header.
9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef TEST_UTIL_H
11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define TEST_UTIL_H
12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <crazy_linker.h>
14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <dirent.h>
16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h>
17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <limits.h>
18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdarg.h>
19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdio.h>
20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdlib.h>
21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/mman.h>
22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/socket.h>
23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/stat.h>
24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/uio.h>
25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <unistd.h>
26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef __STDC_FORMAT_MACROS
27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define __STDC_FORMAT_MACROS // to get PRI and SCN in 32-bit inttypes.h
28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif
29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <inttypes.h>
30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace {
32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Print an error message and exit the process.
34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Message must be terminated by a newline.
35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline void Panic(const char* fmt, ...) {
36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_list args;
37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  fprintf(stderr, "PANIC: ");
38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_start(args, fmt);
39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  vfprintf(stderr, fmt, args);
40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_end(args);
41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  exit(1);
42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Print an error message, the errno message, then exit the process.
45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Message must not be terminated by a newline.
46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline void PanicErrno(const char* fmt, ...) {
47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int old_errno = errno;
48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_list args;
49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  fprintf(stderr, "PANIC: ");
50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_start(args, fmt);
51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  vfprintf(stderr, fmt, args);
52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  va_end(args);
53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  fprintf(stderr, ": %s\n", strerror(old_errno));
54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  exit(1);
55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Simple string class.
58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class String {
59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String() : str_(NULL), len_(0) {}
61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String(const String& other) { String(other.str_, other.len_); }
63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String(const char* str) { String(str, strlen(str)); }
65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String(const char* str, size_t len) : str_(NULL), len_(0) {
67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Append(str, len);
68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ~String() {
71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (str_) {
72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      free(str_);
73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      str_ = NULL;
74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String& operator+=(const char* str) {
78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Append(str, strlen(str));
79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return *this;
80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String& operator+=(const String& other) {
83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Append(other.str_, other.len_);
84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return *this;
85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String& operator+=(char ch) {
88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Append(&ch, 1);
89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return *this;
90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* c_str() const { return len_ ? str_ : ""; }
93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char* ptr() { return str_; }
94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t size() const { return len_; }
95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Append(const char* str, size_t len) {
97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    size_t old_len = len_;
98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Resize(len_ + len);
99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    memcpy(str_ + old_len, str, len);
100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Resize(size_t len) {
103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    str_ = reinterpret_cast<char*>(realloc(str_, len + 1));
104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (len > len_)
105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      memset(str_ + len_, '\0', len - len_);
106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    str_[len] = '\0';
107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    len_ = len;
108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Format(const char* fmt, ...) {
111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    va_list args;
112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    va_start(args, fmt);
113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Resize(128);
114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    for (;;) {
115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      va_list args2;
116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      va_copy(args2, args);
117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      int ret = vsnprintf(str_, len_ + 1, fmt, args2);
118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      va_end(args2);
119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (ret < static_cast<int>(len_ + 1))
120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        break;
121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Resize(len_ * 2);
123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char* str_;
128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t len_;
129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper class to create a temporary directory that gets deleted on scope exit,
132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// as well as all regular files it contains.
133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class TempDirectory {
134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  TempDirectory() {
136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    snprintf(path_, sizeof path_, "/data/local/tmp/temp-XXXXXX");
137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!mktemp(path_))
138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not create temporary directory name: %s\n", strerror(errno));
139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (mkdir(path_, 0700) < 0)
140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not create temporary directory %s: %s\n", strerror(errno));
141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ~TempDirectory() {
144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Remove any file in this directory.
145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    DIR* d = opendir(path_);
146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!d)
147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not open directory %s: %s\n", strerror(errno));
148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    struct dirent* entry;
150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    while ((entry = readdir(d)) != NULL) {
151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, ".."))
152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        continue;
153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      String file_path;
154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      file_path.Format("%s/%s", path_, entry->d_name);
155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (unlink(file_path.c_str()) < 0)
156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        Panic("Could not remove %s: %s\n", file_path.c_str(), strerror(errno));
157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    closedir(d);
159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (rmdir(path_) < 0)
161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not remove dir %s: %s\n", path_, strerror(errno));
162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* path() const { return path_; }
165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char path_[PATH_MAX];
168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Scoped FILE* class. Always closed on destruction.
171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ScopedFILE {
172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public:
173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedFILE() : file_(NULL) {}
174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ~ScopedFILE() {
176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (file_) {
177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      fclose(file_);
178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      file_ = NULL;
179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Open(const char* path, const char* mode) {
183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    file_ = fopen(path, mode);
184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!file_)
185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not open file for reading: %s: %s\n", path, strerror(errno));
186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FILE* file() const { return file_; }
189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private:
191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FILE* file_;
192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Retrieve current executable path as a String.
195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline String GetCurrentExecutable() {
196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String path;
197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  path.Resize(PATH_MAX);
198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ssize_t ret =
199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      TEMP_FAILURE_RETRY(readlink("/proc/self/exe", path.ptr(), path.size()));
200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ret < 0)
201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Panic("Could not read /proc/self/exe: %s\n", strerror(errno));
202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return path;
204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Retrieve current executable directory as a String.
207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline String GetCurrentExecutableDirectory() {
208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String path = GetCurrentExecutable();
209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  // Find basename.
210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* p = reinterpret_cast<const char*>(strrchr(path.c_str(), '/'));
211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (p == NULL)
212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Panic("Current executable does not have directory root?: %s\n",
213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          path.c_str());
214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  path.Resize(p - path.c_str());
216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return path;
217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copy a file named |src_file_name| in directory |src_file_dir| into
220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// a file named |dst_file_name| in directory |dst_file_dir|. Panics on error.
221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline void CopyFile(const char* src_file_name,
222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     const char* src_file_dir,
223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     const char* dst_file_name,
224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                     const char* dst_file_dir) {
225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String src_path;
226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  src_path.Format("%s/%s", src_file_dir, src_file_name);
227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedFILE src_file;
229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  src_file.Open(src_path.c_str(), "rb");
230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  String dst_path;
232f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dst_path.Format("%s/%s", dst_file_dir, dst_file_name);
233f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ScopedFILE dst_file;
234f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  dst_file.Open(dst_path.c_str(), "wb");
235f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
236f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char buffer[8192];
237f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  for (;;) {
238f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    size_t read = fread(buffer, 1, sizeof buffer, src_file.file());
239f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (read > 0) {
240f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      size_t written = fwrite(buffer, 1, read, dst_file.file());
241f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (written != read)
242f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        Panic("Wrote %d bytes instead of %d into %s\n",
243f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              written,
244f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              read,
245f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)              dst_path.c_str());
246f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
247f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (read < sizeof buffer)
248f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      break;
249f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
250f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
251f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
252f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Send a file descriptor |fd| through |socket|.
253f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Return 0 on success, -1/errno on failure.
254f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline int SendFd(int socket, int fd) {
255f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct iovec iov;
256f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
257f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char buffer[1];
258f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  buffer[0] = 0;
259f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
260f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  iov.iov_base = buffer;
261f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  iov.iov_len = 1;
262f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
263f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct msghdr msg;
264f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct cmsghdr* cmsg;
265f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char cms[CMSG_SPACE(sizeof(int))];
266f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
267f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ::memset(&msg, 0, sizeof(msg));
268f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_iov = &iov;
269f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_iovlen = 1;
270f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_control = reinterpret_cast<caddr_t>(cms);
271f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_controllen = CMSG_LEN(sizeof(int));
272f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
273f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cmsg = CMSG_FIRSTHDR(&msg);
274f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cmsg->cmsg_len = CMSG_LEN(sizeof(int));
275f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cmsg->cmsg_level = SOL_SOCKET;
276f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cmsg->cmsg_type = SCM_RIGHTS;
277f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ::memcpy(CMSG_DATA(cmsg), &fd, sizeof(int));
278f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
279f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int ret = sendmsg(socket, &msg, 0);
280f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ret < 0)
281f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return -1;
282f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
283f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ret != iov.iov_len) {
284f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    errno = EIO;
285f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return -1;
286f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
287f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
288f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return 0;
289f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
290f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
291f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline int ReceiveFd(int socket, int* fd) {
292f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char buffer[1];
293f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct iovec iov;
294f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
295f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  iov.iov_base = buffer;
296f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  iov.iov_len = 1;
297f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
298f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct msghdr msg;
299f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  struct cmsghdr* cmsg;
300f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char cms[CMSG_SPACE(sizeof(int))];
301f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
302f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ::memset(&msg, 0, sizeof msg);
303f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_name = 0;
304f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_namelen = 0;
305f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_iov = &iov;
306f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_iovlen = 1;
307f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
308f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_control = reinterpret_cast<caddr_t>(cms);
309f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  msg.msg_controllen = sizeof(cms);
310f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
311f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int ret = recvmsg(socket, &msg, 0);
312f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ret < 0)
313f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return -1;
314f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (ret == 0) {
315f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    errno = EIO;
316f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    return -1;
317f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
318f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
319f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  cmsg = CMSG_FIRSTHDR(&msg);
320f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  ::memcpy(fd, CMSG_DATA(cmsg), sizeof(int));
321f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  return 0;
322f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
324f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Check that there are exactly |expected_count| memory mappings in
325f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// /proc/self/maps that point to a RELRO ashmem region.
326f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline void CheckRelroMaps(int expected_count) {
327f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  printf("Checking for %d RELROs in /proc/self/maps\n", expected_count);
328f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
329f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  FILE* file = fopen("/proc/self/maps", "rb");
330f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (!file)
331f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Panic("Could not open /proc/self/maps (pid %d): %s\n",
332f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          getpid(),
333f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          strerror(errno));
334f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
335f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  char line[512];
336f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int count_relros = 0;
337f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  printf("proc/%d/maps:\n", getpid());
338f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  while (fgets(line, sizeof line, file)) {
339f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (strstr(line, "with_relro")) {
340f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      // The supported library names are "lib<name>_with_relro.so".
341f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      printf("%s", line);
342f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      if (strstr(line, "/dev/ashmem/RELRO:")) {
343f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        count_relros++;
344f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Check that they are read-only mappings.
345f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (!strstr(line, " r--"))
346f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          Panic("Shared RELRO mapping is not readonly!\n");
347f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        // Check that they can't be remapped read-write.
348f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        uint64_t vma_start, vma_end;
349f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (sscanf(line, "%" SCNx64 "-%" SCNx64, &vma_start, &vma_end) != 2)
350f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          Panic("Could not parse VM address range!\n");
351f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        int ret = ::mprotect(
352f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            (void*)vma_start, vma_end - vma_start, PROT_READ | PROT_WRITE);
353f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (ret == 0)
354f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          Panic("Could remap shared RELRO as writable, should not happen!\n");
355f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
356f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        if (errno != EACCES)
357f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)          Panic("remapping shared RELRO to writable failed with: %s\n",
358f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                strerror(errno));
359f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      }
360f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
361f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
362f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  fclose(file);
363f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
364f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  if (count_relros != expected_count)
365f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    Panic(
366f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        "Invalid shared RELRO sections in /proc/self/maps: %d"
367f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        " (expected %d)\n",
368f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        count_relros,
369f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        expected_count);
370f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
371f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  printf("RELRO count check ok!\n");
372f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}
373f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
374f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct RelroInfo {
375f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t start;
376f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  size_t size;
377f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  int fd;
378f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
379f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
380f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct RelroLibrary {
381f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  const char* name;
382f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  crazy_library_t* library;
383f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  RelroInfo relro;
384f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
385f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Init(const char* name, crazy_context_t* context) {
386f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    printf("Loading %s\n", name);
387f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    this->name = name;
388f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!crazy_library_open(&this->library, name, context)) {
389f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not open %s: %s\n", name, crazy_context_get_error(context));
390f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
391f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
392f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
393f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void Close() { crazy_library_close(this->library); }
394f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
395f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void CreateSharedRelro(crazy_context_t* context, size_t load_address) {
396f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!crazy_library_create_shared_relro(this->library,
397f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           context,
398f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           load_address,
399f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           &this->relro.start,
400f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           &this->relro.size,
401f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                           &this->relro.fd)) {
402f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not create shared RELRO for %s: %s",
403f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            this->name,
404f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            crazy_context_get_error(context));
405f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
406f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
407f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    printf("Parent %s relro info relro_start=%p relro_size=%p relro_fd=%d\n",
408f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           this->name,
409f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           (void*)this->relro.start,
410f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           (void*)this->relro.size,
411f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           this->relro.fd);
412f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
413f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
414f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void EnableSharedRelro(crazy_context_t* context) {
415f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    CreateSharedRelro(context, 0);
416f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    UseSharedRelro(context);
417f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
418f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
419f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void SendRelroInfo(int fd) {
420f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (SendFd(fd, this->relro.fd) < 0) {
421f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not send %s RELRO fd: %s", this->name, strerror(errno));
422f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
423f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
424f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int ret =
425f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)        TEMP_FAILURE_RETRY(::write(fd, &this->relro, sizeof(this->relro)));
426f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (ret != static_cast<int>(sizeof(this->relro))) {
427f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Parent could not send %s RELRO info: %s",
428f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            this->name,
429f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            strerror(errno));
430f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
431f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
432f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
433f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void ReceiveRelroInfo(int fd) {
434f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    // Receive relro information from parent.
435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int relro_fd = -1;
436f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (ReceiveFd(fd, &relro_fd) < 0) {
437f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not receive %s relro descriptor from parent", this->name);
438f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
439f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
440f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    printf("Child received %s relro fd %d\n", this->name, relro_fd);
441f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
442f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    int ret = TEMP_FAILURE_RETRY(::read(fd, &this->relro, sizeof(this->relro)));
443f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (ret != static_cast<int>(sizeof(this->relro))) {
444f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not receive %s relro information from parent", this->name);
445f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
446f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
447f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    this->relro.fd = relro_fd;
448f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    printf("Child received %s relro start=%p size=%p\n",
449f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           this->name,
450f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           (void*)this->relro.start,
451f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)           (void*)this->relro.size);
452f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
453f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
454f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  void UseSharedRelro(crazy_context_t* context) {
455f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    if (!crazy_library_use_shared_relro(this->library,
456f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        context,
457f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        this->relro.start,
458f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        this->relro.size,
459f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)                                        this->relro.fd)) {
460f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)      Panic("Could not use %s shared RELRO: %s\n",
461f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            this->name,
462f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)            crazy_context_get_error(context));
463f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)    }
464f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)  }
465f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)};
466f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
467f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}  // namespace
468f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)
469f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif  // TEST_UTIL_H
470