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