LCOV - code coverage report
Current view: top level - src - eh-frame.h (source / functions) Hit Total Coverage
Test: app.info Lines: 17 17 100.0 %
Date: 2019-04-19 Functions: 0 0 -

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_EH_FRAME_H_
       6             : #define V8_EH_FRAME_H_
       7             : 
       8             : #include "src/base/compiler-specific.h"
       9             : #include "src/globals.h"
      10             : #include "src/register-arch.h"
      11             : #include "src/v8memory.h"
      12             : #include "src/zone/zone-containers.h"
      13             : 
      14             : namespace v8 {
      15             : namespace internal {
      16             : 
      17             : class CodeDesc;
      18             : 
      19             : class V8_EXPORT_PRIVATE EhFrameConstants final
      20             :     : public NON_EXPORTED_BASE(AllStatic) {
      21             :  public:
      22             :   enum class DwarfOpcodes : byte {
      23             :     kNop = 0x00,
      24             :     kAdvanceLoc1 = 0x02,
      25             :     kAdvanceLoc2 = 0x03,
      26             :     kAdvanceLoc4 = 0x04,
      27             :     kSameValue = 0x08,
      28             :     kDefCfa = 0x0c,
      29             :     kDefCfaRegister = 0x0d,
      30             :     kDefCfaOffset = 0x0e,
      31             :     kOffsetExtendedSf = 0x11,
      32             :   };
      33             : 
      34             :   enum DwarfEncodingSpecifiers : byte {
      35             :     kUData4 = 0x03,
      36             :     kSData4 = 0x0b,
      37             :     kPcRel = 0x10,
      38             :     kDataRel = 0x30,
      39             :     kOmit = 0xff,
      40             :   };
      41             : 
      42             :   static const int kLocationTag = 1;
      43             :   static const int kLocationMask = 0x3f;
      44             :   static const int kLocationMaskSize = 6;
      45             : 
      46             :   static const int kSavedRegisterTag = 2;
      47             :   static const int kSavedRegisterMask = 0x3f;
      48             :   static const int kSavedRegisterMaskSize = 6;
      49             : 
      50             :   static const int kFollowInitialRuleTag = 3;
      51             :   static const int kFollowInitialRuleMask = 0x3f;
      52             :   static const int kFollowInitialRuleMaskSize = 6;
      53             : 
      54             :   static const int kProcedureAddressOffsetInFde = 2 * kInt32Size;
      55             :   static const int kProcedureSizeOffsetInFde = 3 * kInt32Size;
      56             : 
      57             :   static const int kInitialStateOffsetInCie = 19;
      58             :   static const int kEhFrameTerminatorSize = 4;
      59             : 
      60             :   // Defined in eh-writer-<arch>.cc
      61             :   static const int kCodeAlignmentFactor;
      62             :   static const int kDataAlignmentFactor;
      63             : 
      64             :   static const int kFdeVersionSize = 1;
      65             :   static const int kFdeEncodingSpecifiersSize = 3;
      66             : 
      67             :   static const int kEhFrameHdrVersion = 1;
      68             :   static const int kEhFrameHdrSize = 20;
      69             : };
      70             : 
      71     2643382 : class V8_EXPORT_PRIVATE EhFrameWriter {
      72             :  public:
      73             :   explicit EhFrameWriter(Zone* zone);
      74             : 
      75             :   // The empty frame is a hack to trigger fp-based unwinding in Linux perf
      76             :   // compiled with libunwind support when processing DWARF-based call graphs.
      77             :   //
      78             :   // It is effectively a valid eh_frame_hdr with an empty look up table.
      79             :   //
      80             :   static void WriteEmptyEhFrame(std::ostream& stream);  // NOLINT
      81             : 
      82             :   // Write the CIE and FDE header. Call it before any other method.
      83             :   void Initialize();
      84             : 
      85             :   void AdvanceLocation(int pc_offset);
      86             : 
      87             :   // The <base_address> is the one to which all <offset>s in SaveRegisterToStack
      88             :   // directives are relative. It is given by <base_register> + <base_offset>.
      89             :   //
      90             :   // The <base_offset> must be positive or 0.
      91             :   //
      92             :   void SetBaseAddressRegister(Register base_register);
      93             :   void SetBaseAddressOffset(int base_offset);
      94             :   void IncreaseBaseAddressOffset(int base_delta) {
      95          45 :     SetBaseAddressOffset(base_offset_ + base_delta);
      96             :   }
      97             :   void SetBaseAddressRegisterAndOffset(Register base_register, int base_offset);
      98             : 
      99             :   // Register saved at location <base_address> + <offset>.
     100             :   // The <offset> must be a multiple of EhFrameConstants::kDataAlignment.
     101             :   void RecordRegisterSavedToStack(Register name, int offset) {
     102          24 :     RecordRegisterSavedToStack(RegisterToDwarfCode(name), offset);
     103             :   }
     104             : 
     105             :   // The register has not been modified from the previous frame.
     106             :   void RecordRegisterNotModified(Register name);
     107             : 
     108             :   // The register follows the rule defined in the CIE.
     109             :   void RecordRegisterFollowsInitialRule(Register name);
     110             : 
     111             :   void Finish(int code_size);
     112             : 
     113             :   // Remember to call Finish() before GetEhFrame().
     114             :   //
     115             :   // The EhFrameWriter instance owns the buffer pointed by
     116             :   // CodeDesc::unwinding_info, and must outlive any use of the CodeDesc.
     117             :   //
     118             :   void GetEhFrame(CodeDesc* desc);
     119             : 
     120             :   int last_pc_offset() const { return last_pc_offset_; }
     121             :   Register base_register() const { return base_register_; }
     122             :   int base_offset() const { return base_offset_; }
     123             : 
     124             :  private:
     125             :   enum class InternalState { kUndefined, kInitialized, kFinalized };
     126             : 
     127             :   static const uint32_t kInt32Placeholder = 0xdeadc0de;
     128             : 
     129             :   void WriteSLeb128(int32_t value);
     130             :   void WriteULeb128(uint32_t value);
     131             : 
     132         971 :   void WriteByte(byte value) { eh_frame_buffer_.push_back(value); }
     133             :   void WriteOpcode(EhFrameConstants::DwarfOpcodes opcode) {
     134             :     WriteByte(static_cast<byte>(opcode));
     135             :   }
     136             :   void WriteBytes(const byte* start, int size) {
     137         287 :     eh_frame_buffer_.insert(eh_frame_buffer_.end(), start, start + size);
     138             :   }
     139             :   void WriteInt16(uint16_t value) {
     140             :     WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
     141             :   }
     142             :   void WriteInt32(uint32_t value) {
     143             :     WriteBytes(reinterpret_cast<const byte*>(&value), sizeof(value));
     144             :   }
     145             :   void PatchInt32(int base_offset, uint32_t value) {
     146             :     DCHECK_EQ(
     147             :         ReadUnalignedUInt32(reinterpret_cast<Address>(eh_frame_buffer_.data()) +
     148             :                             base_offset),
     149             :         kInt32Placeholder);
     150             :     DCHECK_LT(base_offset + kInt32Size, eh_frame_offset());
     151         164 :     WriteUnalignedUInt32(
     152             :         reinterpret_cast<Address>(eh_frame_buffer_.data()) + base_offset,
     153             :         value);
     154             :   }
     155             : 
     156             :   // Write the common information entry, which includes encoding specifiers,
     157             :   // alignment factors, the return address (pseudo) register code and the
     158             :   // directives to construct the initial state of the unwinding table.
     159             :   void WriteCie();
     160             : 
     161             :   // Write the header of the function data entry, containing a pointer to the
     162             :   // correspondent CIE and the position and size of the associated routine.
     163             :   void WriteFdeHeader();
     164             : 
     165             :   // Write the contents of the .eh_frame_hdr section, including encoding
     166             :   // specifiers and the routine => FDE lookup table.
     167             :   void WriteEhFrameHdr(int code_size);
     168             : 
     169             :   // Write nops until the size reaches a multiple of 8 bytes.
     170             :   void WritePaddingToAlignedSize(int unpadded_size);
     171             : 
     172             :   // Internal version that directly accepts a DWARF register code, needed for
     173             :   // handling pseudo-registers on some platforms.
     174             :   void RecordRegisterSavedToStack(int register_code, int offset);
     175             : 
     176             :   int GetProcedureAddressOffset() const {
     177          41 :     return fde_offset() + EhFrameConstants::kProcedureAddressOffsetInFde;
     178             :   }
     179             : 
     180             :   int GetProcedureSizeOffset() const {
     181          41 :     return fde_offset() + EhFrameConstants::kProcedureSizeOffsetInFde;
     182             :   }
     183             : 
     184             :   int eh_frame_offset() const {
     185         287 :     return static_cast<int>(eh_frame_buffer_.size());
     186             :   }
     187             : 
     188             :   int fde_offset() const { return cie_size_; }
     189             : 
     190             :   // Platform specific functions implemented in eh-frame-<arch>.cc
     191             : 
     192             :   static int RegisterToDwarfCode(Register name);
     193             : 
     194             :   // Write directives to build the initial state in the CIE.
     195             :   void WriteInitialStateInCie();
     196             : 
     197             :   // Write the return address (pseudo) register code.
     198             :   void WriteReturnAddressRegisterCode();
     199             : 
     200             :   int cie_size_;
     201             :   int last_pc_offset_;
     202             :   InternalState writer_state_;
     203             :   Register base_register_;
     204             :   int base_offset_;
     205             :   ZoneVector<byte> eh_frame_buffer_;
     206             : 
     207             :   DISALLOW_COPY_AND_ASSIGN(EhFrameWriter);
     208             : };
     209             : 
     210             : class V8_EXPORT_PRIVATE EhFrameIterator {
     211             :  public:
     212             :   EhFrameIterator(const byte* start, const byte* end)
     213          10 :       : start_(start), next_(start), end_(end) {
     214             :     DCHECK_LE(start, end);
     215             :   }
     216             : 
     217             :   void SkipCie() {
     218             :     DCHECK_EQ(next_, start_);
     219          16 :     next_ += ReadUnalignedUInt32(reinterpret_cast<Address>(next_)) + kInt32Size;
     220             :   }
     221             : 
     222             :   void SkipToFdeDirectives() {
     223             :     SkipCie();
     224             :     // Skip the FDE header.
     225             :     Skip(kDirectivesOffsetInFde);
     226             :   }
     227             : 
     228             :   void Skip(int how_many) {
     229             :     DCHECK_GE(how_many, 0);
     230          20 :     next_ += how_many;
     231             :     DCHECK_LE(next_, end_);
     232             :   }
     233             : 
     234             :   uint32_t GetNextUInt32() { return GetNextValue<uint32_t>(); }
     235             :   uint16_t GetNextUInt16() { return GetNextValue<uint16_t>(); }
     236             :   byte GetNextByte() { return GetNextValue<byte>(); }
     237             :   EhFrameConstants::DwarfOpcodes GetNextOpcode() {
     238             :     return static_cast<EhFrameConstants::DwarfOpcodes>(GetNextByte());
     239             :   }
     240             : 
     241             :   uint32_t GetNextULeb128();
     242             :   int32_t GetNextSLeb128();
     243             : 
     244             :   bool Done() const {
     245             :     DCHECK_LE(next_, end_);
     246           3 :     return next_ == end_;
     247             :   }
     248             : 
     249             :   int GetCurrentOffset() const {
     250             :     DCHECK_GE(next_, start_);
     251           2 :     return static_cast<int>(next_ - start_);
     252             :   }
     253             : 
     254           2 :   int GetBufferSize() { return static_cast<int>(end_ - start_); }
     255             : 
     256             :   const void* current_address() const {
     257             :     return reinterpret_cast<const void*>(next_);
     258             :   }
     259             : 
     260             :  private:
     261             :   static const int kDirectivesOffsetInFde = 4 * kInt32Size + 1;
     262             : 
     263             :   static uint32_t DecodeULeb128(const byte* encoded, int* encoded_size);
     264             :   static int32_t DecodeSLeb128(const byte* encoded, int* encoded_size);
     265             : 
     266             :   template <typename T>
     267             :   T GetNextValue() {
     268             :     T result;
     269             :     DCHECK_LE(next_ + sizeof(result), end_);
     270           1 :     result = ReadUnalignedValue<T>(reinterpret_cast<Address>(next_));
     271          34 :     next_ += sizeof(result);
     272             :     return result;
     273             :   }
     274             : 
     275             :   const byte* start_;
     276             :   const byte* next_;
     277             :   const byte* end_;
     278             : };
     279             : 
     280             : #ifdef ENABLE_DISASSEMBLER
     281             : 
     282             : class EhFrameDisassembler final {
     283             :  public:
     284             :   EhFrameDisassembler(const byte* start, const byte* end)
     285             :       : start_(start), end_(end) {
     286             :     DCHECK_LT(start, end);
     287             :   }
     288             : 
     289             :   void DisassembleToStream(std::ostream& stream);  // NOLINT
     290             : 
     291             :  private:
     292             :   static void DumpDwarfDirectives(std::ostream& stream,  // NOLINT
     293             :                                   const byte* start, const byte* end);
     294             : 
     295             :   static const char* DwarfRegisterCodeToString(int code);
     296             : 
     297             :   const byte* start_;
     298             :   const byte* end_;
     299             : 
     300             :   DISALLOW_COPY_AND_ASSIGN(EhFrameDisassembler);
     301             : };
     302             : 
     303             : #endif
     304             : 
     305             : }  // namespace internal
     306             : }  // namespace v8
     307             : 
     308             : #endif  // V8_EH_FRAME_H_

Generated by: LCOV version 1.10