summaryrefslogtreecommitdiffstats
path: root/lld/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
blob: d251ca4fa0aa535b49949dd9b9fff566f322cc04 (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
155
156
157
158
159
//===- lib/ReaderWriter/ELF/HexagonELFFile.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_HEXAGON_ELF_FILE_H
#define LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H

#include "ELFReader.h"
#include "HexagonLinkingContext.h"

namespace lld {
namespace elf {

template <class ELFT> class HexagonELFFile;

template <class ELFT>
class HexagonELFDefinedAtom : public ELFDefinedAtom<ELFT> {
  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;

public:
  template<typename... T>
  HexagonELFDefinedAtom(T&&... args)
      : ELFDefinedAtom<ELFT>(std::forward<T>(args)...) {}

  virtual DefinedAtom::ContentType contentType() const {
    if (this->_contentType != DefinedAtom::typeUnknown)
      return this->_contentType;
    else if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) {
      if (this->_section->sh_type == llvm::ELF::SHT_NOBITS)
        return (this->_contentType = DefinedAtom::typeZeroFillFast);
      else
        return (this->_contentType = DefinedAtom::typeDataFast);
    }
    return ELFDefinedAtom<ELFT>::contentType();
  }

  virtual DefinedAtom::ContentPermissions permissions() const {
    if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL)
      return DefinedAtom::permRW_;
    return ELFDefinedAtom<ELFT>::permissions();
  }
};

template <class ELFT> class HexagonELFCommonAtom : public ELFCommonAtom<ELFT> {
  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;

public:
  HexagonELFCommonAtom(const HexagonELFFile<ELFT> &file, StringRef symbolName,
                       const Elf_Sym *symbol)
      : ELFCommonAtom<ELFT>(file, symbolName, symbol) {}

  virtual bool isSmallCommonSymbol() const {
    switch (this->_symbol->st_shndx) {
    // Common symbols
    case llvm::ELF::SHN_HEXAGON_SCOMMON:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
      return true;
    default:
      break;
    }
    return false;
  }

  virtual uint64_t size() const {
    if (isSmallCommonSymbol())
      return this->_symbol->st_size;
    return ELFCommonAtom<ELFT>::size();
  }

  virtual DefinedAtom::Merge merge() const {
    if (this->_symbol->getBinding() == llvm::ELF::STB_WEAK)
      return DefinedAtom::mergeAsWeak;
    if (isSmallCommonSymbol())
      return DefinedAtom::mergeAsTentative;
    return ELFCommonAtom<ELFT>::merge();
  }

  virtual DefinedAtom::ContentType contentType() const {
    if (isSmallCommonSymbol())
      return DefinedAtom::typeZeroFillFast;
    return ELFCommonAtom<ELFT>::contentType();
  }

  virtual DefinedAtom::Alignment alignment() const {
    if (isSmallCommonSymbol())
      return DefinedAtom::Alignment(this->_symbol->st_value);
    return 1;
  }

  virtual DefinedAtom::ContentPermissions permissions() const {
    if (isSmallCommonSymbol())
      return DefinedAtom::permRW_;
    return ELFCommonAtom<ELFT>::permissions();
  }
};

template <class ELFT> class HexagonELFFile : public ELFFile<ELFT> {
  typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
  typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;

public:
  HexagonELFFile(std::unique_ptr<MemoryBuffer> mb, HexagonLinkingContext &ctx)
      : ELFFile<ELFT>(std::move(mb), ctx) {}

  static ErrorOr<std::unique_ptr<HexagonELFFile>>
  create(std::unique_ptr<MemoryBuffer> mb, HexagonLinkingContext &ctx) {
    return std::unique_ptr<HexagonELFFile<ELFT>>(
        new HexagonELFFile<ELFT>(std::move(mb), ctx));
  }

  bool isCommonSymbol(const Elf_Sym *symbol) const override {
    switch (symbol->st_shndx) {
    // Common symbols
    case llvm::ELF::SHN_HEXAGON_SCOMMON:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_2:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_4:
    case llvm::ELF::SHN_HEXAGON_SCOMMON_8:
      return true;
    default:
      break;
    }
    return ELFFile<ELFT>::isCommonSymbol(symbol);
  }

  /// Process the Defined symbol and create an atom for it.
  ErrorOr<ELFDefinedAtom<ELFT> *>
  handleDefinedSymbol(StringRef symName, StringRef sectionName,
                      const Elf_Sym *sym, const Elf_Shdr *sectionHdr,
                      ArrayRef<uint8_t> contentData,
                      unsigned int referenceStart, unsigned int referenceEnd,
                      std::vector<ELFReference<ELFT> *> &referenceList) override {
    return new (this->_readerStorage) HexagonELFDefinedAtom<ELFT>(
        *this, symName, sectionName, sym, sectionHdr, contentData,
        referenceStart, referenceEnd, referenceList);
  }

  /// Process the Common symbol and create an atom for it.
  ErrorOr<ELFCommonAtom<ELFT> *>
  handleCommonSymbol(StringRef symName, const Elf_Sym *sym) override {
    return new (this->_readerStorage)
        HexagonELFCommonAtom<ELFT>(*this, symName, sym);
  }
};

} // elf
} // lld

#endif // LLD_READER_WRITER_ELF_HEXAGON_ELF_FILE_H
OpenPOWER on IntegriCloud