1 //===- lib/MC/ELFObjectWriter.h - ELF File Writer -------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements ELF object file writer information. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_MC_ELFOBJECTWRITER_H 15 #define LLVM_MC_ELFOBJECTWRITER_H 16 17 #include "MCELF.h" 18 #include "llvm/ADT/OwningPtr.h" 19 #include "llvm/ADT/SmallPtrSet.h" 20 #include "llvm/ADT/SmallString.h" 21 #include "llvm/ADT/STLExtras.h" 22 #include "llvm/MC/MCAssembler.h" 23 #include "llvm/MC/MCELFObjectWriter.h" 24 #include "llvm/MC/MCELFSymbolFlags.h" 25 #include "llvm/MC/MCObjectWriter.h" 26 #include "llvm/MC/MCExpr.h" 27 #include "llvm/MC/MCSymbol.h" 28 29 #include <vector> 30 31 namespace llvm { 32 33 class MCSection; 34 class MCDataFragment; 35 class MCSectionELF; 36 37 class ELFObjectWriter : public MCObjectWriter { 38 protected: 39 40 static bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind); 41 static bool RelocNeedsGOT(MCSymbolRefExpr::VariantKind Variant); 42 static uint64_t SymbolValue(MCSymbolData &Data, const MCAsmLayout &Layout); 43 static bool isInSymtab(const MCAssembler &Asm, const MCSymbolData &Data, 44 bool Used, bool Renamed); 45 static bool isLocal(const MCSymbolData &Data, bool isSignature, 46 bool isUsedInReloc); 47 static bool IsELFMetaDataSection(const MCSectionData &SD); 48 static uint64_t DataSectionSize(const MCSectionData &SD); 49 static uint64_t GetSectionFileSize(const MCAsmLayout &Layout, 50 const MCSectionData &SD); 51 static uint64_t GetSectionAddressSize(const MCAsmLayout &Layout, 52 const MCSectionData &SD); 53 54 void WriteDataSectionData(MCAssembler &Asm, 55 const MCAsmLayout &Layout, 56 const MCSectionELF &Section); 57 58 /*static bool isFixupKindX86RIPRel(unsigned Kind) { 59 return Kind == X86::reloc_riprel_4byte || 60 Kind == X86::reloc_riprel_4byte_movq_load; 61 }*/ 62 63 /// ELFSymbolData - Helper struct for containing some precomputed 64 /// information on symbols. 65 struct ELFSymbolData { 66 MCSymbolData *SymbolData; 67 uint64_t StringIndex; 68 uint32_t SectionIndex; 69 70 // Support lexicographic sorting. 71 bool operator<(const ELFSymbolData &RHS) const { 72 if (MCELF::GetType(*SymbolData) == ELF::STT_FILE) 73 return true; 74 if (MCELF::GetType(*RHS.SymbolData) == ELF::STT_FILE) 75 return false; 76 return SymbolData->getSymbol().getName() < 77 RHS.SymbolData->getSymbol().getName(); 78 } 79 }; 80 81 /// @name Relocation Data 82 /// @{ 83 84 struct ELFRelocationEntry { 85 // Make these big enough for both 32-bit and 64-bit 86 uint64_t r_offset; 87 int Index; 88 unsigned Type; 89 const MCSymbol *Symbol; 90 uint64_t r_addend; 91 ELFRelocationEntryELFRelocationEntry92 ELFRelocationEntry() 93 : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {} 94 ELFRelocationEntryELFRelocationEntry95 ELFRelocationEntry(uint64_t RelocOffset, int Idx, 96 unsigned RelType, const MCSymbol *Sym, 97 uint64_t Addend) 98 : r_offset(RelocOffset), Index(Idx), Type(RelType), 99 Symbol(Sym), r_addend(Addend) {} 100 101 // Support lexicographic sorting. 102 bool operator<(const ELFRelocationEntry &RE) const { 103 return RE.r_offset < r_offset; 104 } 105 }; 106 107 /// The target specific ELF writer instance. 108 llvm::OwningPtr<MCELFObjectTargetWriter> TargetObjectWriter; 109 110 SmallPtrSet<const MCSymbol *, 16> UsedInReloc; 111 SmallPtrSet<const MCSymbol *, 16> WeakrefUsedInReloc; 112 DenseMap<const MCSymbol *, const MCSymbol *> Renames; 113 114 llvm::DenseMap<const MCSectionData*, 115 std::vector<ELFRelocationEntry> > Relocations; 116 DenseMap<const MCSection*, uint64_t> SectionStringTableIndex; 117 118 /// @} 119 /// @name Symbol Table Data 120 /// @{ 121 122 SmallString<256> StringTable; 123 std::vector<ELFSymbolData> LocalSymbolData; 124 std::vector<ELFSymbolData> ExternalSymbolData; 125 std::vector<ELFSymbolData> UndefinedSymbolData; 126 127 /// @} 128 129 bool NeedsGOT; 130 131 bool NeedsSymtabShndx; 132 133 // This holds the symbol table index of the last local symbol. 134 unsigned LastLocalSymbolIndex; 135 // This holds the .strtab section index. 136 unsigned StringTableIndex; 137 // This holds the .symtab section index. 138 unsigned SymbolTableIndex; 139 140 unsigned ShstrtabIndex; 141 142 143 virtual const MCSymbol *SymbolToReloc(const MCAssembler &Asm, 144 const MCValue &Target, 145 const MCFragment &F, 146 const MCFixup &Fixup, 147 bool IsPCRel) const; 148 149 // For arch-specific emission of explicit reloc symbol ExplicitRelSym(const MCAssembler & Asm,const MCValue & Target,const MCFragment & F,const MCFixup & Fixup,bool IsPCRel)150 virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 151 const MCValue &Target, 152 const MCFragment &F, 153 const MCFixup &Fixup, 154 bool IsPCRel) const { 155 return NULL; 156 } 157 is64Bit()158 bool is64Bit() const { return TargetObjectWriter->is64Bit(); } hasRelocationAddend()159 bool hasRelocationAddend() const { 160 return TargetObjectWriter->hasRelocationAddend(); 161 } 162 163 public: ELFObjectWriter(MCELFObjectTargetWriter * MOTW,raw_ostream & _OS,bool IsLittleEndian)164 ELFObjectWriter(MCELFObjectTargetWriter *MOTW, 165 raw_ostream &_OS, bool IsLittleEndian) 166 : MCObjectWriter(_OS, IsLittleEndian), 167 TargetObjectWriter(MOTW), 168 NeedsGOT(false), NeedsSymtabShndx(false){ 169 } 170 171 virtual ~ELFObjectWriter(); 172 WriteWord(uint64_t W)173 void WriteWord(uint64_t W) { 174 if (is64Bit()) 175 Write64(W); 176 else 177 Write32(W); 178 } 179 StringLE16(char * buf,uint16_t Value)180 void StringLE16(char *buf, uint16_t Value) { 181 buf[0] = char(Value >> 0); 182 buf[1] = char(Value >> 8); 183 } 184 StringLE32(char * buf,uint32_t Value)185 void StringLE32(char *buf, uint32_t Value) { 186 StringLE16(buf, uint16_t(Value >> 0)); 187 StringLE16(buf + 2, uint16_t(Value >> 16)); 188 } 189 StringLE64(char * buf,uint64_t Value)190 void StringLE64(char *buf, uint64_t Value) { 191 StringLE32(buf, uint32_t(Value >> 0)); 192 StringLE32(buf + 4, uint32_t(Value >> 32)); 193 } 194 StringBE16(char * buf,uint16_t Value)195 void StringBE16(char *buf ,uint16_t Value) { 196 buf[0] = char(Value >> 8); 197 buf[1] = char(Value >> 0); 198 } 199 StringBE32(char * buf,uint32_t Value)200 void StringBE32(char *buf, uint32_t Value) { 201 StringBE16(buf, uint16_t(Value >> 16)); 202 StringBE16(buf + 2, uint16_t(Value >> 0)); 203 } 204 StringBE64(char * buf,uint64_t Value)205 void StringBE64(char *buf, uint64_t Value) { 206 StringBE32(buf, uint32_t(Value >> 32)); 207 StringBE32(buf + 4, uint32_t(Value >> 0)); 208 } 209 String8(MCDataFragment & F,uint8_t Value)210 void String8(MCDataFragment &F, uint8_t Value) { 211 char buf[1]; 212 buf[0] = Value; 213 F.getContents() += StringRef(buf, 1); 214 } 215 String16(MCDataFragment & F,uint16_t Value)216 void String16(MCDataFragment &F, uint16_t Value) { 217 char buf[2]; 218 if (isLittleEndian()) 219 StringLE16(buf, Value); 220 else 221 StringBE16(buf, Value); 222 F.getContents() += StringRef(buf, 2); 223 } 224 String32(MCDataFragment & F,uint32_t Value)225 void String32(MCDataFragment &F, uint32_t Value) { 226 char buf[4]; 227 if (isLittleEndian()) 228 StringLE32(buf, Value); 229 else 230 StringBE32(buf, Value); 231 F.getContents() += StringRef(buf, 4); 232 } 233 String64(MCDataFragment & F,uint64_t Value)234 void String64(MCDataFragment &F, uint64_t Value) { 235 char buf[8]; 236 if (isLittleEndian()) 237 StringLE64(buf, Value); 238 else 239 StringBE64(buf, Value); 240 F.getContents() += StringRef(buf, 8); 241 } 242 243 virtual void WriteHeader(uint64_t SectionDataSize, unsigned NumberOfSections); 244 245 /// Default e_flags = 0 WriteEFlags()246 virtual void WriteEFlags() { Write32(0); } 247 248 virtual void WriteSymbolEntry(MCDataFragment *SymtabF, MCDataFragment *ShndxF, 249 uint64_t name, uint8_t info, 250 uint64_t value, uint64_t size, 251 uint8_t other, uint32_t shndx, 252 bool Reserved); 253 254 virtual void WriteSymbol(MCDataFragment *SymtabF, MCDataFragment *ShndxF, 255 ELFSymbolData &MSD, 256 const MCAsmLayout &Layout); 257 258 typedef DenseMap<const MCSectionELF*, uint32_t> SectionIndexMapTy; 259 virtual void WriteSymbolTable(MCDataFragment *SymtabF, MCDataFragment *ShndxF, 260 const MCAssembler &Asm, 261 const MCAsmLayout &Layout, 262 const SectionIndexMapTy &SectionIndexMap); 263 264 virtual void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout, 265 const MCFragment *Fragment, const MCFixup &Fixup, 266 MCValue Target, uint64_t &FixedValue); 267 268 virtual uint64_t getSymbolIndexInSymbolTable(const MCAssembler &Asm, 269 const MCSymbol *S); 270 271 // Map from a group section to the signature symbol 272 typedef DenseMap<const MCSectionELF*, const MCSymbol*> GroupMapTy; 273 // Map from a signature symbol to the group section 274 typedef DenseMap<const MCSymbol*, const MCSectionELF*> RevGroupMapTy; 275 // Map from a section to the section with the relocations 276 typedef DenseMap<const MCSectionELF*, const MCSectionELF*> RelMapTy; 277 // Map from a section to its offset 278 typedef DenseMap<const MCSectionELF*, uint64_t> SectionOffsetMapTy; 279 280 /// ComputeSymbolTable - Compute the symbol table data 281 /// 282 /// \param StringTable [out] - The string table data. 283 /// \param StringIndexMap [out] - Map from symbol names to offsets in the 284 /// string table. 285 virtual void ComputeSymbolTable(MCAssembler &Asm, 286 const SectionIndexMapTy &SectionIndexMap, 287 RevGroupMapTy RevGroupMap, 288 unsigned NumRegularSections); 289 290 virtual void ComputeIndexMap(MCAssembler &Asm, 291 SectionIndexMapTy &SectionIndexMap, 292 const RelMapTy &RelMap); 293 294 void CreateRelocationSections(MCAssembler &Asm, MCAsmLayout &Layout, 295 RelMapTy &RelMap); 296 297 void WriteRelocations(MCAssembler &Asm, MCAsmLayout &Layout, 298 const RelMapTy &RelMap); 299 300 virtual void CreateMetadataSections(MCAssembler &Asm, MCAsmLayout &Layout, 301 SectionIndexMapTy &SectionIndexMap, 302 const RelMapTy &RelMap); 303 304 // Create the sections that show up in the symbol table. Currently 305 // those are the .note.GNU-stack section and the group sections. 306 virtual void CreateIndexedSections(MCAssembler &Asm, MCAsmLayout &Layout, 307 GroupMapTy &GroupMap, 308 RevGroupMapTy &RevGroupMap, 309 SectionIndexMapTy &SectionIndexMap, 310 const RelMapTy &RelMap); 311 312 virtual void ExecutePostLayoutBinding(MCAssembler &Asm, 313 const MCAsmLayout &Layout); 314 315 void WriteSectionHeader(MCAssembler &Asm, const GroupMapTy &GroupMap, 316 const MCAsmLayout &Layout, 317 const SectionIndexMapTy &SectionIndexMap, 318 const SectionOffsetMapTy &SectionOffsetMap); 319 320 void ComputeSectionOrder(MCAssembler &Asm, 321 std::vector<const MCSectionELF*> &Sections); 322 323 virtual void WriteSecHdrEntry(uint32_t Name, uint32_t Type, uint64_t Flags, 324 uint64_t Address, uint64_t Offset, 325 uint64_t Size, uint32_t Link, uint32_t Info, 326 uint64_t Alignment, uint64_t EntrySize); 327 328 virtual void WriteRelocationsFragment(const MCAssembler &Asm, 329 MCDataFragment *F, 330 const MCSectionData *SD); 331 332 virtual bool 333 IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm, 334 const MCSymbolData &DataA, 335 const MCFragment &FB, 336 bool InSet, 337 bool IsPCRel) const; 338 339 virtual void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout); 340 virtual void WriteSection(MCAssembler &Asm, 341 const SectionIndexMapTy &SectionIndexMap, 342 uint32_t GroupSymbolIndex, 343 uint64_t Offset, uint64_t Size, uint64_t Alignment, 344 const MCSectionELF &Section); 345 346 protected: 347 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 348 bool IsPCRel, bool IsRelocWithSymbol, 349 int64_t Addend) = 0; adjustFixupOffset(const MCFixup & Fixup,uint64_t & RelocOffset)350 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset) { } 351 }; 352 353 //===- X86ELFObjectWriter -------------------------------------------===// 354 355 class X86ELFObjectWriter : public ELFObjectWriter { 356 public: 357 X86ELFObjectWriter(MCELFObjectTargetWriter *MOTW, 358 raw_ostream &_OS, 359 bool IsLittleEndian); 360 361 virtual ~X86ELFObjectWriter(); 362 protected: 363 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 364 bool IsPCRel, bool IsRelocWithSymbol, 365 int64_t Addend); 366 }; 367 368 369 //===- ARMELFObjectWriter -------------------------------------------===// 370 371 class ARMELFObjectWriter : public ELFObjectWriter { 372 public: 373 // FIXME: MCAssembler can't yet return the Subtarget, 374 enum { DefaultEABIVersion = 0x05000000U }; 375 376 ARMELFObjectWriter(MCELFObjectTargetWriter *MOTW, 377 raw_ostream &_OS, 378 bool IsLittleEndian); 379 380 virtual ~ARMELFObjectWriter(); 381 382 virtual void WriteEFlags(); 383 protected: 384 virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, 385 const MCValue &Target, 386 const MCFragment &F, 387 const MCFixup &Fixup, 388 bool IsPCRel) const; 389 390 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 391 bool IsPCRel, bool IsRelocWithSymbol, 392 int64_t Addend); 393 private: 394 unsigned GetRelocTypeInner(const MCValue &Target, 395 const MCFixup &Fixup, bool IsPCRel) const; 396 397 }; 398 399 //===- PPCELFObjectWriter -------------------------------------------===// 400 401 class PPCELFObjectWriter : public ELFObjectWriter { 402 public: 403 PPCELFObjectWriter(MCELFObjectTargetWriter *MOTW, 404 raw_ostream &_OS, 405 bool IsLittleEndian); 406 407 virtual ~PPCELFObjectWriter(); 408 protected: 409 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 410 bool IsPCRel, bool IsRelocWithSymbol, 411 int64_t Addend); 412 virtual void adjustFixupOffset(const MCFixup &Fixup, uint64_t &RelocOffset); 413 }; 414 415 //===- MBlazeELFObjectWriter -------------------------------------------===// 416 417 class MBlazeELFObjectWriter : public ELFObjectWriter { 418 public: 419 MBlazeELFObjectWriter(MCELFObjectTargetWriter *MOTW, 420 raw_ostream &_OS, 421 bool IsLittleEndian); 422 423 virtual ~MBlazeELFObjectWriter(); 424 protected: 425 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 426 bool IsPCRel, bool IsRelocWithSymbol, 427 int64_t Addend); 428 }; 429 430 //===- MipsELFObjectWriter -------------------------------------------===// 431 432 class MipsELFObjectWriter : public ELFObjectWriter { 433 public: 434 MipsELFObjectWriter(MCELFObjectTargetWriter *MOTW, 435 raw_ostream &_OS, 436 bool IsLittleEndian); 437 438 virtual ~MipsELFObjectWriter(); 439 protected: 440 virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, 441 bool IsPCRel, bool IsRelocWithSymbol, 442 int64_t Addend); 443 }; 444 } 445 446 #endif 447