//===- 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>
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;
}
} // namespace mcld