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