C++程序  |  89行  |  2.16 KB

//===- ELFAttributeData.cpp -----------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include <mcld/Target/ELFAttributeData.h>

#include <mcld/Support/LEB128.h>
#include <mcld/Target/ELFAttributeValue.h>
#include <cstring>
#include <cassert>

using namespace mcld;

bool ELFAttributeData::ReadTag(TagType& pTag, const char* &pBuf,
                               size_t &pBufSize)
{
  size_t size = 0;

  pTag = static_cast<ELFAttributeData::TagType>(
            leb128::decode<uint64_t>(pBuf, size));

  if (size > pBufSize)
    return false;

  pBuf += size;
  pBufSize -= size;

  return true;
}

bool ELFAttributeData::ReadValue(ELFAttributeValue& pValue, const char* &pBuf,
                                 size_t &pBufSize)
{
  // An ULEB128-encoded value
  if (pValue.isIntValue()) {
    size_t size = 0;
    uint64_t int_value = leb128::decode<uint64_t>(pBuf, size);
    pValue.setIntValue(static_cast<unsigned int>(int_value));

    if (size > pBufSize)
      return false;

    pBuf += size;
    pBufSize -= size;
  }

  // A null-terminated byte string
  if (pValue.isStringValue()) {
    pValue.setStringValue(pBuf);

    size_t size = pValue.getStringValue().length() + 1 /* '\0' */;
    assert(size <= pBufSize);
    pBuf += size;
    pBufSize -= size;
  }

  return true;
}

bool ELFAttributeData::WriteAttribute(TagType pTag,
                                      const ELFAttributeValue& pValue,
                                      char* &pBuf)
{
  // Write the attribute tag.
  leb128::encode<uint32_t>(pBuf, pTag);

  // Write the attribute value.
  if (pValue.isIntValue())
    leb128::encode<uint32_t>(pBuf, pValue.getIntValue());

  if (pValue.isStringValue()) {
    // Write string data.
    size_t str_val_len = pValue.getStringValue().length();

    if (str_val_len > 0)
      ::memcpy(pBuf, pValue.getStringValue().c_str(), str_val_len);
    pBuf += str_val_len;

    // Write NULL-terminator.
    *pBuf++ = '\0';
  }

  return true;
}