summaryrefslogtreecommitdiff
path: root/include/mcld/LD/ELFObjectWriter.h
blob: ec4311efc4b8689972794714b74e7cba9d49955a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
//===- ELFObjectWriter.h --------------------------------------------------===//
//
//                     The MCLinker Project
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef MCLD_ELF_OBJECT_WRITER_H
#define MCLD_ELF_OBJECT_WRITER_H
#ifdef ENABLE_UNITTEST
#include <gtest.h>
#endif
#include <mcld/LD/ObjectWriter.h>
#include <cassert>

#include <llvm/Support/system_error.h>

namespace mcld {

class Module;
class LinkerConfig;
class GNULDBackend;
class FragmentLinker;
class Relocation;
class LDSection;
class SectionData;
class RelocData;
class Output;
class MemoryRegion;
class MemoryArea;

/** \class ELFObjectWriter
 *  \brief ELFObjectWriter writes the target-independent parts of object files.
 *  ELFObjectWriter reads a MCLDFile and writes into raw_ostream
 *
 */
class ELFObjectWriter : public ObjectWriter
{
public:
  typedef uint64_t FileOffset;

public:
  ELFObjectWriter(GNULDBackend& pBackend,
                  const LinkerConfig& pConfig);

  ~ELFObjectWriter();

  llvm::error_code writeObject(Module& pModule, MemoryArea& pOutput);

private:
  void writeSection(MemoryArea& pOutput, LDSection *section);

  GNULDBackend&       target()        { return m_Backend; }

  const GNULDBackend& target() const  { return m_Backend; }

  // writeELFHeader - emit ElfXX_Ehdr
  template<size_t SIZE>
  void writeELFHeader(const LinkerConfig& pConfig,
                      const Module& pModule,
                      MemoryArea& pOutput) const;

  uint64_t getEntryPoint(const LinkerConfig& pConfig,
                         const Module& pModule) const;

  // emitSectionHeader - emit ElfXX_Shdr
  template<size_t SIZE>
  void emitSectionHeader(const Module& pModule,
                         const LinkerConfig& pConfig,
                         MemoryArea& pOutput) const;

  // emitProgramHeader - emit ElfXX_Phdr
  template<size_t SIZE>
  void emitProgramHeader(MemoryArea& pOutput) const;

  // emitShStrTab - emit .shstrtab
  void emitShStrTab(const LDSection& pShStrTab,
                    const Module& pModule,
                    MemoryArea& pOutput);

  void emitSectionData(const LDSection& pSection,
                       MemoryRegion& pRegion) const;

  void emitRelocation(const LinkerConfig& pConfig,
                      const LDSection& pSection,
                      MemoryRegion& pRegion) const;

  // emitRel - emit ElfXX_Rel
  template<size_t SIZE>
  void emitRel(const LinkerConfig& pConfig,
               const RelocData& pRelocData,
               MemoryRegion& pRegion) const;

  // emitRela - emit ElfXX_Rela
  template<size_t SIZE>
  void emitRela(const LinkerConfig& pConfig,
                const RelocData& pRelocData,
                MemoryRegion& pRegion) const;

  // getSectEntrySize - compute ElfXX_Shdr::sh_entsize
  template<size_t SIZE>
  uint64_t getSectEntrySize(const LDSection& pSection) const;

  // getSectLink - compute ElfXX_Shdr::sh_link
  uint64_t getSectLink(const LDSection& pSection,
                       const LinkerConfig& pConfig) const;

  // getSectInfo - compute ElfXX_Shdr::sh_info
  uint64_t getSectInfo(const LDSection& pSection) const;

  template<size_t SIZE>
  uint64_t getLastStartOffset(const Module& pModule) const
  {
    assert(0 && "Call invalid ELFObjectWriter::getLastStartOffset");
    return 0;
  }

  void emitSectionData(const SectionData& pSD, MemoryRegion& pRegion) const;

private:
  GNULDBackend& m_Backend;

  const LinkerConfig& m_Config;
};

template<>
uint64_t ELFObjectWriter::getLastStartOffset<32>(const Module& pModule) const;

template<>
uint64_t ELFObjectWriter::getLastStartOffset<64>(const Module& pModule) const;

} // namespace of mcld

#endif