blob: d3ff1e4064836a7693960769c1701081d4c0c4ee [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 Kledzik36baa332014-01-08 02:52:58 +000037static uint64_t nextSymbolAddress(const NormalizedFile &normalizedFile,
38 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>>
57normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
58 std::unique_ptr<MachOFile> file(new MachOFile(path));
59
Nick Kledzik36baa332014-01-08 02:52:58 +000060 for (const Symbol &sym : normalizedFile.globalSymbols) {
61 // Mach-O symbol table does have size in it, so need to scan ahead
62 // to find symbol with next highest address.
63 const Section &section = normalizedFile.sections[sym.sect - 1];
64 uint64_t offset = sym.value - section.address;
65 uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value;
66 ArrayRef<uint8_t> atomContent = llvm::makeArrayRef(&section.content[offset],
67 size);
68 file->addDefinedAtom(sym.name, atomContent);
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>>
80normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path) {
81 switch (normalizedFile.fileType) {
82 case MH_OBJECT:
83 return normalizedObjectToAtoms(normalizedFile, path);
84 default:
85 llvm_unreachable("unhandled MachO file type!");
86 }
87}
88
89} // namespace normalized
90} // namespace mach_o
91} // namespace lld