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 //===----------------------------------------------------------------------===// 33 ELFAttribute::~ELFAttribute() 34 { 35 llvm::DeleteContainerPointers(m_Subsections); 36 return; 37 } 38 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 126 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 138 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 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 * 167 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 //===----------------------------------------------------------------------===// 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 293 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 304 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