1//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_READER_WRITER_MACHO_ATOMS_H
10#define LLD_READER_WRITER_MACHO_ATOMS_H
11
12#include "lld/Core/Atom.h"
13#include "lld/Core/DefinedAtom.h"
14#include "lld/Core/SharedLibraryAtom.h"
15#include "lld/Core/Simple.h"
16#include "llvm/ADT/ArrayRef.h"
17#include "llvm/ADT/StringRef.h"
18#include <cstdint>
19#include <string>
20
21namespace lld {
22
23class File;
24
25namespace mach_o {
26
27class MachODefinedAtom : public SimpleDefinedAtom {
28public:
29  MachODefinedAtom(const File &f, const StringRef name, Scope scope,
30                   ContentType type, Merge merge, bool thumb, bool noDeadStrip,
31                   const ArrayRef<uint8_t> content, Alignment align)
32      : SimpleDefinedAtom(f), _name(name), _content(content),
33        _align(align), _contentType(type), _scope(scope), _merge(merge),
34        _thumb(thumb), _noDeadStrip(noDeadStrip) {}
35
36  // Constructor for zero-fill content
37  MachODefinedAtom(const File &f, const StringRef name, Scope scope,
38                   ContentType type, uint64_t size, bool noDeadStrip,
39                   Alignment align)
40      : SimpleDefinedAtom(f), _name(name),
41        _content(ArrayRef<uint8_t>(nullptr, size)), _align(align),
42        _contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
43        _noDeadStrip(noDeadStrip) {}
44
45  ~MachODefinedAtom() override = default;
46
47  uint64_t size() const override { return _content.size(); }
48
49  ContentType contentType() const override { return _contentType; }
50
51  Alignment alignment() const override { return _align; }
52
53  StringRef name() const override { return _name; }
54
55  Scope scope() const override { return _scope; }
56
57  Merge merge() const override { return _merge; }
58
59  DeadStripKind deadStrip() const override {
60    if (_contentType == DefinedAtom::typeInitializerPtr)
61      return deadStripNever;
62    if (_contentType == DefinedAtom::typeTerminatorPtr)
63      return deadStripNever;
64    if (_noDeadStrip)
65      return deadStripNever;
66    return deadStripNormal;
67  }
68
69  ArrayRef<uint8_t> rawContent() const override {
70    // Note: Zerofill atoms have a content pointer which is null.
71    return _content;
72  }
73
74  bool isThumb() const { return _thumb; }
75
76private:
77  const StringRef _name;
78  const ArrayRef<uint8_t> _content;
79  const DefinedAtom::Alignment _align;
80  const ContentType _contentType;
81  const Scope _scope;
82  const Merge _merge;
83  const bool _thumb;
84  const bool _noDeadStrip;
85};
86
87class MachODefinedCustomSectionAtom : public MachODefinedAtom {
88public:
89  MachODefinedCustomSectionAtom(const File &f, const StringRef name,
90                                Scope scope, ContentType type, Merge merge,
91                                bool thumb, bool noDeadStrip,
92                                const ArrayRef<uint8_t> content,
93                                StringRef sectionName, Alignment align)
94      : MachODefinedAtom(f, name, scope, type, merge, thumb, noDeadStrip,
95                         content, align),
96        _sectionName(sectionName) {}
97
98  ~MachODefinedCustomSectionAtom() override = default;
99
100  SectionChoice sectionChoice() const override {
101    return DefinedAtom::sectionCustomRequired;
102  }
103
104  StringRef customSectionName() const override {
105    return _sectionName;
106  }
107private:
108  StringRef _sectionName;
109};
110
111class MachOTentativeDefAtom : public SimpleDefinedAtom {
112public:
113  MachOTentativeDefAtom(const File &f, const StringRef name, Scope scope,
114                        uint64_t size, DefinedAtom::Alignment align)
115      : SimpleDefinedAtom(f), _name(std::string(name)), _scope(scope),
116        _size(size), _align(align) {}
117
118  ~MachOTentativeDefAtom() override = default;
119
120  uint64_t size() const override { return _size; }
121
122  Merge merge() const override { return DefinedAtom::mergeAsTentative; }
123
124  ContentType contentType() const override { return DefinedAtom::typeZeroFill; }
125
126  Alignment alignment() const override { return _align; }
127
128  StringRef name() const override { return _name; }
129
130  Scope scope() const override { return _scope; }
131
132  ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
133
134private:
135  const std::string _name;
136  const Scope _scope;
137  const uint64_t _size;
138  const DefinedAtom::Alignment _align;
139};
140
141class MachOSharedLibraryAtom : public SharedLibraryAtom {
142public:
143  MachOSharedLibraryAtom(const File &file, StringRef name,
144                         StringRef dylibInstallName, bool weakDef)
145      : SharedLibraryAtom(), _file(file), _name(name),
146        _dylibInstallName(dylibInstallName) {}
147  ~MachOSharedLibraryAtom() override = default;
148
149  StringRef loadName() const override { return _dylibInstallName; }
150
151  bool canBeNullAtRuntime() const override {
152    // FIXME: this may actually be changeable. For now, all symbols are strongly
153    // defined though.
154    return false;
155  }
156
157  const File &file() const override { return _file; }
158
159  StringRef name() const override { return _name; }
160
161  Type type() const override {
162    // Unused in MachO (I think).
163    return Type::Unknown;
164  }
165
166  uint64_t size() const override {
167    // Unused in MachO (I think)
168    return 0;
169  }
170
171private:
172  const File &_file;
173  StringRef _name;
174  StringRef _dylibInstallName;
175};
176
177} // end namespace mach_o
178} // end namespace lld
179
180#endif // LLD_READER_WRITER_MACHO_ATOMS_H
181