187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===- ELFAttribute.cpp ---------------------------------------------------===//
287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//                     The MCLinker Project
487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// This file is distributed under the University of Illinois Open Source
687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// License. See LICENSE.TXT for details.
787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//
887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/ELFAttribute.h"
1037b74a387bb3993387029859c2d9d051c41c724eStephen Hines
1137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/ADT/SizeTraits.h"
1237b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Fragment/RegionFragment.h"
1337b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/LDSection.h"
1437b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LD/SectionData.h"
1537b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/LinkerConfig.h"
1637b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/MC/Input.h"
1737b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/LEB128.h"
1837b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MemoryArea.h"
1937b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Support/MsgHandling.h"
2037b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/ELFAttributeValue.h"
2137b74a387bb3993387029859c2d9d051c41c724eStephen Hines#include "mcld/Target/GNULDBackend.h"
2287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/ADT/STLExtras.h>
2487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <llvm/Support/Host.h>
2587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines#include <cstring>
2787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
2837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesnamespace mcld {
2987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
3187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// ELFAttribute
3287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
3337b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFAttribute::~ELFAttribute() {
3487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::DeleteContainerPointers(m_Subsections);
3587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return;
3687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
3787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
3837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFAttribute::merge(const Input& pInput, LDSection& pInputAttrSectHdr) {
3987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Skip corrupt subsection
4087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (pInputAttrSectHdr.size() < MinimalELFAttributeSectionSize)
4187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
4287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Obtain the region containing the attribute data. Expect exactly one
4487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // RegionFragment in the section data.
4587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const SectionData* sect_data = pInputAttrSectHdr.getSectionData();
4687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
4787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // FIXME: Why is 2?
4887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if ((sect_data->size() != 2) ||
4987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      (!llvm::isa<RegionFragment>(sect_data->front()))) {
5087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
5187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
5287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const RegionFragment& region_frag =
5487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      llvm::cast<RegionFragment>(sect_data->front());
5587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  llvm::StringRef region = region_frag.getRegion();
5787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
5887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Parse the ELF attribute section header. ARM [ABI-addenda], 2.2.3.
5987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
6087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // <format-version: ‘A’>
6187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // [ <uint32: subsection-length> NTBS: vendor-name
6287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //   <bytes: vendor-data>
6387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ]*
6437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const char* attribute_data = region.begin();
6587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
6687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // format-version
6787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (attribute_data[0] != FormatVersion) {
6887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    warning(diag::warn_unsupported_attribute_section_format)
6987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        << pInput.name() << attribute_data[0];
7087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return true;
7187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
7287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  size_t subsection_offset = FormatVersionFieldSize;
7487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Iterate all subsections containing in this attribute section.
7687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  do {
7737b74a387bb3993387029859c2d9d051c41c724eStephen Hines    const char* subsection_data = region.begin() + subsection_offset;
7887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
7987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // subsection-length
8087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint32_t subsection_length =
8187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        *reinterpret_cast<const uint32_t*>(subsection_data);
8287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8337b74a387bb3993387029859c2d9d051c41c724eStephen Hines    if (llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian())
8487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      bswap32(subsection_length);
8587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
8687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // vendor-name
8787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const char* vendor_name = subsection_data + SubsectionLengthFieldSize;
8887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    const size_t vendor_name_length = ::strlen(vendor_name) + 1 /* '\0' */;
8987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Check the length.
9187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((vendor_name_length <= 1) ||
9287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        (subsection_length <= (SubsectionLengthFieldSize + vendor_name_length)))
9387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return true;
9487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Select the attribute subsection.
9637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    Subsection* subsection = getSubsection(vendor_name);
9787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
9887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Only process the subsections whose vendor can be recognized.
9987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (subsection == NULL) {
10037b74a387bb3993387029859c2d9d051c41c724eStephen Hines      warning(diag::warn_unrecognized_vendor_subsection) << vendor_name
10137b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                                         << pInput.name();
10287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    } else {
10387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // vendor-data
10437b74a387bb3993387029859c2d9d051c41c724eStephen Hines      size_t vendor_data_offset =
10537b74a387bb3993387029859c2d9d051c41c724eStephen Hines          subsection_offset + SubsectionLengthFieldSize + vendor_name_length;
10637b74a387bb3993387029859c2d9d051c41c724eStephen Hines      size_t vendor_data_size =
10737b74a387bb3993387029859c2d9d051c41c724eStephen Hines          subsection_length - SubsectionLengthFieldSize - vendor_name_length;
10887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
10987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      ConstAddress vendor_data =
11087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          reinterpret_cast<ConstAddress>(region.begin()) + vendor_data_offset;
11187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Merge the vendor data in the subsection.
11387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      if (!subsection->merge(pInput, vendor_data, vendor_data_size))
11487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        return false;
11587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
11687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
11787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    subsection_offset += subsection_length;
11837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  } while ((subsection_offset + SubsectionLengthFieldSize) <
11937b74a387bb3993387029859c2d9d051c41c724eStephen Hines           pInputAttrSectHdr.size());
12087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return true;
12287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
12387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12437b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ELFAttribute::sizeOutput() const {
12587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  size_t total_size = FormatVersionFieldSize;
12687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
12787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
12837b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_it = m_Subsections.begin(),
12937b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_end = m_Subsections.end();
13037b74a387bb3993387029859c2d9d051c41c724eStephen Hines       subsec_it != subsec_end;
13137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++subsec_it) {
13287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    total_size += (*subsec_it)->sizeOutput();
13387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
13487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return total_size;
13587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
13687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
13737b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ELFAttribute::emit(MemoryRegion& pRegion) const {
13887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ARM [ABI-addenda], 2.2.3
13987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint64_t total_size = 0;
14087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write format-version.
14287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  char* buffer = reinterpret_cast<char*>(pRegion.begin());
14387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  buffer[0] = FormatVersion;
14487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  total_size += FormatVersionFieldSize;
14587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
14687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
14737b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_it = m_Subsections.begin(),
14837b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_end = m_Subsections.end();
14937b74a387bb3993387029859c2d9d051c41c724eStephen Hines       subsec_it != subsec_end;
15037b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++subsec_it) {
15187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Write out subsection.
15287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    total_size += (*subsec_it)->emit(buffer + total_size);
15387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
15487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return total_size;
15687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
15787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
15837b74a387bb3993387029859c2d9d051c41c724eStephen Hinesvoid ELFAttribute::registerAttributeData(ELFAttributeData& pAttrData) {
15987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert((getSubsection(pAttrData.getVendorName()) == NULL) &&
16087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines         "Multiple attribute data for a vendor!");
16187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  m_Subsections.push_back(new Subsection(*this, pAttrData));
16287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return;
16387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
16487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
16537b74a387bb3993387029859c2d9d051c41c724eStephen HinesELFAttribute::Subsection* ELFAttribute::getSubsection(
16637b74a387bb3993387029859c2d9d051c41c724eStephen Hines    llvm::StringRef pVendorName) const {
16787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Search m_Subsections linearly.
16887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  for (llvm::SmallVectorImpl<Subsection*>::const_iterator
16937b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_it = m_Subsections.begin(),
17037b74a387bb3993387029859c2d9d051c41c724eStephen Hines           subsec_end = m_Subsections.end();
17137b74a387bb3993387029859c2d9d051c41c724eStephen Hines       subsec_it != subsec_end;
17237b74a387bb3993387029859c2d9d051c41c724eStephen Hines       ++subsec_it) {
17387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    Subsection* const subsection = *subsec_it;
17487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (subsection->isMyAttribute(pVendorName)) {
17587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      return subsection;
17687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
17787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
17887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
17987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Not found
18087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return NULL;
18187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
18287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
18387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
18487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines// ELFAttribute::Subsection
18587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines//===----------------------------------------------------------------------===//
18637b74a387bb3993387029859c2d9d051c41c724eStephen Hinesbool ELFAttribute::Subsection::merge(const Input& pInput,
18787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                                     ConstAddress pData,
18837b74a387bb3993387029859c2d9d051c41c724eStephen Hines                                     size_t pSize) {
18987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const bool need_swap = (llvm::sys::IsLittleEndianHost !=
19037b74a387bb3993387029859c2d9d051c41c724eStephen Hines                          m_Parent.config().targets().isLittleEndian());
19187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Read attribute sub-subsection from vendor data.
19287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
19387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ARM [ABI-addenda], 2.2.4:
19487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
19587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // [   Tag_File    (=1) <uint32: byte-size> <attribute>*
19687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //   | Tag_Section (=2) <uint32: byte-size> <section number>* 0 <attribute>*
19787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //   | Tag_symbol  (=3) <unit32: byte-size> <symbol number>* 0 <attribute>*
19887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ] +
19937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const char* subsubsection_data = reinterpret_cast<const char*>(pData);
20087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  size_t remaining_size = pSize;
20187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  if (!m_AttrData.preMerge(pInput)) {
20387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    return false;
20487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  }
20587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
20687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize) {
20787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // The tag of sub-subsection is encoded in ULEB128.
20887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    size_t tag_size;
20987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    uint64_t tag = leb128::decode<uint64_t>(subsubsection_data, tag_size);
21087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if ((tag_size + 4 /* byte-size */) >= remaining_size)
21287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      break;
21387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    size_t subsubsection_length =
21587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        *reinterpret_cast<const uint32_t*>(subsubsection_data + tag_size);
21687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
21787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (need_swap)
21887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      bswap32(subsubsection_length);
21987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
22087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    if (subsubsection_length > remaining_size) {
22187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // The subsubsection is corrupted. Try our best to process it.
22287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      subsubsection_length = remaining_size;
22387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
22487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
22587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    switch (tag) {
22687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case ELFAttributeData::Tag_File: {
22787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ELFAttributeData::TagType tag;
22887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        ELFAttributeValue in_attr;
22987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // The offset from the start of sub-subsection that <attribute> located
23087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        size_t attribute_offset = tag_size + 4 /* byte-size */;
23187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        const char* attr_buf = subsubsection_data + attribute_offset;
23387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        size_t attr_size = subsubsection_length - attribute_offset;
23487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
23587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        // Read attributes from the stream.
23687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        do {
23787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (!ELFAttributeData::ReadTag(tag, attr_buf, attr_size))
23887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            break;
23987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24037b74a387bb3993387029859c2d9d051c41c724eStephen Hines          ELFAttributeValue* out_attr;
24187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          bool is_newly_created;
24287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24341f2d34f9d4efad1928e890acc5c2924b5033909Stephen Hines          std::tie(out_attr, is_newly_created) =
24487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              m_AttrData.getOrCreateAttributeValue(tag);
24587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          assert(out_attr != NULL);
24787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
24887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          if (is_newly_created) {
24987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Directly read the attribute value to the out_attr.
25087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if (!ELFAttributeData::ReadValue(*out_attr, attr_buf, attr_size))
25187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              break;
25287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          } else {
25387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // The attribute has been defined previously. Read the attribute
25487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // to a temporary storage in_attr and perform the merge.
25587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            in_attr.reset();
25687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            in_attr.setType(out_attr->type());
25787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
25887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Read the attribute value.
25987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if (!ELFAttributeData::ReadValue(in_attr, attr_buf, attr_size))
26087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              break;
26187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
26287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // Merge if the read attribute value is different than current one
26387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            // in output.
26487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            if ((in_attr != *out_attr) &&
26587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines                !m_AttrData.merge(m_Parent.config(), pInput, tag, in_attr)) {
26687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              // Fail to merge the attribute.
26787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines              return false;
26887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines            }
26987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines          }
27087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        } while (attr_size > 0);
27187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
27287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines        break;
27387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      }
27487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Skip sub-subsection tagged with Tag_Section and Tag_Symbol. They are
27587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // deprecated since ARM [ABI-addenda] r2.09.
27687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case ELFAttributeData::Tag_Section:
27787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      case ELFAttributeData::Tag_Symbol:
27887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines      // Skip any unknown tags.
27937b74a387bb3993387029859c2d9d051c41c724eStephen Hines      default: { break; }
28087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    }
28187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
28287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    // Update subsubsection_data and remaining_size for next.
28387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    subsubsection_data += subsubsection_length;
28487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    remaining_size -= subsubsection_length;
28537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  }  // while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize)
28687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
28787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return m_AttrData.postMerge(m_Parent.config(), pInput);
28887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
28987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
29037b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ELFAttribute::Subsection::sizeOutput() const {
29187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ARM [ABI-addenda], 2.2.3 and 2.2.4
29287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return ELFAttribute::SubsectionLengthFieldSize +
29337b74a387bb3993387029859c2d9d051c41c724eStephen Hines         m_AttrData.getVendorName().length() /* vendor-name */ +
29437b74a387bb3993387029859c2d9d051c41c724eStephen Hines         1 /* NULL-terminator for vendor-name */ + 1 /* Tag_File */ +
29537b74a387bb3993387029859c2d9d051c41c724eStephen Hines         sizeof(uint32_t) /* length of sub-subsection */ +
29637b74a387bb3993387029859c2d9d051c41c724eStephen Hines         m_AttrData.sizeOutput();
29787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
29887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
29937b74a387bb3993387029859c2d9d051c41c724eStephen Hinessize_t ELFAttribute::Subsection::emit(char* pBuf) const {
30087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ARM [ABI-addenda], 2.2.3 and 2.2.4
30187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  const bool need_swap = (llvm::sys::IsLittleEndianHost !=
30237b74a387bb3993387029859c2d9d051c41c724eStephen Hines                          m_Parent.config().targets().isLittleEndian());
30387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
30437b74a387bb3993387029859c2d9d051c41c724eStephen Hines  char* buffer = pBuf;
30587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
30687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // The subsection-length and byte-size field in sub-subsection will be patched
30787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // later after writing out all attribute data.
30837b74a387bb3993387029859c2d9d051c41c724eStephen Hines  char* subsection_length_hole = NULL;
30937b74a387bb3993387029859c2d9d051c41c724eStephen Hines  char* subsubsection_length_hole = NULL;
31087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
31187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Reserve space for subsection-length.
31287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  subsection_length_hole = buffer;
31387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  buffer += 4;
31487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
31587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write vendor-name.
31637b74a387bb3993387029859c2d9d051c41c724eStephen Hines  const std::string& vendor_name = m_AttrData.getVendorName();
31787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ::memcpy(buffer, vendor_name.c_str(), vendor_name.length());
31887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  buffer += vendor_name.length();
31987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
32087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write NULL-terminator for vendor-name.
32187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  *buffer++ = '\0';
32287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
32387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write Tag_File (0x01).
32487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  *buffer++ = '\x01';
32587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
32687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Reserve space for byte-size for sub-subsection.
32787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  subsubsection_length_hole = buffer;
32887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  buffer += sizeof(uint32_t);
32987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
33087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write attribute data.
33187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t subsubsection_length = m_AttrData.emit(buffer);
33287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
33387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Calculate value of subsection-length.
33487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  uint32_t subsection_length = (buffer - pBuf) + subsubsection_length;
33587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
33687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // ARM [ABI-addenda] 2.2.4
33787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  //
33887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // The byte-size in sub-subsection includes Tag_File (1-byte) and the size
33987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // field of itself (4-byte).
34087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  subsubsection_length += 1 /* Tag_File */ + 4 /* size of byte-size */;
34187f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
34287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Patch subsubsection_length_hole.
34387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(subsubsection_length_hole != NULL);
34487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
34537b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (need_swap)
34687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bswap32(subsubsection_length);
34787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
34887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ::memcpy(subsubsection_length_hole, &subsubsection_length, sizeof(uint32_t));
34987f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
35087f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  // Write subsection-length in subsection_length_hole.
35137b74a387bb3993387029859c2d9d051c41c724eStephen Hines  if (need_swap)
35287f34658dec9097d987d254a990ea7f311bfc95fStephen Hines    bswap32(subsection_length);
35387f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
35487f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  assert(subsection_length_hole != NULL);
35587f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  ::memcpy(subsection_length_hole, &subsection_length, sizeof(uint32_t));
35687f34658dec9097d987d254a990ea7f311bfc95fStephen Hines
35787f34658dec9097d987d254a990ea7f311bfc95fStephen Hines  return subsection_length;
35887f34658dec9097d987d254a990ea7f311bfc95fStephen Hines}
35937b74a387bb3993387029859c2d9d051c41c724eStephen Hines
36037b74a387bb3993387029859c2d9d051c41c724eStephen Hines}  // namespace mcld
361