1 //===- subzero/src/IceELFObjectWriter.cpp - ELF object file writer --------===// 2 // 3 // The Subzero Code Generator 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 /// 10 /// \file 11 /// \brief Defines the writer for ELF relocatable object files. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "IceELFObjectWriter.h" 16 17 #include "IceAssembler.h" 18 #include "IceDefs.h" 19 #include "IceELFSection.h" 20 #include "IceELFStreamer.h" 21 #include "IceGlobalContext.h" 22 #include "IceGlobalInits.h" 23 #include "IceInst.h" 24 #include "IceOperand.h" 25 26 #include "llvm/Support/ELF.h" 27 #include "llvm/Support/MathExtras.h" 28 29 namespace Ice { 30 31 namespace { 32 33 constexpr struct { 34 bool IsELF64; 35 uint16_t ELFMachine; 36 uint32_t ELFFlags; 37 } ELFTargetInfo[TargetArch_NUM] = { 38 #define X(tag, str, is_elf64, e_machine, e_flags) \ 39 { is_elf64, e_machine, e_flags } \ 40 , 41 TARGETARCH_TABLE 42 #undef X 43 }; 44 45 bool isELF64(const ClFlags &Flags) { 46 const TargetArch Arch = Flags.getTargetArch(); 47 if (Arch >= TargetArch_NUM) { 48 llvm_unreachable("Invalid target arch for isELF64"); 49 return false; 50 } 51 52 if (Flags.getApplicationBinaryInterface() == ABI_PNaCl && 53 !Flags.getUseSandboxing()) { 54 // Unsandboxed PNaCl code is always ELF32 (pexes are ILP32.) 55 return false; 56 } 57 58 return ELFTargetInfo[Arch].IsELF64; 59 } 60 61 uint16_t getELFMachine(TargetArch Arch) { 62 if (Arch < TargetArch_NUM) 63 return ELFTargetInfo[Arch].ELFMachine; 64 llvm_unreachable("Invalid target arch for getELFMachine"); 65 return EM_NONE; 66 } 67 68 uint32_t getELFFlags(TargetArch Arch) { 69 if (Arch < TargetArch_NUM) 70 return ELFTargetInfo[Arch].ELFFlags; 71 llvm_unreachable("Invalid target arch for getELFFlags"); 72 return 0; 73 } 74 75 } // end of anonymous namespace 76 77 ELFObjectWriter::ELFObjectWriter(GlobalContext &Ctx, ELFStreamer &Out) 78 : Ctx(Ctx), Str(Out), ELF64(isELF64(getFlags())) { 79 // Create the special bookkeeping sections now. 80 constexpr char NullSectionName[] = ""; 81 NullSection = new (Ctx.allocate<ELFSection>()) 82 ELFSection(NullSectionName, SHT_NULL, 0, 0, 0); 83 84 constexpr char ShStrTabName[] = ".shstrtab"; 85 ShStrTab = new (Ctx.allocate<ELFStringTableSection>()) 86 ELFStringTableSection(ShStrTabName, SHT_STRTAB, 0, 1, 0); 87 ShStrTab->add(ShStrTabName); 88 89 constexpr char SymTabName[] = ".symtab"; 90 const Elf64_Xword SymTabAlign = ELF64 ? 8 : 4; 91 const Elf64_Xword SymTabEntSize = 92 ELF64 ? sizeof(Elf64_Sym) : sizeof(Elf32_Sym); 93 static_assert(sizeof(Elf64_Sym) == 24 && sizeof(Elf32_Sym) == 16, 94 "Elf_Sym sizes cannot be derived from sizeof"); 95 SymTab = createSection<ELFSymbolTableSection>(SymTabName, SHT_SYMTAB, 0, 96 SymTabAlign, SymTabEntSize); 97 SymTab->createNullSymbol(NullSection, &Ctx); 98 99 constexpr char StrTabName[] = ".strtab"; 100 StrTab = 101 createSection<ELFStringTableSection>(StrTabName, SHT_STRTAB, 0, 1, 0); 102 } 103 104 template <typename T> 105 T *ELFObjectWriter::createSection(const std::string &Name, Elf64_Word ShType, 106 Elf64_Xword ShFlags, Elf64_Xword ShAddralign, 107 Elf64_Xword ShEntsize) { 108 assert(!SectionNumbersAssigned); 109 T *NewSection = 110 new (Ctx.allocate<T>()) T(Name, ShType, ShFlags, ShAddralign, ShEntsize); 111 ShStrTab->add(Name); 112 return NewSection; 113 } 114 115 ELFRelocationSection * 116 ELFObjectWriter::createRelocationSection(const ELFSection *RelatedSection) { 117 // Choice of RELA vs REL is actually separate from elf64 vs elf32, but in 118 // practice we've only had .rela for elf64 (x86-64). In the future, the two 119 // properties may need to be decoupled and the ShEntSize can vary more. 120 const Elf64_Word ShType = ELF64 ? SHT_RELA : SHT_REL; 121 const std::string RelPrefix = ELF64 ? ".rela" : ".rel"; 122 const std::string RelSectionName = RelPrefix + RelatedSection->getName(); 123 const Elf64_Xword ShAlign = ELF64 ? 8 : 4; 124 const Elf64_Xword ShEntSize = ELF64 ? sizeof(Elf64_Rela) : sizeof(Elf32_Rel); 125 static_assert(sizeof(Elf64_Rela) == 24 && sizeof(Elf32_Rel) == 8, 126 "Elf_Rel/Rela sizes cannot be derived from sizeof"); 127 constexpr Elf64_Xword ShFlags = 0; 128 ELFRelocationSection *RelSection = createSection<ELFRelocationSection>( 129 RelSectionName, ShType, ShFlags, ShAlign, ShEntSize); 130 RelSection->setRelatedSection(RelatedSection); 131 return RelSection; 132 } 133 134 template <typename UserSectionList> 135 void ELFObjectWriter::assignRelSectionNumInPairs(SizeT &CurSectionNumber, 136 UserSectionList &UserSections, 137 RelSectionList &RelSections, 138 SectionList &AllSections) { 139 RelSectionList::iterator RelIt = RelSections.begin(); 140 RelSectionList::iterator RelE = RelSections.end(); 141 for (ELFSection *UserSection : UserSections) { 142 UserSection->setNumber(CurSectionNumber++); 143 UserSection->setNameStrIndex(ShStrTab->getIndex(UserSection->getName())); 144 AllSections.push_back(UserSection); 145 if (RelIt != RelE) { 146 ELFRelocationSection *RelSection = *RelIt; 147 if (RelSection->getRelatedSection() == UserSection) { 148 RelSection->setInfoNum(UserSection->getNumber()); 149 RelSection->setNumber(CurSectionNumber++); 150 RelSection->setNameStrIndex(ShStrTab->getIndex(RelSection->getName())); 151 AllSections.push_back(RelSection); 152 ++RelIt; 153 } 154 } 155 } 156 // Should finish with UserIt at the same time as RelIt. 157 assert(RelIt == RelE); 158 return; 159 } 160 161 void ELFObjectWriter::assignRelLinkNum(SizeT SymTabNumber, 162 RelSectionList &RelSections) { 163 for (ELFRelocationSection *S : RelSections) { 164 S->setLinkNum(SymTabNumber); 165 } 166 } 167 168 void ELFObjectWriter::assignSectionNumbersInfo(SectionList &AllSections) { 169 // Go through each section, assigning them section numbers and and fill in 170 // the size for sections that aren't incrementally updated. 171 assert(!SectionNumbersAssigned); 172 SizeT CurSectionNumber = 0; 173 NullSection->setNumber(CurSectionNumber++); 174 // The rest of the fields are initialized to 0, and stay that way. 175 AllSections.push_back(NullSection); 176 177 assignRelSectionNumInPairs<TextSectionList>(CurSectionNumber, TextSections, 178 RelTextSections, AllSections); 179 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, DataSections, 180 RelDataSections, AllSections); 181 for (ELFSection *BSSSection : BSSSections) { 182 BSSSection->setNumber(CurSectionNumber++); 183 BSSSection->setNameStrIndex(ShStrTab->getIndex(BSSSection->getName())); 184 AllSections.push_back(BSSSection); 185 } 186 assignRelSectionNumInPairs<DataSectionList>(CurSectionNumber, RODataSections, 187 RelRODataSections, AllSections); 188 189 ShStrTab->setNumber(CurSectionNumber++); 190 ShStrTab->setNameStrIndex(ShStrTab->getIndex(ShStrTab->getName())); 191 AllSections.push_back(ShStrTab); 192 193 SymTab->setNumber(CurSectionNumber++); 194 SymTab->setNameStrIndex(ShStrTab->getIndex(SymTab->getName())); 195 AllSections.push_back(SymTab); 196 197 StrTab->setNumber(CurSectionNumber++); 198 StrTab->setNameStrIndex(ShStrTab->getIndex(StrTab->getName())); 199 AllSections.push_back(StrTab); 200 201 SymTab->setLinkNum(StrTab->getNumber()); 202 SymTab->setInfoNum(SymTab->getNumLocals()); 203 204 assignRelLinkNum(SymTab->getNumber(), RelTextSections); 205 assignRelLinkNum(SymTab->getNumber(), RelDataSections); 206 assignRelLinkNum(SymTab->getNumber(), RelRODataSections); 207 SectionNumbersAssigned = true; 208 } 209 210 Elf64_Off ELFObjectWriter::alignFileOffset(Elf64_Xword Align) { 211 Elf64_Off OffsetInFile = Str.tell(); 212 Elf64_Xword AlignDiff = Utils::OffsetToAlignment(OffsetInFile, Align); 213 if (AlignDiff == 0) 214 return OffsetInFile; 215 Str.writeZeroPadding(AlignDiff); 216 OffsetInFile += AlignDiff; 217 return OffsetInFile; 218 } 219 220 void ELFObjectWriter::writeFunctionCode(GlobalString FuncName, bool IsInternal, 221 Assembler *Asm) { 222 assert(!SectionNumbersAssigned); 223 TimerMarker T_func(&Ctx, FuncName.toStringOrEmpty()); 224 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 225 ELFTextSection *Section = nullptr; 226 ELFRelocationSection *RelSection = nullptr; 227 const bool FunctionSections = getFlags().getFunctionSections(); 228 if (TextSections.empty() || FunctionSections) { 229 std::string SectionName = ".text"; 230 if (FunctionSections) 231 SectionName += "." + FuncName; 232 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_EXECINSTR; 233 const Elf64_Xword ShAlign = 1 << Asm->getBundleAlignLog2Bytes(); 234 Section = createSection<ELFTextSection>(SectionName, SHT_PROGBITS, ShFlags, 235 ShAlign, 0); 236 Elf64_Off OffsetInFile = alignFileOffset(Section->getSectionAlign()); 237 Section->setFileOffset(OffsetInFile); 238 TextSections.push_back(Section); 239 RelSection = createRelocationSection(Section); 240 RelTextSections.push_back(RelSection); 241 } else { 242 Section = TextSections[0]; 243 RelSection = RelTextSections[0]; 244 } 245 const RelocOffsetT OffsetInSection = Section->getCurrentSize(); 246 // Function symbols are set to 0 size in the symbol table, in contrast to 247 // data symbols which have a proper size. 248 constexpr SizeT SymbolSize = 0; 249 uint8_t SymbolType; 250 uint8_t SymbolBinding; 251 if (IsInternal && !getFlags().getDisableInternal()) { 252 SymbolType = STT_NOTYPE; 253 SymbolBinding = STB_LOCAL; 254 } else { 255 SymbolType = STT_FUNC; 256 SymbolBinding = STB_GLOBAL; 257 } 258 SymTab->createDefinedSym(FuncName, SymbolType, SymbolBinding, Section, 259 OffsetInSection, SymbolSize); 260 StrTab->add(FuncName); 261 262 // Copy the fixup information from per-function Assembler memory to the 263 // object writer's memory, for writing later. 264 const auto &Fixups = Asm->fixups(); 265 if (!Fixups.empty()) { 266 if (!RelSection->isRela()) { 267 // This is a non-rela section, so we need to update the instruction stream 268 // with the relocation addends. 269 for (const auto *Fixup : Fixups) { 270 Fixup->emitOffset(Asm); 271 } 272 } 273 RelSection->addRelocations(OffsetInSection, Asm->fixups(), SymTab); 274 } 275 Section->appendData(Str, Asm->getBufferView()); 276 } 277 278 namespace { 279 280 ELFObjectWriter::SectionType 281 classifyGlobalSection(const VariableDeclaration *Var) { 282 if (Var->getIsConstant()) 283 return ELFObjectWriter::ROData; 284 if (Var->hasNonzeroInitializer()) 285 return ELFObjectWriter::Data; 286 return ELFObjectWriter::BSS; 287 } 288 289 // Partition the Vars list by SectionType into VarsBySection. If TranslateOnly 290 // is non-empty, then only the TranslateOnly variable is kept for emission. 291 void partitionGlobalsBySection(const VariableDeclarationList &Vars, 292 VariableDeclarationPartition VarsBySection[]) { 293 for (VariableDeclaration *Var : Vars) { 294 if (getFlags().matchTranslateOnly(Var->getName(), 0)) { 295 size_t Section = classifyGlobalSection(Var); 296 assert(Section < ELFObjectWriter::NumSectionTypes); 297 VarsBySection[Section].push_back(Var); 298 } 299 } 300 } 301 302 } // end of anonymous namespace 303 304 void ELFObjectWriter::writeTargetRODataSection(const std::string &Name, 305 Elf64_Word ShType, 306 Elf64_Xword ShFlags, 307 Elf64_Xword ShAddralign, 308 Elf64_Xword ShEntsize, 309 const llvm::StringRef &SecData) { 310 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 311 assert(!SectionNumbersAssigned); 312 ELFDataSection *Section = createSection<ELFDataSection>( 313 Name, ShType, ShFlags, ShAddralign, ShEntsize); 314 Section->setFileOffset(alignFileOffset(ShAddralign)); 315 Section->appendData(Str, llvm::StringRef(SecData.data(), SecData.size())); 316 RODataSections.push_back(Section); 317 } 318 319 void ELFObjectWriter::writeDataSection(const VariableDeclarationList &Vars, 320 FixupKind RelocationKind, 321 const std::string &SectionSuffix, 322 bool IsPIC) { 323 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 324 assert(!SectionNumbersAssigned); 325 VariableDeclarationPartition VarsBySection[ELFObjectWriter::NumSectionTypes]; 326 for (auto &SectionList : VarsBySection) 327 SectionList.reserve(Vars.size()); 328 partitionGlobalsBySection(Vars, VarsBySection); 329 size_t I = 0; 330 for (auto &SectionList : VarsBySection) { 331 writeDataOfType(static_cast<SectionType>(I++), SectionList, RelocationKind, 332 SectionSuffix, IsPIC); 333 } 334 } 335 336 namespace { 337 std::string MangleSectionName(const char Base[], const std::string &Suffix) { 338 if (Suffix.empty()) 339 return Base; 340 return Base + ("." + Suffix); 341 } 342 } // end of anonymous namespace 343 344 // TODO(jvoung): Handle fdata-sections. 345 void ELFObjectWriter::writeDataOfType(SectionType ST, 346 const VariableDeclarationPartition &Vars, 347 FixupKind RelocationKind, 348 const std::string &SectionSuffix, 349 bool IsPIC) { 350 if (Vars.empty()) 351 return; 352 ELFDataSection *Section; 353 ELFRelocationSection *RelSection; 354 Elf64_Xword ShAddralign = 1; 355 for (VariableDeclaration *Var : Vars) { 356 Elf64_Xword Align = Var->getAlignment(); 357 ShAddralign = std::max(ShAddralign, Align); 358 } 359 constexpr Elf64_Xword ShEntsize = 0; // non-uniform data element size. 360 // Lift this out, so it can be re-used if we do fdata-sections? 361 switch (ST) { 362 case ROData: { 363 const std::string SectionName = 364 MangleSectionName(IsPIC ? ".data.rel.ro" : ".rodata", SectionSuffix); 365 const Elf64_Xword ShFlags = IsPIC ? (SHF_ALLOC | SHF_WRITE) : SHF_ALLOC; 366 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags, 367 ShAddralign, ShEntsize); 368 Section->setFileOffset(alignFileOffset(ShAddralign)); 369 RODataSections.push_back(Section); 370 RelSection = createRelocationSection(Section); 371 RelRODataSections.push_back(RelSection); 372 break; 373 } 374 case Data: { 375 const std::string SectionName = MangleSectionName(".data", SectionSuffix); 376 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE; 377 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, ShFlags, 378 ShAddralign, ShEntsize); 379 Section->setFileOffset(alignFileOffset(ShAddralign)); 380 DataSections.push_back(Section); 381 RelSection = createRelocationSection(Section); 382 RelDataSections.push_back(RelSection); 383 break; 384 } 385 case BSS: { 386 const std::string SectionName = MangleSectionName(".bss", SectionSuffix); 387 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_WRITE; 388 Section = createSection<ELFDataSection>(SectionName, SHT_NOBITS, ShFlags, 389 ShAddralign, ShEntsize); 390 Section->setFileOffset(alignFileOffset(ShAddralign)); 391 BSSSections.push_back(Section); 392 break; 393 } 394 case NumSectionTypes: 395 llvm::report_fatal_error("Unknown SectionType"); 396 break; 397 } 398 399 constexpr uint8_t SymbolType = STT_OBJECT; 400 for (VariableDeclaration *Var : Vars) { 401 // If the variable declaration does not have an initializer, its symtab 402 // entry will be created separately. 403 if (!Var->hasInitializer()) 404 continue; 405 constexpr Elf64_Xword MinAlign = 1; 406 const auto Align = std::max<Elf64_Xword>(MinAlign, Var->getAlignment()); 407 Section->padToAlignment(Str, Align); 408 SizeT SymbolSize = Var->getNumBytes(); 409 bool IsExternal = Var->isExternal() || getFlags().getDisableInternal(); 410 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; 411 GlobalString Name = Var->getName(); 412 SymTab->createDefinedSym(Name, SymbolType, SymbolBinding, Section, 413 Section->getCurrentSize(), SymbolSize); 414 StrTab->add(Name); 415 if (!Var->hasNonzeroInitializer()) { 416 assert(ST == BSS || ST == ROData); 417 if (ST == ROData) 418 Section->appendZeros(Str, SymbolSize); 419 else 420 Section->setSize(Section->getCurrentSize() + SymbolSize); 421 } else { 422 assert(ST != BSS); 423 for (const auto *Init : Var->getInitializers()) { 424 switch (Init->getKind()) { 425 case VariableDeclaration::Initializer::DataInitializerKind: { 426 const auto &Data = 427 llvm::cast<VariableDeclaration::DataInitializer>(Init) 428 ->getContents(); 429 Section->appendData(Str, llvm::StringRef(Data.data(), Data.size())); 430 break; 431 } 432 case VariableDeclaration::Initializer::ZeroInitializerKind: 433 Section->appendZeros(Str, Init->getNumBytes()); 434 break; 435 case VariableDeclaration::Initializer::RelocInitializerKind: { 436 const auto *Reloc = 437 llvm::cast<VariableDeclaration::RelocInitializer>(Init); 438 AssemblerFixup NewFixup; 439 NewFixup.set_position(Section->getCurrentSize()); 440 NewFixup.set_kind(Reloc->hasFixup() ? Reloc->getFixup() 441 : RelocationKind); 442 assert(NewFixup.kind() != llvm::ELF::R_ARM_NONE); 443 NewFixup.set_value(Ctx.getConstantSym( 444 Reloc->getOffset(), Reloc->getDeclaration()->getName())); 445 RelSection->addRelocation(NewFixup); 446 Section->appendRelocationOffset(Str, RelSection->isRela(), 447 Reloc->getOffset()); 448 break; 449 } 450 } 451 } 452 } 453 } 454 } 455 456 void ELFObjectWriter::writeInitialELFHeader() { 457 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 458 assert(!SectionNumbersAssigned); 459 constexpr Elf64_Off DummySHOffset = 0; 460 constexpr SizeT DummySHStrIndex = 0; 461 constexpr SizeT DummyNumSections = 0; 462 if (ELF64) { 463 writeELFHeaderInternal<true>(DummySHOffset, DummySHStrIndex, 464 DummyNumSections); 465 } else { 466 writeELFHeaderInternal<false>(DummySHOffset, DummySHStrIndex, 467 DummyNumSections); 468 } 469 } 470 471 template <bool IsELF64> 472 void ELFObjectWriter::writeELFHeaderInternal(Elf64_Off SectionHeaderOffset, 473 SizeT SectHeaderStrIndex, 474 SizeT NumSections) { 475 // Write the e_ident: magic number, class, etc. The e_ident is byte order and 476 // ELF class independent. 477 Str.writeBytes(llvm::StringRef(ElfMagic, strlen(ElfMagic))); 478 Str.write8(IsELF64 ? ELFCLASS64 : ELFCLASS32); 479 Str.write8(ELFDATA2LSB); 480 Str.write8(EV_CURRENT); 481 Str.write8(ELFOSABI_NONE); 482 constexpr uint8_t ELF_ABIVersion = 0; 483 Str.write8(ELF_ABIVersion); 484 Str.writeZeroPadding(EI_NIDENT - EI_PAD); 485 486 // TODO(jvoung): Handle and test > 64K sections. See the generic ABI doc: 487 // https://refspecs.linuxbase.org/elf/gabi4+/ch4.eheader.html e_shnum should 488 // be 0 and then actual number of sections is stored in the sh_size member of 489 // the 0th section. 490 assert(NumSections < SHN_LORESERVE); 491 assert(SectHeaderStrIndex < SHN_LORESERVE); 492 493 const TargetArch Arch = getFlags().getTargetArch(); 494 // Write the rest of the file header, which does depend on byte order and ELF 495 // class. 496 Str.writeLE16(ET_REL); // e_type 497 Str.writeLE16(getELFMachine(getFlags().getTargetArch())); // e_machine 498 Str.writeELFWord<IsELF64>(1); // e_version 499 // Since this is for a relocatable object, there is no entry point, and no 500 // program headers. 501 Str.writeAddrOrOffset<IsELF64>(0); // e_entry 502 Str.writeAddrOrOffset<IsELF64>(0); // e_phoff 503 Str.writeAddrOrOffset<IsELF64>(SectionHeaderOffset); // e_shoff 504 Str.writeELFWord<IsELF64>(getELFFlags(Arch)); // e_flags 505 Str.writeLE16(IsELF64 ? sizeof(Elf64_Ehdr) : sizeof(Elf32_Ehdr)); // e_ehsize 506 static_assert(sizeof(Elf64_Ehdr) == 64 && sizeof(Elf32_Ehdr) == 52, 507 "Elf_Ehdr sizes cannot be derived from sizeof"); 508 Str.writeLE16(0); // e_phentsize 509 Str.writeLE16(0); // e_phnum 510 Str.writeLE16(IsELF64 ? sizeof(Elf64_Shdr) 511 : sizeof(Elf32_Shdr)); // e_shentsize 512 static_assert(sizeof(Elf64_Shdr) == 64 && sizeof(Elf32_Shdr) == 40, 513 "Elf_Shdr sizes cannot be derived from sizeof"); 514 Str.writeLE16(static_cast<Elf64_Half>(NumSections)); // e_shnum 515 Str.writeLE16(static_cast<Elf64_Half>(SectHeaderStrIndex)); // e_shstrndx 516 } 517 518 template <typename ConstType> void ELFObjectWriter::writeConstantPool(Type Ty) { 519 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 520 ConstantList Pool = Ctx.getConstantPool(Ty); 521 if (Pool.empty()) { 522 return; 523 } 524 SizeT Align = typeAlignInBytes(Ty); 525 size_t EntSize = typeWidthInBytes(Ty); 526 char Buf[20]; 527 SizeT WriteAmt = std::min(EntSize, llvm::array_lengthof(Buf)); 528 // Check that we write the full PrimType. 529 assert(WriteAmt == EntSize); 530 // Assume that writing WriteAmt bytes at a time allows us to avoid aligning 531 // between entries. 532 assert(WriteAmt % Align == 0); 533 constexpr Elf64_Xword ShFlags = SHF_ALLOC | SHF_MERGE; 534 std::string SecBuffer; 535 llvm::raw_string_ostream SecStrBuf(SecBuffer); 536 SecStrBuf << ".rodata.cst" << WriteAmt; 537 ELFDataSection *Section = createSection<ELFDataSection>( 538 SecStrBuf.str(), SHT_PROGBITS, ShFlags, Align, WriteAmt); 539 RODataSections.push_back(Section); 540 SizeT OffsetInSection = 0; 541 // The symbol table entry doesn't need to know the defined symbol's size 542 // since this is in a section with a fixed Entry Size. 543 constexpr SizeT SymbolSize = 0; 544 Section->setFileOffset(alignFileOffset(Align)); 545 546 // If the -reorder-pooled-constant option is set to true, we should shuffle 547 // the constants before we emit them. 548 if (getFlags().getReorderPooledConstants() && !Pool.empty()) { 549 // Use the constant's kind value as the salt for creating random number 550 // generator. 551 Operand::OperandKind K = (*Pool.begin())->getKind(); 552 RandomNumberGenerator RNG(getFlags().getRandomSeed(), 553 RPE_PooledConstantReordering, K); 554 RandomShuffle(Pool.begin(), Pool.end(), 555 [&RNG](uint64_t N) { return (uint32_t)RNG.next(N); }); 556 } 557 // Write the data. 558 for (Constant *C : Pool) { 559 if (!C->getShouldBePooled()) 560 continue; 561 auto *Const = llvm::cast<ConstType>(C); 562 GlobalString SymName = Const->getLabelName(); 563 SymTab->createDefinedSym(SymName, STT_NOTYPE, STB_LOCAL, Section, 564 OffsetInSection, SymbolSize); 565 StrTab->add(SymName); 566 typename ConstType::PrimType Value = Const->getValue(); 567 memcpy(Buf, &Value, WriteAmt); 568 Str.writeBytes(llvm::StringRef(Buf, WriteAmt)); 569 OffsetInSection += WriteAmt; 570 } 571 Section->setSize(OffsetInSection); 572 } 573 574 // Instantiate known needed versions of the template, since we are defining the 575 // function in the .cpp file instead of the .h file. We may need to instantiate 576 // constant pools for integers as well if we do constant-pooling of large 577 // integers to remove them from the instruction stream (fewer bytes controlled 578 // by an attacker). 579 template void ELFObjectWriter::writeConstantPool<ConstantFloat>(Type Ty); 580 581 template void ELFObjectWriter::writeConstantPool<ConstantDouble>(Type Ty); 582 583 template void ELFObjectWriter::writeConstantPool<ConstantInteger32>(Type Ty); 584 585 void ELFObjectWriter::writeAllRelocationSections() { 586 writeRelocationSections(RelTextSections); 587 writeRelocationSections(RelDataSections); 588 writeRelocationSections(RelRODataSections); 589 } 590 591 void ELFObjectWriter::writeJumpTable(const JumpTableData &JT, 592 FixupKind RelocationKind, bool IsPIC) { 593 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 594 ELFDataSection *Section; 595 ELFRelocationSection *RelSection; 596 const Elf64_Xword PointerSize = typeWidthInBytes(getPointerType()); 597 const Elf64_Xword ShAddralign = PointerSize; 598 const Elf64_Xword ShEntsize = PointerSize; 599 const std::string SectionName = MangleSectionName( 600 IsPIC ? ".data.rel.ro" : ".rodata", JT.getSectionName()); 601 Section = createSection<ELFDataSection>(SectionName, SHT_PROGBITS, SHF_ALLOC, 602 ShAddralign, ShEntsize); 603 Section->setFileOffset(alignFileOffset(ShAddralign)); 604 RODataSections.push_back(Section); 605 RelSection = createRelocationSection(Section); 606 RelRODataSections.push_back(RelSection); 607 608 constexpr uint8_t SymbolType = STT_OBJECT; 609 Section->padToAlignment(Str, PointerSize); 610 const bool IsExternal = getFlags().getDisableInternal(); 611 const uint8_t SymbolBinding = IsExternal ? STB_GLOBAL : STB_LOCAL; 612 const auto JumpTableName = JT.getName(); 613 SymTab->createDefinedSym(JumpTableName, SymbolType, SymbolBinding, Section, 614 Section->getCurrentSize(), PointerSize); 615 StrTab->add(JumpTableName); 616 617 for (intptr_t TargetOffset : JT.getTargetOffsets()) { 618 AssemblerFixup NewFixup; 619 NewFixup.set_position(Section->getCurrentSize()); 620 NewFixup.set_kind(RelocationKind); 621 NewFixup.set_value(Ctx.getConstantSym(TargetOffset, JT.getFunctionName())); 622 RelSection->addRelocation(NewFixup); 623 Section->appendRelocationOffset(Str, RelSection->isRela(), TargetOffset); 624 } 625 } 626 627 void ELFObjectWriter::setUndefinedSyms(const ConstantList &UndefSyms) { 628 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 629 for (const Constant *S : UndefSyms) { 630 const auto *Sym = llvm::cast<ConstantRelocatable>(S); 631 GlobalString Name = Sym->getName(); 632 assert(Name.hasStdString()); 633 bool BadIntrinsic; 634 const Intrinsics::FullIntrinsicInfo *Info = 635 Ctx.getIntrinsicsInfo().find(Name, BadIntrinsic); 636 if (Info) 637 continue; 638 // Ignore BadIntrinsic, which is set if the name begins with "llvm." but 639 // doesn't match a known intrinsic. If we want this to turn into an error, 640 // we should catch it early on. 641 assert(Sym->getOffset() == 0); 642 SymTab->noteUndefinedSym(Name, NullSection); 643 StrTab->add(Name); 644 } 645 } 646 647 void ELFObjectWriter::writeRelocationSections(RelSectionList &RelSections) { 648 for (ELFRelocationSection *RelSec : RelSections) { 649 Elf64_Off Offset = alignFileOffset(RelSec->getSectionAlign()); 650 RelSec->setFileOffset(Offset); 651 RelSec->setSize(RelSec->getSectionDataSize()); 652 if (ELF64) { 653 RelSec->writeData<true>(Str, SymTab); 654 } else { 655 RelSec->writeData<false>(Str, SymTab); 656 } 657 } 658 } 659 660 void ELFObjectWriter::writeNonUserSections() { 661 TimerMarker Timer(TimerStack::TT_writeELF, &Ctx); 662 663 // Write out the shstrtab now that all sections are known. 664 ShStrTab->doLayout(); 665 ShStrTab->setSize(ShStrTab->getSectionDataSize()); 666 Elf64_Off ShStrTabOffset = alignFileOffset(ShStrTab->getSectionAlign()); 667 ShStrTab->setFileOffset(ShStrTabOffset); 668 Str.writeBytes(ShStrTab->getSectionData()); 669 670 SectionList AllSections; 671 assignSectionNumbersInfo(AllSections); 672 673 // Finalize the regular StrTab and fix up references in the SymTab. 674 StrTab->doLayout(); 675 StrTab->setSize(StrTab->getSectionDataSize()); 676 677 SymTab->updateIndices(StrTab); 678 679 Elf64_Off SymTabOffset = alignFileOffset(SymTab->getSectionAlign()); 680 SymTab->setFileOffset(SymTabOffset); 681 SymTab->setSize(SymTab->getSectionDataSize()); 682 SymTab->writeData(Str, ELF64); 683 684 Elf64_Off StrTabOffset = alignFileOffset(StrTab->getSectionAlign()); 685 StrTab->setFileOffset(StrTabOffset); 686 Str.writeBytes(StrTab->getSectionData()); 687 688 writeAllRelocationSections(); 689 690 // Write out the section headers. 691 const size_t ShdrAlign = ELF64 ? 8 : 4; 692 Elf64_Off ShOffset = alignFileOffset(ShdrAlign); 693 for (const auto S : AllSections) { 694 if (ELF64) 695 S->writeHeader<true>(Str); 696 else 697 S->writeHeader<false>(Str); 698 } 699 700 // Finally write the updated ELF header w/ the correct number of sections. 701 Str.seek(0); 702 if (ELF64) { 703 writeELFHeaderInternal<true>(ShOffset, ShStrTab->getNumber(), 704 AllSections.size()); 705 } else { 706 writeELFHeaderInternal<false>(ShOffset, ShStrTab->getNumber(), 707 AllSections.size()); 708 } 709 } 710 711 } // end of namespace Ice 712