/*========================== begin_copyright_notice ============================

Copyright (C) 2017-2021 Intel Corporation

SPDX-License-Identifier: MIT

============================= end_copyright_notice ===========================*/

#pragma once

#include "CLElfTypes.h"
#include <queue>
#include <string>

#if defined(_WIN32) && (__KLOCWORK__ == 0)
  #define ELF_CALL __stdcall
#else
  #define ELF_CALL
#endif

using namespace std;

namespace CLElfLib
{
static const unsigned int g_scElfHeaderAlignment    = 16;   // allocation alignment restriction
static const unsigned int g_scInitialElfSize        = 2048; // initial elf size (in bytes)
static const unsigned int g_scInitNumSectionHeaders = 8;

struct SSectionNode
{
    E_SH_TYPE    Type;
    unsigned int Flags;
    string Name;
    char* pData;
    unsigned int DataSize;

    SSectionNode()
    {
        Type     = SH_TYPE_NULL;
        Flags    = 0;
        pData    = NULL;
        DataSize = 0;
    }

    ~SSectionNode()
    {
    }
};

/******************************************************************************\

 Class:         CElfWriter

 Description:   Class to provide simpler interaction with the ELF standard
                binary object.  SElf64Header defines the ELF header type and
                SElf64SectionHeader defines the section header type.

\******************************************************************************/
class CElfWriter
{
public:
    static CElfWriter* ELF_CALL Create(
        E_EH_TYPE type,
        E_EH_MACHINE machine,
        Elf64_Xword flags );

    static void ELF_CALL Delete( CElfWriter* &pElfWriter );

    E_RETVAL ELF_CALL AddSection(
        SSectionNode* pSectionNode );

    E_RETVAL ELF_CALL ResolveBinary(
        char* const pBinary,
        size_t& dataSize );

    E_RETVAL ELF_CALL Initialize();
    E_RETVAL ELF_CALL PatchElfHeader( char* const pBinary );

protected:
    ELF_CALL CElfWriter(
        E_EH_TYPE type,
        E_EH_MACHINE machine,
        Elf64_Xword flags );

    ELF_CALL ~CElfWriter();

    E_EH_TYPE m_type;
    E_EH_MACHINE m_machine;
    Elf64_Xword m_flags;

    std::queue<SSectionNode*> m_nodeQueue;

    unsigned int m_dataSize;
    unsigned int m_numSections;
    size_t       m_stringTableSize;
    size_t       m_totalBinarySize;
};

/******************************************************************************\

 Class:         CElfWriterDeleter

 Description:   Dummy class to be used with unique_ptr to call Delete on
                CElfReader when going out of scope.

\******************************************************************************/
class CElfWriterDeleter
{
public:
  void operator()(CElfWriter* ptr) const
  {
    CElfWriter::Delete(ptr);
  }
};

} // namespace ELFLib
