]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h
Merge clang trunk r321017 to contrib/llvm/tools/clang.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / lib / ReaderWriter / MachO / MachONormalizedFile.h
1 //===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 ///
11 /// \file These data structures comprise the "normalized" view of
12 /// mach-o object files. The normalized view is an in-memory only data structure
13 /// which is always in native endianness and pointer size.
14 ///
15 /// The normalized view easily converts to and from YAML using YAML I/O.
16 ///
17 /// The normalized view converts to and from binary mach-o object files using
18 /// the writeBinary() and readBinary() functions.
19 ///
20 /// The normalized view converts to and from lld::Atoms using the
21 /// normalizedToAtoms() and normalizedFromAtoms().
22 ///
23 /// Overall, the conversion paths available look like:
24 ///
25 ///                 +---------------+
26 ///                 | binary mach-o |
27 ///                 +---------------+
28 ///                        ^
29 ///                        |
30 ///                        v
31 ///                  +------------+         +------+
32 ///                  | normalized |   <->   | yaml |
33 ///                  +------------+         +------+
34 ///                        ^
35 ///                        |
36 ///                        v
37 ///                    +-------+
38 ///                    | Atoms |
39 ///                    +-------+
40 ///
41
42 #ifndef LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
43 #define LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H
44
45 #include "DebugInfo.h"
46 #include "lld/Core/Error.h"
47 #include "lld/Core/LLVM.h"
48 #include "lld/ReaderWriter/MachOLinkingContext.h"
49 #include "llvm/ADT/SmallString.h"
50 #include "llvm/ADT/StringRef.h"
51 #include "llvm/BinaryFormat/MachO.h"
52 #include "llvm/Support/Allocator.h"
53 #include "llvm/Support/Debug.h"
54 #include "llvm/Support/ErrorOr.h"
55 #include "llvm/Support/YAMLTraits.h"
56
57 using llvm::BumpPtrAllocator;
58 using llvm::yaml::Hex64;
59 using llvm::yaml::Hex32;
60 using llvm::yaml::Hex16;
61 using llvm::yaml::Hex8;
62 using llvm::yaml::SequenceTraits;
63 using llvm::MachO::HeaderFileType;
64 using llvm::MachO::BindType;
65 using llvm::MachO::RebaseType;
66 using llvm::MachO::NListType;
67 using llvm::MachO::RelocationInfoType;
68 using llvm::MachO::SectionType;
69 using llvm::MachO::LoadCommandType;
70 using llvm::MachO::ExportSymbolKind;
71 using llvm::MachO::DataRegionType;
72
73 namespace lld {
74 namespace mach_o {
75 namespace normalized {
76
77
78 /// The real mach-o relocation record is 8-bytes on disk and is
79 /// encoded in one of two different bit-field patterns.  This
80 /// normalized form has the union of all possible fields.
81 struct Relocation {
82   Relocation() : offset(0), scattered(false),
83                  type(llvm::MachO::GENERIC_RELOC_VANILLA),
84                  length(0), pcRel(false), isExtern(false), value(0),
85                  symbol(0) { }
86
87   Hex32               offset;
88   bool                scattered;
89   RelocationInfoType  type;
90   uint8_t             length;
91   bool                pcRel;
92   bool                isExtern;
93   Hex32               value;
94   uint32_t            symbol;
95 };
96
97 /// A typedef so that YAML I/O can treat this vector as a sequence.
98 typedef std::vector<Relocation> Relocations;
99
100 /// A typedef so that YAML I/O can process the raw bytes in a section.
101 typedef std::vector<Hex8> ContentBytes;
102
103 /// A typedef so that YAML I/O can treat indirect symbols as a flow sequence.
104 typedef std::vector<uint32_t> IndirectSymbols;
105
106 /// A typedef so that YAML I/O can encode/decode section attributes.
107 LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
108
109 /// A typedef so that YAML I/O can encode/decode section alignment.
110 LLVM_YAML_STRONG_TYPEDEF(uint16_t, SectionAlignment)
111
112 /// Mach-O has a 32-bit and 64-bit section record.  This normalized form
113 /// can support either kind.
114 struct Section {
115   Section() : type(llvm::MachO::S_REGULAR),
116               attributes(0), alignment(1), address(0) { }
117
118   StringRef       segmentName;
119   StringRef       sectionName;
120   SectionType     type;
121   SectionAttr     attributes;
122   SectionAlignment        alignment;
123   Hex64           address;
124   ArrayRef<uint8_t> content;
125   Relocations     relocations;
126   IndirectSymbols indirectSymbols;
127
128 #ifndef NDEBUG
129   raw_ostream& operator<<(raw_ostream &OS) const {
130     dump(OS);
131     return OS;
132   }
133
134   void dump(raw_ostream &OS = llvm::dbgs()) const;
135 #endif
136 };
137
138
139 /// A typedef so that YAML I/O can encode/decode the scope bits of an nlist.
140 LLVM_YAML_STRONG_TYPEDEF(uint8_t, SymbolScope)
141
142 /// A typedef so that YAML I/O can encode/decode the desc bits of an nlist.
143 LLVM_YAML_STRONG_TYPEDEF(uint16_t, SymbolDesc)
144
145 /// Mach-O has a 32-bit and 64-bit symbol table entry (nlist), and the symbol
146 /// type and scope and mixed in the same n_type field.  This normalized form
147 /// works for any pointer size and separates out the type and scope.
148 struct Symbol {
149   Symbol() : type(llvm::MachO::N_UNDF), scope(0), sect(0), desc(0), value(0) { }
150
151   StringRef     name;
152   NListType     type;
153   SymbolScope   scope;
154   uint8_t       sect;
155   SymbolDesc    desc;
156   Hex64         value;
157 };
158
159 /// Check whether the given section type indicates a zero-filled section.
160 // FIXME: Utility functions of this kind should probably be moved into
161 //        llvm/Support.
162 inline bool isZeroFillSection(SectionType T) {
163   return (T == llvm::MachO::S_ZEROFILL ||
164           T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
165 }
166
167 /// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
168 LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)
169
170 /// A typedef to hold verions X.Y.X packed into 32-bit xxxx.yy.zz
171 LLVM_YAML_STRONG_TYPEDEF(uint32_t, PackedVersion)
172
173 /// Segments are only used in normalized final linked images (not in relocatable
174 /// object files). They specify how a range of the file is loaded.
175 struct Segment {
176   StringRef     name;
177   Hex64         address;
178   Hex64         size;
179   VMProtect     init_access;
180   VMProtect     max_access;
181 };
182
183 /// Only used in normalized final linked images to specify on which dylibs
184 /// it depends.
185 struct DependentDylib {
186   StringRef       path;
187   LoadCommandType kind;
188   PackedVersion   compatVersion;
189   PackedVersion   currentVersion;
190 };
191
192 /// A normalized rebasing entry.  Only used in normalized final linked images.
193 struct RebaseLocation {
194   Hex32         segOffset;
195   uint8_t       segIndex;
196   RebaseType    kind;
197 };
198
199 /// A normalized binding entry.  Only used in normalized final linked images.
200 struct BindLocation {
201   Hex32           segOffset;
202   uint8_t         segIndex;
203   BindType        kind;
204   bool            canBeNull;
205   int             ordinal;
206   StringRef       symbolName;
207   Hex64           addend;
208 };
209
210 /// A typedef so that YAML I/O can encode/decode export flags.
211 LLVM_YAML_STRONG_TYPEDEF(uint32_t, ExportFlags)
212
213 /// A normalized export entry.  Only used in normalized final linked images.
214 struct Export {
215   StringRef         name;
216   Hex64             offset;
217   ExportSymbolKind  kind;
218   ExportFlags       flags;
219   Hex32             otherOffset;
220   StringRef         otherName;
221 };
222
223 /// A normalized data-in-code entry.
224 struct DataInCode {
225   Hex32           offset;
226   Hex16           length;
227   DataRegionType  kind;
228 };
229
230 /// A typedef so that YAML I/O can encode/decode mach_header.flags.
231 LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
232
233 ///
234 struct NormalizedFile {
235   MachOLinkingContext::Arch   arch = MachOLinkingContext::arch_unknown;
236   HeaderFileType              fileType = llvm::MachO::MH_OBJECT;
237   FileFlags                   flags = 0;
238   std::vector<Segment>        segments; // Not used in object files.
239   std::vector<Section>        sections;
240
241   // Symbols sorted by kind.
242   std::vector<Symbol>         localSymbols;
243   std::vector<Symbol>         globalSymbols;
244   std::vector<Symbol>         undefinedSymbols;
245   std::vector<Symbol>         stabsSymbols;
246
247   // Maps to load commands with no LINKEDIT content (final linked images only).
248   std::vector<DependentDylib> dependentDylibs;
249   StringRef                   installName;        // dylibs only
250   PackedVersion               compatVersion = 0;  // dylibs only
251   PackedVersion               currentVersion = 0; // dylibs only
252   bool                        hasUUID = false;
253   bool                        hasMinVersionLoadCommand = false;
254   bool                        generateDataInCodeLoadCommand = false;
255   std::vector<StringRef>      rpaths;
256   Hex64                       entryAddress = 0;
257   Hex64                       stackSize = 0;
258   MachOLinkingContext::OS     os = MachOLinkingContext::OS::unknown;
259   Hex64                       sourceVersion = 0;
260   PackedVersion               minOSverson = 0;
261   PackedVersion               sdkVersion = 0;
262   LoadCommandType             minOSVersionKind = (LoadCommandType)0;
263
264   // Maps to load commands with LINKEDIT content (final linked images only).
265   Hex32                       pageSize = 0;
266   std::vector<RebaseLocation> rebasingInfo;
267   std::vector<BindLocation>   bindingInfo;
268   std::vector<BindLocation>   weakBindingInfo;
269   std::vector<BindLocation>   lazyBindingInfo;
270   std::vector<Export>         exportInfo;
271   std::vector<uint8_t>        functionStarts;
272   std::vector<DataInCode>     dataInCode;
273
274   // TODO:
275   // code-signature
276   // split-seg-info
277   // function-starts
278
279   // For any allocations in this struct which need to be owned by this struct.
280   BumpPtrAllocator            ownedAllocations;
281 };
282
283 /// Tests if a file is a non-fat mach-o object file.
284 bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch);
285
286 /// If the buffer is a fat file with the request arch, then this function
287 /// returns true with 'offset' and 'size' set to location of the arch slice
288 /// within the buffer.  Otherwise returns false;
289 bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
290                       uint32_t &offset, uint32_t &size);
291
292 /// Reads a mach-o file and produces an in-memory normalized view.
293 llvm::Expected<std::unique_ptr<NormalizedFile>>
294 readBinary(std::unique_ptr<MemoryBuffer> &mb,
295            const MachOLinkingContext::Arch arch);
296
297 /// Takes in-memory normalized view and writes a mach-o object file.
298 llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
299
300 size_t headerAndLoadCommandsSize(const NormalizedFile &file);
301
302
303 /// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
304 llvm::Expected<std::unique_ptr<NormalizedFile>>
305 readYaml(std::unique_ptr<MemoryBuffer> &mb);
306
307 /// Writes a yaml encoded mach-o files given an in-memory normalized view.
308 std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out);
309
310 llvm::Error
311 normalizedObjectToAtoms(MachOFile *file,
312                         const NormalizedFile &normalizedFile,
313                         bool copyRefs);
314
315 llvm::Error
316 normalizedDylibToAtoms(MachODylibFile *file,
317                        const NormalizedFile &normalizedFile,
318                        bool copyRefs);
319
320 /// Takes in-memory normalized dylib or object and parses it into lld::File
321 llvm::Expected<std::unique_ptr<lld::File>>
322 normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
323                   bool copyRefs);
324
325 /// Takes atoms and generates a normalized macho-o view.
326 llvm::Expected<std::unique_ptr<NormalizedFile>>
327 normalizedFromAtoms(const lld::File &atomFile, const MachOLinkingContext &ctxt);
328
329
330 } // namespace normalized
331
332 /// Class for interfacing mach-o yaml files into generic yaml parsing
333 class MachOYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
334 public:
335   MachOYamlIOTaggedDocumentHandler(MachOLinkingContext::Arch arch)
336     : _arch(arch) { }
337   bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override;
338 private:
339   const MachOLinkingContext::Arch _arch;
340 };
341
342 } // namespace mach_o
343 } // namespace lld
344
345 #endif // LLD_READER_WRITER_MACHO_NORMALIZE_FILE_H