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 |