xref: /aosp_15_r20/art/dex2oat/linker/image_test.cc (revision 795d594fd825385562da6b089ea9b2033f3abf5a)
1*795d594fSAndroid Build Coastguard Worker /*
2*795d594fSAndroid Build Coastguard Worker  * Copyright (C) 2011 The Android Open Source Project
3*795d594fSAndroid Build Coastguard Worker  *
4*795d594fSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*795d594fSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*795d594fSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*795d594fSAndroid Build Coastguard Worker  *
8*795d594fSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*795d594fSAndroid Build Coastguard Worker  *
10*795d594fSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*795d594fSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*795d594fSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*795d594fSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*795d594fSAndroid Build Coastguard Worker  * limitations under the License.
15*795d594fSAndroid Build Coastguard Worker  */
16*795d594fSAndroid Build Coastguard Worker 
17*795d594fSAndroid Build Coastguard Worker #include <string.h>
18*795d594fSAndroid Build Coastguard Worker #include <vector>
19*795d594fSAndroid Build Coastguard Worker 
20*795d594fSAndroid Build Coastguard Worker #include "image_test.h"
21*795d594fSAndroid Build Coastguard Worker 
22*795d594fSAndroid Build Coastguard Worker #include "base/pointer_size.h"
23*795d594fSAndroid Build Coastguard Worker #include "oat/image.h"
24*795d594fSAndroid Build Coastguard Worker #include "scoped_thread_state_change-inl.h"
25*795d594fSAndroid Build Coastguard Worker #include "thread.h"
26*795d594fSAndroid Build Coastguard Worker 
27*795d594fSAndroid Build Coastguard Worker namespace art {
28*795d594fSAndroid Build Coastguard Worker namespace linker {
29*795d594fSAndroid Build Coastguard Worker 
TEST_F(ImageTest,TestImageLayout)30*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, TestImageLayout) {
31*795d594fSAndroid Build Coastguard Worker   std::vector<size_t> image_sizes;
32*795d594fSAndroid Build Coastguard Worker   std::vector<size_t> image_sizes_extra;
33*795d594fSAndroid Build Coastguard Worker   // Compile multi-image with ImageLayoutA being the last image.
34*795d594fSAndroid Build Coastguard Worker   {
35*795d594fSAndroid Build Coastguard Worker     CompilationHelper helper;
36*795d594fSAndroid Build Coastguard Worker     Compile(ImageHeader::kStorageModeUncompressed,
37*795d594fSAndroid Build Coastguard Worker             /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
38*795d594fSAndroid Build Coastguard Worker             helper,
39*795d594fSAndroid Build Coastguard Worker             "ImageLayoutA",
40*795d594fSAndroid Build Coastguard Worker             {"LMyClass;"});
41*795d594fSAndroid Build Coastguard Worker     image_sizes = helper.GetImageObjectSectionSizes();
42*795d594fSAndroid Build Coastguard Worker   }
43*795d594fSAndroid Build Coastguard Worker   TearDown();
44*795d594fSAndroid Build Coastguard Worker   runtime_.reset();
45*795d594fSAndroid Build Coastguard Worker   SetUp();
46*795d594fSAndroid Build Coastguard Worker   // Compile multi-image with ImageLayoutB being the last image.
47*795d594fSAndroid Build Coastguard Worker   {
48*795d594fSAndroid Build Coastguard Worker     CompilationHelper helper;
49*795d594fSAndroid Build Coastguard Worker     Compile(ImageHeader::kStorageModeUncompressed,
50*795d594fSAndroid Build Coastguard Worker             /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
51*795d594fSAndroid Build Coastguard Worker             helper,
52*795d594fSAndroid Build Coastguard Worker             "ImageLayoutB",
53*795d594fSAndroid Build Coastguard Worker             {"LMyClass;"});
54*795d594fSAndroid Build Coastguard Worker     image_sizes_extra = helper.GetImageObjectSectionSizes();
55*795d594fSAndroid Build Coastguard Worker   }
56*795d594fSAndroid Build Coastguard Worker   // Make sure that the new stuff in the clinit in ImageLayoutB is in the last image and not in the
57*795d594fSAndroid Build Coastguard Worker   // first two images.
58*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(image_sizes.size(), image_sizes.size());
59*795d594fSAndroid Build Coastguard Worker   // Sizes of the object sections should be the same for all but the last image.
60*795d594fSAndroid Build Coastguard Worker   for (size_t i = 0; i < image_sizes.size() - 1; ++i) {
61*795d594fSAndroid Build Coastguard Worker     EXPECT_EQ(image_sizes[i], image_sizes_extra[i]);
62*795d594fSAndroid Build Coastguard Worker   }
63*795d594fSAndroid Build Coastguard Worker   // Last image should be larger since it has a hash map and a string.
64*795d594fSAndroid Build Coastguard Worker   EXPECT_LT(image_sizes.back(), image_sizes_extra.back());
65*795d594fSAndroid Build Coastguard Worker }
66*795d594fSAndroid Build Coastguard Worker 
TEST_F(ImageTest,ImageHeaderIsValid)67*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, ImageHeaderIsValid) {
68*795d594fSAndroid Build Coastguard Worker   uint32_t image_begin = ART_BASE_ADDRESS;
69*795d594fSAndroid Build Coastguard Worker   uint32_t image_size_ = kElfSegmentAlignment;
70*795d594fSAndroid Build Coastguard Worker   uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
71*795d594fSAndroid Build Coastguard Worker   uint32_t oat_checksum = 0;
72*795d594fSAndroid Build Coastguard Worker   uint32_t oat_file_begin = ART_BASE_ADDRESS + (kElfSegmentAlignment);
73*795d594fSAndroid Build Coastguard Worker   uint32_t oat_data_begin = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment);
74*795d594fSAndroid Build Coastguard Worker   uint32_t oat_data_end = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment + 1 * KB);
75*795d594fSAndroid Build Coastguard Worker   uint32_t oat_file_end = ART_BASE_ADDRESS + (2 * kElfSegmentAlignment + 2 * KB);
76*795d594fSAndroid Build Coastguard Worker   ImageSection sections[ImageHeader::kSectionCount];
77*795d594fSAndroid Build Coastguard Worker   uint32_t image_reservation_size = RoundUp(oat_file_end - image_begin, kElfSegmentAlignment);
78*795d594fSAndroid Build Coastguard Worker   ImageHeader image_header(image_reservation_size,
79*795d594fSAndroid Build Coastguard Worker                            /*component_count=*/ 1u,
80*795d594fSAndroid Build Coastguard Worker                            image_begin,
81*795d594fSAndroid Build Coastguard Worker                            image_size_,
82*795d594fSAndroid Build Coastguard Worker                            sections,
83*795d594fSAndroid Build Coastguard Worker                            image_roots,
84*795d594fSAndroid Build Coastguard Worker                            oat_checksum,
85*795d594fSAndroid Build Coastguard Worker                            oat_file_begin,
86*795d594fSAndroid Build Coastguard Worker                            oat_data_begin,
87*795d594fSAndroid Build Coastguard Worker                            oat_data_end,
88*795d594fSAndroid Build Coastguard Worker                            oat_file_end,
89*795d594fSAndroid Build Coastguard Worker                            /*boot_image_begin=*/ 0u,
90*795d594fSAndroid Build Coastguard Worker                            /*boot_image_size=*/ 0u,
91*795d594fSAndroid Build Coastguard Worker                            /*boot_image_component_count=*/ 0u,
92*795d594fSAndroid Build Coastguard Worker                            /*boot_image_checksum=*/ 0u,
93*795d594fSAndroid Build Coastguard Worker                            kRuntimePointerSize);
94*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(image_header.IsValid());
95*795d594fSAndroid Build Coastguard Worker 
96*795d594fSAndroid Build Coastguard Worker   // Please note that for the following condition to be true, the above values should be chosen in
97*795d594fSAndroid Build Coastguard Worker   // a way that image_reservation_size != RoundUp(image_size_, kElfSegmentAlignment).
98*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(!image_header.IsAppImage());
99*795d594fSAndroid Build Coastguard Worker 
100*795d594fSAndroid Build Coastguard Worker   char* magic = const_cast<char*>(image_header.GetMagic());
101*795d594fSAndroid Build Coastguard Worker   strcpy(magic, "");  // bad magic
102*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(image_header.IsValid());
103*795d594fSAndroid Build Coastguard Worker   strcpy(magic, "art\n000");  // bad version
104*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(image_header.IsValid());
105*795d594fSAndroid Build Coastguard Worker }
106*795d594fSAndroid Build Coastguard Worker 
107*795d594fSAndroid Build Coastguard Worker // Test that pointer to quick code is the same in
108*795d594fSAndroid Build Coastguard Worker // a default method of an interface and in a copied method
109*795d594fSAndroid Build Coastguard Worker // of a class which implements the interface. This should be true
110*795d594fSAndroid Build Coastguard Worker // only if the copied method and the origin method are located in the
111*795d594fSAndroid Build Coastguard Worker // same oat file.
TEST_F(ImageTest,TestDefaultMethods)112*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, TestDefaultMethods) {
113*795d594fSAndroid Build Coastguard Worker   // TODO(b/376621099): investigate LUCI failures (timeouts?) and re-enable this test.
114*795d594fSAndroid Build Coastguard Worker   // This is probably not related to riscv64 arch, but a combination of riscv64 and running
115*795d594fSAndroid Build Coastguard Worker   // on VM, but we don't use TEST_DISABLED_ON_VM to keep running it on other VM builders.
116*795d594fSAndroid Build Coastguard Worker   TEST_DISABLED_FOR_RISCV64();
117*795d594fSAndroid Build Coastguard Worker 
118*795d594fSAndroid Build Coastguard Worker   // Use this test to compile managed code to catch crashes when compiling the boot class path.
119*795d594fSAndroid Build Coastguard Worker   // This test already needs to compile some managed methods and by compiling with "speed" we
120*795d594fSAndroid Build Coastguard Worker   // avoid the need to create a specialized profile for the "speed-profile" compilation.
121*795d594fSAndroid Build Coastguard Worker   // (Using "speed" shall compile most methods. We could compile more with "everything".)
122*795d594fSAndroid Build Coastguard Worker   SetCompilerFilter(CompilerFilter::kSpeed);
123*795d594fSAndroid Build Coastguard Worker   CompilationHelper helper;
124*795d594fSAndroid Build Coastguard Worker   Compile(ImageHeader::kStorageModeUncompressed,
125*795d594fSAndroid Build Coastguard Worker           /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
126*795d594fSAndroid Build Coastguard Worker           helper,
127*795d594fSAndroid Build Coastguard Worker           "DefaultMethods",
128*795d594fSAndroid Build Coastguard Worker           {"LIface;", "LImpl;", "LIterableBase;"});
129*795d594fSAndroid Build Coastguard Worker 
130*795d594fSAndroid Build Coastguard Worker   PointerSize pointer_size = class_linker_->GetImagePointerSize();
131*795d594fSAndroid Build Coastguard Worker   Thread* self = Thread::Current();
132*795d594fSAndroid Build Coastguard Worker   ScopedObjectAccess soa(self);
133*795d594fSAndroid Build Coastguard Worker 
134*795d594fSAndroid Build Coastguard Worker   // Test the pointer to quick code is the same in origin method
135*795d594fSAndroid Build Coastguard Worker   // and in the copied method from the same oat file.
136*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> iface_klass =
137*795d594fSAndroid Build Coastguard Worker       class_linker_->LookupClass(self, "LIface;", /*class_loader=*/ nullptr);
138*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, iface_klass);
139*795d594fSAndroid Build Coastguard Worker   ArtMethod* origin = iface_klass->FindInterfaceMethod("defaultMethod", "()V", pointer_size);
140*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, origin);
141*795d594fSAndroid Build Coastguard Worker   ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iface_klass);
142*795d594fSAndroid Build Coastguard Worker   const void* code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
143*795d594fSAndroid Build Coastguard Worker   // The origin method should have a pointer to quick code
144*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, code);
145*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
146*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> impl_klass =
147*795d594fSAndroid Build Coastguard Worker       class_linker_->LookupClass(self, "LImpl;", /*class_loader=*/ nullptr);
148*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, impl_klass);
149*795d594fSAndroid Build Coastguard Worker   ArtMethod* copied = FindCopiedMethod(origin, impl_klass);
150*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, copied);
151*795d594fSAndroid Build Coastguard Worker   // the copied method should have pointer to the same quick code as the origin method
152*795d594fSAndroid Build Coastguard Worker   ASSERT_EQ(code, copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size));
153*795d594fSAndroid Build Coastguard Worker 
154*795d594fSAndroid Build Coastguard Worker   // Test the origin method has pointer to quick code
155*795d594fSAndroid Build Coastguard Worker   // but the copied method has pointer to interpreter
156*795d594fSAndroid Build Coastguard Worker   // because these methods are in different oat files.
157*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> iterable_klass =
158*795d594fSAndroid Build Coastguard Worker       class_linker_->LookupClass(self, "Ljava/lang/Iterable;", /*class_loader=*/ nullptr);
159*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, iterable_klass);
160*795d594fSAndroid Build Coastguard Worker   origin = iterable_klass->FindClassMethod(
161*795d594fSAndroid Build Coastguard Worker       "forEach", "(Ljava/util/function/Consumer;)V", pointer_size);
162*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, origin);
163*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(origin->IsDirect());
164*795d594fSAndroid Build Coastguard Worker   ASSERT_OBJ_PTR_EQ(origin->GetDeclaringClass(), iterable_klass);
165*795d594fSAndroid Build Coastguard Worker   code = origin->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
166*795d594fSAndroid Build Coastguard Worker   // the origin method should have a pointer to quick code
167*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, code);
168*795d594fSAndroid Build Coastguard Worker   ASSERT_FALSE(class_linker_->IsQuickToInterpreterBridge(code));
169*795d594fSAndroid Build Coastguard Worker   ObjPtr<mirror::Class> iterablebase_klass =
170*795d594fSAndroid Build Coastguard Worker       class_linker_->LookupClass(self, "LIterableBase;", /*class_loader=*/ nullptr);
171*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, iterablebase_klass);
172*795d594fSAndroid Build Coastguard Worker   copied = FindCopiedMethod(origin, iterablebase_klass);
173*795d594fSAndroid Build Coastguard Worker   ASSERT_NE(nullptr, copied);
174*795d594fSAndroid Build Coastguard Worker   code = copied->GetEntryPointFromQuickCompiledCodePtrSize(pointer_size);
175*795d594fSAndroid Build Coastguard Worker   // the copied method should have a pointer to interpreter
176*795d594fSAndroid Build Coastguard Worker   ASSERT_TRUE(class_linker_->IsQuickToInterpreterBridge(code));
177*795d594fSAndroid Build Coastguard Worker }
178*795d594fSAndroid Build Coastguard Worker 
179*795d594fSAndroid Build Coastguard Worker // Regression test for dex2oat crash for soft verification failure during
180*795d594fSAndroid Build Coastguard Worker // class initialization check from the transactional interpreter while
181*795d594fSAndroid Build Coastguard Worker // running the class initializer for another class.
TEST_F(ImageTest,TestSoftVerificationFailureDuringClassInitialization)182*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, TestSoftVerificationFailureDuringClassInitialization) {
183*795d594fSAndroid Build Coastguard Worker   CompilationHelper helper;
184*795d594fSAndroid Build Coastguard Worker   Compile(ImageHeader::kStorageModeUncompressed,
185*795d594fSAndroid Build Coastguard Worker           /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
186*795d594fSAndroid Build Coastguard Worker           helper,
187*795d594fSAndroid Build Coastguard Worker           "VerifySoftFailDuringClinit",
188*795d594fSAndroid Build Coastguard Worker           /*image_classes=*/ {"LClassToInitialize;"},
189*795d594fSAndroid Build Coastguard Worker           /*image_classes_failing_aot_clinit=*/ {"LClassToInitialize;"});
190*795d594fSAndroid Build Coastguard Worker }
191*795d594fSAndroid Build Coastguard Worker 
TEST_F(ImageTest,TestImageClassWithArrayClassWithUnresolvedComponent)192*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, TestImageClassWithArrayClassWithUnresolvedComponent) {
193*795d594fSAndroid Build Coastguard Worker   CompilationHelper helper;
194*795d594fSAndroid Build Coastguard Worker   Compile(ImageHeader::kStorageModeUncompressed,
195*795d594fSAndroid Build Coastguard Worker           /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
196*795d594fSAndroid Build Coastguard Worker           helper,
197*795d594fSAndroid Build Coastguard Worker           "ArrayClassWithUnresolvedComponent",
198*795d594fSAndroid Build Coastguard Worker           /*image_classes=*/ {"LClassWithStatic;",
199*795d594fSAndroid Build Coastguard Worker                               "LClassWithStaticConst;",
200*795d594fSAndroid Build Coastguard Worker                               "[LClassWithMissingInterface;",
201*795d594fSAndroid Build Coastguard Worker                               "[[LClassWithMissingInterface;",
202*795d594fSAndroid Build Coastguard Worker                               "[LClassWithMissingSuper",
203*795d594fSAndroid Build Coastguard Worker                               "[[LClassWithMissingSuper"},
204*795d594fSAndroid Build Coastguard Worker           /*image_classes_failing_aot_clinit=*/ {
205*795d594fSAndroid Build Coastguard Worker                               "LClassWithStatic;",
206*795d594fSAndroid Build Coastguard Worker                               "LClassWithStaticConst;"},
207*795d594fSAndroid Build Coastguard Worker           /*image_classes_failing_resolution=*/ {
208*795d594fSAndroid Build Coastguard Worker                               "[LClassWithMissingInterface;",
209*795d594fSAndroid Build Coastguard Worker                               "[[LClassWithMissingInterface;",
210*795d594fSAndroid Build Coastguard Worker                               "[LClassWithMissingSuper",
211*795d594fSAndroid Build Coastguard Worker                               "[[LClassWithMissingSuper"});
212*795d594fSAndroid Build Coastguard Worker }
213*795d594fSAndroid Build Coastguard Worker 
TEST_F(ImageTest,TestSuperWithAccessChecks)214*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, TestSuperWithAccessChecks) {
215*795d594fSAndroid Build Coastguard Worker   CompilationHelper helper;
216*795d594fSAndroid Build Coastguard Worker   Compile(ImageHeader::kStorageModeUncompressed,
217*795d594fSAndroid Build Coastguard Worker           /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
218*795d594fSAndroid Build Coastguard Worker           helper,
219*795d594fSAndroid Build Coastguard Worker           "SuperWithAccessChecks",
220*795d594fSAndroid Build Coastguard Worker           /*image_classes=*/ {"LSubClass;", "LImplementsClass;"},
221*795d594fSAndroid Build Coastguard Worker           /*image_classes_failing_aot_clinit=*/ {"LSubClass;", "LImplementsClass;"});
222*795d594fSAndroid Build Coastguard Worker }
223*795d594fSAndroid Build Coastguard Worker 
224*795d594fSAndroid Build Coastguard Worker // Regression test for b/297453985, where we used to generate a bogus image
225*795d594fSAndroid Build Coastguard Worker // checksum.
TEST_F(ImageTest,ImageChecksum)226*795d594fSAndroid Build Coastguard Worker TEST_F(ImageTest, ImageChecksum) {
227*795d594fSAndroid Build Coastguard Worker   uint32_t image_begin = ART_BASE_ADDRESS;
228*795d594fSAndroid Build Coastguard Worker   uint32_t image_roots = ART_BASE_ADDRESS + (1 * KB);
229*795d594fSAndroid Build Coastguard Worker   ImageSection sections[ImageHeader::kSectionCount];
230*795d594fSAndroid Build Coastguard Worker   // We require bitmap section to be at least kElfSegmentAlignment.
231*795d594fSAndroid Build Coastguard Worker   sections[ImageHeader::kSectionImageBitmap] = ImageSection(0, kElfSegmentAlignment);
232*795d594fSAndroid Build Coastguard Worker   ImageHeader image_header(/*image_reservation_size=*/ kElfSegmentAlignment,
233*795d594fSAndroid Build Coastguard Worker                            /*component_count=*/ 1u,
234*795d594fSAndroid Build Coastguard Worker                            image_begin,
235*795d594fSAndroid Build Coastguard Worker                            /*image_size=*/ sizeof(ImageHeader),
236*795d594fSAndroid Build Coastguard Worker                            sections,
237*795d594fSAndroid Build Coastguard Worker                            image_roots,
238*795d594fSAndroid Build Coastguard Worker                            /*oat_checksum=*/ 0u,
239*795d594fSAndroid Build Coastguard Worker                            /*oat_file_begin=*/ 0u,
240*795d594fSAndroid Build Coastguard Worker                            /*oat_data_begin=*/ 0u,
241*795d594fSAndroid Build Coastguard Worker                            /*oat_data_end=*/ 0u,
242*795d594fSAndroid Build Coastguard Worker                            /*oat_file_end=*/ 0u,
243*795d594fSAndroid Build Coastguard Worker                            /*boot_image_begin=*/ 0u,
244*795d594fSAndroid Build Coastguard Worker                            /*boot_image_size=*/ 0u,
245*795d594fSAndroid Build Coastguard Worker                            /*boot_image_component_count=*/ 0u,
246*795d594fSAndroid Build Coastguard Worker                            /*boot_image_checksum=*/ 0u,
247*795d594fSAndroid Build Coastguard Worker                            kRuntimePointerSize);
248*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(image_header.IsValid());
249*795d594fSAndroid Build Coastguard Worker 
250*795d594fSAndroid Build Coastguard Worker     std::string error_msg;
251*795d594fSAndroid Build Coastguard Worker     ImageFileGuard image_file;
252*795d594fSAndroid Build Coastguard Worker     ScratchFile location;
253*795d594fSAndroid Build Coastguard Worker     image_file.reset(OS::CreateEmptyFile(location.GetFilename().c_str()));
254*795d594fSAndroid Build Coastguard Worker     const uint8_t* data = reinterpret_cast<const uint8_t*>(&image_header);
255*795d594fSAndroid Build Coastguard Worker     std::unique_ptr<uint8_t> bitmap(new uint8_t[kElfSegmentAlignment]);
256*795d594fSAndroid Build Coastguard Worker     memset(bitmap.get(), 0, kElfSegmentAlignment);
257*795d594fSAndroid Build Coastguard Worker     ASSERT_EQ(image_header.GetImageChecksum(), 0u);
258*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(image_header.WriteData(
259*795d594fSAndroid Build Coastguard Worker         image_file,
260*795d594fSAndroid Build Coastguard Worker         data,
261*795d594fSAndroid Build Coastguard Worker         bitmap.get(),
262*795d594fSAndroid Build Coastguard Worker         ImageHeader::kStorageModeUncompressed,
263*795d594fSAndroid Build Coastguard Worker         /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
264*795d594fSAndroid Build Coastguard Worker         /*update_checksum=*/ true,
265*795d594fSAndroid Build Coastguard Worker         &error_msg)) << error_msg;
266*795d594fSAndroid Build Coastguard Worker 
267*795d594fSAndroid Build Coastguard Worker     uint32_t first_checksum = image_header.GetImageChecksum();
268*795d594fSAndroid Build Coastguard Worker     // Reset the image checksum, `WriteData` updated it.
269*795d594fSAndroid Build Coastguard Worker     image_header.SetImageChecksum(0u);
270*795d594fSAndroid Build Coastguard Worker 
271*795d594fSAndroid Build Coastguard Worker     // Change the header to ensure the checksum will be different.
272*795d594fSAndroid Build Coastguard Worker     image_header.SetOatChecksum(0xFFFF);
273*795d594fSAndroid Build Coastguard Worker 
274*795d594fSAndroid Build Coastguard Worker     ASSERT_TRUE(image_header.WriteData(
275*795d594fSAndroid Build Coastguard Worker         image_file,
276*795d594fSAndroid Build Coastguard Worker         data,
277*795d594fSAndroid Build Coastguard Worker         bitmap.get(),
278*795d594fSAndroid Build Coastguard Worker         ImageHeader::kStorageModeUncompressed,
279*795d594fSAndroid Build Coastguard Worker         /*max_image_block_size=*/std::numeric_limits<uint32_t>::max(),
280*795d594fSAndroid Build Coastguard Worker         /*update_checksum=*/ true,
281*795d594fSAndroid Build Coastguard Worker         &error_msg)) << error_msg;
282*795d594fSAndroid Build Coastguard Worker 
283*795d594fSAndroid Build Coastguard Worker     ASSERT_NE(first_checksum, image_header.GetImageChecksum());
284*795d594fSAndroid Build Coastguard Worker }
285*795d594fSAndroid Build Coastguard Worker 
286*795d594fSAndroid Build Coastguard Worker }  // namespace linker
287*795d594fSAndroid Build Coastguard Worker }  // namespace art
288