xref: /aosp_15_r20/external/zucchini/abs32_utils_unittest.cc (revision a03ca8b91e029cd15055c20c78c2e087c84792e4)
1*a03ca8b9SKrzysztof Kosiński // Copyright 2017 The Chromium Authors. All rights reserved.
2*a03ca8b9SKrzysztof Kosiński // Use of this source code is governed by a BSD-style license that can be
3*a03ca8b9SKrzysztof Kosiński // found in the LICENSE file.
4*a03ca8b9SKrzysztof Kosiński 
5*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/abs32_utils.h"
6*a03ca8b9SKrzysztof Kosiński 
7*a03ca8b9SKrzysztof Kosiński #include <stdint.h>
8*a03ca8b9SKrzysztof Kosiński 
9*a03ca8b9SKrzysztof Kosiński #include <algorithm>
10*a03ca8b9SKrzysztof Kosiński #include <string>
11*a03ca8b9SKrzysztof Kosiński #include <utility>
12*a03ca8b9SKrzysztof Kosiński 
13*a03ca8b9SKrzysztof Kosiński #include "base/numerics/safe_conversions.h"
14*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/address_translator.h"
15*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/image_utils.h"
16*a03ca8b9SKrzysztof Kosiński #include "components/zucchini/test_utils.h"
17*a03ca8b9SKrzysztof Kosiński #include "testing/gtest/include/gtest/gtest.h"
18*a03ca8b9SKrzysztof Kosiński 
19*a03ca8b9SKrzysztof Kosiński namespace zucchini {
20*a03ca8b9SKrzysztof Kosiński 
21*a03ca8b9SKrzysztof Kosiński namespace {
22*a03ca8b9SKrzysztof Kosiński 
23*a03ca8b9SKrzysztof Kosiński // A trivial AddressTranslator that applies constant shift.
24*a03ca8b9SKrzysztof Kosiński class TestAddressTranslator : public AddressTranslator {
25*a03ca8b9SKrzysztof Kosiński  public:
TestAddressTranslator(size_t image_size,rva_t rva_begin)26*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator(size_t image_size, rva_t rva_begin) {
27*a03ca8b9SKrzysztof Kosiński     DCHECK_GE(rva_begin, 0U);
28*a03ca8b9SKrzysztof Kosiński     CHECK_EQ(AddressTranslator::kSuccess,
29*a03ca8b9SKrzysztof Kosiński              Initialize({{0, base::checked_cast<offset_t>(image_size),
30*a03ca8b9SKrzysztof Kosiński                           rva_begin, base::checked_cast<rva_t>(image_size)}}));
31*a03ca8b9SKrzysztof Kosiński   }
32*a03ca8b9SKrzysztof Kosiński };
33*a03ca8b9SKrzysztof Kosiński 
34*a03ca8b9SKrzysztof Kosiński // Helper to translate address |value| to RVA. May return |kInvalidRva|.
AddrValueToRva(uint64_t value,AbsoluteAddress * addr)35*a03ca8b9SKrzysztof Kosiński rva_t AddrValueToRva(uint64_t value, AbsoluteAddress* addr) {
36*a03ca8b9SKrzysztof Kosiński   *addr->mutable_value() = value;
37*a03ca8b9SKrzysztof Kosiński   return addr->ToRva();
38*a03ca8b9SKrzysztof Kosiński }
39*a03ca8b9SKrzysztof Kosiński 
40*a03ca8b9SKrzysztof Kosiński }  // namespace
41*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,AbsoluteAddress32)42*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, AbsoluteAddress32) {
43*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data32 = ParseHexString(
44*a03ca8b9SKrzysztof Kosiński       "00 00 32 00  21 43 65 4A  00 00 00 00  FF FF FF FF  FF FF 31 00");
45*a03ca8b9SKrzysztof Kosiński   ConstBufferView image32(data32.data(), data32.size());
46*a03ca8b9SKrzysztof Kosiński   MutableBufferView mutable_image32(data32.data(), data32.size());
47*a03ca8b9SKrzysztof Kosiński 
48*a03ca8b9SKrzysztof Kosiński   AbsoluteAddress addr32(kBit32, 0x00320000U);
49*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Read(0x0U, image32));
50*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x00000000U, addr32.ToRva());
51*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Read(0x4U, image32));
52*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x4A334321U, addr32.ToRva());
53*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Read(0x8U, image32));
54*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Underflow.
55*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Read(0xCU, image32));
56*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Translated RVA would be too large.
57*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Read(0x10U, image32));
58*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr32.ToRva());  // Underflow (boundary case).
59*a03ca8b9SKrzysztof Kosiński 
60*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Read(0x11U, image32));
61*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Read(0x14U, image32));
62*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Read(0x100000U, image32));
63*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Read(0x80000000U, image32));
64*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Read(0xFFFFFFFFU, image32));
65*a03ca8b9SKrzysztof Kosiński 
66*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.FromRva(0x11223344U));
67*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Write(0x2U, &mutable_image32));
68*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.Write(0x10U, &mutable_image32));
69*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> expected_data32 = ParseHexString(
70*a03ca8b9SKrzysztof Kosiński       "00 00  44 33 54 11  65 4A 00 00 00 00 FF FF FF FF  44 33 54 11");
71*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data32, data32);
72*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Write(0x11U, &mutable_image32));
73*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.Write(0xFFFFFFFFU, &mutable_image32));
74*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data32, data32);
75*a03ca8b9SKrzysztof Kosiński }
76*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,AbsoluteAddress32Overflow)77*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, AbsoluteAddress32Overflow) {
78*a03ca8b9SKrzysztof Kosiński   AbsoluteAddress addr32(kBit32, 0xC0000000U);
79*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.FromRva(0x00000000U));
80*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.FromRva(0x11223344U));
81*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr32.FromRva(0x3FFFFFFFU));
82*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.FromRva(0x40000000U));
83*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.FromRva(0x40000001U));
84*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.FromRva(0x80000000U));
85*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr32.FromRva(0xFFFFFFFFU));
86*a03ca8b9SKrzysztof Kosiński 
87*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x00000000U, AddrValueToRva(0xC0000000U, &addr32));
88*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, AddrValueToRva(0xBFFFFFFFU, &addr32));
89*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, AddrValueToRva(0x00000000U, &addr32));
90*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x3FFFFFFFU, AddrValueToRva(0xFFFFFFFFU, &addr32));
91*a03ca8b9SKrzysztof Kosiński }
92*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,AbsoluteAddress64)93*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, AbsoluteAddress64) {
94*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data64 = ParseHexString(
95*a03ca8b9SKrzysztof Kosiński       "00 00 00 00 64 00 00 00  21 43 65 4A 64 00 00 00 "
96*a03ca8b9SKrzysztof Kosiński       "00 00 00 00 00 00 00 00  FF FF FF FF FF FF FF FF "
97*a03ca8b9SKrzysztof Kosiński       "00 00 00 00 64 00 00 80  FF FF FF FF 63 00 00 00");
98*a03ca8b9SKrzysztof Kosiński   ConstBufferView image64(data64.data(), data64.size());
99*a03ca8b9SKrzysztof Kosiński   MutableBufferView mutable_image64(data64.data(), data64.size());
100*a03ca8b9SKrzysztof Kosiński 
101*a03ca8b9SKrzysztof Kosiński   AbsoluteAddress addr64(kBit64, 0x0000006400000000ULL);
102*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x0U, image64));
103*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x00000000U, addr64.ToRva());
104*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x8U, image64));
105*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(0x4A654321U, addr64.ToRva());
106*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x10U, image64));  // Succeeds, in spite of value.
107*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr64.ToRva());    // Underflow.
108*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x18U, image64));
109*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr64.ToRva());  // Translated RVA too large.
110*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x20U, image64));
111*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr64.ToRva());  // Translated RVA toolarge.
112*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Read(0x28U, image64));
113*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(kInvalidRva, addr64.ToRva());  // Underflow.
114*a03ca8b9SKrzysztof Kosiński 
115*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Read(0x29U, image64));  // Extends outside.
116*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Read(0x30U, image64));  // Entirely outside (note: hex).
117*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Read(0x100000U, image64));
118*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Read(0x80000000U, image64));
119*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Read(0xFFFFFFFFU, image64));
120*a03ca8b9SKrzysztof Kosiński 
121*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.FromRva(0x11223344U));
122*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Write(0x13U, &mutable_image64));
123*a03ca8b9SKrzysztof Kosiński   EXPECT_TRUE(addr64.Write(0x20U, &mutable_image64));
124*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> expected_data64 = ParseHexString(
125*a03ca8b9SKrzysztof Kosiński       "00 00 00 00 64 00 00 00  21 43 65 4A 64 00 00 00 "
126*a03ca8b9SKrzysztof Kosiński       "00 00 00 44 33 22 11 64  00 00 00 FF FF FF FF FF "
127*a03ca8b9SKrzysztof Kosiński       "44 33 22 11 64 00 00 00  FF FF FF FF 63 00 00 00");
128*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data64, data64);
129*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Write(0x29U, &mutable_image64));
130*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Write(0x30U, &mutable_image64));
131*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.Write(0xFFFFFFFFU, &mutable_image64));
132*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data64, data64);
133*a03ca8b9SKrzysztof Kosiński 
134*a03ca8b9SKrzysztof Kosiński   EXPECT_FALSE(addr64.FromRva(0xFFFFFFFFU));
135*a03ca8b9SKrzysztof Kosiński }
136*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,AbsoluteAddress64Overflow)137*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, AbsoluteAddress64Overflow) {
138*a03ca8b9SKrzysztof Kosiński   {
139*a03ca8b9SKrzysztof Kosiński     // Counterpart to AbsoluteAddress632verflow test.
140*a03ca8b9SKrzysztof Kosiński     AbsoluteAddress addr64(kBit64, 0xFFFFFFFFC0000000ULL);
141*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x00000000U));
142*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x11223344U));
143*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x3FFFFFFFU));
144*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0x40000000U));
145*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0x40000001U));
146*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0x80000000U));
147*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0xFFFFFFFFU));
148*a03ca8b9SKrzysztof Kosiński 
149*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x00000000U, AddrValueToRva(0xFFFFFFFFC0000000U, &addr64));
150*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0xFFFFFFFFBFFFFFFFU, &addr64));
151*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0x0000000000000000U, &addr64));
152*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0xFFFFFFFF00000000U, &addr64));
153*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x3FFFFFFFU, AddrValueToRva(0xFFFFFFFFFFFFFFFFU, &addr64));
154*a03ca8b9SKrzysztof Kosiński   }
155*a03ca8b9SKrzysztof Kosiński   {
156*a03ca8b9SKrzysztof Kosiński     // Pseudo-counterpart to AbsoluteAddress632verflow test: Some now pass.
157*a03ca8b9SKrzysztof Kosiński     AbsoluteAddress addr64(kBit64, 0xC0000000U);
158*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x00000000U));
159*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x11223344U));
160*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x3FFFFFFFU));
161*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x40000000U));
162*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x40000001U));
163*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0x80000000U));
164*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0xFFFFFFFFU));
165*a03ca8b9SKrzysztof Kosiński 
166*a03ca8b9SKrzysztof Kosiński     // ToRva() still fail though.
167*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x00000000U, AddrValueToRva(0xC0000000U, &addr64));
168*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0xBFFFFFFFU, &addr64));
169*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0x00000000U, &addr64));
170*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x3FFFFFFFU, AddrValueToRva(0xFFFFFFFFU, &addr64));
171*a03ca8b9SKrzysztof Kosiński   }
172*a03ca8b9SKrzysztof Kosiński   {
173*a03ca8b9SKrzysztof Kosiński     AbsoluteAddress addr64(kBit64, 0xC000000000000000ULL);
174*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x00000000ULL));
175*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x11223344ULL));
176*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x3FFFFFFFULL));
177*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x40000000ULL));
178*a03ca8b9SKrzysztof Kosiński     EXPECT_TRUE(addr64.FromRva(0x40000001ULL));
179*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0x80000000ULL));
180*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(addr64.FromRva(0xFFFFFFFFULL));
181*a03ca8b9SKrzysztof Kosiński 
182*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x00000000U, AddrValueToRva(0xC000000000000000ULL, &addr64));
183*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0xBFFFFFFFFFFFFFFFULL, &addr64));
184*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0x0000000000000000ULL, &addr64));
185*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(0x3FFFFFFFU, AddrValueToRva(0xC00000003FFFFFFFULL, &addr64));
186*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(kInvalidRva, AddrValueToRva(0xFFFFFFFFFFFFFFFFULL, &addr64));
187*a03ca8b9SKrzysztof Kosiński   }
188*a03ca8b9SKrzysztof Kosiński }
189*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,Win32Read32)190*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, Win32Read32) {
191*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kImageBase = 0xA0000000U;
192*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kRvaBegin = 0x00C00000U;
193*a03ca8b9SKrzysztof Kosiński   struct {
194*a03ca8b9SKrzysztof Kosiński     std::vector<uint8_t> data32;
195*a03ca8b9SKrzysztof Kosiński     std::vector<offset_t> abs32_locations;  // Assumtion: Sorted.
196*a03ca8b9SKrzysztof Kosiński     offset_t lo;  // Assumption: In range, does not straddle |abs32_location|.
197*a03ca8b9SKrzysztof Kosiński     offset_t hi;  // Assumption: Also >= |lo|.
198*a03ca8b9SKrzysztof Kosiński     std::vector<Reference> expected_refs;
199*a03ca8b9SKrzysztof Kosiński   } test_cases[] = {
200*a03ca8b9SKrzysztof Kosiński       // Targets at beginning and end.
201*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF FF 0F 00 C0 A0 00 00 C0 A0 FF FF FF FF"),
202*a03ca8b9SKrzysztof Kosiński        {0x4U, 0x8U},
203*a03ca8b9SKrzysztof Kosiński        0x0U,
204*a03ca8b9SKrzysztof Kosiński        0x10U,
205*a03ca8b9SKrzysztof Kosiński        {{0x4U, 0xFU}, {0x8U, 0x0U}}},
206*a03ca8b9SKrzysztof Kosiński       // Targets at beginning and end are out of bound: Rejected.
207*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF FF 10 00 C0 A0 FF FF BF A0 FF FF FF FF"),
208*a03ca8b9SKrzysztof Kosiński        {0x4U, 0x8U},
209*a03ca8b9SKrzysztof Kosiński        0x0U,
210*a03ca8b9SKrzysztof Kosiński        0x10U,
211*a03ca8b9SKrzysztof Kosiński        std::vector<Reference>()},
212*a03ca8b9SKrzysztof Kosiński       // Same with more extreme target values: Rejected.
213*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF FF FF FF FF FF 00 00 00 00 FF FF FF FF"),
214*a03ca8b9SKrzysztof Kosiński        {0x4U, 0x8U},
215*a03ca8b9SKrzysztof Kosiński        0x0U,
216*a03ca8b9SKrzysztof Kosiński        0x10U,
217*a03ca8b9SKrzysztof Kosiński        std::vector<Reference>()},
218*a03ca8b9SKrzysztof Kosiński       // Locations at beginning and end, plus invalid locations.
219*a03ca8b9SKrzysztof Kosiński       {ParseHexString("08 00 C0 A0 FF FF FF FF FF FF FF FF 04 00 C0 A0"),
220*a03ca8b9SKrzysztof Kosiński        {0x0U, 0xCU, 0x10U, 0x1000U, 0x80000000U, 0xFFFFFFFFU},
221*a03ca8b9SKrzysztof Kosiński        0x0U,
222*a03ca8b9SKrzysztof Kosiński        0x10U,
223*a03ca8b9SKrzysztof Kosiński        {{0x0U, 0x8U}, {0xCU, 0x4U}}},
224*a03ca8b9SKrzysztof Kosiński       // Odd size, location, target.
225*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF 09 00 C0 A0 FF FF FF FF FF FF FF FF FF "
226*a03ca8b9SKrzysztof Kosiński                       "FF FF FF"),
227*a03ca8b9SKrzysztof Kosiński        {0x3U},
228*a03ca8b9SKrzysztof Kosiński        0x0U,
229*a03ca8b9SKrzysztof Kosiński        0x13U,
230*a03ca8b9SKrzysztof Kosiński        {{0x3U, 0x9U}}},
231*a03ca8b9SKrzysztof Kosiński       // No location given.
232*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF FF 0C 00 C0 A0 00 00 C0 A0 FF FF FF FF"),
233*a03ca8b9SKrzysztof Kosiński        std::vector<offset_t>(), 0x0U, 0x10U, std::vector<Reference>()},
234*a03ca8b9SKrzysztof Kosiński       // Simple alternation.
235*a03ca8b9SKrzysztof Kosiński       {ParseHexString("04 00 C0 A0 FF FF FF FF 0C 00 C0 A0 FF FF FF FF "
236*a03ca8b9SKrzysztof Kosiński                       "14 00 C0 A0 FF FF FF FF 1C 00 C0 A0 FF FF FF FF"),
237*a03ca8b9SKrzysztof Kosiński        {0x0U, 0x8U, 0x10U, 0x18U},
238*a03ca8b9SKrzysztof Kosiński        0x0U,
239*a03ca8b9SKrzysztof Kosiński        0x20U,
240*a03ca8b9SKrzysztof Kosiński        {{0x0U, 0x4U}, {0x8U, 0xCU}, {0x10U, 0x14U}, {0x18U, 0x1CU}}},
241*a03ca8b9SKrzysztof Kosiński       // Same, with locations limited by |lo| and |hi|. By assumption these must
242*a03ca8b9SKrzysztof Kosiński       // not cut accross Reference body.
243*a03ca8b9SKrzysztof Kosiński       {ParseHexString("04 00 C0 A0 FF FF FF FF 0C 00 C0 A0 FF FF FF FF "
244*a03ca8b9SKrzysztof Kosiński                       "14 00 C0 A0 FF FF FF FF 1C 00 C0 A0 FF FF FF FF"),
245*a03ca8b9SKrzysztof Kosiński        {0x0U, 0x8U, 0x10U, 0x18U},
246*a03ca8b9SKrzysztof Kosiński        0x04U,
247*a03ca8b9SKrzysztof Kosiński        0x17U,
248*a03ca8b9SKrzysztof Kosiński        {{0x8U, 0xCU}, {0x10U, 0x14U}}},
249*a03ca8b9SKrzysztof Kosiński       // Same, with very limiting |lo| and |hi|.
250*a03ca8b9SKrzysztof Kosiński       {ParseHexString("04 00 C0 A0 FF FF FF FF 0C 00 C0 A0 FF FF FF FF "
251*a03ca8b9SKrzysztof Kosiński                       "14 00 C0 A0 FF FF FF FF 1C 00 C0 A0 FF FF FF FF"),
252*a03ca8b9SKrzysztof Kosiński        {0x0U, 0x8U, 0x10U, 0x18U},
253*a03ca8b9SKrzysztof Kosiński        0x0CU,
254*a03ca8b9SKrzysztof Kosiński        0x10U,
255*a03ca8b9SKrzysztof Kosiński        std::vector<Reference>()},
256*a03ca8b9SKrzysztof Kosiński       // Same, |lo| == |hi|.
257*a03ca8b9SKrzysztof Kosiński       {ParseHexString("04 00 C0 A0 FF FF FF FF 0C 00 C0 A0 FF FF FF FF "
258*a03ca8b9SKrzysztof Kosiński                       "14 00 C0 A0 FF FF FF FF 1C 00 C0 A0 FF FF FF FF"),
259*a03ca8b9SKrzysztof Kosiński        {0x0U, 0x8U, 0x10U, 0x18U},
260*a03ca8b9SKrzysztof Kosiński        0x14U,
261*a03ca8b9SKrzysztof Kosiński        0x14U,
262*a03ca8b9SKrzysztof Kosiński        std::vector<Reference>()},
263*a03ca8b9SKrzysztof Kosiński       // Same, |lo| and |hi| at end.
264*a03ca8b9SKrzysztof Kosiński       {ParseHexString("04 00 C0 A0 FF FF FF FF 0C 00 C0 A0 FF FF FF FF "
265*a03ca8b9SKrzysztof Kosiński                       "14 00 C0 A0 FF FF FF FF 1C 00 C0 A0 FF FF FF FF"),
266*a03ca8b9SKrzysztof Kosiński        {0x0U, 0x8U, 0x10U, 0x18U},
267*a03ca8b9SKrzysztof Kosiński        0x20U,
268*a03ca8b9SKrzysztof Kosiński        0x20U,
269*a03ca8b9SKrzysztof Kosiński        std::vector<Reference>()},
270*a03ca8b9SKrzysztof Kosiński       // Mix. Note that targets can overlap.
271*a03ca8b9SKrzysztof Kosiński       {ParseHexString("FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF "
272*a03ca8b9SKrzysztof Kosiński                       "06 00 C0 A0 2C 00 C0 A0 FF FF C0 A0 2B 00 C0 A0 "
273*a03ca8b9SKrzysztof Kosiński                       "FF 06 00 C0 A0 00 00 C0 A0 FF FF FF FF FF FF FF"),
274*a03ca8b9SKrzysztof Kosiński        {0x10U, 0x14U, 0x18U, 0x1CU, 0x21U, 0x25U, 0xAAAAU},
275*a03ca8b9SKrzysztof Kosiński        0x07U,
276*a03ca8b9SKrzysztof Kosiński        0x25U,
277*a03ca8b9SKrzysztof Kosiński        {{0x10U, 0x6U}, {0x14U, 0x2CU}, {0x1CU, 0x2BU}, {0x21, 0x6U}}},
278*a03ca8b9SKrzysztof Kosiński   };
279*a03ca8b9SKrzysztof Kosiński 
280*a03ca8b9SKrzysztof Kosiński   for (const auto& test_case : test_cases) {
281*a03ca8b9SKrzysztof Kosiński     ConstBufferView image32(test_case.data32.data(), test_case.data32.size());
282*a03ca8b9SKrzysztof Kosiński     Abs32RvaExtractorWin32 extractor(image32, {kBit32, kImageBase},
283*a03ca8b9SKrzysztof Kosiński                                      test_case.abs32_locations, test_case.lo,
284*a03ca8b9SKrzysztof Kosiński                                      test_case.hi);
285*a03ca8b9SKrzysztof Kosiński 
286*a03ca8b9SKrzysztof Kosiński     TestAddressTranslator translator(test_case.data32.size(), kRvaBegin);
287*a03ca8b9SKrzysztof Kosiński     Abs32ReaderWin32 reader(std::move(extractor), translator);
288*a03ca8b9SKrzysztof Kosiński 
289*a03ca8b9SKrzysztof Kosiński     // Loop over |expected_ref| to check element-by-element.
290*a03ca8b9SKrzysztof Kosiński     std::optional<Reference> ref;
291*a03ca8b9SKrzysztof Kosiński     for (const auto& expected_ref : test_case.expected_refs) {
292*a03ca8b9SKrzysztof Kosiński       ref = reader.GetNext();
293*a03ca8b9SKrzysztof Kosiński       EXPECT_TRUE(ref.has_value());
294*a03ca8b9SKrzysztof Kosiński       EXPECT_EQ(expected_ref, ref.value());
295*a03ca8b9SKrzysztof Kosiński     }
296*a03ca8b9SKrzysztof Kosiński     // Check that nothing is left.
297*a03ca8b9SKrzysztof Kosiński     ref = reader.GetNext();
298*a03ca8b9SKrzysztof Kosiński     EXPECT_FALSE(ref.has_value());
299*a03ca8b9SKrzysztof Kosiński   }
300*a03ca8b9SKrzysztof Kosiński }
301*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,Win32Read64)302*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, Win32Read64) {
303*a03ca8b9SKrzysztof Kosiński   constexpr uint64_t kImageBase = 0x31415926A0000000U;
304*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kRvaBegin = 0x00C00000U;
305*a03ca8b9SKrzysztof Kosiński   // For simplicity, just test mixed case.
306*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data64 = ParseHexString(
307*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF FF FF FF FF 00 00 C0 A0 26 59 41 31 "
308*a03ca8b9SKrzysztof Kosiński       "06 00 C0 A0 26 59 41 31 02 00 C0 A0 26 59 41 31 "
309*a03ca8b9SKrzysztof Kosiński       "FF FF FF BF 26 59 41 31 FF FF FF FF FF FF FF FF "
310*a03ca8b9SKrzysztof Kosiński       "02 00 C0 A0 26 59 41 31 07 00 C0 A0 26 59 41 31");
311*a03ca8b9SKrzysztof Kosiński   std::vector<offset_t> abs32_locations = {0x8U,  0x10U, 0x18U, 0x20U,
312*a03ca8b9SKrzysztof Kosiński                                            0x28U, 0x30U, 0x38U, 0x40U};
313*a03ca8b9SKrzysztof Kosiński   offset_t lo = 0x10U;
314*a03ca8b9SKrzysztof Kosiński   offset_t hi = 0x38U;
315*a03ca8b9SKrzysztof Kosiński   std::vector<Reference> expected_refs = {
316*a03ca8b9SKrzysztof Kosiński       {0x10U, 0x06U}, {0x18U, 0x02U}, {0x30U, 0x02U}};
317*a03ca8b9SKrzysztof Kosiński 
318*a03ca8b9SKrzysztof Kosiński   ConstBufferView image64(data64.data(), data64.size());
319*a03ca8b9SKrzysztof Kosiński   Abs32RvaExtractorWin32 extractor(image64, {kBit64, kImageBase},
320*a03ca8b9SKrzysztof Kosiński                                    abs32_locations, lo, hi);
321*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator(data64.size(), kRvaBegin);
322*a03ca8b9SKrzysztof Kosiński   Abs32ReaderWin32 reader(std::move(extractor), translator);
323*a03ca8b9SKrzysztof Kosiński 
324*a03ca8b9SKrzysztof Kosiński   std::vector<Reference> refs;
325*a03ca8b9SKrzysztof Kosiński   std::optional<Reference> ref;
326*a03ca8b9SKrzysztof Kosiński   for (ref = reader.GetNext(); ref.has_value(); ref = reader.GetNext())
327*a03ca8b9SKrzysztof Kosiński     refs.push_back(ref.value());
328*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_refs, refs);
329*a03ca8b9SKrzysztof Kosiński }
330*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,Win32ReadFail)331*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, Win32ReadFail) {
332*a03ca8b9SKrzysztof Kosiński   // Make |bitness| a state to reduce repetition.
333*a03ca8b9SKrzysztof Kosiński   Bitness bitness = kBit32;
334*a03ca8b9SKrzysztof Kosiński 
335*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kImageBase = 0xA0000000U;  // Shared for 32-bit and 64-bit.
336*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data(32U, 0xFFU);
337*a03ca8b9SKrzysztof Kosiński   ConstBufferView image(data.data(), data.size());
338*a03ca8b9SKrzysztof Kosiński 
339*a03ca8b9SKrzysztof Kosiński   auto try_make = [&](std::vector<offset_t>&& abs32_locations, offset_t lo,
340*a03ca8b9SKrzysztof Kosiński                       offset_t hi) {
341*a03ca8b9SKrzysztof Kosiński     Abs32RvaExtractorWin32 extractor(image, {bitness, kImageBase},
342*a03ca8b9SKrzysztof Kosiński                                      abs32_locations, lo, hi);
343*a03ca8b9SKrzysztof Kosiński     extractor.GetNext();  // Dummy call so |extractor| gets used.
344*a03ca8b9SKrzysztof Kosiński   };
345*a03ca8b9SKrzysztof Kosiński 
346*a03ca8b9SKrzysztof Kosiński   // 32-bit tests.
347*a03ca8b9SKrzysztof Kosiński   bitness = kBit32;
348*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 0U, 32U);
349*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({4U, 24U}, 32U, 0U), "");  // |lo| > |hi|.
350*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 0U, 12U);
351*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 0U, 28U);
352*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 8U, 32U);
353*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 24U, 32U);
354*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({8U, 24U}, 0U, 11U), "");   // |hi| straddles.
355*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({8U, 24U}, 26U, 32U), "");  // |lo| straddles.
356*a03ca8b9SKrzysztof Kosiński   try_make({8U, 24U}, 12U, 24U);
357*a03ca8b9SKrzysztof Kosiński 
358*a03ca8b9SKrzysztof Kosiński   // 64-bit tests.
359*a03ca8b9SKrzysztof Kosiński   bitness = kBit64;
360*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 0U, 32U);
361*a03ca8b9SKrzysztof Kosiński   // |lo| > |hi|.
362*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make(std::vector<offset_t>(), 32U, 31U), "");
363*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 0U, 14U);
364*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 0U, 30U);
365*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 6U, 32U);
366*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 22U, 32U);
367*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({6U, 22U}, 0U, 29U), "");  // |hi| straddles.
368*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({6U, 22U}, 7U, 32U), "");  // |lo| straddles.
369*a03ca8b9SKrzysztof Kosiński   try_make({6U, 22U}, 14U, 20U);
370*a03ca8b9SKrzysztof Kosiński   try_make({16U}, 16U, 24U);
371*a03ca8b9SKrzysztof Kosiński   EXPECT_DEATH(try_make({16U}, 18U, 18U), "");  // |lo|, |hi| straddle.
372*a03ca8b9SKrzysztof Kosiński }
373*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,Win32Write32)374*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, Win32Write32) {
375*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kImageBase = 0xA0000000U;
376*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kRvaBegin = 0x00C00000U;
377*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data32(0x30, 0xFFU);
378*a03ca8b9SKrzysztof Kosiński   MutableBufferView image32(data32.data(), data32.size());
379*a03ca8b9SKrzysztof Kosiński   AbsoluteAddress addr(kBit32, kImageBase);
380*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator(data32.size(), kRvaBegin);
381*a03ca8b9SKrzysztof Kosiński   Abs32WriterWin32 writer(image32, std::move(addr), translator);
382*a03ca8b9SKrzysztof Kosiński 
383*a03ca8b9SKrzysztof Kosiński   // Successful writes.
384*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x02U, 0x10U});
385*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x0BU, 0x21U});
386*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x16U, 0x10U});
387*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x2CU, 0x00U});
388*a03ca8b9SKrzysztof Kosiński 
389*a03ca8b9SKrzysztof Kosiński   // Invalid data: For simplicity, Abs32WriterWin32 simply ignores bad writes.
390*a03ca8b9SKrzysztof Kosiński   // Invalid location.
391*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x2DU, 0x20U});
392*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x80000000U, 0x20U});
393*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0xFFFFFFFFU, 0x20U});
394*a03ca8b9SKrzysztof Kosiński   // Invalid target.
395*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x1CU, 0x00001111U});
396*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x10U, 0xFFFFFF00U});
397*a03ca8b9SKrzysztof Kosiński 
398*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> expected_data32 = ParseHexString(
399*a03ca8b9SKrzysztof Kosiński       "FF FF 10 00 C0 A0 FF FF FF FF FF 21 00 C0 A0 FF "
400*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF FF FF 10 00 C0 A0 FF FF FF FF FF FF "
401*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF FF FF FF FF FF FF FF FF 00 00 C0 A0");
402*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data32, data32);
403*a03ca8b9SKrzysztof Kosiński }
404*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,Win32Write64)405*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, Win32Write64) {
406*a03ca8b9SKrzysztof Kosiński   constexpr uint64_t kImageBase = 0x31415926A0000000U;
407*a03ca8b9SKrzysztof Kosiński   constexpr uint32_t kRvaBegin = 0x00C00000U;
408*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data64(0x30, 0xFFU);
409*a03ca8b9SKrzysztof Kosiński   MutableBufferView image32(data64.data(), data64.size());
410*a03ca8b9SKrzysztof Kosiński   AbsoluteAddress addr(kBit64, kImageBase);
411*a03ca8b9SKrzysztof Kosiński   TestAddressTranslator translator(data64.size(), kRvaBegin);
412*a03ca8b9SKrzysztof Kosiński   Abs32WriterWin32 writer(image32, std::move(addr), translator);
413*a03ca8b9SKrzysztof Kosiński 
414*a03ca8b9SKrzysztof Kosiński   // Successful writes.
415*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x02U, 0x10U});
416*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x0BU, 0x21U});
417*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x16U, 0x10U});
418*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x28U, 0x00U});
419*a03ca8b9SKrzysztof Kosiński 
420*a03ca8b9SKrzysztof Kosiński   // Invalid data: For simplicity, Abs32WriterWin32 simply ignores bad writes.
421*a03ca8b9SKrzysztof Kosiński   // Invalid location.
422*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x29U, 0x20U});
423*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x80000000U, 0x20U});
424*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0xFFFFFFFFU, 0x20U});
425*a03ca8b9SKrzysztof Kosiński   // Invalid target.
426*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x1CU, 0x00001111U});
427*a03ca8b9SKrzysztof Kosiński   writer.PutNext({0x10U, 0xFFFFFF00U});
428*a03ca8b9SKrzysztof Kosiński 
429*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> expected_data64 = ParseHexString(
430*a03ca8b9SKrzysztof Kosiński       "FF FF 10 00 C0 A0 26 59 41 31 FF 21 00 C0 A0 26 "
431*a03ca8b9SKrzysztof Kosiński       "59 41 31 FF FF FF 10 00 C0 A0 26 59 41 31 FF FF "
432*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF FF FF FF FF 00 00 C0 A0 26 59 41 31");
433*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(expected_data64, data64);
434*a03ca8b9SKrzysztof Kosiński }
435*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,RemoveUntranslatableAbs32)436*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, RemoveUntranslatableAbs32) {
437*a03ca8b9SKrzysztof Kosiński   Bitness kBitness = kBit32;
438*a03ca8b9SKrzysztof Kosiński   uint64_t kImageBase = 0x2BCD0000;
439*a03ca8b9SKrzysztof Kosiński 
440*a03ca8b9SKrzysztof Kosiński   // Valid RVAs: [0x00001A00, 0x00001A28) and [0x00003A00, 0x00004000).
441*a03ca8b9SKrzysztof Kosiński   // Valid AVAs: [0x2BCD1A00, 0x2BCD1A28) and [0x2BCD3A00, 0x2BCD4000).
442*a03ca8b9SKrzysztof Kosiński   // Notice that the second section has has dangling RVA.
443*a03ca8b9SKrzysztof Kosiński   AddressTranslator translator;
444*a03ca8b9SKrzysztof Kosiński   ASSERT_EQ(AddressTranslator::kSuccess,
445*a03ca8b9SKrzysztof Kosiński             translator.Initialize(
446*a03ca8b9SKrzysztof Kosiński                 {{0x04, +0x28, 0x1A00, +0x28}, {0x30, +0x30, 0x3A00, +0x600}}));
447*a03ca8b9SKrzysztof Kosiński 
448*a03ca8b9SKrzysztof Kosiński   std::vector<uint8_t> data = ParseHexString(
449*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF  0B 3A CD 2B  00 00 00  04 3A CD 2B  00 "
450*a03ca8b9SKrzysztof Kosiński       "FC 3F CD 2B  14 1A CD 2B  44 00 00 00  CC 00 00 00 "
451*a03ca8b9SKrzysztof Kosiński       "00 00 55 00  00 00  1E 1A CD 2B  00 99  FF FF FF FF "
452*a03ca8b9SKrzysztof Kosiński       "10 3A CD 2B  22 00 00 00  00 00 00 11  00 00 00 00 "
453*a03ca8b9SKrzysztof Kosiński       "66 00 00 00  28 1A CD 2B  00 00 CD 2B  27 1A CD 2B "
454*a03ca8b9SKrzysztof Kosiński       "FF 39 CD 2B  00 00 00 00  18 1A CD 2B  00 00 00 00 "
455*a03ca8b9SKrzysztof Kosiński       "FF FF FF FF  FF FF FF FF");
456*a03ca8b9SKrzysztof Kosiński   MutableBufferView image(data.data(), data.size());
457*a03ca8b9SKrzysztof Kosiński 
458*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs1 = 0x04;  // a:2BCD3A0B = r:3A0B = o:3B
459*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs2 = 0x0B;  // a:2BCD3A04 = r:3A04 = o:34
460*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs3 = 0x10;  // a:2BCD3FFF = r:3FFF (dangling)
461*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs4 = 0x14;  // a:2BCD1A14 = r:1A14 = o:18
462*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs5 = 0x26;  // a:2BCD1A1E = r:1A1E = o:22
463*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs6 = 0x30;  // a:2BCD3A10 = r:3A10 = 0x40
464*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs7 = 0x44;  // a:2BCD1A28 = r:1A28 (bad: sentinel)
465*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs8 = 0x48;  // a:2BCD0000 = r:0000 (bad: not covered)
466*a03ca8b9SKrzysztof Kosiński   const offset_t kAbs9 = 0x4C;  // a:2BCD1A27 = r:1A27 = 0x2B
467*a03ca8b9SKrzysztof Kosiński   const offset_t kAbsA = 0x50;  // a:2BCD39FF (bad: not covered)
468*a03ca8b9SKrzysztof Kosiński   const offset_t kAbsB = 0x54;  // a:00000000 (bad: underflow)
469*a03ca8b9SKrzysztof Kosiński   const offset_t kAbsC = 0x58;  // a:2BCD1A18 = r:1A18 = 0x1C
470*a03ca8b9SKrzysztof Kosiński 
471*a03ca8b9SKrzysztof Kosiński   std::vector<offset_t> locations = {kAbs1, kAbs2, kAbs3, kAbs4, kAbs5, kAbs6,
472*a03ca8b9SKrzysztof Kosiński                                      kAbs7, kAbs8, kAbs9, kAbsA, kAbsB, kAbsC};
473*a03ca8b9SKrzysztof Kosiński   std::vector<offset_t> exp_locations = {kAbs1, kAbs2, kAbs3, kAbs4,
474*a03ca8b9SKrzysztof Kosiński                                          kAbs5, kAbs6, kAbs9, kAbsC};
475*a03ca8b9SKrzysztof Kosiński   size_t exp_num_removed = locations.size() - exp_locations.size();
476*a03ca8b9SKrzysztof Kosiński   size_t num_removed = RemoveUntranslatableAbs32(image, {kBitness, kImageBase},
477*a03ca8b9SKrzysztof Kosiński                                                  translator, &locations);
478*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(exp_num_removed, num_removed);
479*a03ca8b9SKrzysztof Kosiński   EXPECT_EQ(exp_locations, locations);
480*a03ca8b9SKrzysztof Kosiński }
481*a03ca8b9SKrzysztof Kosiński 
TEST(Abs32UtilsTest,RemoveOverlappingAbs32Locations)482*a03ca8b9SKrzysztof Kosiński TEST(Abs32UtilsTest, RemoveOverlappingAbs32Locations) {
483*a03ca8b9SKrzysztof Kosiński   // Make |width| a state to reduce repetition.
484*a03ca8b9SKrzysztof Kosiński   uint32_t width = WidthOf(kBit32);
485*a03ca8b9SKrzysztof Kosiński 
486*a03ca8b9SKrzysztof Kosiński   auto run_test = [&width](const std::vector<offset_t>& expected_locations,
487*a03ca8b9SKrzysztof Kosiński                            std::vector<offset_t>&& locations) {
488*a03ca8b9SKrzysztof Kosiński     ASSERT_TRUE(std::is_sorted(locations.begin(), locations.end()));
489*a03ca8b9SKrzysztof Kosiński     size_t expected_removals = locations.size() - expected_locations.size();
490*a03ca8b9SKrzysztof Kosiński     size_t removals = RemoveOverlappingAbs32Locations(width, &locations);
491*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected_removals, removals);
492*a03ca8b9SKrzysztof Kosiński     EXPECT_EQ(expected_locations, locations);
493*a03ca8b9SKrzysztof Kosiński   };
494*a03ca8b9SKrzysztof Kosiński 
495*a03ca8b9SKrzysztof Kosiński   // 32-bit tests.
496*a03ca8b9SKrzysztof Kosiński   width = WidthOf(kBit32);
497*a03ca8b9SKrzysztof Kosiński   run_test(std::vector<offset_t>(), std::vector<offset_t>());
498*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U});
499*a03ca8b9SKrzysztof Kosiński   run_test({4U, 10U}, {4U, 10U});
500*a03ca8b9SKrzysztof Kosiński   run_test({4U, 8U}, {4U, 8U});
501*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 7U});
502*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 4U});
503*a03ca8b9SKrzysztof Kosiński   run_test({4U, 8U}, {4U, 7U, 8U});
504*a03ca8b9SKrzysztof Kosiński   run_test({4U, 10U}, {4U, 7U, 10U});
505*a03ca8b9SKrzysztof Kosiński   run_test({4U, 9U}, {4U, 9U, 10U});
506*a03ca8b9SKrzysztof Kosiński   run_test({3U}, {3U, 5U, 6U});
507*a03ca8b9SKrzysztof Kosiński   run_test({3U, 7U}, {3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U});
508*a03ca8b9SKrzysztof Kosiński   run_test({3U, 7U, 11U}, {3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U});
509*a03ca8b9SKrzysztof Kosiński   run_test({4U, 8U, 12U}, {4U, 6U, 8U, 10U, 12U});
510*a03ca8b9SKrzysztof Kosiński   run_test({4U, 8U, 12U, 16U}, {4U, 8U, 12U, 16U});
511*a03ca8b9SKrzysztof Kosiński   run_test({4U, 8U, 12U}, {4U, 8U, 9U, 12U});
512*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 4U, 4U, 4U, 4U, 4U});
513*a03ca8b9SKrzysztof Kosiński   run_test({3U}, {3U, 4U, 4U, 4U, 5U, 5U});
514*a03ca8b9SKrzysztof Kosiński   run_test({3U, 7U}, {3U, 4U, 4U, 4U, 7U, 7U, 8U});
515*a03ca8b9SKrzysztof Kosiński   run_test({10U, 20U, 30U, 40U}, {10U, 20U, 22U, 22U, 30U, 40U});
516*a03ca8b9SKrzysztof Kosiński   run_test({1000000U, 1000004U}, {1000000U, 1000004U});
517*a03ca8b9SKrzysztof Kosiński   run_test({1000000U}, {1000000U, 1000002U});
518*a03ca8b9SKrzysztof Kosiński 
519*a03ca8b9SKrzysztof Kosiński   // 64-bit tests.
520*a03ca8b9SKrzysztof Kosiński   width = WidthOf(kBit64);
521*a03ca8b9SKrzysztof Kosiński   run_test(std::vector<offset_t>(), std::vector<offset_t>());
522*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U});
523*a03ca8b9SKrzysztof Kosiński   run_test({4U, 20U}, {4U, 20U});
524*a03ca8b9SKrzysztof Kosiński   run_test({4U, 12U}, {4U, 12U});
525*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 11U});
526*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 5U});
527*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 4U});
528*a03ca8b9SKrzysztof Kosiński   run_test({4U, 12U, 20U}, {4U, 12U, 20U});
529*a03ca8b9SKrzysztof Kosiński   run_test({1U, 9U, 17U}, {1U, 9U, 17U});
530*a03ca8b9SKrzysztof Kosiński   run_test({1U, 17U}, {1U, 8U, 17U});
531*a03ca8b9SKrzysztof Kosiński   run_test({1U, 10U}, {1U, 10U, 17U});
532*a03ca8b9SKrzysztof Kosiński   run_test({3U, 11U}, {3U, 4U, 5U, 6U, 7U, 8U, 9U, 10U, 11U, 12U});
533*a03ca8b9SKrzysztof Kosiński   run_test({4U, 12U}, {4U, 6U, 8U, 10U, 12U});
534*a03ca8b9SKrzysztof Kosiński   run_test({4U, 12U}, {4U, 12U, 16U});
535*a03ca8b9SKrzysztof Kosiński   run_test({4U, 12U, 20U, 28U}, {4U, 12U, 20U, 28U});
536*a03ca8b9SKrzysztof Kosiński   run_test({4U}, {4U, 4U, 4U, 4U, 5U, 5U});
537*a03ca8b9SKrzysztof Kosiński   run_test({3U, 11U}, {3U, 4U, 4U, 4U, 11U, 11U, 12U});
538*a03ca8b9SKrzysztof Kosiński   run_test({10U, 20U, 30U, 40U}, {10U, 20U, 22U, 22U, 30U, 40U});
539*a03ca8b9SKrzysztof Kosiński   run_test({1000000U, 1000008U}, {1000000U, 1000008U});
540*a03ca8b9SKrzysztof Kosiński   run_test({1000000U}, {1000000U, 1000004U});
541*a03ca8b9SKrzysztof Kosiński }
542*a03ca8b9SKrzysztof Kosiński 
543*a03ca8b9SKrzysztof Kosiński }  // namespace zucchini
544