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
28namespace mcld {
29
30//===----------------------------------------------------------------------===//
31// ELFAttribute
32//===----------------------------------------------------------------------===//
33ELFAttribute::~ELFAttribute() {
34  llvm::DeleteContainerPointers(m_Subsections);
35  return;
36}
37
38bool 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
124size_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
137size_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
158void 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
165ELFAttribute::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//===----------------------------------------------------------------------===//
186bool 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
290size_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
299size_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