1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
/*
* Copyright (C) 2023 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <android-base/properties.h>
#include <android/api-level.h>
#include <elf.h>
#include <gtest/gtest.h>
#include <libelf64/parse.h>
class Vts16KPageSizeTest : public ::testing::Test {
protected:
static int VendorApiLevel() {
// "ro.vendor.api_level" is added in Android T.
// Undefined indicates S or below
return android::base::GetIntProperty("ro.vendor.api_level", __ANDROID_API_S__);
}
static std::string Architecture() { return android::base::GetProperty("ro.bionic.arch", ""); }
static ssize_t MaxPageSize(const std::string& filepath) {
ssize_t maxPageSize = -1;
android::elf64::Elf64Binary elf;
if (!android::elf64::Elf64Parser::ParseElfFile(filepath, elf)) {
return -1;
}
for (int i = 0; i < elf.phdrs.size(); i++) {
Elf64_Phdr phdr = elf.phdrs[i];
if ((phdr.p_type != PT_LOAD) || !(phdr.p_type & PF_X)) {
continue;
}
maxPageSize = phdr.p_align;
break;
}
return maxPageSize;
}
static void SetUpTestSuite() {
if (VendorApiLevel() < __ANDROID_API_V__) {
GTEST_SKIP() << "16kB support is only required on V and later releases.";
}
}
/*
* x86_64 also needs to be at least 16KB aligned, since Android
* supports page size emulation in x86_64 for app development.
*/
size_t RequiredMaxPageSize() {
if (mArch == "arm64" || mArch == "aarch64" || mArch == "x86_64") {
return 0x4000;
} else {
return 0x1000;
}
}
const std::string mArch = Architecture();
};
/**
* Checks the max-page-size of init against the architecture's
* required max-page-size.
*
*/
TEST_F(Vts16KPageSizeTest, InitMaxPageSizeTest) {
constexpr char initPath[] = "/system/bin/init";
ssize_t expectedMaxPageSize = RequiredMaxPageSize();
ASSERT_NE(expectedMaxPageSize, -1)
<< "Failed to get required max page size for arch: " << mArch;
ssize_t initMaxPageSize = MaxPageSize(initPath);
ASSERT_NE(initMaxPageSize, -1) << "Failed to get max page size of ELF: " << initPath;
ASSERT_EQ(initMaxPageSize % expectedMaxPageSize, 0)
<< "ELF " << initPath << " with page size " << initMaxPageSize
<< " was not built with the required max-page-size " << expectedMaxPageSize;
}
|