11cb0ef41Sopenharmony_ci// Copyright 2019 the V8 project authors. All rights reserved. 21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci// found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci#include "src/snapshot/embedded/platform-embedded-file-writer-generic.h" 61cb0ef41Sopenharmony_ci 71cb0ef41Sopenharmony_ci#include <algorithm> 81cb0ef41Sopenharmony_ci#include <cinttypes> 91cb0ef41Sopenharmony_ci 101cb0ef41Sopenharmony_ci#include "src/common/globals.h" 111cb0ef41Sopenharmony_ci#include "src/objects/code.h" 121cb0ef41Sopenharmony_ci 131cb0ef41Sopenharmony_cinamespace v8 { 141cb0ef41Sopenharmony_cinamespace internal { 151cb0ef41Sopenharmony_ci 161cb0ef41Sopenharmony_ci#define SYMBOL_PREFIX "" 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_cinamespace { 191cb0ef41Sopenharmony_ci 201cb0ef41Sopenharmony_ciconst char* DirectiveAsString(DataDirective directive) { 211cb0ef41Sopenharmony_ci switch (directive) { 221cb0ef41Sopenharmony_ci case kByte: 231cb0ef41Sopenharmony_ci return ".byte"; 241cb0ef41Sopenharmony_ci case kLong: 251cb0ef41Sopenharmony_ci return ".long"; 261cb0ef41Sopenharmony_ci case kQuad: 271cb0ef41Sopenharmony_ci return ".quad"; 281cb0ef41Sopenharmony_ci case kOcta: 291cb0ef41Sopenharmony_ci return ".octa"; 301cb0ef41Sopenharmony_ci } 311cb0ef41Sopenharmony_ci UNREACHABLE(); 321cb0ef41Sopenharmony_ci} 331cb0ef41Sopenharmony_ci 341cb0ef41Sopenharmony_ci} // namespace 351cb0ef41Sopenharmony_ci 361cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::SectionText() { 371cb0ef41Sopenharmony_ci if (target_os_ == EmbeddedTargetOs::kChromeOS) { 381cb0ef41Sopenharmony_ci fprintf(fp_, ".section .text.hot.embedded\n"); 391cb0ef41Sopenharmony_ci } else { 401cb0ef41Sopenharmony_ci fprintf(fp_, ".section .text\n"); 411cb0ef41Sopenharmony_ci } 421cb0ef41Sopenharmony_ci} 431cb0ef41Sopenharmony_ci 441cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::SectionData() { 451cb0ef41Sopenharmony_ci fprintf(fp_, ".section .data\n"); 461cb0ef41Sopenharmony_ci} 471cb0ef41Sopenharmony_ci 481cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::SectionRoData() { 491cb0ef41Sopenharmony_ci fprintf(fp_, ".section .rodata\n"); 501cb0ef41Sopenharmony_ci} 511cb0ef41Sopenharmony_ci 521cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareUint32(const char* name, 531cb0ef41Sopenharmony_ci uint32_t value) { 541cb0ef41Sopenharmony_ci DeclareSymbolGlobal(name); 551cb0ef41Sopenharmony_ci DeclareLabel(name); 561cb0ef41Sopenharmony_ci IndentedDataDirective(kLong); 571cb0ef41Sopenharmony_ci fprintf(fp_, "%d", value); 581cb0ef41Sopenharmony_ci Newline(); 591cb0ef41Sopenharmony_ci} 601cb0ef41Sopenharmony_ci 611cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclarePointerToSymbol( 621cb0ef41Sopenharmony_ci const char* name, const char* target) { 631cb0ef41Sopenharmony_ci DeclareSymbolGlobal(name); 641cb0ef41Sopenharmony_ci DeclareLabel(name); 651cb0ef41Sopenharmony_ci fprintf(fp_, " %s %s%s\n", DirectiveAsString(PointerSizeDirective()), 661cb0ef41Sopenharmony_ci SYMBOL_PREFIX, target); 671cb0ef41Sopenharmony_ci} 681cb0ef41Sopenharmony_ci 691cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareSymbolGlobal(const char* name) { 701cb0ef41Sopenharmony_ci fprintf(fp_, ".global %s%s\n", SYMBOL_PREFIX, name); 711cb0ef41Sopenharmony_ci // These symbols are not visible outside of the final binary, this allows for 721cb0ef41Sopenharmony_ci // reduced binary size, and less work for the dynamic linker. 731cb0ef41Sopenharmony_ci fprintf(fp_, ".hidden %s\n", name); 741cb0ef41Sopenharmony_ci} 751cb0ef41Sopenharmony_ci 761cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::AlignToCodeAlignment() { 771cb0ef41Sopenharmony_ci#if V8_TARGET_ARCH_X64 781cb0ef41Sopenharmony_ci // On x64 use 64-bytes code alignment to allow 64-bytes loop header alignment. 791cb0ef41Sopenharmony_ci STATIC_ASSERT(64 >= kCodeAlignment); 801cb0ef41Sopenharmony_ci fprintf(fp_, ".balign 64\n"); 811cb0ef41Sopenharmony_ci#elif V8_TARGET_ARCH_PPC64 821cb0ef41Sopenharmony_ci // 64 byte alignment is needed on ppc64 to make sure p10 prefixed instructions 831cb0ef41Sopenharmony_ci // don't cross 64-byte boundaries. 841cb0ef41Sopenharmony_ci STATIC_ASSERT(64 >= kCodeAlignment); 851cb0ef41Sopenharmony_ci fprintf(fp_, ".balign 64\n"); 861cb0ef41Sopenharmony_ci#else 871cb0ef41Sopenharmony_ci STATIC_ASSERT(32 >= kCodeAlignment); 881cb0ef41Sopenharmony_ci fprintf(fp_, ".balign 32\n"); 891cb0ef41Sopenharmony_ci#endif 901cb0ef41Sopenharmony_ci} 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::AlignToDataAlignment() { 931cb0ef41Sopenharmony_ci // On Windows ARM64, s390, PPC and possibly more platforms, aligned load 941cb0ef41Sopenharmony_ci // instructions are used to retrieve v8_Default_embedded_blob_ and/or 951cb0ef41Sopenharmony_ci // v8_Default_embedded_blob_size_. The generated instructions require the 961cb0ef41Sopenharmony_ci // load target to be aligned at 8 bytes (2^3). 971cb0ef41Sopenharmony_ci STATIC_ASSERT(8 >= Code::kMetadataAlignment); 981cb0ef41Sopenharmony_ci fprintf(fp_, ".balign 8\n"); 991cb0ef41Sopenharmony_ci} 1001cb0ef41Sopenharmony_ci 1011cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::Comment(const char* string) { 1021cb0ef41Sopenharmony_ci fprintf(fp_, "// %s\n", string); 1031cb0ef41Sopenharmony_ci} 1041cb0ef41Sopenharmony_ci 1051cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareLabel(const char* name) { 1061cb0ef41Sopenharmony_ci fprintf(fp_, "%s%s:\n", SYMBOL_PREFIX, name); 1071cb0ef41Sopenharmony_ci} 1081cb0ef41Sopenharmony_ci 1091cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::SourceInfo(int fileid, 1101cb0ef41Sopenharmony_ci const char* filename, 1111cb0ef41Sopenharmony_ci int line) { 1121cb0ef41Sopenharmony_ci fprintf(fp_, ".loc %d %d\n", fileid, line); 1131cb0ef41Sopenharmony_ci} 1141cb0ef41Sopenharmony_ci 1151cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareFunctionBegin(const char* name, 1161cb0ef41Sopenharmony_ci uint32_t size) { 1171cb0ef41Sopenharmony_ci if (ENABLE_CONTROL_FLOW_INTEGRITY_BOOL) { 1181cb0ef41Sopenharmony_ci DeclareSymbolGlobal(name); 1191cb0ef41Sopenharmony_ci } 1201cb0ef41Sopenharmony_ci 1211cb0ef41Sopenharmony_ci DeclareLabel(name); 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_ci if (target_arch_ == EmbeddedTargetArch::kArm || 1241cb0ef41Sopenharmony_ci target_arch_ == EmbeddedTargetArch::kArm64) { 1251cb0ef41Sopenharmony_ci // ELF format binaries on ARM use ".type <function name>, %function" 1261cb0ef41Sopenharmony_ci // to create a DWARF subprogram entry. 1271cb0ef41Sopenharmony_ci fprintf(fp_, ".type %s, %%function\n", name); 1281cb0ef41Sopenharmony_ci } else { 1291cb0ef41Sopenharmony_ci // Other ELF Format binaries use ".type <function name>, @function" 1301cb0ef41Sopenharmony_ci // to create a DWARF subprogram entry. 1311cb0ef41Sopenharmony_ci fprintf(fp_, ".type %s, @function\n", name); 1321cb0ef41Sopenharmony_ci } 1331cb0ef41Sopenharmony_ci fprintf(fp_, ".size %s, %u\n", name, size); 1341cb0ef41Sopenharmony_ci} 1351cb0ef41Sopenharmony_ci 1361cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareFunctionEnd(const char* name) {} 1371cb0ef41Sopenharmony_ci 1381cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::FilePrologue() {} 1391cb0ef41Sopenharmony_ci 1401cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::DeclareExternalFilename( 1411cb0ef41Sopenharmony_ci int fileid, const char* filename) { 1421cb0ef41Sopenharmony_ci // Replace any Windows style paths (backslashes) with forward 1431cb0ef41Sopenharmony_ci // slashes. 1441cb0ef41Sopenharmony_ci std::string fixed_filename(filename); 1451cb0ef41Sopenharmony_ci std::replace(fixed_filename.begin(), fixed_filename.end(), '\\', '/'); 1461cb0ef41Sopenharmony_ci fprintf(fp_, ".file %d \"%s\"\n", fileid, fixed_filename.c_str()); 1471cb0ef41Sopenharmony_ci} 1481cb0ef41Sopenharmony_ci 1491cb0ef41Sopenharmony_civoid PlatformEmbeddedFileWriterGeneric::FileEpilogue() { 1501cb0ef41Sopenharmony_ci // Omitting this section can imply an executable stack, which is usually 1511cb0ef41Sopenharmony_ci // a linker warning/error. C++ compilers add these automatically, but 1521cb0ef41Sopenharmony_ci // compiling assembly requires the .note.GNU-stack section to be inserted 1531cb0ef41Sopenharmony_ci // manually. 1541cb0ef41Sopenharmony_ci // Additional documentation: 1551cb0ef41Sopenharmony_ci // https://wiki.gentoo.org/wiki/Hardened/GNU_stack_quickstart 1561cb0ef41Sopenharmony_ci fprintf(fp_, ".section .note.GNU-stack,\"\",%%progbits\n"); 1571cb0ef41Sopenharmony_ci} 1581cb0ef41Sopenharmony_ci 1591cb0ef41Sopenharmony_ciint PlatformEmbeddedFileWriterGeneric::IndentedDataDirective( 1601cb0ef41Sopenharmony_ci DataDirective directive) { 1611cb0ef41Sopenharmony_ci return fprintf(fp_, " %s ", DirectiveAsString(directive)); 1621cb0ef41Sopenharmony_ci} 1631cb0ef41Sopenharmony_ci 1641cb0ef41Sopenharmony_ciDataDirective PlatformEmbeddedFileWriterGeneric::ByteChunkDataDirective() 1651cb0ef41Sopenharmony_ci const { 1661cb0ef41Sopenharmony_ci#if defined(V8_TARGET_ARCH_MIPS) || defined(V8_TARGET_ARCH_MIPS64) || \ 1671cb0ef41Sopenharmony_ci defined(V8_TARGET_ARCH_LOONG64) 1681cb0ef41Sopenharmony_ci // MIPS and LOONG64 uses a fixed 4 byte instruction set, using .long 1691cb0ef41Sopenharmony_ci // to prevent any unnecessary padding. 1701cb0ef41Sopenharmony_ci return kLong; 1711cb0ef41Sopenharmony_ci#else 1721cb0ef41Sopenharmony_ci // Other ISAs just listen to the base 1731cb0ef41Sopenharmony_ci return PlatformEmbeddedFileWriterBase::ByteChunkDataDirective(); 1741cb0ef41Sopenharmony_ci#endif 1751cb0ef41Sopenharmony_ci} 1761cb0ef41Sopenharmony_ci 1771cb0ef41Sopenharmony_ci#undef SYMBOL_PREFIX 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci} // namespace internal 1801cb0ef41Sopenharmony_ci} // namespace v8 181