1f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===- ELFAttributeData.cpp -----------------------------------------------===//
2f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
3f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//                     The MCLinker Project
4f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
5f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// This file is distributed under the University of Illinois Open Source
6f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines// License. See LICENSE.TXT for details.
7f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//
8f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/ELFAttributeData.h"
10f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/LEB128.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/ELFAttributeValue.h"
13f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cstring>
14f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines#include <cassert>
15f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
17f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFAttributeData::ReadTag(TagType& pTag,
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               const char*& pBuf,
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                               size_t& pBufSize) {
21f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  size_t size = 0;
22f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
23f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pTag = static_cast<ELFAttributeData::TagType>(
2437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      leb128::decode<uint64_t>(pBuf, size));
25f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
26f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (size > pBufSize)
27f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    return false;
28f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
29f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pBuf += size;
30f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  pBufSize -= size;
31f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
32f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return true;
33f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
34f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
3537b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFAttributeData::ReadValue(ELFAttributeValue& pValue,
3637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 const char*& pBuf,
3737b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                 size_t& pBufSize) {
38f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // An ULEB128-encoded value
39f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pValue.isIntValue()) {
40f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    size_t size = 0;
41f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    uint64_t int_value = leb128::decode<uint64_t>(pBuf, size);
42f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pValue.setIntValue(static_cast<unsigned int>(int_value));
43f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
44f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (size > pBufSize)
45f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      return false;
46f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
47f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pBuf += size;
48f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pBufSize -= size;
49f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
50f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
51f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // A null-terminated byte string
52f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pValue.isStringValue()) {
53f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pValue.setStringValue(pBuf);
54f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
55f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    size_t size = pValue.getStringValue().length() + 1 /* '\0' */;
56f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    assert(size <= pBufSize);
57f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pBuf += size;
58f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pBufSize -= size;
59f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
60f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
61f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return true;
62f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
63f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
64f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hinesbool ELFAttributeData::WriteAttribute(TagType pTag,
65f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines                                      const ELFAttributeValue& pValue,
6637b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                      char*& pBuf) {
67f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // Write the attribute tag.
68f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  leb128::encode<uint32_t>(pBuf, pTag);
69f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
70f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  // Write the attribute value.
71f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pValue.isIntValue())
72f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    leb128::encode<uint32_t>(pBuf, pValue.getIntValue());
73f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
74f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  if (pValue.isStringValue()) {
75f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Write string data.
76f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    size_t str_val_len = pValue.getStringValue().length();
77f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
78f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    if (str_val_len > 0)
79f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines      ::memcpy(pBuf, pValue.getStringValue().c_str(), str_val_len);
80f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    pBuf += str_val_len;
81f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
82f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    // Write NULL-terminator.
83f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines    *pBuf++ = '\0';
84f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  }
85f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines
86f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines  return true;
87f33f6de54db174aa679a4b6d1e040d37e95541c0Stephen Hines}
8837b74a387bb3993387029859c2d9d051c41c724eStephen Hines
8937b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
90