blob: 7c3ac8f1b28e53fd04dc3265ecb16f83ebcb5052 [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 }
53 return closestAddr;
54}
55
Joey Goulyceb16de2014-01-03 23:12:02 +000056static ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +000057normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
58 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +000059 std::unique_ptr<MachOFile> file(new MachOFile(path));
60
Nick Kledzik6edd7222014-01-11 01:07:43 +000061 for (const Symbol &sym : normalizedFile.globalSymbols) {
Nick Kledzik36baa332014-01-08 02:52:58 +000062 // Mach-O symbol table does have size in it, so need to scan ahead
63 // to find symbol with next highest address.
64 const Section &section = normalizedFile.sections[sym.sect - 1];
65 uint64_t offset = sym.value - section.address;
66 uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value;
Nick Kledzik6edd7222014-01-11 01:07:43 +000067 ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
68 file->addDefinedAtom(sym.name, atomContent, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +000069 }
70
71 assert(normalizedFile.localSymbols.empty() &&
72 "local symbols not supported yet!");
73 assert(normalizedFile.undefinedSymbols.empty() &&
74 "undefined symbols not supported yet!");
75
76 return std::unique_ptr<File>(std::move(file));
77}
78
79ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +000080normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
81 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +000082 switch (normalizedFile.fileType) {
83 case MH_OBJECT:
Nick Kledzik6edd7222014-01-11 01:07:43 +000084 return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +000085 default:
86 llvm_unreachable("unhandled MachO file type!");
87 }
88}
89
90} // namespace normalized
91} // namespace mach_o
92} // namespace lld