blob: b53d0de55e6f59603542d954ff45b2675431c32b [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 Gouly9c826c102014-01-12 22:55:49 +000056static void processSymbol(const NormalizedFile &normalizedFile, MachOFile &file,
57 const Symbol &sym, bool copyRefs) {
58 // Mach-O symbol table does have size in it, so need to scan ahead
59 // to find symbol with next highest address.
60 const Section &section = normalizedFile.sections[sym.sect - 1];
61 uint64_t offset = sym.value - section.address;
62 uint64_t size = nextSymbolAddress(normalizedFile, sym) - sym.value;
63 ArrayRef<uint8_t> atomContent = section.content.slice(offset, size);
64 file.addDefinedAtom(sym.name, atomContent, copyRefs);
65}
66
Joey Goulyceb16de2014-01-03 23:12:02 +000067static ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +000068normalizedObjectToAtoms(const NormalizedFile &normalizedFile, StringRef path,
69 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +000070 std::unique_ptr<MachOFile> file(new MachOFile(path));
71
Nick Kledzik6edd7222014-01-11 01:07:43 +000072 for (const Symbol &sym : normalizedFile.globalSymbols) {
Joey Gouly9c826c102014-01-12 22:55:49 +000073 processSymbol(normalizedFile, *file, sym, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +000074 }
75
76 assert(normalizedFile.localSymbols.empty() &&
77 "local symbols not supported yet!");
78 assert(normalizedFile.undefinedSymbols.empty() &&
79 "undefined symbols not supported yet!");
80
81 return std::unique_ptr<File>(std::move(file));
82}
83
84ErrorOr<std::unique_ptr<lld::File>>
Nick Kledzik6edd7222014-01-11 01:07:43 +000085normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
86 bool copyRefs) {
Joey Goulyceb16de2014-01-03 23:12:02 +000087 switch (normalizedFile.fileType) {
88 case MH_OBJECT:
Nick Kledzik6edd7222014-01-11 01:07:43 +000089 return normalizedObjectToAtoms(normalizedFile, path, copyRefs);
Joey Goulyceb16de2014-01-03 23:12:02 +000090 default:
91 llvm_unreachable("unhandled MachO file type!");
92 }
93}
94
95} // namespace normalized
96} // namespace mach_o
97} // namespace lld