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 //===----------------------------------------------------------------------===//
~ELFAttribute()33 ELFAttribute::~ELFAttribute() {
34 llvm::DeleteContainerPointers(m_Subsections);
35 return;
36 }
37
merge(const Input & pInput,LDSection & pInputAttrSectHdr)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
sizeOutput() const124 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
emit(MemoryRegion & pRegion) const137 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
registerAttributeData(ELFAttributeData & pAttrData)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
getSubsection(llvm::StringRef pVendorName) const165 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 //===----------------------------------------------------------------------===//
merge(const Input & pInput,ConstAddress pData,size_t pSize)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
sizeOutput() const290 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
emit(char * pBuf) const299 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