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