summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/HeaderChunks.h
blob: 51fbe38f1a0081864bf21388151905ac58834cf9 (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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
//===- lib/ReaderWriter/ELF/HeaderChunks.h --------------------------------===//
//
//                             The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef LLD_READER_WRITER_ELF_HEADER_CHUNKS_H
#define LLD_READER_WRITER_ELF_HEADER_CHUNKS_H

#include "SegmentChunks.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Object/ELF.h"
#include "llvm/Support/Allocator.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"

/// \brief An Header represents the Elf[32/64]_Ehdr structure at the
///        start of an ELF executable file.
namespace lld {
namespace elf {

template <class ELFT> class ELFHeader : public Chunk<ELFT> {
public:
  typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;

  ELFHeader(const ELFLinkingContext &);

  void e_ident(int I, unsigned char C) { _eh.e_ident[I] = C; }
  void e_type(uint16_t type)           { _eh.e_type = type; }
  void e_machine(uint16_t machine)     { _eh.e_machine = machine; }
  void e_version(uint32_t version)     { _eh.e_version = version; }
  void e_entry(int64_t entry)          { _eh.e_entry = entry; }
  void e_phoff(int64_t phoff)          { _eh.e_phoff = phoff; }
  void e_shoff(int64_t shoff)          { _eh.e_shoff = shoff; }
  void e_flags(uint32_t flags)         { _eh.e_flags = flags; }
  void e_ehsize(uint16_t ehsize)       { _eh.e_ehsize = ehsize; }
  void e_phentsize(uint16_t phentsize) { _eh.e_phentsize = phentsize; }
  void e_phnum(uint16_t phnum)         { _eh.e_phnum = phnum; }
  void e_shentsize(uint16_t shentsize) { _eh.e_shentsize = shentsize; }
  void e_shnum(uint16_t shnum)         { _eh.e_shnum = shnum; }
  void e_shstrndx(uint16_t shstrndx)   { _eh.e_shstrndx = shstrndx; }
  uint64_t fileSize() const override { return sizeof(Elf_Ehdr); }

  static bool classof(const Chunk<ELFT> *c) {
    return c->kind() == Chunk<ELFT>::Kind::ELFHeader;
  }

  int getContentType() const override {
    return Chunk<ELFT>::ContentType::Header;
  }

  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
             llvm::FileOutputBuffer &buffer) override;

  void finalize() override;

private:
  Elf_Ehdr _eh;
};

/// \brief An ProgramHeader represents the Elf[32/64]_Phdr structure at the
///        start of an ELF executable file.
template<class ELFT>
class ProgramHeader : public Chunk<ELFT> {
public:
  typedef llvm::object::Elf_Phdr_Impl<ELFT> Elf_Phdr;
  typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
  typedef typename std::reverse_iterator<PhIterT> ReversePhIterT;

  ProgramHeader(const ELFLinkingContext &ctx)
      : Chunk<ELFT>("elfphdr", Chunk<ELFT>::Kind::ProgramHeader, ctx) {
    this->_alignment = ELFT::Is64Bits ? 8 : 4;
    resetProgramHeaders();
  }

  bool addSegment(Segment<ELFT> *segment);
  void resetProgramHeaders() { _phi = _ph.begin(); }
  uint64_t fileSize() const override { return sizeof(Elf_Phdr) * _ph.size(); }

  static bool classof(const Chunk<ELFT> *c) {
    return c->kind() == Chunk<ELFT>::Kind::ProgramHeader;
  }

  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
             llvm::FileOutputBuffer &buffer) override;

  PhIterT begin() { return _ph.begin(); }
  PhIterT end() { return _ph.end(); }
  ReversePhIterT rbegin() { return _ph.rbegin(); }
  ReversePhIterT rend() { return _ph.rend(); }

  int64_t entsize() { return sizeof(Elf_Phdr); }
  int64_t numHeaders() { return _ph.size();  }

  int getContentType() const override {
    return Chunk<ELFT>::ContentType::Header;
  }

private:
  Elf_Phdr *allocateProgramHeader(bool &allocatedNew);

  std::vector<Elf_Phdr *> _ph;
  PhIterT _phi;
  llvm::BumpPtrAllocator _allocator;
};

/// \brief An SectionHeader represents the Elf[32/64]_Shdr structure
/// at the end of the file
template<class ELFT>
class SectionHeader : public Chunk<ELFT> {
public:
  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;

  SectionHeader(const ELFLinkingContext &, int32_t order);
  void appendSection(OutputSection<ELFT> *section);
  void updateSection(Section<ELFT> *section);

  static bool classof(const Chunk<ELFT> *c) {
    return c->kind() == Chunk<ELFT>::Kind::SectionHeader;
  }

  void setStringSection(StringTable<ELFT> *s) {
    _stringSection = s;
  }

  void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
             llvm::FileOutputBuffer &buffer) override;

  uint64_t fileSize() const override {
    return sizeof(Elf_Shdr) * _sectionInfo.size();
  }

  uint64_t entsize() { return sizeof(Elf_Shdr); }

  int getContentType() const override {
    return Chunk<ELFT>::ContentType::Header;
  }

  uint64_t numHeaders() { return _sectionInfo.size(); }

private:
  StringTable<ELFT> *_stringSection;
  std::vector<Elf_Shdr *> _sectionInfo;
  llvm::BumpPtrAllocator _sectionAllocate;
};

} // end namespace elf
} // end namespace lld

#endif
OpenPOWER on IntegriCloud