1// Copyright 2014 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#if defined(__arm__)  // nacl_irt_icache is supported only on ARM.
6
7#include <errno.h>
8#include <sys/mman.h>
9
10#include "components/nacl/loader/nonsfi/irt_interfaces.h"
11#include "testing/gtest/include/gtest/gtest.h"
12
13TEST(NaClIrtIcacheTest, ClearCache) {
14  int (*irt_clear_cache)(void*, size_t) =
15      nacl::nonsfi::kIrtIcache.clear_cache;
16  // Create code for a function to return 0x01.
17  static const uint32_t code_template[] = {
18    0xe3000001,  // movw r0, #0x1
19    0xe12fff1e,  // bx lr
20  };
21  void* start =
22      mmap(NULL, sizeof(code_template), PROT_READ | PROT_WRITE | PROT_EXEC,
23           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
24  EXPECT_NE(MAP_FAILED, start);
25  memcpy(start, code_template, sizeof(code_template));
26  size_t size = sizeof(code_template);
27  EXPECT_EQ(0, irt_clear_cache(start, size));
28  typedef int (*TestFunc)(void);
29  TestFunc func = reinterpret_cast<TestFunc>(start);
30  EXPECT_EQ(0x1, func());
31  // Modify the function to return 0x11.
32  *reinterpret_cast<uint32_t*>(start) = 0xe3000011;  // movw r0, #0x11
33  // In most cases 0x1 is still returned because the cached code is executed
34  // although the CPU is not obliged to do so.
35  // Uncomment the following line to see if the cached code is executed.
36  // EXPECT_EQ(0x1, func());
37  EXPECT_EQ(0, irt_clear_cache(start, size));
38  // Now it is ensured that 0x11 is returned because I-cache was invalidated
39  // and updated with the new code.
40  EXPECT_EQ(0x11, func());
41  EXPECT_EQ(0, munmap(start, sizeof(code_template)));
42}
43
44TEST(NaClIrtIcacheTest, ClearCacheInvalidArg) {
45  int (*irt_clear_cache)(void*, size_t) =
46      nacl::nonsfi::kIrtIcache.clear_cache;
47  const size_t mem_size = 256;
48  void* start =
49      mmap(NULL, mem_size, PROT_READ | PROT_WRITE | PROT_EXEC,
50           MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
51  EXPECT_EQ(0, irt_clear_cache(start, mem_size));
52  EXPECT_EQ(EINVAL, irt_clear_cache(start, 0));
53  EXPECT_EQ(EINVAL, irt_clear_cache(NULL, mem_size));
54  EXPECT_EQ(0, munmap(start, mem_size));
55}
56
57#endif
58