blob: 1e52136232d2d42de1e473c4dfebf70fe7e822d1 [file] [log] [blame]
Etienne Pierre-doraye57c4e62018-08-10 17:44:37 +00001// Copyright 2018 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#include "components/zucchini/disassembler_elf.h"
6
7#include <stddef.h>
8#include <stdint.h>
9
10#include <algorithm>
11#include <random>
Samuel Huangfa10b052021-08-05 16:46:38 +000012#include <string>
Etienne Pierre-doraye57c4e62018-08-10 17:44:37 +000013#include <vector>
14
15#include "components/zucchini/test_utils.h"
16#include "components/zucchini/type_elf.h"
17#include "testing/gtest/include/gtest/gtest.h"
18
19namespace zucchini {
20
Samuel Huangfa10b052021-08-05 16:46:38 +000021TEST(DisassemblerElfTest, IsTargetOffsetInElfSectionList) {
22 // Minimal required fields for IsTargetOffsetInElfSectionList().
23 struct FakeElfShdr {
24 offset_t sh_offset;
25 offset_t sh_size;
26 };
27
28 // Calls IsTargetOffsetInElfSectionList() for fixed |sorted_list|, and sweeps
29 // offsets in [lo, hi). Renders results into a string consisting of '.' (not
30 // in list) and '*' (in list).
31 auto test = [&](const std::vector<FakeElfShdr>& sorted_list, offset_t lo,
32 offset_t hi) -> std::string {
33 // Ensure |sorted_list| is indeed sorted, without overlaps.
34 for (size_t i = 1; i < sorted_list.size(); ++i) {
35 if (sorted_list[i].sh_offset <
36 sorted_list[i - 1].sh_offset + sorted_list[i - 1].sh_size) {
37 return "(Bad input)";
38 }
39 }
40 // The interface to IsTargetOffsetInElfSectionList() takes a list of
41 // pointers (since data can be casted from images), so make the conversion.
42 std::vector<const FakeElfShdr*> ptr_list;
43 for (const FakeElfShdr& header : sorted_list)
44 ptr_list.push_back(&header);
45 std::string result;
46 for (offset_t offset = lo; offset < hi; ++offset) {
47 result += IsTargetOffsetInElfSectionList(ptr_list, offset) ? '*' : '.';
48 }
49 return result;
50 };
51
52 EXPECT_EQ("..........", test(std::vector<FakeElfShdr>(), 0, 10));
53 EXPECT_EQ("*.........", test({{0, 1}}, 0, 10));
54 EXPECT_EQ("...*......", test({{3, 1}}, 0, 10));
55 EXPECT_EQ("...****...", test({{3, 4}}, 0, 10));
56 EXPECT_EQ("...****...", test({{10003, 4}}, 10000, 10010));
57 EXPECT_EQ("...********...", test({{3, 4}, {7, 4}}, 0, 14));
58 EXPECT_EQ("...****.****...", test({{3, 4}, {8, 4}}, 0, 15));
59 EXPECT_EQ("...****..****...", test({{3, 4}, {9, 4}}, 0, 16));
60 EXPECT_EQ("..****...*****..", test({{2, 4}, {9, 5}}, 0, 16));
61 EXPECT_EQ("...***......***..", test({{3, 3}, {12, 3}}, 0, 17));
62
63 // Many small ranges.
64 EXPECT_EQ("..**.**.*.*...*.*.**...**.*.**.*..", // (Comment strut).
65 test({{2, 2},
66 {5, 2},
67 {8, 1},
68 {10, 1},
69 {14, 1},
70 {16, 1},
71 {18, 2},
72 {23, 2},
73 {26, 1},
74 {28, 2},
75 {31, 1}},
76 0, 34));
77 EXPECT_EQ("..*****.****.***.**.*..",
78 test({{137, 5}, {143, 4}, {148, 3}, {152, 2}, {155, 1}}, 135, 158));
79 // Consecutive.
80 EXPECT_EQ("..***************..",
81 test({{137, 5}, {142, 4}, {146, 3}, {149, 2}, {151, 1}}, 135, 154));
82 // Hover around 32 (power of 2).
83 EXPECT_EQ("..*******************************..",
84 test({{2002, 31}}, 2000, 2035));
85 EXPECT_EQ("..********************************..",
86 test({{5002, 32}}, 5000, 5036));
87 EXPECT_EQ("..*********************************..",
88 test({{8002, 33}}, 8000, 8037));
89 // Consecutive + small gap.
90 EXPECT_EQ(
91 "..*****************.***********..",
92 test({{9876543, 8}, {9876551, 9}, {9876561, 11}}, 9876541, 9876574));
93 // Sample internal of big range.
94 EXPECT_EQ("**************************************************",
95 test({{100, 1000000}}, 5000, 5050));
96 // Sample boundaries of big range.
97 EXPECT_EQ(".........................*************************",
98 test({{100, 1000000}}, 75, 125));
99 EXPECT_EQ("*************************.........................",
100 test({{100, 1000000}}, 1000075, 1000125));
101 // 1E9 is still good.
102 EXPECT_EQ(".....*.....", test({{1000000000, 1}}, 999999995, 1000000006));
103}
104
Etienne Pierre-doraye57c4e62018-08-10 17:44:37 +0000105TEST(DisassemblerElfTest, QuickDetect) {
106 std::vector<uint8_t> image_data;
107 ConstBufferView image;
108
109 // Empty.
110 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
111 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
112
113 // Unrelated.
114 image_data = ParseHexString("DE AD");
115 image = {image_data.data(), image_data.size()};
116 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
117 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
118
119 // Only Magic.
120 image_data = ParseHexString("7F 45 4C 46");
121 image = {image_data.data(), image_data.size()};
122 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
123 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
124
125 // Only identification.
126 image_data =
127 ParseHexString("7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00");
128 image = {image_data.data(), image_data.size()};
129 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
130 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
131
132 // Large enough, filled with zeros.
133 image_data.assign(sizeof(elf::Elf32_Ehdr), 0);
134 image = {image_data.data(), image_data.size()};
135 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
136 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
137
138 // Random.
139 std::random_device rd;
140 std::mt19937 gen{rd()};
141 std::generate(image_data.begin(), image_data.end(), gen);
142 image = {image_data.data(), image_data.size()};
143 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
144 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
145
146 // Typical x86 elf header.
147 {
148 elf::Elf32_Ehdr header = {};
149 auto e_ident =
150 ParseHexString("7F 45 4C 46 01 01 01 00 00 00 00 00 00 00 00 00");
151 std::copy(e_ident.begin(), e_ident.end(), header.e_ident);
152 header.e_type = elf::ET_EXEC;
153 header.e_machine = elf::EM_386;
154 header.e_version = 1;
155 header.e_shentsize = sizeof(elf::Elf32_Shdr);
Peter Kasting9ff43f52021-09-08 17:53:30 +0000156 image = {reinterpret_cast<const uint8_t*>(&header), sizeof(header)};
Etienne Pierre-doraye57c4e62018-08-10 17:44:37 +0000157 EXPECT_TRUE(DisassemblerElfX86::QuickDetect(image));
158 EXPECT_FALSE(DisassemblerElfX64::QuickDetect(image));
159 }
160
161 // Typical x64 elf header.
162 {
163 elf::Elf64_Ehdr header = {};
164 auto e_ident =
165 ParseHexString("7F 45 4C 46 02 01 01 00 00 00 00 00 00 00 00 00");
166 std::copy(e_ident.begin(), e_ident.end(), header.e_ident);
167 header.e_type = elf::ET_EXEC;
168 header.e_machine = elf::EM_X86_64;
169 header.e_version = 1;
170 header.e_shentsize = sizeof(elf::Elf64_Shdr);
Peter Kasting9ff43f52021-09-08 17:53:30 +0000171 image = {reinterpret_cast<const uint8_t*>(&header), sizeof(header)};
Etienne Pierre-doraye57c4e62018-08-10 17:44:37 +0000172 EXPECT_FALSE(DisassemblerElfX86::QuickDetect(image));
173 EXPECT_TRUE(DisassemblerElfX64::QuickDetect(image));
174 }
175}
176
177} // namespace zucchini