Home | History | Annotate | Download | only in Target
      1 //===- ELFAttribute.cpp ---------------------------------------------------===//
      2 //
      3 //                     The MCLinker Project
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 #include <mcld/Target/ELFAttribute.h>
     10 
     11 #include <mcld/ADT/SizeTraits.h>
     12 #include <mcld/Fragment/RegionFragment.h>
     13 #include <mcld/LD/LDSection.h>
     14 #include <mcld/LD/SectionData.h>
     15 #include <mcld/LinkerConfig.h>
     16 #include <mcld/MC/Input.h>
     17 #include <mcld/Support/LEB128.h>
     18 #include <mcld/Support/MemoryArea.h>
     19 #include <mcld/Support/MsgHandling.h>
     20 #include <mcld/Target/ELFAttributeValue.h>
     21 #include <mcld/Target/GNULDBackend.h>
     22 
     23 #include <llvm/ADT/STLExtras.h>
     24 #include <llvm/Support/Host.h>
     25 
     26 #include <cstring>
     27 
     28 using namespace mcld;
     29 
     30 //===----------------------------------------------------------------------===//
     31 // ELFAttribute
     32 //===----------------------------------------------------------------------===//
     33 ELFAttribute::~ELFAttribute()
     34 {
     35   llvm::DeleteContainerPointers(m_Subsections);
     36   return;
     37 }
     38 
     39 bool ELFAttribute::merge(const Input &pInput, LDSection &pInputAttrSectHdr)
     40 {
     41   // Skip corrupt subsection
     42   if (pInputAttrSectHdr.size() < MinimalELFAttributeSectionSize)
     43     return true;
     44 
     45   // Obtain the region containing the attribute data. Expect exactly one
     46   // RegionFragment in the section data.
     47   const SectionData* sect_data = pInputAttrSectHdr.getSectionData();
     48 
     49   // FIXME: Why is 2?
     50   if ((sect_data->size() != 2) ||
     51       (!llvm::isa<RegionFragment>(sect_data->front()))) {
     52     return true;
     53   }
     54 
     55   const RegionFragment& region_frag =
     56       llvm::cast<RegionFragment>(sect_data->front());
     57 
     58   llvm::StringRef region = region_frag.getRegion();
     59 
     60   // Parse the ELF attribute section header. ARM [ABI-addenda], 2.2.3.
     61   //
     62   // <format-version: A>
     63   // [ <uint32: subsection-length> NTBS: vendor-name
     64   //   <bytes: vendor-data>
     65   // ]*
     66   const char *attribute_data = region.begin();
     67 
     68   // format-version
     69   if (attribute_data[0] != FormatVersion) {
     70     warning(diag::warn_unsupported_attribute_section_format)
     71         << pInput.name() << attribute_data[0];
     72     return true;
     73   }
     74 
     75   size_t subsection_offset = FormatVersionFieldSize;
     76 
     77   // Iterate all subsections containing in this attribute section.
     78   do {
     79     const char *subsection_data = region.begin() + subsection_offset;
     80 
     81     // subsection-length
     82     uint32_t subsection_length =
     83         *reinterpret_cast<const uint32_t*>(subsection_data);
     84 
     85     if(llvm::sys::IsLittleEndianHost != m_Config.targets().isLittleEndian())
     86       bswap32(subsection_length);
     87 
     88     // vendor-name
     89     const char* vendor_name = subsection_data + SubsectionLengthFieldSize;
     90     const size_t vendor_name_length = ::strlen(vendor_name) + 1 /* '\0' */;
     91 
     92     // Check the length.
     93     if ((vendor_name_length <= 1) ||
     94         (subsection_length <= (SubsectionLengthFieldSize + vendor_name_length)))
     95       return true;
     96 
     97     // Select the attribute subsection.
     98     Subsection *subsection = getSubsection(vendor_name);
     99 
    100     // Only process the subsections whose vendor can be recognized.
    101     if (subsection == NULL) {
    102       warning(diag::warn_unrecognized_vendor_subsection)
    103           << vendor_name << pInput.name();
    104     } else {
    105       // vendor-data
    106       size_t vendor_data_offset = subsection_offset +
    107                                   SubsectionLengthFieldSize +
    108                                   vendor_name_length;
    109       size_t vendor_data_size = subsection_length - SubsectionLengthFieldSize -
    110                                 vendor_name_length;
    111 
    112       ConstAddress vendor_data =
    113           reinterpret_cast<ConstAddress>(region.begin()) + vendor_data_offset;
    114 
    115       // Merge the vendor data in the subsection.
    116       if (!subsection->merge(pInput, vendor_data, vendor_data_size))
    117         return false;
    118     }
    119 
    120     subsection_offset += subsection_length;
    121   } while ((subsection_offset + SubsectionLengthFieldSize) < pInputAttrSectHdr.size());
    122 
    123   return true;
    124 }
    125 
    126 size_t ELFAttribute::sizeOutput() const
    127 {
    128   size_t total_size = FormatVersionFieldSize;
    129 
    130   for (llvm::SmallVectorImpl<Subsection*>::const_iterator
    131           subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
    132        subsec_it != subsec_end; ++subsec_it) {
    133     total_size += (*subsec_it)->sizeOutput();
    134   }
    135   return total_size;
    136 }
    137 
    138 size_t ELFAttribute::emit(MemoryRegion &pRegion) const
    139 {
    140   // ARM [ABI-addenda], 2.2.3
    141   uint64_t total_size = 0;
    142 
    143   // Write format-version.
    144   char* buffer = reinterpret_cast<char*>(pRegion.begin());
    145   buffer[0] = FormatVersion;
    146   total_size += FormatVersionFieldSize;
    147 
    148   for (llvm::SmallVectorImpl<Subsection*>::const_iterator
    149           subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
    150        subsec_it != subsec_end; ++subsec_it) {
    151     // Write out subsection.
    152     total_size += (*subsec_it)->emit(buffer + total_size);
    153   }
    154 
    155   return total_size;
    156 }
    157 
    158 void ELFAttribute::registerAttributeData(ELFAttributeData& pAttrData)
    159 {
    160   assert((getSubsection(pAttrData.getVendorName()) == NULL) &&
    161          "Multiple attribute data for a vendor!");
    162   m_Subsections.push_back(new Subsection(*this, pAttrData));
    163   return;
    164 }
    165 
    166 ELFAttribute::Subsection *
    167 ELFAttribute::getSubsection(llvm::StringRef pVendorName) const
    168 {
    169   // Search m_Subsections linearly.
    170   for (llvm::SmallVectorImpl<Subsection*>::const_iterator
    171           subsec_it = m_Subsections.begin(), subsec_end = m_Subsections.end();
    172        subsec_it != subsec_end; ++subsec_it) {
    173     Subsection* const subsection = *subsec_it;
    174     if (subsection->isMyAttribute(pVendorName)) {
    175       return subsection;
    176     }
    177   }
    178 
    179   // Not found
    180   return NULL;
    181 }
    182 
    183 //===----------------------------------------------------------------------===//
    184 // ELFAttribute::Subsection
    185 //===----------------------------------------------------------------------===//
    186 bool ELFAttribute::Subsection::merge(const Input &pInput,
    187                                      ConstAddress pData,
    188                                      size_t pSize)
    189 {
    190   const bool need_swap = (llvm::sys::IsLittleEndianHost !=
    191                               m_Parent.config().targets().isLittleEndian());
    192   // Read attribute sub-subsection from vendor data.
    193   //
    194   // ARM [ABI-addenda], 2.2.4:
    195   //
    196   // [   Tag_File    (=1) <uint32: byte-size> <attribute>*
    197   //   | Tag_Section (=2) <uint32: byte-size> <section number>* 0 <attribute>*
    198   //   | Tag_symbol  (=3) <unit32: byte-size> <symbol number>* 0 <attribute>*
    199   // ] +
    200   const char *subsubsection_data = reinterpret_cast<const char*>(pData);
    201   size_t remaining_size = pSize;
    202 
    203   if (!m_AttrData.preMerge(pInput)) {
    204     return false;
    205   }
    206 
    207   while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize) {
    208     // The tag of sub-subsection is encoded in ULEB128.
    209     size_t tag_size;
    210     uint64_t tag = leb128::decode<uint64_t>(subsubsection_data, tag_size);
    211 
    212     if ((tag_size + 4 /* byte-size */) >= remaining_size)
    213       break;
    214 
    215     size_t subsubsection_length =
    216         *reinterpret_cast<const uint32_t*>(subsubsection_data + tag_size);
    217 
    218     if (need_swap)
    219       bswap32(subsubsection_length);
    220 
    221     if (subsubsection_length > remaining_size) {
    222       // The subsubsection is corrupted. Try our best to process it.
    223       subsubsection_length = remaining_size;
    224     }
    225 
    226     switch (tag) {
    227       case ELFAttributeData::Tag_File: {
    228         ELFAttributeData::TagType tag;
    229         ELFAttributeValue in_attr;
    230         // The offset from the start of sub-subsection that <attribute> located
    231         size_t attribute_offset = tag_size + 4 /* byte-size */;
    232 
    233         const char* attr_buf = subsubsection_data + attribute_offset;
    234         size_t attr_size = subsubsection_length - attribute_offset;
    235 
    236         // Read attributes from the stream.
    237         do {
    238           if (!ELFAttributeData::ReadTag(tag, attr_buf, attr_size))
    239             break;
    240 
    241           ELFAttributeValue *out_attr;
    242           bool is_newly_created;
    243 
    244           std::tie(out_attr, is_newly_created) =
    245               m_AttrData.getOrCreateAttributeValue(tag);
    246 
    247           assert(out_attr != NULL);
    248 
    249           if (is_newly_created) {
    250             // Directly read the attribute value to the out_attr.
    251             if (!ELFAttributeData::ReadValue(*out_attr, attr_buf, attr_size))
    252               break;
    253           } else {
    254             // The attribute has been defined previously. Read the attribute
    255             // to a temporary storage in_attr and perform the merge.
    256             in_attr.reset();
    257             in_attr.setType(out_attr->type());
    258 
    259             // Read the attribute value.
    260             if (!ELFAttributeData::ReadValue(in_attr, attr_buf, attr_size))
    261               break;
    262 
    263             // Merge if the read attribute value is different than current one
    264             // in output.
    265             if ((in_attr != *out_attr) &&
    266                 !m_AttrData.merge(m_Parent.config(), pInput, tag, in_attr)) {
    267               // Fail to merge the attribute.
    268               return false;
    269             }
    270           }
    271         } while (attr_size > 0);
    272 
    273         break;
    274       }
    275       // Skip sub-subsection tagged with Tag_Section and Tag_Symbol. They are
    276       // deprecated since ARM [ABI-addenda] r2.09.
    277       case ELFAttributeData::Tag_Section:
    278       case ELFAttributeData::Tag_Symbol:
    279       // Skip any unknown tags.
    280       default: {
    281         break;
    282       }
    283     }
    284 
    285     // Update subsubsection_data and remaining_size for next.
    286     subsubsection_data += subsubsection_length;
    287     remaining_size -= subsubsection_length;
    288   } // while (remaining_size > ELFAttribute::MinimalELFAttributeSubsectionSize)
    289 
    290   return m_AttrData.postMerge(m_Parent.config(), pInput);
    291 }
    292 
    293 size_t ELFAttribute::Subsection::sizeOutput() const
    294 {
    295   // ARM [ABI-addenda], 2.2.3 and 2.2.4
    296   return ELFAttribute::SubsectionLengthFieldSize +
    297             m_AttrData.getVendorName().length() /* vendor-name */ +
    298             1 /* NULL-terminator for vendor-name */ +
    299             1 /* Tag_File */ +
    300             sizeof(uint32_t) /* length of sub-subsection */ +
    301             m_AttrData.sizeOutput();
    302 }
    303 
    304 size_t ELFAttribute::Subsection::emit(char *pBuf) const
    305 {
    306   // ARM [ABI-addenda], 2.2.3 and 2.2.4
    307   const bool need_swap = (llvm::sys::IsLittleEndianHost !=
    308                               m_Parent.config().targets().isLittleEndian());
    309 
    310   char *buffer = pBuf;
    311 
    312   // The subsection-length and byte-size field in sub-subsection will be patched
    313   // later after writing out all attribute data.
    314   char *subsection_length_hole = NULL;
    315   char *subsubsection_length_hole = NULL;
    316 
    317   // Reserve space for subsection-length.
    318   subsection_length_hole = buffer;
    319   buffer += 4;
    320 
    321   // Write vendor-name.
    322   const std::string &vendor_name = m_AttrData.getVendorName();
    323   ::memcpy(buffer, vendor_name.c_str(), vendor_name.length());
    324   buffer += vendor_name.length();
    325 
    326   // Write NULL-terminator for vendor-name.
    327   *buffer++ = '\0';
    328 
    329   // Write Tag_File (0x01).
    330   *buffer++ = '\x01';
    331 
    332   // Reserve space for byte-size for sub-subsection.
    333   subsubsection_length_hole = buffer;
    334   buffer += sizeof(uint32_t);
    335 
    336   // Write attribute data.
    337   uint32_t subsubsection_length = m_AttrData.emit(buffer);
    338 
    339   // Calculate value of subsection-length.
    340   uint32_t subsection_length = (buffer - pBuf) + subsubsection_length;
    341 
    342   // ARM [ABI-addenda] 2.2.4
    343   //
    344   // The byte-size in sub-subsection includes Tag_File (1-byte) and the size
    345   // field of itself (4-byte).
    346   subsubsection_length += 1 /* Tag_File */ + 4 /* size of byte-size */;
    347 
    348   // Patch subsubsection_length_hole.
    349   assert(subsubsection_length_hole != NULL);
    350 
    351   if(need_swap)
    352     bswap32(subsubsection_length);
    353 
    354   ::memcpy(subsubsection_length_hole, &subsubsection_length, sizeof(uint32_t));
    355 
    356   // Write subsection-length in subsection_length_hole.
    357   if(need_swap)
    358     bswap32(subsection_length);
    359 
    360   assert(subsection_length_hole != NULL);
    361   ::memcpy(subsection_length_hole, &subsection_length, sizeof(uint32_t));
    362 
    363   return subsection_length;
    364 }
    365