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 //===----------------------------------------------------------------------===//
~ELFAttribute()33 ELFAttribute::~ELFAttribute()
34 {
35 llvm::DeleteContainerPointers(m_Subsections);
36 return;
37 }
38
merge(const Input & pInput,LDSection & pInputAttrSectHdr)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
sizeOutput() const126 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
emit(MemoryRegion & pRegion) const138 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
registerAttributeData(ELFAttributeData & pAttrData)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 *
getSubsection(llvm::StringRef pVendorName) const167 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 //===----------------------------------------------------------------------===//
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 {
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
sizeOutput() const293 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
emit(char * pBuf) const304 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