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