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
28using namespace mcld;
29
30//===----------------------------------------------------------------------===//
31// ELFAttribute
32//===----------------------------------------------------------------------===//
33ELFAttribute::~ELFAttribute()
34{
35  llvm::DeleteContainerPointers(m_Subsections);
36  return;
37}
38
39bool 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
126size_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
138size_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
158void 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
166ELFAttribute::Subsection *
167ELFAttribute::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//===----------------------------------------------------------------------===//
186bool 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
293size_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
304size_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