| OLD | NEW | 
|---|
| 1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// | 1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// | 
| 2 // | 2 // | 
| 3 //                        The Subzero Code Generator | 3 //                        The Subzero Code Generator | 
| 4 // | 4 // | 
| 5 // This file is distributed under the University of Illinois Open Source | 5 // This file is distributed under the University of Illinois Open Source | 
| 6 // License. See LICENSE.TXT for details. | 6 // License. See LICENSE.TXT for details. | 
| 7 // | 7 // | 
| 8 //===----------------------------------------------------------------------===// | 8 //===----------------------------------------------------------------------===// | 
| 9 // | 9 // | 
| 10 // This file defines the writer for ELF relocatable object files. | 10 // This file defines the writer for ELF relocatable object files. | 
| 11 // | 11 // | 
| 12 //===----------------------------------------------------------------------===// | 12 //===----------------------------------------------------------------------===// | 
| 13 | 13 | 
|  | 14 #include "assembler.h" | 
| 14 #include "IceDefs.h" | 15 #include "IceDefs.h" | 
| 15 #include "IceELFObjectWriter.h" | 16 #include "IceELFObjectWriter.h" | 
| 16 #include "IceELFSection.h" | 17 #include "IceELFSection.h" | 
| 17 #include "IceELFStreamer.h" | 18 #include "IceELFStreamer.h" | 
| 18 #include "IceGlobalContext.h" | 19 #include "IceGlobalContext.h" | 
| 19 #include "IceGlobalInits.h" | 20 #include "IceGlobalInits.h" | 
| 20 #include "IceOperand.h" | 21 #include "IceOperand.h" | 
| 21 | 22 | 
| 22 using namespace llvm::ELF; | 23 using namespace llvm::ELF; | 
| 23 | 24 | 
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 107                                                  UserSectionList &UserSections, | 108                                                  UserSectionList &UserSections, | 
| 108                                                  RelSectionList &RelSections, | 109                                                  RelSectionList &RelSections, | 
| 109                                                  SectionList &AllSections) { | 110                                                  SectionList &AllSections) { | 
| 110   RelSectionList::iterator RelIt = RelSections.begin(); | 111   RelSectionList::iterator RelIt = RelSections.begin(); | 
| 111   RelSectionList::iterator RelE = RelSections.end(); | 112   RelSectionList::iterator RelE = RelSections.end(); | 
| 112   for (ELFSection *UserSection : UserSections) { | 113   for (ELFSection *UserSection : UserSections) { | 
| 113     UserSection->setNumber(CurSectionNumber++); | 114     UserSection->setNumber(CurSectionNumber++); | 
| 114     UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName())); | 115     UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName())); | 
| 115     AllSections.push_back(UserSection); | 116     AllSections.push_back(UserSection); | 
| 116     if (RelIt != RelE) { | 117     if (RelIt != RelE) { | 
| 117       ELFRelocationSectionBase *RelSection = *RelIt; | 118       ELFRelocationSection *RelSection = *RelIt; | 
| 118       if (RelSection->getRelatedSection() == UserSection) { | 119       if (RelSection->getRelatedSection() == UserSection) { | 
| 119         RelSection->setInfoNum(UserSection->getNumber()); | 120         RelSection->setInfoNum(UserSection->getNumber()); | 
| 120         RelSection->setNumber(CurSectionNumber++); | 121         RelSection->setNumber(CurSectionNumber++); | 
| 121         RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName())); | 122         RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName())); | 
| 122         AllSections.push_back(RelSection); | 123         AllSections.push_back(RelSection); | 
| 123         ++RelIt; | 124         ++RelIt; | 
| 124       } | 125       } | 
| 125     } | 126     } | 
| 126   } | 127   } | 
| 127   // Should finish with UserIt at the same time as RelIt. | 128   // Should finish with UserIt at the same time as RelIt. | 
| 128   assert(RelIt == RelE); | 129   assert(RelIt == RelE); | 
| 129   return; | 130   return; | 
| 130 } | 131 } | 
| 131 | 132 | 
| 132 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, | 133 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, | 
| 133                                        RelSectionList &RelSections) { | 134                                        RelSectionList &RelSections) { | 
| 134   for (ELFRelocationSectionBase *S : RelSections) { | 135   for (ELFRelocationSection *S : RelSections) { | 
| 135     S->setLinkNum(SymTabNumber); | 136     S->setLinkNum(SymTabNumber); | 
| 136   } | 137   } | 
| 137 } | 138 } | 
| 138 | 139 | 
| 139 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) { | 140 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) { | 
| 140   // Go through each section, assigning them section numbers and | 141   // Go through each section, assigning them section numbers and | 
| 141   // and fill in the size for sections that aren't incrementally updated. | 142   // and fill in the size for sections that aren't incrementally updated. | 
| 142   assert(!SectionNumbersAssigned); | 143   assert(!SectionNumbersAssigned); | 
| 143   SizeT CurSectionNumber = 0; | 144   SizeT CurSectionNumber = 0; | 
| 144   NullSection->setNumber(CurSectionNumber++); | 145   NullSection->setNumber(CurSectionNumber++); | 
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 180   if (Mod == 0) | 181   if (Mod == 0) | 
| 181     return OffsetInFile; | 182     return OffsetInFile; | 
| 182   Elf64_Xword AlignDiff = Align - Mod; | 183   Elf64_Xword AlignDiff = Align - Mod; | 
| 183   Str.writeZeroPadding(AlignDiff); | 184   Str.writeZeroPadding(AlignDiff); | 
| 184   OffsetInFile += AlignDiff; | 185   OffsetInFile += AlignDiff; | 
| 185   assert((OffsetInFile & (Align - 1)) == 0); | 186   assert((OffsetInFile & (Align - 1)) == 0); | 
| 186   return OffsetInFile; | 187   return OffsetInFile; | 
| 187 } | 188 } | 
| 188 | 189 | 
| 189 void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, | 190 void ELFObjectWriter::writeFunctionCode(const IceString &FuncName, | 
| 190                                         bool IsInternal, | 191                                         bool IsInternal, const Assembler *Asm) { | 
| 191                                         const llvm::StringRef Data) { |  | 
| 192   assert(!SectionNumbersAssigned); | 192   assert(!SectionNumbersAssigned); | 
|  | 193   ELFTextSection *Section = nullptr; | 
| 193   // TODO(jvoung): handle ffunction-sections. | 194   // TODO(jvoung): handle ffunction-sections. | 
| 194   IceString SectionName = ".text"; | 195   IceString SectionName = ".text"; | 
| 195   ELFTextSection *Section = nullptr; |  | 
| 196   if (TextSections.size() == 0) { | 196   if (TextSections.size() == 0) { | 
| 197     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; | 197     const Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; | 
| 198     // TODO(jvoung): Should be bundle size. Grab it from that target? | 198     // TODO(jvoung): Should be bundle size. Grab it from that target? | 
| 199     const Elf64_Xword ShAlign = 32; | 199     const Elf64_Xword ShAlign = 32; | 
| 200     Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, | 200     Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, | 
| 201                                             ShAlign, 0); | 201                                             ShAlign, 0); | 
| 202     Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); | 202     Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); | 
| 203     Section->setFileOffset(OffsetInFile); | 203     Section->setFileOffset(OffsetInFile); | 
| 204     TextSections.push_back(Section); | 204     TextSections.push_back(Section); | 
| 205   } else { | 205   } else { | 
| 206     Section = TextSections[0]; | 206     Section = TextSections[0]; | 
| 207   } | 207   } | 
| 208   RelocOffsetT OffsetInSection = Section->getCurrentSize(); | 208   RelocOffsetT OffsetInSection = Section->getCurrentSize(); | 
| 209   // Function symbols are set to 0 size in the symbol table, | 209   // Function symbols are set to 0 size in the symbol table, | 
| 210   // in contrast to data symbols which have a proper size. | 210   // in contrast to data symbols which have a proper size. | 
| 211   SizeT SymbolSize = 0; | 211   SizeT SymbolSize = 0; | 
| 212   Section->appendData(Str, Data); | 212   Section->appendData(Str, Asm->getBufferView()); | 
| 213   uint8_t SymbolType; | 213   uint8_t SymbolType; | 
| 214   uint8_t SymbolBinding; | 214   uint8_t SymbolBinding; | 
| 215   if (IsInternal) { | 215   if (IsInternal) { | 
| 216     SymbolType = STT_NOTYPE; | 216     SymbolType = STT_NOTYPE; | 
| 217     SymbolBinding = STB_LOCAL; | 217     SymbolBinding = STB_LOCAL; | 
| 218   } else { | 218   } else { | 
| 219     SymbolType = STT_FUNC; | 219     SymbolType = STT_FUNC; | 
| 220     SymbolBinding = STB_GLOBAL; | 220     SymbolBinding = STB_GLOBAL; | 
| 221   } | 221   } | 
| 222   SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, | 222   SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, | 
| 223                            OffsetInSection, SymbolSize); | 223                            OffsetInSection, SymbolSize); | 
| 224   StrTab->add(FuncName); | 224   StrTab->add(FuncName); | 
|  | 225 | 
|  | 226   // Create a relocation section for the text section if needed, and copy the | 
|  | 227   // fixup information from per-function Assembler memory to the object | 
|  | 228   // writer's memory, for writing later. | 
|  | 229   if (!Asm->fixups().empty()) { | 
|  | 230     bool IsELF64 = isELF64(Ctx.getTargetArch()); | 
|  | 231     IceString RelSectionName = IsELF64 ? ".rela" : ".rel"; | 
|  | 232     RelSectionName += SectionName; | 
|  | 233     ELFRelocationSection *RelSection = nullptr; | 
|  | 234     // TODO(jvoung): Make this more efficient if -ffunction-sections | 
|  | 235     // efficiency becomes a problem. | 
|  | 236     auto RSI = | 
|  | 237         std::find_if(RelTextSections.begin(), RelTextSections.end(), | 
|  | 238                      [&RelSectionName](const ELFRelocationSection *S) | 
|  | 239                          -> bool { return S->getName() == RelSectionName; }); | 
|  | 240     if (RSI != RelTextSections.end()) { | 
|  | 241       RelSection = *RSI; | 
|  | 242     } else { | 
|  | 243       const Elf64_Word ShType = IsELF64 ? SHT_RELA : SHT_REL; | 
|  | 244       const Elf64_Xword ShAlign = IsELF64 ? 8 : 4; | 
|  | 245       const Elf64_Xword ShEntSize = | 
|  | 246           IsELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); | 
|  | 247       static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, | 
|  | 248                     "Elf_Rel/Rela sizes cannot be derived from sizeof"); | 
|  | 249       const Elf64_Xword ShFlags = 0; | 
|  | 250       RelSection = createSection<ELFRelocationSection>( | 
|  | 251           RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); | 
|  | 252       RelSection->setRelatedSection(Section); | 
|  | 253       RelTextSections.push_back(RelSection); | 
|  | 254     } | 
|  | 255     RelSection->addRelocations(OffsetInSection, Asm->fixups()); | 
|  | 256   } | 
| 225 } | 257 } | 
| 226 | 258 | 
| 227 void ELFObjectWriter::writeDataInitializer(const IceString &VarName, | 259 void ELFObjectWriter::writeDataInitializer(const IceString &VarName, | 
| 228                                            const llvm::StringRef Data) { | 260                                            const llvm::StringRef Data) { | 
| 229   assert(!SectionNumbersAssigned); | 261   assert(!SectionNumbersAssigned); | 
| 230   (void)Data; | 262   (void)Data; | 
| 231   llvm_unreachable("TODO"); | 263   llvm_unreachable("TODO"); | 
| 232   StrTab->add(VarName); | 264   StrTab->add(VarName); | 
| 233 } | 265 } | 
| 234 | 266 | 
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 340 | 372 | 
| 341 // Instantiate known needed versions of the template, since we are | 373 // Instantiate known needed versions of the template, since we are | 
| 342 // defining the function in the .cpp file instead of the .h file. | 374 // defining the function in the .cpp file instead of the .h file. | 
| 343 // We may need to instantiate constant pools for integers as well | 375 // We may need to instantiate constant pools for integers as well | 
| 344 // if we do constant-pooling of large integers to remove them | 376 // if we do constant-pooling of large integers to remove them | 
| 345 // from the instruction stream (fewer bytes controlled by an attacker). | 377 // from the instruction stream (fewer bytes controlled by an attacker). | 
| 346 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); | 378 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); | 
| 347 | 379 | 
| 348 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); | 380 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); | 
| 349 | 381 | 
|  | 382 void ELFObjectWriter::writeAllRelocationSections(bool IsELF64) { | 
|  | 383   writeRelocationSections(IsELF64, RelTextSections); | 
|  | 384   writeRelocationSections(IsELF64, RelDataSections); | 
|  | 385   writeRelocationSections(IsELF64, RelRoDataSections); | 
|  | 386 } | 
|  | 387 | 
|  | 388 void ELFObjectWriter::writeRelocationSections(bool IsELF64, | 
|  | 389                                               RelSectionList &RelSections) { | 
|  | 390   for (ELFRelocationSection *RelSec : RelSections) { | 
|  | 391     Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); | 
|  | 392     RelSec->setFileOffset(Offset); | 
|  | 393     RelSec->setSize(RelSec->getSectionDataSize(Ctx, SymTab)); | 
|  | 394     if (IsELF64) { | 
|  | 395       RelSec->writeData<true>(Ctx, Str, SymTab); | 
|  | 396     } else { | 
|  | 397       RelSec->writeData<false>(Ctx, Str, SymTab); | 
|  | 398     } | 
|  | 399   } | 
|  | 400 } | 
|  | 401 | 
| 350 void ELFObjectWriter::writeNonUserSections() { | 402 void ELFObjectWriter::writeNonUserSections() { | 
| 351   bool IsELF64 = isELF64(Ctx.getTargetArch()); | 403   bool IsELF64 = isELF64(Ctx.getTargetArch()); | 
| 352 | 404 | 
| 353   // Write out the shstrtab now that all sections are known. | 405   // Write out the shstrtab now that all sections are known. | 
| 354   ShStrTab->doLayout(); | 406   ShStrTab->doLayout(); | 
| 355   ShStrTab->setSize(ShStrTab->getSectionDataSize()); | 407   ShStrTab->setSize(ShStrTab->getSectionDataSize()); | 
| 356   Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); | 408   Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); | 
| 357   ShStrTab->setFileOffset(ShStrTabOffset); | 409   ShStrTab->setFileOffset(ShStrTabOffset); | 
| 358   Str.writeBytes(ShStrTab->getSectionData()); | 410   Str.writeBytes(ShStrTab->getSectionData()); | 
| 359 | 411 | 
| 360   SectionList AllSections; | 412   SectionList AllSections; | 
| 361   assignSectionNumbersInfo(AllSections); | 413   assignSectionNumbersInfo(AllSections); | 
| 362 | 414 | 
| 363   // Finalize the regular StrTab and fix up references in the SymTab. | 415   // Finalize the regular StrTab and fix up references in the SymTab. | 
| 364   StrTab->doLayout(); | 416   StrTab->doLayout(); | 
| 365   StrTab->setSize(StrTab->getSectionDataSize()); | 417   StrTab->setSize(StrTab->getSectionDataSize()); | 
| 366 | 418 | 
| 367   SymTab->updateIndices(StrTab); | 419   SymTab->updateIndices(StrTab); | 
| 368 | 420 | 
| 369   Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign()); | 421   Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign()); | 
| 370   SymTab->setFileOffset(SymTabOffset); | 422   SymTab->setFileOffset(SymTabOffset); | 
| 371   SymTab->setSize(SymTab->getSectionDataSize()); | 423   SymTab->setSize(SymTab->getSectionDataSize()); | 
| 372   SymTab->writeData(Str, IsELF64); | 424   SymTab->writeData(Str, IsELF64); | 
| 373 | 425 | 
| 374   Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign()); | 426   Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign()); | 
| 375   StrTab->setFileOffset(StrTabOffset); | 427   StrTab->setFileOffset(StrTabOffset); | 
| 376   Str.writeBytes(StrTab->getSectionData()); | 428   Str.writeBytes(StrTab->getSectionData()); | 
| 377 | 429 | 
| 378   // TODO: Write out the relocation sections. | 430   writeAllRelocationSections(IsELF64); | 
| 379   // May also be able to seek around the file and resolve function calls |  | 
| 380   // that are for functions within the same section. |  | 
| 381 | 431 | 
| 382   // Write out the section headers. | 432   // Write out the section headers. | 
| 383   const size_t ShdrAlign = IsELF64 ? 8 : 4; | 433   const size_t ShdrAlign = IsELF64 ? 8 : 4; | 
| 384   Elf64_Off ShOffset = alignFileOffset(ShdrAlign); | 434   Elf64_Off ShOffset = alignFileOffset(ShdrAlign); | 
| 385   for (const auto S : AllSections) { | 435   for (const auto S : AllSections) { | 
| 386     if (IsELF64) | 436     if (IsELF64) | 
| 387       S->writeHeader<true>(Str); | 437       S->writeHeader<true>(Str); | 
| 388     else | 438     else | 
| 389       S->writeHeader<false>(Str); | 439       S->writeHeader<false>(Str); | 
| 390   } | 440   } | 
| 391 | 441 | 
| 392   // Finally write the updated ELF header w/ the correct number of sections. | 442   // Finally write the updated ELF header w/ the correct number of sections. | 
| 393   Str.seek(0); | 443   Str.seek(0); | 
| 394   if (IsELF64) { | 444   if (IsELF64) { | 
| 395     writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 445     writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), | 
| 396                                  AllSections.size()); | 446                                  AllSections.size()); | 
| 397   } else { | 447   } else { | 
| 398     writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 448     writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), | 
| 399                                   AllSections.size()); | 449                                   AllSections.size()); | 
| 400   } | 450   } | 
| 401 } | 451 } | 
| 402 | 452 | 
| 403 } // end of namespace Ice | 453 } // end of namespace Ice | 
| OLD | NEW | 
|---|