blob: c84ca77367b0767ba5d23a5884620fef9d1680a2 [file] [log] [blame]
Joey Goulyceb16de2014-01-03 23:12:02 +00001//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
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 Converts from in-memory normalized mach-o to in-memory Atoms.
12///
13/// +------------+
14/// | normalized |
15/// +------------+
16/// |
17/// |
18/// v
19/// +-------+
20/// | Atoms |
21/// +-------+
22
23#include "MachONormalizedFile.h"
24#include "File.h"
25#include "Atoms.h"
26
27#include "lld/Core/LLVM.h"
28
29#include "llvm/Support/MachO.h"
30
31using namespace llvm::MachO;
32
33namespace lld {
34namespace mach_o {
35namespace normalized {
36
Nick Kledzik6edd7222014-01-11 01:07:43 +000037static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile,
Nick Kledzik36baa332014-01-08 02:52:58 +000038 const Symbol &symbol) {
39 uint64_t symbolAddr = symbol.value;
40 uint8_t symbolSectionIndex = symbol.sect;
41 const Section &section = normalizedFile.sections[symbolSectionIndex - 1];
42 // If no symbol after this address, use end of section address.
43 uint64_t closestAddr = section.address + section.content.size();
44 for (const Symbol &s : normalizedFile.globalSymbols) {
45 if (s.sect != symbolSectionIndex)
46 continue;
47 uint64_t sValue = s.value;
48 if (sValue <= symbolAddr)
49 continue;
50 if (sValue < closestAddr)
51 closestAddr = s.value;
52 }
Joey Goulyd2215372014-01-13 22:28:02 +000053 for (const Symbol &s : normalizedFile.localSymbols) {
54 if (s.sect != symbolSectionIndex)
55 continue;
56 uint64_t sValue = s.value;
57 if (sValue <= symbolAddr)
58 continue;
59 if (sValue < closestAddr)
60 closestAddr = s.value;
61 }
Nick Kledzik36baa332014-01-08 02:52:58 +000062 return closestAddr;
63}
64
Joey Goulyd2215372014-01-13 22:28:02 +000065static Atom::Scope atomScope(uint8_t scope) {
66 switch (scope) {
67 case N_EXT:
68 return Atom::scopeGlobal;
69 case N_PEXT | N_EXT:
70 return Atom::scopeLinkageUnit;
71 case 0:
72 return Atom::scopeTranslationUnit;
73 }
74 llvm_unreachable("unknown scope value!");
75}
76
Joey Gouly9c826c102014-01-12 22:55:49 +000077static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file,
78 const Symbol &sym, bool copyRefs) {
79 // Mach-O symbol table does have size in it, so need to scan ahead
80 // to find symbol with next highest address.
81 const Section &section = normalizedFile.sections[sym.sect - 1];
82 uint64_t offset = sym.value - section.address;
83 uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value;
84 ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
Joey Goulyd2215372014-01-13 22:28:02 +000085 file.addDefinedAtom(sym.name, atomContent, atomScope(sym.scope), copyRefs);
Joey Gouly9c826c102014-01-12 22:55:49 +000086}
87
Joey Goulyceb16de2014-01-03 23:12:02 +000088static ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +000089normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
90 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +000091 std::unique_ptr<MachOFile> file(new MachOFile(path));
92
Nick Kledzik6edd7222014-01-11 01:07:43 +000093 for (const Symbol &sym : normalizedFile.globalSymbols) {
Joey Gouly9c826c102014-01-12 22:55:49 +000094 processSymbol(normalizedFile, *file, sym, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +000095 }
96
Joey Goulyd2215372014-01-13 22:28:02 +000097 for (const Symbol &sym : normalizedFile.localSymbols) {
98 processSymbol(normalizedFile, *file, sym, copyRefs);
99 }
100
Joey Goulycf466802014-02-02 19:34:55 +0000101 for (auto &sym : normalizedFile.undefinedSymbols) {
102 file->addUndefinedAtom(sym.name, copyRefs);
103 }
Joey Goulyceb16de2014-01-03 23:12:02 +0000104
105 return std::unique_ptr<File>(std::move(file));
106}
107
108ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +0000109normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
110 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +0000111 switch (normalizedFile.fileType) {
112 case MH_OBJECT:
Nick Kledzik6edd7222014-01-11 01:07:43 +0000113 return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +0000114 default:
115 llvm_unreachable("unhandled MachO file type!");
116 }
117}
118
119} // namespace normalized
120} // namespace mach_o
121} // namespace lld