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
31namespace llvm {
32
33class MCSection;
34class MCDataFragment;
35class MCSectionELF;
36
37class 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
92      ELFRelocationEntry()
93        : r_offset(0), Index(0), Type(0), Symbol(0), r_addend(0) {}
94
95      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
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
158    bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
159    bool hasRelocationAddend() const {
160      return TargetObjectWriter->hasRelocationAddend();
161    }
162
163  public:
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
173    void WriteWord(uint64_t W) {
174      if (is64Bit())
175        Write64(W);
176      else
177        Write32(W);
178    }
179
180    void StringLE16(char *buf, uint16_t Value) {
181      buf[0] = char(Value >> 0);
182      buf[1] = char(Value >> 8);
183    }
184
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
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
195    void StringBE16(char *buf ,uint16_t Value) {
196      buf[0] = char(Value >> 8);
197      buf[1] = char(Value >> 0);
198    }
199
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
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
210    void String8(MCDataFragment &F, uint8_t Value) {
211      char buf[1];
212      buf[0] = Value;
213      F.getContents() += StringRef(buf, 1);
214    }
215
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
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
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
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;
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