14int ef_load(
const char* path,
int version) {
16 void* library = dlopen(path, RTLD_NOW | RTLD_LOCAL);
18 fprintf(stderr,
"EXECUTABLE-FILE-CONTRACT: dlopen %s: %s\n", path, dlerror());
20 int (*warm)(void) = (
int (*)(void))dlsym(library,
"executable_fixture_warm");
21 int (*cold)(void) = (
int (*)(void))dlsym(library,
"executable_fixture_cold");
22 CHECK(warm && cold && warm() == version && cold() == version);
30 int failed = 0, fd = -1, probe = -1;
31 char path[PATH_MAX], staged[PATH_MAX];
34 snprintf(path,
sizeof(path),
"%s/current.so", ef_directory);
35 snprintf(staged,
sizeof(staged),
"%s/staged.so", ef_directory);
36 CHECK(!ef_copy(
"/libraries/libexecutable-file-fixture-v1.so", path));
37 CHECK((fd = open(path, O_RDWR | O_CLOEXEC)) >= 0);
38 struct stat before, after;
39 CHECK(!fstat(fd, &before));
40 library = dlopen(path, RTLD_NOW | RTLD_LOCAL);
42 fprintf(stderr,
"EXECUTABLE-FILE-CONTRACT: dlopen %s: %s\n", path, dlerror());
44 int (*warm)(void) = (
int (*)(void))dlsym(library,
"executable_fixture_warm");
45 int (*cold)(void) = (
int (*)(void))dlsym(library,
"executable_fixture_cold");
46 const volatile unsigned char* data = dlsym(library,
"executable_fixture_data");
47 CHECK(warm && cold && data && warm() == 1);
48 CHECK(pwrite(fd,
"x", 1, 0) == -1 && errno == ETXTBSY);
49 CHECK(ftruncate(fd, 0) == -1 && errno == ETXTBSY);
50 probe = open(path, O_WRONLY | O_TRUNC);
51 CHECK(probe == -1 && errno == ETXTBSY);
52 CHECK(!fstat(fd, &after) && before.st_size == after.st_size);
54 CHECK(pread(fd, magic,
sizeof(magic), 0) ==
sizeof(magic) && !memcmp(magic,
"\177ELF", 4));
55 CHECK(!ef_copy(
"/libraries/libexecutable-file-fixture-v2.so", staged));
56 uintptr_t code_page = (uintptr_t)cold / ef_page * ef_page;
57 uintptr_t data_page = (uintptr_t)(data + 8192) / ef_page * ef_page;
58 CHECK(code_page != (uintptr_t)warm / ef_page * ef_page);
60 CHECK(!madvise((
void*)code_page, ef_page, MADV_DONTNEED));
61 CHECK(!madvise((
void*)data_page, ef_page, MADV_DONTNEED));
62 CHECK(!rename(staged, path));
63 CHECK(!stat(path, &after) && before.st_ino != after.st_ino);
64 CHECK(cold() == 1 && data[8192] == 1 && warm() == 1);
65 CHECK((child = fork()) >= 0);
67 execl(ef_self, ef_self,
"--load", path,
"2", NULL);
70 int status = ef_reap(child);