%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/sandbox/
Upload File :
Create Path :
Current File : /home/vacivi36/vittasync.vacivitta.com.br/vittasync/node/deps/v8/src/sandbox/code-pointer-table.h

// Copyright 2023 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_SANDBOX_CODE_POINTER_TABLE_H_
#define V8_SANDBOX_CODE_POINTER_TABLE_H_

#include "include/v8config.h"
#include "src/base/atomicops.h"
#include "src/base/memory.h"
#include "src/base/platform/mutex.h"
#include "src/common/globals.h"
#include "src/sandbox/external-entity-table.h"

#ifdef V8_COMPRESS_POINTERS

namespace v8 {
namespace internal {

class Isolate;
class Counters;

/**
 * The entries of a CodePointerTable.
 *
 * Each entry contains a pointer to a Code object as well as a raw pointer to
 * the Code's entrypoint.
 */
struct CodePointerTableEntry {
  // Make this entry a code pointer entry for the given code object and
  // entrypoint.
  inline void MakeCodePointerEntry(Address code, Address entrypoint);

  // Make this entry a freelist entry, containing the index of the next entry
  // on the freelist.
  inline void MakeFreelistEntry(uint32_t next_entry_index);

  // Load code entrypoint pointer stored in this entry.
  // This entry must be a code pointer entry.
  inline Address GetEntrypoint() const;

  // Store the given code entrypoint pointer in this entry.
  // This entry must be a code pointer entry.
  inline void SetEntrypoint(Address value);

  // Load the code object pointer stored in this entry.
  // This entry must be a code pointer entry.
  inline Address GetCodeObject() const;

  // Store the given code object pointer in this entry.
  // This entry must be a code pointer entry.
  inline void SetCodeObject(Address value);

  // Returns true if this entry is a freelist entry.
  inline bool IsFreelistEntry() const;

  // Get the index of the next entry on the freelist. This method may be
  // called even when the entry is not a freelist entry. However, the result
  // is only valid if this is a freelist entry. This behaviour is required
  // for efficient entry allocation, see TryAllocateEntryFromFreelist.
  inline uint32_t GetNextFreelistEntryIndex() const;

  // Mark this entry as alive during garbage collection.
  inline void Mark();

  // Unmark this entry during sweeping.
  inline void Unmark();

  // Test whether this entry is currently marked as alive.
  inline bool IsMarked() const;

 private:
  friend class CodePointerTable;

  // Freelist entries contain the index of the next free entry in their lower 32
  // bits and this tag in the upper 32 bits.
  static constexpr Address kFreeEntryTag = 0xffffffffULL << 32;

  // The marking bit is stored in the code_ field, see below.
  static constexpr Address kMarkingBit = 1;

  std::atomic<Address> entrypoint_;
  // The pointer to the Code object also contains the marking bit: since this is
  // a tagged pointer to a V8 HeapObject, we know that it will be 4-byte aligned
  // and that the LSB should always be set. We therefore use the LSB as marking
  // bit. In this way:
  //  - When loading the pointer, we only need to perform an unconditional OR 1
  //  to get the correctly tagged pointer
  //  - When storing the pointer we don't need to do anything since the tagged
  //  pointer will automatically be marked
  std::atomic<Address> code_;
};

static_assert(sizeof(CodePointerTableEntry) == kCodePointerTableEntrySize);

/**
 * A table containing pointers to Code.
 *
 * Essentially a specialized version of the indirect pointer table (IPT). A
 * code pointer table entry contains both a pointer to a Code object as well as
 * a pointer to the entrypoint. This way, the performance sensitive code paths
 * that for example call a JSFunction can directly load the entrypoint from the
 * table without having to load it from the Code object.
 *
 * When the sandbox is enabled, a code pointer table (CPT) is used to ensure
 * basic control-flow integrity in the absence of special hardware support
 * (such as landing pad instructions): by referencing code through an index
 * into a CPT, and ensuring that only valid code entrypoints are stored inside
 * the table, it is then guaranteed that any indirect control-flow transfer
 * ends up on a valid entrypoint as long as an attacker is still confined to
 * the sandbox.
 */
class V8_EXPORT_PRIVATE CodePointerTable
    : public ExternalEntityTable<CodePointerTableEntry,
                                 kCodePointerTableReservationSize> {
 public:
  // Size of a CodePointerTable, for layout computation in IsolateData.
  static int constexpr kSize = 2 * kSystemPointerSize;
  static_assert(kMaxCodePointers == kMaxCapacity);

  CodePointerTable() = default;
  CodePointerTable(const CodePointerTable&) = delete;
  CodePointerTable& operator=(const CodePointerTable&) = delete;

  // The Spaces used by a CodePointerTable.
  using Space = ExternalEntityTable<CodePointerTableEntry,
                                    kCodePointerTableReservationSize>::Space;

  //
  // This method is atomic and can be called from background threads.
  inline Address GetEntrypoint(CodePointerHandle handle) const;

  // Retrieves the code object of the entry referenced by the given handle.
  //
  // This method is atomic and can be called from background threads.
  inline Address GetCodeObject(CodePointerHandle handle) const;

  // Sets the entrypoint of the entry referenced by the given handle.
  //
  // This method is atomic and can be called from background threads.
  inline void SetEntrypoint(CodePointerHandle handle, Address value);

  // Sets the code object of the entry referenced by the given handle.
  //
  // This method is atomic and can be called from background threads.
  inline void SetCodeObject(CodePointerHandle handle, Address value);

  // Allocates a new entry in the table and initialize it.
  //
  // This method is atomic and can be called from background threads.
  inline CodePointerHandle AllocateAndInitializeEntry(Space* space,
                                                      Address code,
                                                      Address entrypoint);

  // Marks the specified entry as alive.
  //
  // This method is atomic and can be called from background threads.
  inline void Mark(Space* space, CodePointerHandle handle);

  // Frees all unmarked entries in the given space.
  //
  // This method must only be called while mutator threads are stopped as it is
  // not safe to allocate table entries while a space is being swept.
  //
  // Returns the number of live entries after sweeping.
  uint32_t Sweep(Space* space, Counters* counters);

  // The base address of this table, for use in JIT compilers.
  Address base_address() const { return base(); }

 private:
  inline uint32_t HandleToIndex(CodePointerHandle handle) const;
  inline CodePointerHandle IndexToHandle(uint32_t index) const;
};

static_assert(sizeof(CodePointerTable) == CodePointerTable::kSize);

V8_EXPORT_PRIVATE CodePointerTable* GetProcessWideCodePointerTable();

}  // namespace internal
}  // namespace v8

#endif  // V8_COMPRESS_POINTERS

#endif  // V8_SANDBOX_CODE_POINTER_TABLE_H_

Zerion Mini Shell 1.0