64 #include "runtime/mutexLocker.hpp"
65 #include "runtime/os.hpp"
66 #include "runtime/vm_version.hpp"
67 #include "utilities/align.hpp"
68 #include "utilities/bitMap.inline.hpp"
69 #include "utilities/classpathStream.hpp"
70 #include "utilities/defaultStream.hpp"
71 #include "utilities/ostream.hpp"
72 #if INCLUDE_G1GC
73 #include "gc/g1/g1CollectedHeap.hpp"
74 #include "gc/g1/g1HeapRegion.hpp"
75 #endif
76
77 # include <sys/stat.h>
78 # include <errno.h>
79
80 #ifndef O_BINARY // if defined (Win32) use binary files.
81 #define O_BINARY 0 // otherwise do nothing.
82 #endif
83
84 // Fill in the fileMapInfo structure with data about this VM instance.
85
86 // This method copies the vm version info into header_version. If the version is too
87 // long then a truncated version, which has a hash code appended to it, is copied.
88 //
89 // Using a template enables this method to verify that header_version is an array of
90 // length JVM_IDENT_MAX. This ensures that the code that writes to the CDS file and
91 // the code that reads the CDS file will both use the same size buffer. Hence, will
92 // use identical truncation. This is necessary for matching of truncated versions.
93 template <int N> static void get_header_version(char (&header_version) [N]) {
94 assert(N == JVM_IDENT_MAX, "Bad header_version size");
95
96 const char *vm_version = VM_Version::internal_vm_info_string();
97 const int version_len = (int)strlen(vm_version);
98
99 memset(header_version, 0, JVM_IDENT_MAX);
100
101 if (version_len < (JVM_IDENT_MAX-1)) {
102 strcpy(header_version, vm_version);
103
197 set_magic(CDSConfig::is_dumping_dynamic_archive() ? CDS_DYNAMIC_ARCHIVE_MAGIC : CDS_ARCHIVE_MAGIC);
198 set_version(CURRENT_CDS_ARCHIVE_VERSION);
199
200 if (!info->is_static() && base_archive_name_size != 0) {
201 // copy base archive name
202 copy_base_archive_name(CDSConfig::static_archive_path());
203 }
204 _core_region_alignment = core_region_alignment;
205 _obj_alignment = ObjectAlignmentInBytes;
206 _compact_strings = CompactStrings;
207 if (CDSConfig::is_dumping_heap()) {
208 _narrow_oop_mode = CompressedOops::mode();
209 _narrow_oop_base = CompressedOops::base();
210 _narrow_oop_shift = CompressedOops::shift();
211 }
212 _compressed_oops = UseCompressedOops;
213 _compressed_class_ptrs = UseCompressedClassPointers;
214 _max_heap_size = MaxHeapSize;
215 _use_optimized_module_handling = CDSConfig::is_using_optimized_module_handling();
216 _has_full_module_graph = CDSConfig::is_dumping_full_module_graph();
217
218 // The following fields are for sanity checks for whether this archive
219 // will function correctly with this JVM and the bootclasspath it's
220 // invoked with.
221
222 // JVM version string ... changes on each build.
223 get_header_version(_jvm_ident);
224
225 _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
226 _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
227 _max_used_path_index = ClassLoaderExt::max_used_path_index();
228 _num_module_paths = ClassLoader::num_module_path_entries();
229
230 _verify_local = BytecodeVerificationLocal;
231 _verify_remote = BytecodeVerificationRemote;
232 _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
233 _has_non_jar_in_classpath = ClassLoaderExt::has_non_jar_in_classpath();
234 _requested_base_address = (char*)SharedBaseAddress;
235 _mapped_base_address = (char*)SharedBaseAddress;
236 _allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
237
238 if (!CDSConfig::is_dumping_dynamic_archive()) {
239 set_shared_path_table(info->_shared_path_table);
240 }
241 }
242
243 void FileMapHeader::copy_base_archive_name(const char* archive) {
244 assert(base_archive_name_size() != 0, "_base_archive_name_size not set");
245 assert(base_archive_name_offset() != 0, "_base_archive_name_offset not set");
246 assert(header_size() > sizeof(*this), "_base_archive_name_size not included in header size?");
247 memcpy((char*)this + base_archive_name_offset(), archive, base_archive_name_size());
248 }
249
250 void FileMapHeader::print(outputStream* st) {
251 ResourceMark rm;
252
253 st->print_cr("- magic: 0x%08x", magic());
254 st->print_cr("- crc: 0x%08x", crc());
255 st->print_cr("- version: 0x%x", version());
256 st->print_cr("- header_size: " UINT32_FORMAT, header_size());
282 st->print_cr("- num_module_paths: %d", _num_module_paths);
283 st->print_cr("- max_used_path_index: %d", _max_used_path_index);
284 st->print_cr("- verify_local: %d", _verify_local);
285 st->print_cr("- verify_remote: %d", _verify_remote);
286 st->print_cr("- has_platform_or_app_classes: %d", _has_platform_or_app_classes);
287 st->print_cr("- has_non_jar_in_classpath: %d", _has_non_jar_in_classpath);
288 st->print_cr("- requested_base_address: " INTPTR_FORMAT, p2i(_requested_base_address));
289 st->print_cr("- mapped_base_address: " INTPTR_FORMAT, p2i(_mapped_base_address));
290 st->print_cr("- heap_root_segments.roots_count: %d" , _heap_root_segments.roots_count());
291 st->print_cr("- heap_root_segments.base_offset: " SIZE_FORMAT_X, _heap_root_segments.base_offset());
292 st->print_cr("- heap_root_segments.count: " SIZE_FORMAT, _heap_root_segments.count());
293 st->print_cr("- heap_root_segments.max_size_elems: %d", _heap_root_segments.max_size_in_elems());
294 st->print_cr("- heap_root_segments.max_size_bytes: %d", _heap_root_segments.max_size_in_bytes());
295 st->print_cr("- _heap_oopmap_start_pos: " SIZE_FORMAT, _heap_oopmap_start_pos);
296 st->print_cr("- _heap_ptrmap_start_pos: " SIZE_FORMAT, _heap_ptrmap_start_pos);
297 st->print_cr("- _rw_ptrmap_start_pos: " SIZE_FORMAT, _rw_ptrmap_start_pos);
298 st->print_cr("- _ro_ptrmap_start_pos: " SIZE_FORMAT, _ro_ptrmap_start_pos);
299 st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
300 st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling);
301 st->print_cr("- has_full_module_graph %d", _has_full_module_graph);
302 }
303
304 void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
305 _type = non_existent_entry;
306 set_name(path, CHECK);
307 }
308
309 void SharedClassPathEntry::init(bool is_modules_image,
310 bool is_module_path,
311 ClassPathEntry* cpe, TRAPS) {
312 assert(CDSConfig::is_dumping_archive(), "sanity");
313 _timestamp = 0;
314 _filesize = 0;
315 _from_class_path_attr = false;
316
317 struct stat st;
318 if (os::stat(cpe->name(), &st) == 0) {
319 if ((st.st_mode & S_IFMT) == S_IFDIR) {
320 _type = dir_entry;
321 } else {
1366 if (strncmp(actual_ident, expected_ident, JVM_IDENT_MAX-1) != 0) {
1367 log_info(cds)("_jvm_ident expected: %s", expected_ident);
1368 log_info(cds)(" actual: %s", actual_ident);
1369 log_warning(cds)("The shared archive file was created by a different"
1370 " version or build of HotSpot");
1371 return false;
1372 }
1373
1374 _file_offset = header()->header_size(); // accounts for the size of _base_archive_name
1375
1376 size_t len = os::lseek(fd, 0, SEEK_END);
1377
1378 for (int i = 0; i < MetaspaceShared::n_regions; i++) {
1379 FileMapRegion* r = region_at(i);
1380 if (r->file_offset() > len || len - r->file_offset() < r->used()) {
1381 log_warning(cds)("The shared archive file has been truncated.");
1382 return false;
1383 }
1384 }
1385
1386 return true;
1387 }
1388
1389 void FileMapInfo::seek_to_position(size_t pos) {
1390 if (os::lseek(_fd, (long)pos, SEEK_SET) < 0) {
1391 log_error(cds)("Unable to seek to position " SIZE_FORMAT, pos);
1392 MetaspaceShared::unrecoverable_loading_error();
1393 }
1394 }
1395
1396 // Read the FileMapInfo information from the file.
1397 bool FileMapInfo::open_for_read() {
1398 if (_file_open) {
1399 return true;
1400 }
1401 log_info(cds)("trying to map %s", _full_path);
1402 int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
1403 if (fd < 0) {
1404 if (errno == ENOENT) {
1405 log_info(cds)("Specified shared archive not found (%s)", _full_path);
2472 // while AllowArchivingWithJavaAgent is set during the current run.
2473 if (_allow_archiving_with_java_agent && !AllowArchivingWithJavaAgent) {
2474 log_warning(cds)("The setting of the AllowArchivingWithJavaAgent is different "
2475 "from the setting in the shared archive.");
2476 return false;
2477 }
2478
2479 if (_allow_archiving_with_java_agent) {
2480 log_warning(cds)("This archive was created with AllowArchivingWithJavaAgent. It should be used "
2481 "for testing purposes only and should not be used in a production environment");
2482 }
2483
2484 log_info(cds)("Archive was created with UseCompressedOops = %d, UseCompressedClassPointers = %d",
2485 compressed_oops(), compressed_class_pointers());
2486 if (compressed_oops() != UseCompressedOops || compressed_class_pointers() != UseCompressedClassPointers) {
2487 log_info(cds)("Unable to use shared archive.\nThe saved state of UseCompressedOops and UseCompressedClassPointers is "
2488 "different from runtime, CDS will be disabled.");
2489 return false;
2490 }
2491
2492 if (!_use_optimized_module_handling) {
2493 CDSConfig::stop_using_optimized_module_handling();
2494 log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling");
2495 }
2496
2497 if (is_static() && !_has_full_module_graph) {
2498 // Only the static archive can contain the full module graph.
2499 CDSConfig::stop_using_full_module_graph("archive was created without full module graph");
2500 }
2501
2502 return true;
2503 }
2504
2505 bool FileMapInfo::validate_header() {
2506 if (!header()->validate()) {
2507 return false;
2508 }
2509 if (_is_static) {
2510 return true;
2511 } else {
|
64 #include "runtime/mutexLocker.hpp"
65 #include "runtime/os.hpp"
66 #include "runtime/vm_version.hpp"
67 #include "utilities/align.hpp"
68 #include "utilities/bitMap.inline.hpp"
69 #include "utilities/classpathStream.hpp"
70 #include "utilities/defaultStream.hpp"
71 #include "utilities/ostream.hpp"
72 #if INCLUDE_G1GC
73 #include "gc/g1/g1CollectedHeap.hpp"
74 #include "gc/g1/g1HeapRegion.hpp"
75 #endif
76
77 # include <sys/stat.h>
78 # include <errno.h>
79
80 #ifndef O_BINARY // if defined (Win32) use binary files.
81 #define O_BINARY 0 // otherwise do nothing.
82 #endif
83
84 inline void CDSMustMatchFlags::do_print(outputStream* st, bool v) {
85 st->print("%s", v ? "true" : "false");
86 }
87
88 inline void CDSMustMatchFlags::do_print(outputStream* st, intx v) {
89 st->print(INTX_FORMAT, v);
90 }
91
92 inline void CDSMustMatchFlags::do_print(outputStream* st, uintx v) {
93 st->print(UINTX_FORMAT, v);
94 }
95
96 inline void CDSMustMatchFlags::do_print(outputStream* st, double v) {
97 st->print("%f", v);
98 }
99
100 void CDSMustMatchFlags::init() {
101 assert(CDSConfig::is_dumping_archive(), "sanity");
102 _max_name_width = 0;
103
104 #define INIT_CDS_MUST_MATCH_FLAG(n) \
105 _v_##n = n; \
106 _max_name_width = MAX2(_max_name_width,strlen(#n));
107 CDS_MUST_MATCH_FLAGS_DO(INIT_CDS_MUST_MATCH_FLAG);
108 #undef INIT_CDS_MUST_MATCH_FLAG
109 }
110
111 bool CDSMustMatchFlags::runtime_check() const {
112 #define CHECK_CDS_MUST_MATCH_FLAG(n) \
113 if (_v_##n != n) { \
114 ResourceMark rm; \
115 stringStream ss; \
116 ss.print("VM option %s is different between dumptime (", #n); \
117 do_print(&ss, _v_ ## n); \
118 ss.print(") and runtime ("); \
119 do_print(&ss, n); \
120 ss.print(")"); \
121 log_info(cds)("%s", ss.as_string()); \
122 return false; \
123 }
124 CDS_MUST_MATCH_FLAGS_DO(CHECK_CDS_MUST_MATCH_FLAG);
125 #undef CHECK_CDS_MUST_MATCH_FLAG
126
127 return true;
128 }
129
130 void CDSMustMatchFlags::print_info() const {
131 LogTarget(Info, cds) lt;
132 if (lt.is_enabled()) {
133 LogStream ls(lt);
134 ls.print_cr("Recorded VM flags during dumptime:");
135 print(&ls);
136 }
137 }
138
139 void CDSMustMatchFlags::print(outputStream* st) const {
140 #define PRINT_CDS_MUST_MATCH_FLAG(n) \
141 st->print("- %-s ", #n); \
142 st->sp(int(_max_name_width - strlen(#n))); \
143 do_print(st, _v_##n); \
144 st->cr();
145 CDS_MUST_MATCH_FLAGS_DO(PRINT_CDS_MUST_MATCH_FLAG);
146 #undef PRINT_CDS_MUST_MATCH_FLAG
147 }
148
149 // Fill in the fileMapInfo structure with data about this VM instance.
150
151 // This method copies the vm version info into header_version. If the version is too
152 // long then a truncated version, which has a hash code appended to it, is copied.
153 //
154 // Using a template enables this method to verify that header_version is an array of
155 // length JVM_IDENT_MAX. This ensures that the code that writes to the CDS file and
156 // the code that reads the CDS file will both use the same size buffer. Hence, will
157 // use identical truncation. This is necessary for matching of truncated versions.
158 template <int N> static void get_header_version(char (&header_version) [N]) {
159 assert(N == JVM_IDENT_MAX, "Bad header_version size");
160
161 const char *vm_version = VM_Version::internal_vm_info_string();
162 const int version_len = (int)strlen(vm_version);
163
164 memset(header_version, 0, JVM_IDENT_MAX);
165
166 if (version_len < (JVM_IDENT_MAX-1)) {
167 strcpy(header_version, vm_version);
168
262 set_magic(CDSConfig::is_dumping_dynamic_archive() ? CDS_DYNAMIC_ARCHIVE_MAGIC : CDS_ARCHIVE_MAGIC);
263 set_version(CURRENT_CDS_ARCHIVE_VERSION);
264
265 if (!info->is_static() && base_archive_name_size != 0) {
266 // copy base archive name
267 copy_base_archive_name(CDSConfig::static_archive_path());
268 }
269 _core_region_alignment = core_region_alignment;
270 _obj_alignment = ObjectAlignmentInBytes;
271 _compact_strings = CompactStrings;
272 if (CDSConfig::is_dumping_heap()) {
273 _narrow_oop_mode = CompressedOops::mode();
274 _narrow_oop_base = CompressedOops::base();
275 _narrow_oop_shift = CompressedOops::shift();
276 }
277 _compressed_oops = UseCompressedOops;
278 _compressed_class_ptrs = UseCompressedClassPointers;
279 _max_heap_size = MaxHeapSize;
280 _use_optimized_module_handling = CDSConfig::is_using_optimized_module_handling();
281 _has_full_module_graph = CDSConfig::is_dumping_full_module_graph();
282 _has_valhalla_patched_classes = CDSConfig::is_valhalla_preview();
283 // The following fields are for sanity checks for whether this archive
284 // will function correctly with this JVM and the bootclasspath it's
285 // invoked with.
286
287 // JVM version string ... changes on each build.
288 get_header_version(_jvm_ident);
289
290 _app_class_paths_start_index = ClassLoaderExt::app_class_paths_start_index();
291 _app_module_paths_start_index = ClassLoaderExt::app_module_paths_start_index();
292 _max_used_path_index = ClassLoaderExt::max_used_path_index();
293 _num_module_paths = ClassLoader::num_module_path_entries();
294
295 _verify_local = BytecodeVerificationLocal;
296 _verify_remote = BytecodeVerificationRemote;
297 _has_platform_or_app_classes = ClassLoaderExt::has_platform_or_app_classes();
298 _has_non_jar_in_classpath = ClassLoaderExt::has_non_jar_in_classpath();
299 _requested_base_address = (char*)SharedBaseAddress;
300 _mapped_base_address = (char*)SharedBaseAddress;
301 _allow_archiving_with_java_agent = AllowArchivingWithJavaAgent;
302 _must_match.init();
303
304 if (!CDSConfig::is_dumping_dynamic_archive()) {
305 set_shared_path_table(info->_shared_path_table);
306 }
307 }
308
309 void FileMapHeader::copy_base_archive_name(const char* archive) {
310 assert(base_archive_name_size() != 0, "_base_archive_name_size not set");
311 assert(base_archive_name_offset() != 0, "_base_archive_name_offset not set");
312 assert(header_size() > sizeof(*this), "_base_archive_name_size not included in header size?");
313 memcpy((char*)this + base_archive_name_offset(), archive, base_archive_name_size());
314 }
315
316 void FileMapHeader::print(outputStream* st) {
317 ResourceMark rm;
318
319 st->print_cr("- magic: 0x%08x", magic());
320 st->print_cr("- crc: 0x%08x", crc());
321 st->print_cr("- version: 0x%x", version());
322 st->print_cr("- header_size: " UINT32_FORMAT, header_size());
348 st->print_cr("- num_module_paths: %d", _num_module_paths);
349 st->print_cr("- max_used_path_index: %d", _max_used_path_index);
350 st->print_cr("- verify_local: %d", _verify_local);
351 st->print_cr("- verify_remote: %d", _verify_remote);
352 st->print_cr("- has_platform_or_app_classes: %d", _has_platform_or_app_classes);
353 st->print_cr("- has_non_jar_in_classpath: %d", _has_non_jar_in_classpath);
354 st->print_cr("- requested_base_address: " INTPTR_FORMAT, p2i(_requested_base_address));
355 st->print_cr("- mapped_base_address: " INTPTR_FORMAT, p2i(_mapped_base_address));
356 st->print_cr("- heap_root_segments.roots_count: %d" , _heap_root_segments.roots_count());
357 st->print_cr("- heap_root_segments.base_offset: " SIZE_FORMAT_X, _heap_root_segments.base_offset());
358 st->print_cr("- heap_root_segments.count: " SIZE_FORMAT, _heap_root_segments.count());
359 st->print_cr("- heap_root_segments.max_size_elems: %d", _heap_root_segments.max_size_in_elems());
360 st->print_cr("- heap_root_segments.max_size_bytes: %d", _heap_root_segments.max_size_in_bytes());
361 st->print_cr("- _heap_oopmap_start_pos: " SIZE_FORMAT, _heap_oopmap_start_pos);
362 st->print_cr("- _heap_ptrmap_start_pos: " SIZE_FORMAT, _heap_ptrmap_start_pos);
363 st->print_cr("- _rw_ptrmap_start_pos: " SIZE_FORMAT, _rw_ptrmap_start_pos);
364 st->print_cr("- _ro_ptrmap_start_pos: " SIZE_FORMAT, _ro_ptrmap_start_pos);
365 st->print_cr("- allow_archiving_with_java_agent:%d", _allow_archiving_with_java_agent);
366 st->print_cr("- use_optimized_module_handling: %d", _use_optimized_module_handling);
367 st->print_cr("- has_full_module_graph %d", _has_full_module_graph);
368 st->print_cr("- has_valhalla_patched_classes %d", _has_valhalla_patched_classes);
369 _must_match.print(st);
370 }
371
372 void SharedClassPathEntry::init_as_non_existent(const char* path, TRAPS) {
373 _type = non_existent_entry;
374 set_name(path, CHECK);
375 }
376
377 void SharedClassPathEntry::init(bool is_modules_image,
378 bool is_module_path,
379 ClassPathEntry* cpe, TRAPS) {
380 assert(CDSConfig::is_dumping_archive(), "sanity");
381 _timestamp = 0;
382 _filesize = 0;
383 _from_class_path_attr = false;
384
385 struct stat st;
386 if (os::stat(cpe->name(), &st) == 0) {
387 if ((st.st_mode & S_IFMT) == S_IFDIR) {
388 _type = dir_entry;
389 } else {
1434 if (strncmp(actual_ident, expected_ident, JVM_IDENT_MAX-1) != 0) {
1435 log_info(cds)("_jvm_ident expected: %s", expected_ident);
1436 log_info(cds)(" actual: %s", actual_ident);
1437 log_warning(cds)("The shared archive file was created by a different"
1438 " version or build of HotSpot");
1439 return false;
1440 }
1441
1442 _file_offset = header()->header_size(); // accounts for the size of _base_archive_name
1443
1444 size_t len = os::lseek(fd, 0, SEEK_END);
1445
1446 for (int i = 0; i < MetaspaceShared::n_regions; i++) {
1447 FileMapRegion* r = region_at(i);
1448 if (r->file_offset() > len || len - r->file_offset() < r->used()) {
1449 log_warning(cds)("The shared archive file has been truncated.");
1450 return false;
1451 }
1452 }
1453
1454 if (!header()->check_must_match_flags()) {
1455 return false;
1456 }
1457
1458 return true;
1459 }
1460
1461 void FileMapInfo::seek_to_position(size_t pos) {
1462 if (os::lseek(_fd, (long)pos, SEEK_SET) < 0) {
1463 log_error(cds)("Unable to seek to position " SIZE_FORMAT, pos);
1464 MetaspaceShared::unrecoverable_loading_error();
1465 }
1466 }
1467
1468 // Read the FileMapInfo information from the file.
1469 bool FileMapInfo::open_for_read() {
1470 if (_file_open) {
1471 return true;
1472 }
1473 log_info(cds)("trying to map %s", _full_path);
1474 int fd = os::open(_full_path, O_RDONLY | O_BINARY, 0);
1475 if (fd < 0) {
1476 if (errno == ENOENT) {
1477 log_info(cds)("Specified shared archive not found (%s)", _full_path);
2544 // while AllowArchivingWithJavaAgent is set during the current run.
2545 if (_allow_archiving_with_java_agent && !AllowArchivingWithJavaAgent) {
2546 log_warning(cds)("The setting of the AllowArchivingWithJavaAgent is different "
2547 "from the setting in the shared archive.");
2548 return false;
2549 }
2550
2551 if (_allow_archiving_with_java_agent) {
2552 log_warning(cds)("This archive was created with AllowArchivingWithJavaAgent. It should be used "
2553 "for testing purposes only and should not be used in a production environment");
2554 }
2555
2556 log_info(cds)("Archive was created with UseCompressedOops = %d, UseCompressedClassPointers = %d",
2557 compressed_oops(), compressed_class_pointers());
2558 if (compressed_oops() != UseCompressedOops || compressed_class_pointers() != UseCompressedClassPointers) {
2559 log_info(cds)("Unable to use shared archive.\nThe saved state of UseCompressedOops and UseCompressedClassPointers is "
2560 "different from runtime, CDS will be disabled.");
2561 return false;
2562 }
2563
2564 if (is_static()) {
2565 const char* err = nullptr;
2566 if (CDSConfig::is_valhalla_preview()) {
2567 if (!_has_valhalla_patched_classes) {
2568 err = "not created";
2569 }
2570 } else {
2571 if (_has_valhalla_patched_classes) {
2572 err = "created";
2573 }
2574 }
2575 if (err != nullptr) {
2576 log_warning(cds)("This archive was %s with --enable-preview -XX:+EnableValhalla. It is "
2577 "incompatible with the current JVM setting", err);
2578 return false;
2579 }
2580 }
2581
2582 if (!_use_optimized_module_handling) {
2583 CDSConfig::stop_using_optimized_module_handling();
2584 log_info(cds)("optimized module handling: disabled because archive was created without optimized module handling");
2585 }
2586
2587 if (is_static() && !_has_full_module_graph) {
2588 // Only the static archive can contain the full module graph.
2589 CDSConfig::stop_using_full_module_graph("archive was created without full module graph");
2590 }
2591
2592 return true;
2593 }
2594
2595 bool FileMapInfo::validate_header() {
2596 if (!header()->validate()) {
2597 return false;
2598 }
2599 if (_is_static) {
2600 return true;
2601 } else {
|