Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Object/MachOObjectFile.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MachOObjectFile.cpp - Mach-O object file binding -------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// This file defines the MachOObjectFile class, which binds the MachOObject
10
// class to the generic ObjectFile wrapper.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm/ADT/ArrayRef.h"
15
#include "llvm/ADT/None.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/ADT/SmallVector.h"
18
#include "llvm/ADT/StringRef.h"
19
#include "llvm/ADT/StringSwitch.h"
20
#include "llvm/ADT/Triple.h"
21
#include "llvm/ADT/Twine.h"
22
#include "llvm/BinaryFormat/MachO.h"
23
#include "llvm/Object/Error.h"
24
#include "llvm/Object/MachO.h"
25
#include "llvm/Object/ObjectFile.h"
26
#include "llvm/Object/SymbolicFile.h"
27
#include "llvm/Support/DataExtractor.h"
28
#include "llvm/Support/Debug.h"
29
#include "llvm/Support/Error.h"
30
#include "llvm/Support/ErrorHandling.h"
31
#include "llvm/Support/Format.h"
32
#include "llvm/Support/Host.h"
33
#include "llvm/Support/LEB128.h"
34
#include "llvm/Support/MemoryBuffer.h"
35
#include "llvm/Support/SwapByteOrder.h"
36
#include "llvm/Support/raw_ostream.h"
37
#include <algorithm>
38
#include <cassert>
39
#include <cstddef>
40
#include <cstdint>
41
#include <cstring>
42
#include <limits>
43
#include <list>
44
#include <memory>
45
#include <string>
46
#include <system_error>
47
48
using namespace llvm;
49
using namespace object;
50
51
namespace {
52
53
  struct section_base {
54
    char sectname[16];
55
    char segname[16];
56
  };
57
58
} // end anonymous namespace
59
60
220
static Error malformedError(const Twine &Msg) {
61
220
  return make_error<GenericBinaryError>("truncated or malformed object (" +
62
220
                                            Msg + ")",
63
220
                                        object_error::parse_failed);
64
220
}
65
66
// FIXME: Replace all uses of this function with getStructOrErr.
67
template <typename T>
68
160k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
160k
  // Don't read before the beginning or past the end of the file
70
160k
  if (
P < O.getData().begin()160k
|| P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
160k
73
160k
  T Cmd;
74
160k
  memcpy(&Cmd, P, sizeof(T));
75
160k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
672
    MachO::swapStruct(Cmd);
77
160k
  return Cmd;
78
160k
}
MachOObjectFile.cpp:llvm::MachO::nlist_base getStruct<llvm::MachO::nlist_base>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
30.7k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
30.7k
  // Don't read before the beginning or past the end of the file
70
30.7k
  if (
P < O.getData().begin()30.7k
|| P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
30.7k
73
30.7k
  T Cmd;
74
30.7k
  memcpy(&Cmd, P, sizeof(T));
75
30.7k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
73
    MachO::swapStruct(Cmd);
77
30.7k
  return Cmd;
78
30.7k
}
MachOObjectFile.cpp:llvm::MachO::encryption_info_command getStruct<llvm::MachO::encryption_info_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
5
static T getStruct(const MachOObjectFile &O, const char *P) {
69
5
  // Don't read before the beginning or past the end of the file
70
5
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
5
73
5
  T Cmd;
74
5
  memcpy(&Cmd, P, sizeof(T));
75
5
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
5
  return Cmd;
78
5
}
MachOObjectFile.cpp:llvm::MachO::encryption_info_command_64 getStruct<llvm::MachO::encryption_info_command_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
18
static T getStruct(const MachOObjectFile &O, const char *P) {
69
18
  // Don't read before the beginning or past the end of the file
70
18
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
18
73
18
  T Cmd;
74
18
  memcpy(&Cmd, P, sizeof(T));
75
18
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
18
  return Cmd;
78
18
}
MachOObjectFile.cpp:llvm::MachO::sub_framework_command getStruct<llvm::MachO::sub_framework_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
6
static T getStruct(const MachOObjectFile &O, const char *P) {
69
6
  // Don't read before the beginning or past the end of the file
70
6
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
6
73
6
  T Cmd;
74
6
  memcpy(&Cmd, P, sizeof(T));
75
6
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
6
  return Cmd;
78
6
}
MachOObjectFile.cpp:llvm::MachO::sub_umbrella_command getStruct<llvm::MachO::sub_umbrella_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
3
static T getStruct(const MachOObjectFile &O, const char *P) {
69
3
  // Don't read before the beginning or past the end of the file
70
3
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
3
73
3
  T Cmd;
74
3
  memcpy(&Cmd, P, sizeof(T));
75
3
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
3
  return Cmd;
78
3
}
MachOObjectFile.cpp:llvm::MachO::sub_library_command getStruct<llvm::MachO::sub_library_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
3
static T getStruct(const MachOObjectFile &O, const char *P) {
69
3
  // Don't read before the beginning or past the end of the file
70
3
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
3
73
3
  T Cmd;
74
3
  memcpy(&Cmd, P, sizeof(T));
75
3
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
3
  return Cmd;
78
3
}
MachOObjectFile.cpp:llvm::MachO::sub_client_command getStruct<llvm::MachO::sub_client_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
3
static T getStruct(const MachOObjectFile &O, const char *P) {
69
3
  // Don't read before the beginning or past the end of the file
70
3
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
3
73
3
  T Cmd;
74
3
  memcpy(&Cmd, P, sizeof(T));
75
3
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
3
  return Cmd;
78
3
}
MachOObjectFile.cpp:llvm::MachO::symtab_command getStruct<llvm::MachO::symtab_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
17.6k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
17.6k
  // Don't read before the beginning or past the end of the file
70
17.6k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
17.6k
73
17.6k
  T Cmd;
74
17.6k
  memcpy(&Cmd, P, sizeof(T));
75
17.6k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
76
    MachO::swapStruct(Cmd);
77
17.6k
  return Cmd;
78
17.6k
}
MachOObjectFile.cpp:llvm::MachO::dysymtab_command getStruct<llvm::MachO::dysymtab_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
3.27k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
3.27k
  // Don't read before the beginning or past the end of the file
70
3.27k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
3.27k
73
3.27k
  T Cmd;
74
3.27k
  memcpy(&Cmd, P, sizeof(T));
75
3.27k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
12
    MachO::swapStruct(Cmd);
77
3.27k
  return Cmd;
78
3.27k
}
MachOObjectFile.cpp:llvm::MachO::section getStruct<llvm::MachO::section>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
16.1k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
16.1k
  // Don't read before the beginning or past the end of the file
70
16.1k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
16.1k
73
16.1k
  T Cmd;
74
16.1k
  memcpy(&Cmd, P, sizeof(T));
75
16.1k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
228
    MachO::swapStruct(Cmd);
77
16.1k
  return Cmd;
78
16.1k
}
MachOObjectFile.cpp:llvm::MachO::section_64 getStruct<llvm::MachO::section_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
66.4k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
66.4k
  // Don't read before the beginning or past the end of the file
70
66.4k
  if (
P < O.getData().begin()66.4k
|| P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
66.4k
73
66.4k
  T Cmd;
74
66.4k
  memcpy(&Cmd, P, sizeof(T));
75
66.4k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
106
    MachO::swapStruct(Cmd);
77
66.4k
  return Cmd;
78
66.4k
}
MachOObjectFile.cpp:llvm::MachO::nlist getStruct<llvm::MachO::nlist>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
1.83k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
1.83k
  // Don't read before the beginning or past the end of the file
70
1.83k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
1.83k
73
1.83k
  T Cmd;
74
1.83k
  memcpy(&Cmd, P, sizeof(T));
75
1.83k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
6
    MachO::swapStruct(Cmd);
77
1.83k
  return Cmd;
78
1.83k
}
MachOObjectFile.cpp:llvm::MachO::nlist_64 getStruct<llvm::MachO::nlist_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
10.9k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
10.9k
  // Don't read before the beginning or past the end of the file
70
10.9k
  if (
P < O.getData().begin()10.9k
|| P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
10.9k
73
10.9k
  T Cmd;
74
10.9k
  memcpy(&Cmd, P, sizeof(T));
75
10.9k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
4
    MachO::swapStruct(Cmd);
77
10.9k
  return Cmd;
78
10.9k
}
MachOObjectFile.cpp:llvm::MachO::linkedit_data_command getStruct<llvm::MachO::linkedit_data_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
215
static T getStruct(const MachOObjectFile &O, const char *P) {
69
215
  // Don't read before the beginning or past the end of the file
70
215
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
215
73
215
  T Cmd;
74
215
  memcpy(&Cmd, P, sizeof(T));
75
215
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
215
  return Cmd;
78
215
}
MachOObjectFile.cpp:llvm::MachO::segment_command getStruct<llvm::MachO::segment_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
184
static T getStruct(const MachOObjectFile &O, const char *P) {
69
184
  // Don't read before the beginning or past the end of the file
70
184
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
184
73
184
  T Cmd;
74
184
  memcpy(&Cmd, P, sizeof(T));
75
184
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
184
  return Cmd;
78
184
}
MachOObjectFile.cpp:llvm::MachO::segment_command_64 getStruct<llvm::MachO::segment_command_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
1.60k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
1.60k
  // Don't read before the beginning or past the end of the file
70
1.60k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
1.60k
73
1.60k
  T Cmd;
74
1.60k
  memcpy(&Cmd, P, sizeof(T));
75
1.60k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
1.60k
  return Cmd;
78
1.60k
}
MachOObjectFile.cpp:llvm::MachO::linker_option_command getStruct<llvm::MachO::linker_option_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
7
static T getStruct(const MachOObjectFile &O, const char *P) {
69
7
  // Don't read before the beginning or past the end of the file
70
7
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
7
73
7
  T Cmd;
74
7
  memcpy(&Cmd, P, sizeof(T));
75
7
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
7
  return Cmd;
78
7
}
MachOObjectFile.cpp:llvm::MachO::version_min_command getStruct<llvm::MachO::version_min_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
58
static T getStruct(const MachOObjectFile &O, const char *P) {
69
58
  // Don't read before the beginning or past the end of the file
70
58
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
58
73
58
  T Cmd;
74
58
  memcpy(&Cmd, P, sizeof(T));
75
58
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
58
  return Cmd;
78
58
}
MachOObjectFile.cpp:llvm::MachO::note_command getStruct<llvm::MachO::note_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
1
static T getStruct(const MachOObjectFile &O, const char *P) {
69
1
  // Don't read before the beginning or past the end of the file
70
1
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
1
73
1
  T Cmd;
74
1
  memcpy(&Cmd, P, sizeof(T));
75
1
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
1
  return Cmd;
78
1
}
MachOObjectFile.cpp:llvm::MachO::build_version_command getStruct<llvm::MachO::build_version_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
7
static T getStruct(const MachOObjectFile &O, const char *P) {
69
7
  // Don't read before the beginning or past the end of the file
70
7
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
7
73
7
  T Cmd;
74
7
  memcpy(&Cmd, P, sizeof(T));
75
7
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
7
  return Cmd;
78
7
}
MachOObjectFile.cpp:llvm::MachO::build_tool_version getStruct<llvm::MachO::build_tool_version>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
2
static T getStruct(const MachOObjectFile &O, const char *P) {
69
2
  // Don't read before the beginning or past the end of the file
70
2
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
2
73
2
  T Cmd;
74
2
  memcpy(&Cmd, P, sizeof(T));
75
2
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
2
  return Cmd;
78
2
}
MachOObjectFile.cpp:llvm::MachO::dylib_command getStruct<llvm::MachO::dylib_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
104
static T getStruct(const MachOObjectFile &O, const char *P) {
69
104
  // Don't read before the beginning or past the end of the file
70
104
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
104
73
104
  T Cmd;
74
104
  memcpy(&Cmd, P, sizeof(T));
75
104
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
104
  return Cmd;
78
104
}
MachOObjectFile.cpp:llvm::MachO::dyld_info_command getStruct<llvm::MachO::dyld_info_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
52
static T getStruct(const MachOObjectFile &O, const char *P) {
69
52
  // Don't read before the beginning or past the end of the file
70
52
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
52
73
52
  T Cmd;
74
52
  memcpy(&Cmd, P, sizeof(T));
75
52
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
52
  return Cmd;
78
52
}
MachOObjectFile.cpp:llvm::MachO::dylinker_command getStruct<llvm::MachO::dylinker_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
31
static T getStruct(const MachOObjectFile &O, const char *P) {
69
31
  // Don't read before the beginning or past the end of the file
70
31
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
31
73
31
  T Cmd;
74
31
  memcpy(&Cmd, P, sizeof(T));
75
31
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
31
  return Cmd;
78
31
}
MachOObjectFile.cpp:llvm::MachO::uuid_command getStruct<llvm::MachO::uuid_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
76
static T getStruct(const MachOObjectFile &O, const char *P) {
69
76
  // Don't read before the beginning or past the end of the file
70
76
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
76
73
76
  T Cmd;
74
76
  memcpy(&Cmd, P, sizeof(T));
75
76
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
76
  return Cmd;
78
76
}
MachOObjectFile.cpp:llvm::MachO::rpath_command getStruct<llvm::MachO::rpath_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
2
static T getStruct(const MachOObjectFile &O, const char *P) {
69
2
  // Don't read before the beginning or past the end of the file
70
2
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
2
73
2
  T Cmd;
74
2
  memcpy(&Cmd, P, sizeof(T));
75
2
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
2
  return Cmd;
78
2
}
MachOObjectFile.cpp:llvm::MachO::source_version_command getStruct<llvm::MachO::source_version_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
53
static T getStruct(const MachOObjectFile &O, const char *P) {
69
53
  // Don't read before the beginning or past the end of the file
70
53
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
53
73
53
  T Cmd;
74
53
  memcpy(&Cmd, P, sizeof(T));
75
53
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
53
  return Cmd;
78
53
}
MachOObjectFile.cpp:llvm::MachO::entry_point_command getStruct<llvm::MachO::entry_point_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
31
static T getStruct(const MachOObjectFile &O, const char *P) {
69
31
  // Don't read before the beginning or past the end of the file
70
31
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
31
73
31
  T Cmd;
74
31
  memcpy(&Cmd, P, sizeof(T));
75
31
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
31
  return Cmd;
78
31
}
Unexecuted instantiation: MachOObjectFile.cpp:llvm::MachO::routines_command getStruct<llvm::MachO::routines_command>(llvm::object::MachOObjectFile const&, char const*)
MachOObjectFile.cpp:llvm::MachO::routines_command_64 getStruct<llvm::MachO::routines_command_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
1
static T getStruct(const MachOObjectFile &O, const char *P) {
69
1
  // Don't read before the beginning or past the end of the file
70
1
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
1
73
1
  T Cmd;
74
1
  memcpy(&Cmd, P, sizeof(T));
75
1
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
1
  return Cmd;
78
1
}
MachOObjectFile.cpp:llvm::MachO::thread_command getStruct<llvm::MachO::thread_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
5
static T getStruct(const MachOObjectFile &O, const char *P) {
69
5
  // Don't read before the beginning or past the end of the file
70
5
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
5
73
5
  T Cmd;
74
5
  memcpy(&Cmd, P, sizeof(T));
75
5
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
5
  return Cmd;
78
5
}
MachOObjectFile.cpp:llvm::MachO::any_relocation_info getStruct<llvm::MachO::any_relocation_info>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
10.9k
static T getStruct(const MachOObjectFile &O, const char *P) {
69
10.9k
  // Don't read before the beginning or past the end of the file
70
10.9k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
10.9k
73
10.9k
  T Cmd;
74
10.9k
  memcpy(&Cmd, P, sizeof(T));
75
10.9k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
167
    MachO::swapStruct(Cmd);
77
10.9k
  return Cmd;
78
10.9k
}
MachOObjectFile.cpp:llvm::MachO::data_in_code_entry getStruct<llvm::MachO::data_in_code_entry>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
79
static T getStruct(const MachOObjectFile &O, const char *P) {
69
79
  // Don't read before the beginning or past the end of the file
70
79
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
79
73
79
  T Cmd;
74
79
  memcpy(&Cmd, P, sizeof(T));
75
79
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
79
  return Cmd;
78
79
}
MachOObjectFile.cpp:unsigned int getStruct<unsigned int>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
68
91
static T getStruct(const MachOObjectFile &O, const char *P) {
69
91
  // Don't read before the beginning or past the end of the file
70
91
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
71
0
    report_fatal_error("Malformed MachO file.");
72
91
73
91
  T Cmd;
74
91
  memcpy(&Cmd, P, sizeof(T));
75
91
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
76
0
    MachO::swapStruct(Cmd);
77
91
  return Cmd;
78
91
}
79
80
template <typename T>
81
46.8k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
46.8k
  // Don't read before the beginning or past the end of the file
83
46.8k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
46.8k
86
46.8k
  T Cmd;
87
46.8k
  memcpy(&Cmd, P, sizeof(T));
88
46.8k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
190
    MachO::swapStruct(Cmd);
90
46.8k
  return Cmd;
91
46.8k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::load_command> getStructOrErr<llvm::MachO::load_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
14.1k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
14.1k
  // Don't read before the beginning or past the end of the file
83
14.1k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
14.1k
86
14.1k
  T Cmd;
87
14.1k
  memcpy(&Cmd, P, sizeof(T));
88
14.1k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
52
    MachO::swapStruct(Cmd);
90
14.1k
  return Cmd;
91
14.1k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::symtab_command> getStructOrErr<llvm::MachO::symtab_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
2.34k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
2.34k
  // Don't read before the beginning or past the end of the file
83
2.34k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
2.34k
86
2.34k
  T Cmd;
87
2.34k
  memcpy(&Cmd, P, sizeof(T));
88
2.34k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
13
    MachO::swapStruct(Cmd);
90
2.34k
  return Cmd;
91
2.34k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::dysymtab_command> getStructOrErr<llvm::MachO::dysymtab_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
2.20k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
2.20k
  // Don't read before the beginning or past the end of the file
83
2.20k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
2.20k
86
2.20k
  T Cmd;
87
2.20k
  memcpy(&Cmd, P, sizeof(T));
88
2.20k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
12
    MachO::swapStruct(Cmd);
90
2.20k
  return Cmd;
91
2.20k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::linkedit_data_command> getStructOrErr<llvm::MachO::linkedit_data_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
1.06k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
1.06k
  // Don't read before the beginning or past the end of the file
83
1.06k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
1.06k
86
1.06k
  T Cmd;
87
1.06k
  memcpy(&Cmd, P, sizeof(T));
88
1.06k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
1.06k
  return Cmd;
91
1.06k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::dylinker_command> getStructOrErr<llvm::MachO::dylinker_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
303
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
303
  // Don't read before the beginning or past the end of the file
83
303
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
303
86
303
  T Cmd;
87
303
  memcpy(&Cmd, P, sizeof(T));
88
303
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
1
    MachO::swapStruct(Cmd);
90
303
  return Cmd;
91
303
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::note_command> getStructOrErr<llvm::MachO::note_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
2
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
2
  // Don't read before the beginning or past the end of the file
83
2
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
2
86
2
  T Cmd;
87
2
  memcpy(&Cmd, P, sizeof(T));
88
2
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
2
  return Cmd;
91
2
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::build_version_command> getStructOrErr<llvm::MachO::build_version_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
46
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
46
  // Don't read before the beginning or past the end of the file
83
46
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
46
86
46
  T Cmd;
87
46
  memcpy(&Cmd, P, sizeof(T));
88
46
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
46
  return Cmd;
91
46
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::rpath_command> getStructOrErr<llvm::MachO::rpath_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
11
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
11
  // Don't read before the beginning or past the end of the file
83
11
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
11
86
11
  T Cmd;
87
11
  memcpy(&Cmd, P, sizeof(T));
88
11
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
11
  return Cmd;
91
11
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::linker_option_command> getStructOrErr<llvm::MachO::linker_option_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
108
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
108
  // Don't read before the beginning or past the end of the file
83
108
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
108
86
108
  T Cmd;
87
108
  memcpy(&Cmd, P, sizeof(T));
88
108
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
108
  return Cmd;
91
108
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::thread_command> getStructOrErr<llvm::MachO::thread_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
21
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
21
  // Don't read before the beginning or past the end of the file
83
21
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
21
86
21
  T Cmd;
87
21
  memcpy(&Cmd, P, sizeof(T));
88
21
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
1
    MachO::swapStruct(Cmd);
90
21
  return Cmd;
91
21
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::twolevel_hints_command> getStructOrErr<llvm::MachO::twolevel_hints_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
6
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
6
  // Don't read before the beginning or past the end of the file
83
6
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
6
86
6
  T Cmd;
87
6
  memcpy(&Cmd, P, sizeof(T));
88
6
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
6
  return Cmd;
91
6
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::dyld_info_command> getStructOrErr<llvm::MachO::dyld_info_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
579
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
579
  // Don't read before the beginning or past the end of the file
83
579
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
579
86
579
  T Cmd;
87
579
  memcpy(&Cmd, P, sizeof(T));
88
579
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
0
    MachO::swapStruct(Cmd);
90
579
  return Cmd;
91
579
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::dylib_command> getStructOrErr<llvm::MachO::dylib_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
764
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
764
  // Don't read before the beginning or past the end of the file
83
764
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
764
86
764
  T Cmd;
87
764
  memcpy(&Cmd, P, sizeof(T));
88
764
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
2
    MachO::swapStruct(Cmd);
90
764
  return Cmd;
91
764
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::mach_header_64> getStructOrErr<llvm::MachO::mach_header_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
2.17k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
2.17k
  // Don't read before the beginning or past the end of the file
83
2.17k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
2.17k
86
2.17k
  T Cmd;
87
2.17k
  memcpy(&Cmd, P, sizeof(T));
88
2.17k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
6
    MachO::swapStruct(Cmd);
90
2.17k
  return Cmd;
91
2.17k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::mach_header> getStructOrErr<llvm::MachO::mach_header>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
550
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
550
  // Don't read before the beginning or past the end of the file
83
550
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
550
86
550
  T Cmd;
87
550
  memcpy(&Cmd, P, sizeof(T));
88
550
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
10
    MachO::swapStruct(Cmd);
90
550
  return Cmd;
91
550
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::segment_command_64> getStructOrErr<llvm::MachO::segment_command_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
3.48k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
3.48k
  // Don't read before the beginning or past the end of the file
83
3.48k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
3.48k
86
3.48k
  T Cmd;
87
3.48k
  memcpy(&Cmd, P, sizeof(T));
88
3.48k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
4
    MachO::swapStruct(Cmd);
90
3.48k
  return Cmd;
91
3.48k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::section_64> getStructOrErr<llvm::MachO::section_64>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
16.5k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
16.5k
  // Don't read before the beginning or past the end of the file
83
16.5k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
16.5k
86
16.5k
  T Cmd;
87
16.5k
  memcpy(&Cmd, P, sizeof(T));
88
16.5k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
19
    MachO::swapStruct(Cmd);
90
16.5k
  return Cmd;
91
16.5k
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::segment_command> getStructOrErr<llvm::MachO::segment_command>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
585
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
585
  // Don't read before the beginning or past the end of the file
83
585
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
585
86
585
  T Cmd;
87
585
  memcpy(&Cmd, P, sizeof(T));
88
585
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
12
    MachO::swapStruct(Cmd);
90
585
  return Cmd;
91
585
}
MachOObjectFile.cpp:llvm::Expected<llvm::MachO::section> getStructOrErr<llvm::MachO::section>(llvm::object::MachOObjectFile const&, char const*)
Line
Count
Source
81
1.87k
static Expected<T> getStructOrErr(const MachOObjectFile &O, const char *P) {
82
1.87k
  // Don't read before the beginning or past the end of the file
83
1.87k
  if (P < O.getData().begin() || P + sizeof(T) > O.getData().end())
84
0
    return malformedError("Structure read out-of-range");
85
1.87k
86
1.87k
  T Cmd;
87
1.87k
  memcpy(&Cmd, P, sizeof(T));
88
1.87k
  if (O.isLittleEndian() != sys::IsLittleEndianHost)
89
58
    MachO::swapStruct(Cmd);
90
1.87k
  return Cmd;
91
1.87k
}
92
93
static const char *
94
getSectionPtr(const MachOObjectFile &O, MachOObjectFile::LoadCommandInfo L,
95
20.2k
              unsigned Sec) {
96
20.2k
  uintptr_t CommandAddr = reinterpret_cast<uintptr_t>(L.Ptr);
97
20.2k
98
20.2k
  bool Is64 = O.is64Bit();
99
20.2k
  unsigned SegmentLoadSize = Is64 ? 
sizeof(MachO::segment_command_64)18.2k
:
100
20.2k
                                    
sizeof(MachO::segment_command)1.96k
;
101
20.2k
  unsigned SectionSize = Is64 ? 
sizeof(MachO::section_64)18.2k
:
102
20.2k
                                
sizeof(MachO::section)1.96k
;
103
20.2k
104
20.2k
  uintptr_t SectionAddr = CommandAddr + SegmentLoadSize + Sec * SectionSize;
105
20.2k
  return reinterpret_cast<const char*>(SectionAddr);
106
20.2k
}
107
108
24.2k
static const char *getPtr(const MachOObjectFile &O, size_t Offset) {
109
24.2k
  assert(Offset <= O.getData().size());
110
24.2k
  return O.getData().data() + Offset;
111
24.2k
}
112
113
static MachO::nlist_base
114
30.7k
getSymbolTableEntryBase(const MachOObjectFile &O, DataRefImpl DRI) {
115
30.7k
  const char *P = reinterpret_cast<const char *>(DRI.p);
116
30.7k
  return getStruct<MachO::nlist_base>(O, P);
117
30.7k
}
118
119
43.1k
static StringRef parseSegmentOrSectionName(const char *P) {
120
43.1k
  if (P[15] == 0)
121
38.3k
    // Null terminated.
122
38.3k
    return P;
123
4.78k
  // Not null terminated, so this is a 16 char string.
124
4.78k
  return StringRef(P, 16);
125
4.78k
}
126
127
23.0k
static unsigned getCPUType(const MachOObjectFile &O) {
128
23.0k
  return O.getHeader().cputype;
129
23.0k
}
130
131
static uint32_t
132
7.52k
getPlainRelocationAddress(const MachO::any_relocation_info &RE) {
133
7.52k
  return RE.r_word0;
134
7.52k
}
135
136
static unsigned
137
160
getScatteredRelocationAddress(const MachO::any_relocation_info &RE) {
138
160
  return RE.r_word0 & 0xffffff;
139
160
}
140
141
static bool getPlainRelocationPCRel(const MachOObjectFile &O,
142
1.13k
                                    const MachO::any_relocation_info &RE) {
143
1.13k
  if (O.isLittleEndian())
144
1.12k
    return (RE.r_word1 >> 24) & 1;
145
10
  return (RE.r_word1 >> 7) & 1;
146
10
}
147
148
static bool
149
98
getScatteredRelocationPCRel(const MachO::any_relocation_info &RE) {
150
98
  return (RE.r_word0 >> 30) & 1;
151
98
}
152
153
static unsigned getPlainRelocationLength(const MachOObjectFile &O,
154
2.06k
                                         const MachO::any_relocation_info &RE) {
155
2.06k
  if (O.isLittleEndian())
156
2.05k
    return (RE.r_word1 >> 25) & 3;
157
10
  return (RE.r_word1 >> 5) & 3;
158
10
}
159
160
static unsigned
161
105
getScatteredRelocationLength(const MachO::any_relocation_info &RE) {
162
105
  return (RE.r_word0 >> 28) & 3;
163
105
}
164
165
static unsigned getPlainRelocationType(const MachOObjectFile &O,
166
3.15k
                                       const MachO::any_relocation_info &RE) {
167
3.15k
  if (O.isLittleEndian())
168
3.13k
    return RE.r_word1 >> 28;
169
20
  return RE.r_word1 & 0xf;
170
20
}
171
172
static uint32_t getSectionFlags(const MachOObjectFile &O,
173
28.2k
                                DataRefImpl Sec) {
174
28.2k
  if (O.is64Bit()) {
175
25.9k
    MachO::section_64 Sect = O.getSection64(Sec);
176
25.9k
    return Sect.flags;
177
25.9k
  }
178
2.32k
  MachO::section Sect = O.getSection(Sec);
179
2.32k
  return Sect.flags;
180
2.32k
}
181
182
static Expected<MachOObjectFile::LoadCommandInfo>
183
getLoadCommandInfo(const MachOObjectFile &Obj, const char *Ptr,
184
14.1k
                   uint32_t LoadCommandIndex) {
185
14.1k
  if (auto CmdOrErr = getStructOrErr<MachO::load_command>(Obj, Ptr)) {
186
14.1k
    if (CmdOrErr->cmdsize + Ptr > Obj.getData().end())
187
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
188
1
                            " extends past end of file");
189
14.1k
    if (CmdOrErr->cmdsize < 8)
190
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
191
1
                            " with size less than 8 bytes");
192
14.1k
    return MachOObjectFile::LoadCommandInfo({Ptr, *CmdOrErr});
193
14.1k
  } else
194
0
    return CmdOrErr.takeError();
195
14.1k
}
196
197
static Expected<MachOObjectFile::LoadCommandInfo>
198
2.68k
getFirstLoadCommandInfo(const MachOObjectFile &Obj) {
199
2.68k
  unsigned HeaderSize = Obj.is64Bit() ? 
sizeof(MachO::mach_header_64)2.15k
200
2.68k
                                      : 
sizeof(MachO::mach_header)526
;
201
2.68k
  if (sizeof(MachO::load_command) > Obj.getHeader().sizeofcmds)
202
1
    return malformedError("load command 0 extends past the end all load "
203
1
                          "commands in the file");
204
2.68k
  return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
205
2.68k
}
206
207
static Expected<MachOObjectFile::LoadCommandInfo>
208
getNextLoadCommandInfo(const MachOObjectFile &Obj, uint32_t LoadCommandIndex,
209
11.5k
                       const MachOObjectFile::LoadCommandInfo &L) {
210
11.5k
  unsigned HeaderSize = Obj.is64Bit() ? 
sizeof(MachO::mach_header_64)9.85k
211
11.5k
                                      : 
sizeof(MachO::mach_header)1.64k
;
212
11.5k
  if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
213
11.5k
      Obj.getData().data() + HeaderSize + Obj.getHeader().sizeofcmds)
214
1
    return malformedError("load command " + Twine(LoadCommandIndex + 1) +
215
1
                          " extends past the end all load commands in the file");
216
11.4k
  return getLoadCommandInfo(Obj, L.Ptr + L.C.cmdsize, LoadCommandIndex + 1);
217
11.4k
}
218
219
template <typename T>
220
static void parseHeader(const MachOObjectFile &Obj, T &Header,
221
2.72k
                        Error &Err) {
222
2.72k
  if (sizeof(T) > Obj.getData().size()) {
223
0
    Err = malformedError("the mach header extends past the end of the "
224
0
                         "file");
225
0
    return;
226
0
  }
227
2.72k
  if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
228
2.72k
    Header = *HeaderOrErr;
229
0
  else
230
0
    Err = HeaderOrErr.takeError();
231
2.72k
}
MachOObjectFile.cpp:void parseHeader<llvm::MachO::mach_header_64>(llvm::object::MachOObjectFile const&, llvm::MachO::mach_header_64&, llvm::Error&)
Line
Count
Source
221
2.17k
                        Error &Err) {
222
2.17k
  if (sizeof(T) > Obj.getData().size()) {
223
0
    Err = malformedError("the mach header extends past the end of the "
224
0
                         "file");
225
0
    return;
226
0
  }
227
2.17k
  if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
228
2.17k
    Header = *HeaderOrErr;
229
0
  else
230
0
    Err = HeaderOrErr.takeError();
231
2.17k
}
MachOObjectFile.cpp:void parseHeader<llvm::MachO::mach_header>(llvm::object::MachOObjectFile const&, llvm::MachO::mach_header&, llvm::Error&)
Line
Count
Source
221
550
                        Error &Err) {
222
550
  if (sizeof(T) > Obj.getData().size()) {
223
0
    Err = malformedError("the mach header extends past the end of the "
224
0
                         "file");
225
0
    return;
226
0
  }
227
550
  if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
228
550
    Header = *HeaderOrErr;
229
0
  else
230
0
    Err = HeaderOrErr.takeError();
231
550
}
232
233
// This is used to check for overlapping of Mach-O elements.
234
struct MachOElement {
235
  uint64_t Offset;
236
  uint64_t Size;
237
  const char *Name;
238
};
239
240
static Error checkOverlappingElement(std::list<MachOElement> &Elements,
241
                                     uint64_t Offset, uint64_t Size,
242
55.6k
                                     const char *Name) {
243
55.6k
  if (Size == 0)
244
30.6k
    return Error::success();
245
25.0k
246
186k
  
for (auto it=Elements.begin() ; 25.0k
it != Elements.end();
++it161k
) {
247
170k
    auto E = *it;
248
170k
    if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
249
170k
        
(170k
Offset + Size > E.Offset170k
&&
Offset + Size < E.Offset + E.Size170k
) ||
250
170k
        
(170k
Offset <= E.Offset170k
&&
Offset + Size >= E.Offset + E.Size0
))
251
20
      return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
252
20
                            " with a size of " + Twine(Size) + ", overlaps " +
253
20
                            E.Name + " at offset " + Twine(E.Offset) + " with "
254
20
                            "a size of " + Twine(E.Size));
255
170k
    auto nt = it;
256
170k
    nt++;
257
170k
    if (nt != Elements.end()) {
258
154k
      auto N = *nt;
259
154k
      if (Offset + Size <= N.Offset) {
260
9.06k
        Elements.insert(nt, {Offset, Size, Name});
261
9.06k
        return Error::success();
262
9.06k
      }
263
154k
    }
264
170k
  }
265
25.0k
  Elements.push_back({Offset, Size, Name});
266
15.9k
  return Error::success();
267
25.0k
}
268
269
// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
270
// sections to \param Sections, and optionally sets
271
// \param IsPageZeroSegment to true.
272
template <typename Segment, typename Section>
273
static Error parseSegmentLoadCommand(
274
    const MachOObjectFile &Obj, const MachOObjectFile::LoadCommandInfo &Load,
275
    SmallVectorImpl<const char *> &Sections, bool &IsPageZeroSegment,
276
    uint32_t LoadCommandIndex, const char *CmdName, uint64_t SizeOfHeaders,
277
4.07k
    std::list<MachOElement> &Elements) {
278
4.07k
  const unsigned SegmentLoadSize = sizeof(Segment);
279
4.07k
  if (Load.C.cmdsize < SegmentLoadSize)
280
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
281
1
                          " " + CmdName + " cmdsize too small");
282
4.06k
  if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
283
4.06k
    Segment S = SegOrErr.get();
284
4.06k
    const unsigned SectionSize = sizeof(Section);
285
4.06k
    uint64_t FileSize = Obj.getData().size();
286
4.06k
    if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
287
4.06k
        S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
288
2
      return malformedError("load command " + Twine(LoadCommandIndex) +
289
2
                            " inconsistent cmdsize in " + CmdName +
290
2
                            " for the number of sections");
291
22.5k
    
for (unsigned J = 0; 4.06k
J < S.nsects;
++J18.4k
) {
292
18.4k
      const char *Sec = getSectionPtr(Obj, Load, J);
293
18.4k
      Sections.push_back(Sec);
294
18.4k
      auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
295
18.4k
      if (!SectionOrErr)
296
0
        return SectionOrErr.takeError();
297
18.4k
      Section s = SectionOrErr.get();
298
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
299
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
300
18.4k
          
s.flags != MachO::S_ZEROFILL16.6k
&&
301
18.4k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL16.2k
&&
302
18.4k
          
s.offset > FileSize16.1k
)
303
1
        return malformedError("offset field of section " + Twine(J) + " in " +
304
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
305
1
                              " extends past the end of the file");
306
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
307
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
308
18.4k
          
s.flags != MachO::S_ZEROFILL16.6k
&&
309
18.4k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL16.2k
&&
S.fileoff == 016.1k
&&
310
18.4k
          
s.offset < SizeOfHeaders1.30k
&&
s.size != 033
)
311
1
        return malformedError("offset field of section " + Twine(J) + " in " +
312
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
313
1
                              " not past the headers of the file");
314
18.4k
      uint64_t BigSize = s.offset;
315
18.4k
      BigSize += s.size;
316
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
317
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
318
18.4k
          
s.flags != MachO::S_ZEROFILL16.6k
&&
319
18.4k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL16.1k
&&
320
18.4k
          
BigSize > FileSize16.1k
)
321
2
        return malformedError("offset field plus size field of section " +
322
2
                              Twine(J) + " in " + CmdName + " command " +
323
2
                              Twine(LoadCommandIndex) +
324
2
                              " extends past the end of the file");
325
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
326
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
327
18.4k
          
s.flags != MachO::S_ZEROFILL16.6k
&&
328
18.4k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL16.1k
&&
329
18.4k
          
s.size > S.filesize16.1k
)
330
1
        return malformedError("size field of section " +
331
1
                              Twine(J) + " in " + CmdName + " command " +
332
1
                              Twine(LoadCommandIndex) +
333
1
                              " greater than the segment");
334
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
335
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
s.size != 016.6k
&&
336
18.4k
          
s.addr < S.vmaddr14.8k
)
337
1
        return malformedError("addr field of section " + Twine(J) + " in " +
338
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
339
1
                              " less than the segment's vmaddr");
340
18.4k
      BigSize = s.addr;
341
18.4k
      BigSize += s.size;
342
18.4k
      uint64_t BigEnd = S.vmaddr;
343
18.4k
      BigEnd += S.vmsize;
344
18.4k
      if (S.vmsize != 0 && 
s.size != 018.3k
&&
BigSize > BigEnd16.6k
)
345
3
        return malformedError("addr field plus size of section " + Twine(J) +
346
3
                              " in " + CmdName + " command " +
347
3
                              Twine(LoadCommandIndex) +
348
3
                              " greater than than "
349
3
                              "the segment's vmaddr plus vmsize");
350
18.4k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
351
18.4k
          
Obj.getHeader().filetype != MachO::MH_DSYM18.4k
&&
352
18.4k
          
s.flags != MachO::S_ZEROFILL16.6k
&&
353
18.4k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL16.1k
)
354
16.1k
        if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
355
2
                                                "section contents"))
356
2
          return Err;
357
18.4k
      if (s.reloff > FileSize)
358
1
        return malformedError("reloff field of section " + Twine(J) + " in " +
359
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
360
1
                              " extends past the end of the file");
361
18.4k
      BigSize = s.nreloc;
362
18.4k
      BigSize *= sizeof(struct MachO::relocation_info);
363
18.4k
      BigSize += s.reloff;
364
18.4k
      if (BigSize > FileSize)
365
1
        return malformedError("reloff field plus nreloc field times sizeof("
366
1
                              "struct relocation_info) of section " +
367
1
                              Twine(J) + " in " + CmdName + " command " +
368
1
                              Twine(LoadCommandIndex) +
369
1
                              " extends past the end of the file");
370
18.4k
      if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
371
2
                                              sizeof(struct
372
2
                                              MachO::relocation_info),
373
2
                                              "section relocation entries"))
374
2
        return Err;
375
18.4k
    }
376
4.06k
    
if (4.05k
S.fileoff > FileSize4.05k
)
377
3
      return malformedError("load command " + Twine(LoadCommandIndex) +
378
3
                            " fileoff field in " + CmdName +
379
3
                            " extends past the end of the file");
380
4.04k
    uint64_t BigSize = S.fileoff;
381
4.04k
    BigSize += S.filesize;
382
4.04k
    if (BigSize > FileSize)
383
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
384
1
                            " fileoff field plus filesize field in " +
385
1
                            CmdName + " extends past the end of the file");
386
4.04k
    if (S.vmsize != 0 && 
S.filesize > S.vmsize4.00k
)
387
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
388
1
                            " filesize field in " + CmdName +
389
1
                            " greater than vmsize field");
390
4.04k
    IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
391
4.04k
  } else
392
0
    return SegOrErr.takeError();
393
4.04k
394
4.04k
  return Error::success();
395
4.04k
}
MachOObjectFile.cpp:llvm::Error parseSegmentLoadCommand<llvm::MachO::segment_command_64, llvm::MachO::section_64>(llvm::object::MachOObjectFile const&, llvm::object::MachOObjectFile::LoadCommandInfo const&, llvm::SmallVectorImpl<char const*>&, bool&, unsigned int, char const*, unsigned long long, std::__1::list<MachOElement, std::__1::allocator<MachOElement> >&)
Line
Count
Source
277
3.48k
    std::list<MachOElement> &Elements) {
278
3.48k
  const unsigned SegmentLoadSize = sizeof(Segment);
279
3.48k
  if (Load.C.cmdsize < SegmentLoadSize)
280
0
    return malformedError("load command " + Twine(LoadCommandIndex) +
281
0
                          " " + CmdName + " cmdsize too small");
282
3.48k
  if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
283
3.48k
    Segment S = SegOrErr.get();
284
3.48k
    const unsigned SectionSize = sizeof(Section);
285
3.48k
    uint64_t FileSize = Obj.getData().size();
286
3.48k
    if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
287
3.48k
        S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
288
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
289
1
                            " inconsistent cmdsize in " + CmdName +
290
1
                            " for the number of sections");
291
20.0k
    
for (unsigned J = 0; 3.48k
J < S.nsects;
++J16.5k
) {
292
16.5k
      const char *Sec = getSectionPtr(Obj, Load, J);
293
16.5k
      Sections.push_back(Sec);
294
16.5k
      auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
295
16.5k
      if (!SectionOrErr)
296
0
        return SectionOrErr.takeError();
297
16.5k
      Section s = SectionOrErr.get();
298
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
299
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
300
16.5k
          
s.flags != MachO::S_ZEROFILL14.7k
&&
301
16.5k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL14.4k
&&
302
16.5k
          
s.offset > FileSize14.3k
)
303
0
        return malformedError("offset field of section " + Twine(J) + " in " +
304
0
                              CmdName + " command " + Twine(LoadCommandIndex) +
305
0
                              " extends past the end of the file");
306
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
307
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
308
16.5k
          
s.flags != MachO::S_ZEROFILL14.7k
&&
309
16.5k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL14.4k
&&
S.fileoff == 014.3k
&&
310
16.5k
          
s.offset < SizeOfHeaders1.15k
&&
s.size != 024
)
311
0
        return malformedError("offset field of section " + Twine(J) + " in " +
312
0
                              CmdName + " command " + Twine(LoadCommandIndex) +
313
0
                              " not past the headers of the file");
314
16.5k
      uint64_t BigSize = s.offset;
315
16.5k
      BigSize += s.size;
316
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
317
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
318
16.5k
          
s.flags != MachO::S_ZEROFILL14.7k
&&
319
16.5k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL14.4k
&&
320
16.5k
          
BigSize > FileSize14.3k
)
321
1
        return malformedError("offset field plus size field of section " +
322
1
                              Twine(J) + " in " + CmdName + " command " +
323
1
                              Twine(LoadCommandIndex) +
324
1
                              " extends past the end of the file");
325
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
326
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
327
16.5k
          
s.flags != MachO::S_ZEROFILL14.7k
&&
328
16.5k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL14.3k
&&
329
16.5k
          
s.size > S.filesize14.3k
)
330
0
        return malformedError("size field of section " +
331
0
                              Twine(J) + " in " + CmdName + " command " +
332
0
                              Twine(LoadCommandIndex) +
333
0
                              " greater than the segment");
334
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
335
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
s.size != 014.7k
&&
336
16.5k
          
s.addr < S.vmaddr13.2k
)
337
0
        return malformedError("addr field of section " + Twine(J) + " in " +
338
0
                              CmdName + " command " + Twine(LoadCommandIndex) +
339
0
                              " less than the segment's vmaddr");
340
16.5k
      BigSize = s.addr;
341
16.5k
      BigSize += s.size;
342
16.5k
      uint64_t BigEnd = S.vmaddr;
343
16.5k
      BigEnd += S.vmsize;
344
16.5k
      if (S.vmsize != 0 && 
s.size != 016.5k
&&
BigSize > BigEnd15.0k
)
345
2
        return malformedError("addr field plus size of section " + Twine(J) +
346
2
                              " in " + CmdName + " command " +
347
2
                              Twine(LoadCommandIndex) +
348
2
                              " greater than than "
349
2
                              "the segment's vmaddr plus vmsize");
350
16.5k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
351
16.5k
          
Obj.getHeader().filetype != MachO::MH_DSYM16.5k
&&
352
16.5k
          
s.flags != MachO::S_ZEROFILL14.7k
&&
353
16.5k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL14.3k
)
354
14.3k
        if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
355
2
                                                "section contents"))
356
2
          return Err;
357
16.5k
      if (s.reloff > FileSize)
358
0
        return malformedError("reloff field of section " + Twine(J) + " in " +
359
0
                              CmdName + " command " + Twine(LoadCommandIndex) +
360
0
                              " extends past the end of the file");
361
16.5k
      BigSize = s.nreloc;
362
16.5k
      BigSize *= sizeof(struct MachO::relocation_info);
363
16.5k
      BigSize += s.reloff;
364
16.5k
      if (BigSize > FileSize)
365
0
        return malformedError("reloff field plus nreloc field times sizeof("
366
0
                              "struct relocation_info) of section " +
367
0
                              Twine(J) + " in " + CmdName + " command " +
368
0
                              Twine(LoadCommandIndex) +
369
0
                              " extends past the end of the file");
370
16.5k
      if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
371
1
                                              sizeof(struct
372
1
                                              MachO::relocation_info),
373
1
                                              "section relocation entries"))
374
1
        return Err;
375
16.5k
    }
376
3.48k
    
if (3.47k
S.fileoff > FileSize3.47k
)
377
0
      return malformedError("load command " + Twine(LoadCommandIndex) +
378
0
                            " fileoff field in " + CmdName +
379
0
                            " extends past the end of the file");
380
3.47k
    uint64_t BigSize = S.fileoff;
381
3.47k
    BigSize += S.filesize;
382
3.47k
    if (BigSize > FileSize)
383
0
      return malformedError("load command " + Twine(LoadCommandIndex) +
384
0
                            " fileoff field plus filesize field in " +
385
0
                            CmdName + " extends past the end of the file");
386
3.47k
    if (S.vmsize != 0 && 
S.filesize > S.vmsize3.44k
)
387
0
      return malformedError("load command " + Twine(LoadCommandIndex) +
388
0
                            " filesize field in " + CmdName +
389
0
                            " greater than vmsize field");
390
3.47k
    IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
391
3.47k
  } else
392
0
    return SegOrErr.takeError();
393
3.47k
394
3.47k
  return Error::success();
395
3.47k
}
MachOObjectFile.cpp:llvm::Error parseSegmentLoadCommand<llvm::MachO::segment_command, llvm::MachO::section>(llvm::object::MachOObjectFile const&, llvm::object::MachOObjectFile::LoadCommandInfo const&, llvm::SmallVectorImpl<char const*>&, bool&, unsigned int, char const*, unsigned long long, std::__1::list<MachOElement, std::__1::allocator<MachOElement> >&)
Line
Count
Source
277
586
    std::list<MachOElement> &Elements) {
278
586
  const unsigned SegmentLoadSize = sizeof(Segment);
279
586
  if (Load.C.cmdsize < SegmentLoadSize)
280
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
281
1
                          " " + CmdName + " cmdsize too small");
282
585
  if (auto SegOrErr = getStructOrErr<Segment>(Obj, Load.Ptr)) {
283
585
    Segment S = SegOrErr.get();
284
585
    const unsigned SectionSize = sizeof(Section);
285
585
    uint64_t FileSize = Obj.getData().size();
286
585
    if (S.nsects > std::numeric_limits<uint32_t>::max() / SectionSize ||
287
585
        S.nsects * SectionSize > Load.C.cmdsize - SegmentLoadSize)
288
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
289
1
                            " inconsistent cmdsize in " + CmdName +
290
1
                            " for the number of sections");
291
2.45k
    
for (unsigned J = 0; 584
J < S.nsects;
++J1.87k
) {
292
1.87k
      const char *Sec = getSectionPtr(Obj, Load, J);
293
1.87k
      Sections.push_back(Sec);
294
1.87k
      auto SectionOrErr = getStructOrErr<Section>(Obj, Sec);
295
1.87k
      if (!SectionOrErr)
296
0
        return SectionOrErr.takeError();
297
1.87k
      Section s = SectionOrErr.get();
298
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
299
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM &&
300
1.87k
          
s.flags != MachO::S_ZEROFILL1.84k
&&
301
1.87k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL1.80k
&&
302
1.87k
          
s.offset > FileSize1.79k
)
303
1
        return malformedError("offset field of section " + Twine(J) + " in " +
304
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
305
1
                              " extends past the end of the file");
306
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
307
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM &&
308
1.87k
          
s.flags != MachO::S_ZEROFILL1.84k
&&
309
1.87k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL1.80k
&&
S.fileoff == 01.79k
&&
310
1.87k
          
s.offset < SizeOfHeaders149
&&
s.size != 09
)
311
1
        return malformedError("offset field of section " + Twine(J) + " in " +
312
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
313
1
                              " not past the headers of the file");
314
1.87k
      uint64_t BigSize = s.offset;
315
1.87k
      BigSize += s.size;
316
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
317
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM &&
318
1.87k
          
s.flags != MachO::S_ZEROFILL1.84k
&&
319
1.87k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL1.79k
&&
320
1.87k
          
BigSize > FileSize1.79k
)
321
1
        return malformedError("offset field plus size field of section " +
322
1
                              Twine(J) + " in " + CmdName + " command " +
323
1
                              Twine(LoadCommandIndex) +
324
1
                              " extends past the end of the file");
325
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
326
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM &&
327
1.87k
          
s.flags != MachO::S_ZEROFILL1.84k
&&
328
1.87k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL1.79k
&&
329
1.87k
          
s.size > S.filesize1.79k
)
330
1
        return malformedError("size field of section " +
331
1
                              Twine(J) + " in " + CmdName + " command " +
332
1
                              Twine(LoadCommandIndex) +
333
1
                              " greater than the segment");
334
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
335
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM && 
s.size != 01.83k
&&
336
1.87k
          
s.addr < S.vmaddr1.51k
)
337
1
        return malformedError("addr field of section " + Twine(J) + " in " +
338
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
339
1
                              " less than the segment's vmaddr");
340
1.87k
      BigSize = s.addr;
341
1.87k
      BigSize += s.size;
342
1.87k
      uint64_t BigEnd = S.vmaddr;
343
1.87k
      BigEnd += S.vmsize;
344
1.87k
      if (S.vmsize != 0 && 
s.size != 01.79k
&&
BigSize > BigEnd1.54k
)
345
1
        return malformedError("addr field plus size of section " + Twine(J) +
346
1
                              " in " + CmdName + " command " +
347
1
                              Twine(LoadCommandIndex) +
348
1
                              " greater than than "
349
1
                              "the segment's vmaddr plus vmsize");
350
1.87k
      if (Obj.getHeader().filetype != MachO::MH_DYLIB_STUB &&
351
1.87k
          Obj.getHeader().filetype != MachO::MH_DSYM &&
352
1.87k
          
s.flags != MachO::S_ZEROFILL1.83k
&&
353
1.87k
          
s.flags != MachO::S_THREAD_LOCAL_ZEROFILL1.79k
)
354
1.79k
        if (Error Err = checkOverlappingElement(Elements, s.offset, s.size,
355
0
                                                "section contents"))
356
0
          return Err;
357
1.87k
      if (s.reloff > FileSize)
358
1
        return malformedError("reloff field of section " + Twine(J) + " in " +
359
1
                              CmdName + " command " + Twine(LoadCommandIndex) +
360
1
                              " extends past the end of the file");
361
1.87k
      BigSize = s.nreloc;
362
1.87k
      BigSize *= sizeof(struct MachO::relocation_info);
363
1.87k
      BigSize += s.reloff;
364
1.87k
      if (BigSize > FileSize)
365
1
        return malformedError("reloff field plus nreloc field times sizeof("
366
1
                              "struct relocation_info) of section " +
367
1
                              Twine(J) + " in " + CmdName + " command " +
368
1
                              Twine(LoadCommandIndex) +
369
1
                              " extends past the end of the file");
370
1.87k
      if (Error Err = checkOverlappingElement(Elements, s.reloff, s.nreloc *
371
1
                                              sizeof(struct
372
1
                                              MachO::relocation_info),
373
1
                                              "section relocation entries"))
374
1
        return Err;
375
1.87k
    }
376
584
    
if (575
S.fileoff > FileSize575
)
377
3
      return malformedError("load command " + Twine(LoadCommandIndex) +
378
3
                            " fileoff field in " + CmdName +
379
3
                            " extends past the end of the file");
380
572
    uint64_t BigSize = S.fileoff;
381
572
    BigSize += S.filesize;
382
572
    if (BigSize > FileSize)
383
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
384
1
                            " fileoff field plus filesize field in " +
385
1
                            CmdName + " extends past the end of the file");
386
571
    if (S.vmsize != 0 && 
S.filesize > S.vmsize562
)
387
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
388
1
                            " filesize field in " + CmdName +
389
1
                            " greater than vmsize field");
390
570
    IsPageZeroSegment |= StringRef("__PAGEZERO").equals(S.segname);
391
570
  } else
392
0
    return SegOrErr.takeError();
393
570
394
570
  return Error::success();
395
570
}
396
397
static Error checkSymtabCommand(const MachOObjectFile &Obj,
398
                                const MachOObjectFile::LoadCommandInfo &Load,
399
                                uint32_t LoadCommandIndex,
400
                                const char **SymtabLoadCmd,
401
2.34k
                                std::list<MachOElement> &Elements) {
402
2.34k
  if (Load.C.cmdsize < sizeof(MachO::symtab_command))
403
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
404
1
                          " LC_SYMTAB cmdsize too small");
405
2.34k
  if (*SymtabLoadCmd != nullptr)
406
1
    return malformedError("more than one LC_SYMTAB command");
407
2.34k
  auto SymtabOrErr = getStructOrErr<MachO::symtab_command>(Obj, Load.Ptr);
408
2.34k
  if (!SymtabOrErr)
409
0
    return SymtabOrErr.takeError();
410
2.34k
  MachO::symtab_command Symtab = SymtabOrErr.get();
411
2.34k
  if (Symtab.cmdsize != sizeof(MachO::symtab_command))
412
1
    return malformedError("LC_SYMTAB command " + Twine(LoadCommandIndex) +
413
1
                          " has incorrect cmdsize");
414
2.34k
  uint64_t FileSize = Obj.getData().size();
415
2.34k
  if (Symtab.symoff > FileSize)
416
1
    return malformedError("symoff field of LC_SYMTAB command " +
417
1
                          Twine(LoadCommandIndex) + " extends past the end "
418
1
                          "of the file");
419
2.34k
  uint64_t SymtabSize = Symtab.nsyms;
420
2.34k
  const char *struct_nlist_name;
421
2.34k
  if (Obj.is64Bit()) {
422
1.97k
    SymtabSize *= sizeof(MachO::nlist_64);
423
1.97k
    struct_nlist_name = "struct nlist_64";
424
1.97k
  } else {
425
362
    SymtabSize *= sizeof(MachO::nlist);
426
362
    struct_nlist_name = "struct nlist";
427
362
  }
428
2.34k
  uint64_t BigSize = SymtabSize;
429
2.34k
  BigSize += Symtab.symoff;
430
2.34k
  if (BigSize > FileSize)
431
1
    return malformedError("symoff field plus nsyms field times sizeof(" +
432
1
                          Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
433
1
                          Twine(LoadCommandIndex) + " extends past the end "
434
1
                          "of the file");
435
2.33k
  if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
436
2
                                          "symbol table"))
437
2
    return Err;
438
2.33k
  if (Symtab.stroff > FileSize)
439
1
    return malformedError("stroff field of LC_SYMTAB command " +
440
1
                          Twine(LoadCommandIndex) + " extends past the end "
441
1
                          "of the file");
442
2.33k
  BigSize = Symtab.stroff;
443
2.33k
  BigSize += Symtab.strsize;
444
2.33k
  if (BigSize > FileSize)
445
1
    return malformedError("stroff field plus strsize field of LC_SYMTAB "
446
1
                          "command " + Twine(LoadCommandIndex) + " extends "
447
1
                          "past the end of the file");
448
2.33k
  if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
449
1
                                          Symtab.strsize, "string table"))
450
1
    return Err;
451
2.33k
  *SymtabLoadCmd = Load.Ptr;
452
2.33k
  return Error::success();
453
2.33k
}
454
455
static Error checkDysymtabCommand(const MachOObjectFile &Obj,
456
                                  const MachOObjectFile::LoadCommandInfo &Load,
457
                                  uint32_t LoadCommandIndex,
458
                                  const char **DysymtabLoadCmd,
459
2.20k
                                  std::list<MachOElement> &Elements) {
460
2.20k
  if (Load.C.cmdsize < sizeof(MachO::dysymtab_command))
461
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
462
1
                          " LC_DYSYMTAB cmdsize too small");
463
2.20k
  if (*DysymtabLoadCmd != nullptr)
464
1
    return malformedError("more than one LC_DYSYMTAB command");
465
2.20k
  auto DysymtabOrErr =
466
2.20k
    getStructOrErr<MachO::dysymtab_command>(Obj, Load.Ptr);
467
2.20k
  if (!DysymtabOrErr)
468
0
    return DysymtabOrErr.takeError();
469
2.20k
  MachO::dysymtab_command Dysymtab = DysymtabOrErr.get();
470
2.20k
  if (Dysymtab.cmdsize != sizeof(MachO::dysymtab_command))
471
1
    return malformedError("LC_DYSYMTAB command " + Twine(LoadCommandIndex) +
472
1
                          " has incorrect cmdsize");
473
2.20k
  uint64_t FileSize = Obj.getData().size();
474
2.20k
  if (Dysymtab.tocoff > FileSize)
475
1
    return malformedError("tocoff field of LC_DYSYMTAB command " +
476
1
                          Twine(LoadCommandIndex) + " extends past the end of "
477
1
                          "the file");
478
2.20k
  uint64_t BigSize = Dysymtab.ntoc;
479
2.20k
  BigSize *= sizeof(MachO::dylib_table_of_contents);
480
2.20k
  BigSize += Dysymtab.tocoff;
481
2.20k
  if (BigSize > FileSize)
482
1
    return malformedError("tocoff field plus ntoc field times sizeof(struct "
483
1
                          "dylib_table_of_contents) of LC_DYSYMTAB command " +
484
1
                          Twine(LoadCommandIndex) + " extends past the end of "
485
1
                          "the file");
486
2.20k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.tocoff,
487
1
                                          Dysymtab.ntoc * sizeof(struct
488
1
                                          MachO::dylib_table_of_contents),
489
1
                                          "table of contents"))
490
1
    return Err;
491
2.20k
  if (Dysymtab.modtaboff > FileSize)
492
1
    return malformedError("modtaboff field of LC_DYSYMTAB command " +
493
1
                          Twine(LoadCommandIndex) + " extends past the end of "
494
1
                          "the file");
495
2.20k
  BigSize = Dysymtab.nmodtab;
496
2.20k
  const char *struct_dylib_module_name;
497
2.20k
  uint64_t sizeof_modtab;
498
2.20k
  if (Obj.is64Bit()) {
499
1.85k
    sizeof_modtab = sizeof(MachO::dylib_module_64);
500
1.85k
    struct_dylib_module_name = "struct dylib_module_64";
501
1.85k
  } else {
502
350
    sizeof_modtab = sizeof(MachO::dylib_module);
503
350
    struct_dylib_module_name = "struct dylib_module";
504
350
  }
505
2.20k
  BigSize *= sizeof_modtab;
506
2.20k
  BigSize += Dysymtab.modtaboff;
507
2.20k
  if (BigSize > FileSize)
508
1
    return malformedError("modtaboff field plus nmodtab field times sizeof(" +
509
1
                          Twine(struct_dylib_module_name) + ") of LC_DYSYMTAB "
510
1
                          "command " + Twine(LoadCommandIndex) + " extends "
511
1
                          "past the end of the file");
512
2.20k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.modtaboff,
513
1
                                          Dysymtab.nmodtab * sizeof_modtab,
514
1
                                          "module table"))
515
1
    return Err;
516
2.19k
  if (Dysymtab.extrefsymoff > FileSize)
517
1
    return malformedError("extrefsymoff field of LC_DYSYMTAB command " +
518
1
                          Twine(LoadCommandIndex) + " extends past the end of "
519
1
                          "the file");
520
2.19k
  BigSize = Dysymtab.nextrefsyms;
521
2.19k
  BigSize *= sizeof(MachO::dylib_reference);
522
2.19k
  BigSize += Dysymtab.extrefsymoff;
523
2.19k
  if (BigSize > FileSize)
524
1
    return malformedError("extrefsymoff field plus nextrefsyms field times "
525
1
                          "sizeof(struct dylib_reference) of LC_DYSYMTAB "
526
1
                          "command " + Twine(LoadCommandIndex) + " extends "
527
1
                          "past the end of the file");
528
2.19k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.extrefsymoff,
529
1
                                          Dysymtab.nextrefsyms *
530
1
                                              sizeof(MachO::dylib_reference),
531
1
                                          "reference table"))
532
1
    return Err;
533
2.19k
  if (Dysymtab.indirectsymoff > FileSize)
534
1
    return malformedError("indirectsymoff field of LC_DYSYMTAB command " +
535
1
                          Twine(LoadCommandIndex) + " extends past the end of "
536
1
                          "the file");
537
2.19k
  BigSize = Dysymtab.nindirectsyms;
538
2.19k
  BigSize *= sizeof(uint32_t);
539
2.19k
  BigSize += Dysymtab.indirectsymoff;
540
2.19k
  if (BigSize > FileSize)
541
1
    return malformedError("indirectsymoff field plus nindirectsyms field times "
542
1
                          "sizeof(uint32_t) of LC_DYSYMTAB command " +
543
1
                          Twine(LoadCommandIndex) + " extends past the end of "
544
1
                          "the file");
545
2.19k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.indirectsymoff,
546
1
                                          Dysymtab.nindirectsyms *
547
1
                                          sizeof(uint32_t),
548
1
                                          "indirect table"))
549
1
    return Err;
550
2.19k
  if (Dysymtab.extreloff > FileSize)
551
1
    return malformedError("extreloff field of LC_DYSYMTAB command " +
552
1
                          Twine(LoadCommandIndex) + " extends past the end of "
553
1
                          "the file");
554
2.19k
  BigSize = Dysymtab.nextrel;
555
2.19k
  BigSize *= sizeof(MachO::relocation_info);
556
2.19k
  BigSize += Dysymtab.extreloff;
557
2.19k
  if (BigSize > FileSize)
558
1
    return malformedError("extreloff field plus nextrel field times sizeof"
559
1
                          "(struct relocation_info) of LC_DYSYMTAB command " +
560
1
                          Twine(LoadCommandIndex) + " extends past the end of "
561
1
                          "the file");
562
2.19k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.extreloff,
563
1
                                          Dysymtab.nextrel *
564
1
                                              sizeof(MachO::relocation_info),
565
1
                                          "external relocation table"))
566
1
    return Err;
567
2.19k
  if (Dysymtab.locreloff > FileSize)
568
1
    return malformedError("locreloff field of LC_DYSYMTAB command " +
569
1
                          Twine(LoadCommandIndex) + " extends past the end of "
570
1
                          "the file");
571
2.18k
  BigSize = Dysymtab.nlocrel;
572
2.18k
  BigSize *= sizeof(MachO::relocation_info);
573
2.18k
  BigSize += Dysymtab.locreloff;
574
2.18k
  if (BigSize > FileSize)
575
1
    return malformedError("locreloff field plus nlocrel field times sizeof"
576
1
                          "(struct relocation_info) of LC_DYSYMTAB command " +
577
1
                          Twine(LoadCommandIndex) + " extends past the end of "
578
1
                          "the file");
579
2.18k
  if (Error Err = checkOverlappingElement(Elements, Dysymtab.locreloff,
580
1
                                          Dysymtab.nlocrel *
581
1
                                              sizeof(MachO::relocation_info),
582
1
                                          "local relocation table"))
583
1
    return Err;
584
2.18k
  *DysymtabLoadCmd = Load.Ptr;
585
2.18k
  return Error::success();
586
2.18k
}
587
588
static Error checkLinkeditDataCommand(const MachOObjectFile &Obj,
589
                                 const MachOObjectFile::LoadCommandInfo &Load,
590
                                 uint32_t LoadCommandIndex,
591
                                 const char **LoadCmd, const char *CmdName,
592
                                 std::list<MachOElement> &Elements,
593
1.06k
                                 const char *ElementName) {
594
1.06k
  if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
595
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
596
1
                          CmdName + " cmdsize too small");
597
1.06k
  if (*LoadCmd != nullptr)
598
1
    return malformedError("more than one " + Twine(CmdName) + " command");
599
1.06k
  auto LinkDataOrError =
600
1.06k
    getStructOrErr<MachO::linkedit_data_command>(Obj, Load.Ptr);
601
1.06k
  if (!LinkDataOrError)
602
0
    return LinkDataOrError.takeError();
603
1.06k
  MachO::linkedit_data_command LinkData = LinkDataOrError.get();
604
1.06k
  if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
605
3
    return malformedError(Twine(CmdName) + " command " +
606
3
                          Twine(LoadCommandIndex) + " has incorrect cmdsize");
607
1.06k
  uint64_t FileSize = Obj.getData().size();
608
1.06k
  if (LinkData.dataoff > FileSize)
609
2
    return malformedError("dataoff field of " + Twine(CmdName) + " command " +
610
2
                          Twine(LoadCommandIndex) + " extends past the end of "
611
2
                          "the file");
612
1.06k
  uint64_t BigSize = LinkData.dataoff;
613
1.06k
  BigSize += LinkData.datasize;
614
1.06k
  if (BigSize > FileSize)
615
2
    return malformedError("dataoff field plus datasize field of " +
616
2
                          Twine(CmdName) + " command " +
617
2
                          Twine(LoadCommandIndex) + " extends past the end of "
618
2
                          "the file");
619
1.06k
  if (Error Err = checkOverlappingElement(Elements, LinkData.dataoff,
620
1
                                          LinkData.datasize, ElementName))
621
1
    return Err;
622
1.05k
  *LoadCmd = Load.Ptr;
623
1.05k
  return Error::success();
624
1.05k
}
625
626
static Error checkDyldInfoCommand(const MachOObjectFile &Obj,
627
                                  const MachOObjectFile::LoadCommandInfo &Load,
628
                                  uint32_t LoadCommandIndex,
629
                                  const char **LoadCmd, const char *CmdName,
630
441
                                  std::list<MachOElement> &Elements) {
631
441
  if (Load.C.cmdsize < sizeof(MachO::dyld_info_command))
632
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
633
1
                          CmdName + " cmdsize too small");
634
440
  if (*LoadCmd != nullptr)
635
1
    return malformedError("more than one LC_DYLD_INFO and or LC_DYLD_INFO_ONLY "
636
1
                          "command");
637
439
  auto DyldInfoOrErr =
638
439
    getStructOrErr<MachO::dyld_info_command>(Obj, Load.Ptr);
639
439
  if (!DyldInfoOrErr)
640
0
    return DyldInfoOrErr.takeError();
641
439
  MachO::dyld_info_command DyldInfo = DyldInfoOrErr.get();
642
439
  if (DyldInfo.cmdsize != sizeof(MachO::dyld_info_command))
643
1
    return malformedError(Twine(CmdName) + " command " +
644
1
                          Twine(LoadCommandIndex) + " has incorrect cmdsize");
645
438
  uint64_t FileSize = Obj.getData().size();
646
438
  if (DyldInfo.rebase_off > FileSize)
647
1
    return malformedError("rebase_off field of " + Twine(CmdName) +
648
1
                          " command " + Twine(LoadCommandIndex) + " extends "
649
1
                          "past the end of the file");
650
437
  uint64_t BigSize = DyldInfo.rebase_off;
651
437
  BigSize += DyldInfo.rebase_size;
652
437
  if (BigSize > FileSize)
653
1
    return malformedError("rebase_off field plus rebase_size field of " +
654
1
                          Twine(CmdName) + " command " +
655
1
                          Twine(LoadCommandIndex) + " extends past the end of "
656
1
                          "the file");
657
436
  if (Error Err = checkOverlappingElement(Elements, DyldInfo.rebase_off,
658
1
                                          DyldInfo.rebase_size,
659
1
                                          "dyld rebase info"))
660
1
    return Err;
661
435
  if (DyldInfo.bind_off > FileSize)
662
1
    return malformedError("bind_off field of " + Twine(CmdName) +
663
1
                          " command " + Twine(LoadCommandIndex) + " extends "
664
1
                          "past the end of the file");
665
434
  BigSize = DyldInfo.bind_off;
666
434
  BigSize += DyldInfo.bind_size;
667
434
  if (BigSize > FileSize)
668
1
    return malformedError("bind_off field plus bind_size field of " +
669
1
                          Twine(CmdName) + " command " +
670
1
                          Twine(LoadCommandIndex) + " extends past the end of "
671
1
                          "the file");
672
433
  if (Error Err = checkOverlappingElement(Elements, DyldInfo.bind_off,
673
1
                                          DyldInfo.bind_size,
674
1
                                          "dyld bind info"))
675
1
    return Err;
676
432
  if (DyldInfo.weak_bind_off > FileSize)
677
1
    return malformedError("weak_bind_off field of " + Twine(CmdName) +
678
1
                          " command " + Twine(LoadCommandIndex) + " extends "
679
1
                          "past the end of the file");
680
431
  BigSize = DyldInfo.weak_bind_off;
681
431
  BigSize += DyldInfo.weak_bind_size;
682
431
  if (BigSize > FileSize)
683
1
    return malformedError("weak_bind_off field plus weak_bind_size field of " +
684
1
                          Twine(CmdName) + " command " +
685
1
                          Twine(LoadCommandIndex) + " extends past the end of "
686
1
                          "the file");
687
430
  if (Error Err = checkOverlappingElement(Elements, DyldInfo.weak_bind_off,
688
1
                                          DyldInfo.weak_bind_size,
689
1
                                          "dyld weak bind info"))
690
1
    return Err;
691
429
  if (DyldInfo.lazy_bind_off > FileSize)
692
1
    return malformedError("lazy_bind_off field of " + Twine(CmdName) +
693
1
                          " command " + Twine(LoadCommandIndex) + " extends "
694
1
                          "past the end of the file");
695
428
  BigSize = DyldInfo.lazy_bind_off;
696
428
  BigSize += DyldInfo.lazy_bind_size;
697
428
  if (BigSize > FileSize)
698
1
    return malformedError("lazy_bind_off field plus lazy_bind_size field of " +
699
1
                          Twine(CmdName) + " command " +
700
1
                          Twine(LoadCommandIndex) + " extends past the end of "
701
1
                          "the file");
702
427
  if (Error Err = checkOverlappingElement(Elements, DyldInfo.lazy_bind_off,
703
1
                                          DyldInfo.lazy_bind_size,
704
1
                                          "dyld lazy bind info"))
705
1
    return Err;
706
426
  if (DyldInfo.export_off > FileSize)
707
1
    return malformedError("export_off field of " + Twine(CmdName) +
708
1
                          " command " + Twine(LoadCommandIndex) + " extends "
709
1
                          "past the end of the file");
710
425
  BigSize = DyldInfo.export_off;
711
425
  BigSize += DyldInfo.export_size;
712
425
  if (BigSize > FileSize)
713
1
    return malformedError("export_off field plus export_size field of " +
714
1
                          Twine(CmdName) + " command " +
715
1
                          Twine(LoadCommandIndex) + " extends past the end of "
716
1
                          "the file");
717
424
  if (Error Err = checkOverlappingElement(Elements, DyldInfo.export_off,
718
1
                                          DyldInfo.export_size,
719
1
                                          "dyld export info"))
720
1
    return Err;
721
423
  *LoadCmd = Load.Ptr;
722
423
  return Error::success();
723
423
}
724
725
static Error checkDylibCommand(const MachOObjectFile &Obj,
726
                               const MachOObjectFile::LoadCommandInfo &Load,
727
675
                               uint32_t LoadCommandIndex, const char *CmdName) {
728
675
  if (Load.C.cmdsize < sizeof(MachO::dylib_command))
729
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
730
1
                          CmdName + " cmdsize too small");
731
674
  auto CommandOrErr = getStructOrErr<MachO::dylib_command>(Obj, Load.Ptr);
732
674
  if (!CommandOrErr)
733
0
    return CommandOrErr.takeError();
734
674
  MachO::dylib_command D = CommandOrErr.get();
735
674
  if (D.dylib.name < sizeof(MachO::dylib_command))
736
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
737
1
                          CmdName + " name.offset field too small, not past "
738
1
                          "the end of the dylib_command struct");
739
673
  if (D.dylib.name >= D.cmdsize)
740
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
741
1
                          CmdName + " name.offset field extends past the end "
742
1
                          "of the load command");
743
672
  // Make sure there is a null between the starting offset of the name and
744
672
  // the end of the load command.
745
672
  uint32_t i;
746
672
  const char *P = (const char *)Load.Ptr;
747
21.0k
  for (i = D.dylib.name; i < D.cmdsize; 
i++20.3k
)
748
21.0k
    if (P[i] == '\0')
749
671
      break;
750
672
  if (i >= D.cmdsize)
751
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
752
1
                          CmdName + " library name extends past the end of the "
753
1
                          "load command");
754
671
  return Error::success();
755
671
}
756
757
static Error checkDylibIdCommand(const MachOObjectFile &Obj,
758
                                 const MachOObjectFile::LoadCommandInfo &Load,
759
                                 uint32_t LoadCommandIndex,
760
124
                                 const char **LoadCmd) {
761
124
  if (Error Err = checkDylibCommand(Obj, Load, LoadCommandIndex,
762
0
                                     "LC_ID_DYLIB"))
763
0
    return Err;
764
124
  if (*LoadCmd != nullptr)
765
1
    return malformedError("more than one LC_ID_DYLIB command");
766
123
  if (Obj.getHeader().filetype != MachO::MH_DYLIB &&
767
123
      
Obj.getHeader().filetype != MachO::MH_DYLIB_STUB2
)
768
1
    return malformedError("LC_ID_DYLIB load command in non-dynamic library "
769
1
                          "file type");
770
122
  *LoadCmd = Load.Ptr;
771
122
  return Error::success();
772
122
}
773
774
static Error checkDyldCommand(const MachOObjectFile &Obj,
775
                              const MachOObjectFile::LoadCommandInfo &Load,
776
304
                              uint32_t LoadCommandIndex, const char *CmdName) {
777
304
  if (Load.C.cmdsize < sizeof(MachO::dylinker_command))
778
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
779
1
                          CmdName + " cmdsize too small");
780
303
  auto CommandOrErr = getStructOrErr<MachO::dylinker_command>(Obj, Load.Ptr);
781
303
  if (!CommandOrErr)
782
0
    return CommandOrErr.takeError();
783
303
  MachO::dylinker_command D = CommandOrErr.get();
784
303
  if (D.name < sizeof(MachO::dylinker_command))
785
0
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
786
0
                          CmdName + " name.offset field too small, not past "
787
0
                          "the end of the dylinker_command struct");
788
303
  if (D.name >= D.cmdsize)
789
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
790
1
                          CmdName + " name.offset field extends past the end "
791
1
                          "of the load command");
792
302
  // Make sure there is a null between the starting offset of the name and
793
302
  // the end of the load command.
794
302
  uint32_t i;
795
302
  const char *P = (const char *)Load.Ptr;
796
4.19k
  for (i = D.name; i < D.cmdsize; 
i++3.89k
)
797
4.19k
    if (P[i] == '\0')
798
301
      break;
799
302
  if (i >= D.cmdsize)
800
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
801
1
                          CmdName + " dyld name extends past the end of the "
802
1
                          "load command");
803
301
  return Error::success();
804
301
}
805
806
static Error checkVersCommand(const MachOObjectFile &Obj,
807
                              const MachOObjectFile::LoadCommandInfo &Load,
808
                              uint32_t LoadCommandIndex,
809
1.67k
                              const char **LoadCmd, const char *CmdName) {
810
1.67k
  if (Load.C.cmdsize != sizeof(MachO::version_min_command))
811
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
812
1
                          CmdName + " has incorrect cmdsize");
813
1.67k
  if (*LoadCmd != nullptr)
814
1
    return malformedError("more than one LC_VERSION_MIN_MACOSX, "
815
1
                          "LC_VERSION_MIN_IPHONEOS, LC_VERSION_MIN_TVOS or "
816
1
                          "LC_VERSION_MIN_WATCHOS command");
817
1.67k
  *LoadCmd = Load.Ptr;
818
1.67k
  return Error::success();
819
1.67k
}
820
821
static Error checkNoteCommand(const MachOObjectFile &Obj,
822
                              const MachOObjectFile::LoadCommandInfo &Load,
823
                              uint32_t LoadCommandIndex,
824
2
                              std::list<MachOElement> &Elements) {
825
2
  if (Load.C.cmdsize != sizeof(MachO::note_command))
826
0
    return malformedError("load command " + Twine(LoadCommandIndex) +
827
0
                          " LC_NOTE has incorrect cmdsize");
828
2
  auto NoteCmdOrErr = getStructOrErr<MachO::note_command>(Obj, Load.Ptr);
829
2
  if (!NoteCmdOrErr)
830
0
    return NoteCmdOrErr.takeError();
831
2
  MachO::note_command Nt = NoteCmdOrErr.get();
832
2
  uint64_t FileSize = Obj.getData().size();
833
2
  if (Nt.offset > FileSize)
834
0
    return malformedError("offset field of LC_NOTE command " +
835
0
                          Twine(LoadCommandIndex) + " extends "
836
0
                          "past the end of the file");
837
2
  uint64_t BigSize = Nt.offset;
838
2
  BigSize += Nt.size;
839
2
  if (BigSize > FileSize)
840
1
    return malformedError("size field plus offset field of LC_NOTE command " +
841
1
                          Twine(LoadCommandIndex) + " extends past the end of "
842
1
                          "the file");
843
1
  if (Error Err = checkOverlappingElement(Elements, Nt.offset, Nt.size,
844
0
                                          "LC_NOTE data"))
845
0
    return Err;
846
1
  return Error::success();
847
1
}
848
849
static Error
850
parseBuildVersionCommand(const MachOObjectFile &Obj,
851
                         const MachOObjectFile::LoadCommandInfo &Load,
852
                         SmallVectorImpl<const char*> &BuildTools,
853
46
                         uint32_t LoadCommandIndex) {
854
46
  auto BVCOrErr =
855
46
    getStructOrErr<MachO::build_version_command>(Obj, Load.Ptr);
856
46
  if (!BVCOrErr)
857
0
    return BVCOrErr.takeError();
858
46
  MachO::build_version_command BVC = BVCOrErr.get();
859
46
  if (Load.C.cmdsize !=
860
46
      sizeof(MachO::build_version_command) +
861
46
          BVC.ntools * sizeof(MachO::build_tool_version))
862
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
863
1
                          " LC_BUILD_VERSION_COMMAND has incorrect cmdsize");
864
45
865
45
  auto Start = Load.Ptr + sizeof(MachO::build_version_command);
866
45
  BuildTools.resize(BVC.ntools);
867
59
  for (unsigned i = 0; i < BVC.ntools; 
++i14
)
868
14
    BuildTools[i] = Start + i * sizeof(MachO::build_tool_version);
869
45
870
45
  return Error::success();
871
45
}
872
873
static Error checkRpathCommand(const MachOObjectFile &Obj,
874
                               const MachOObjectFile::LoadCommandInfo &Load,
875
12
                               uint32_t LoadCommandIndex) {
876
12
  if (Load.C.cmdsize < sizeof(MachO::rpath_command))
877
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
878
1
                          " LC_RPATH cmdsize too small");
879
11
  auto ROrErr = getStructOrErr<MachO::rpath_command>(Obj, Load.Ptr);
880
11
  if (!ROrErr)
881
0
    return ROrErr.takeError();
882
11
  MachO::rpath_command R = ROrErr.get();
883
11
  if (R.path < sizeof(MachO::rpath_command))
884
0
    return malformedError("load command " + Twine(LoadCommandIndex) +
885
0
                          " LC_RPATH path.offset field too small, not past "
886
0
                          "the end of the rpath_command struct");
887
11
  if (R.path >= R.cmdsize)
888
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
889
1
                          " LC_RPATH path.offset field extends past the end "
890
1
                          "of the load command");
891
10
  // Make sure there is a null between the starting offset of the path and
892
10
  // the end of the load command.
893
10
  uint32_t i;
894
10
  const char *P = (const char *)Load.Ptr;
895
326
  for (i = R.path; i < R.cmdsize; 
i++316
)
896
325
    if (P[i] == '\0')
897
9
      break;
898
10
  if (i >= R.cmdsize)
899
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
900
1
                          " LC_RPATH library name extends past the end of the "
901
1
                          "load command");
902
9
  return Error::success();
903
9
}
904
905
static Error checkEncryptCommand(const MachOObjectFile &Obj,
906
                                 const MachOObjectFile::LoadCommandInfo &Load,
907
                                 uint32_t LoadCommandIndex,
908
                                 uint64_t cryptoff, uint64_t cryptsize,
909
21
                                 const char **LoadCmd, const char *CmdName) {
910
21
  if (*LoadCmd != nullptr)
911
1
    return malformedError("more than one LC_ENCRYPTION_INFO and or "
912
1
                          "LC_ENCRYPTION_INFO_64 command");
913
20
  uint64_t FileSize = Obj.getData().size();
914
20
  if (cryptoff > FileSize)
915
1
    return malformedError("cryptoff field of " + Twine(CmdName) +
916
1
                          " command " + Twine(LoadCommandIndex) + " extends "
917
1
                          "past the end of the file");
918
19
  uint64_t BigSize = cryptoff;
919
19
  BigSize += cryptsize;
920
19
  if (BigSize > FileSize)
921
1
    return malformedError("cryptoff field plus cryptsize field of " +
922
1
                          Twine(CmdName) + " command " +
923
1
                          Twine(LoadCommandIndex) + " extends past the end of "
924
1
                          "the file");
925
18
  *LoadCmd = Load.Ptr;
926
18
  return Error::success();
927
18
}
928
929
static Error checkLinkerOptCommand(const MachOObjectFile &Obj,
930
                                   const MachOObjectFile::LoadCommandInfo &Load,
931
109
                                   uint32_t LoadCommandIndex) {
932
109
  if (Load.C.cmdsize < sizeof(MachO::linker_option_command))
933
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
934
1
                          " LC_LINKER_OPTION cmdsize too small");
935
108
  auto LinkOptionOrErr =
936
108
    getStructOrErr<MachO::linker_option_command>(Obj, Load.Ptr);
937
108
  if (!LinkOptionOrErr)
938
0
    return LinkOptionOrErr.takeError();
939
108
  MachO::linker_option_command L = LinkOptionOrErr.get();
940
108
  // Make sure the count of strings is correct.
941
108
  const char *string = (const char *)Load.Ptr +
942
108
                       sizeof(struct MachO::linker_option_command);
943
108
  uint32_t left = L.cmdsize - sizeof(struct MachO::linker_option_command);
944
108
  uint32_t i = 0;
945
401
  while (left > 0) {
946
588
    while (*string == '\0' && 
left > 0296
) {
947
294
      string++;
948
294
      left--;
949
294
    }
950
294
    if (left > 0) {
951
212
      i++;
952
212
      uint32_t NullPos = StringRef(string, left).find('\0');
953
212
      if (0xffffffff == NullPos)
954
1
        return malformedError("load command " + Twine(LoadCommandIndex) +
955
1
                              " LC_LINKER_OPTION string #" + Twine(i) +
956
1
                              " is not NULL terminated");
957
211
      uint32_t len = std::min(NullPos, left) + 1;
958
211
      string += len;
959
211
      left -= len;
960
211
    }
961
294
  }
962
108
  
if (107
L.count != i107
)
963
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
964
1
                          " LC_LINKER_OPTION string count " + Twine(L.count) +
965
1
                          " does not match number of strings");
966
106
  return Error::success();
967
106
}
968
969
static Error checkSubCommand(const MachOObjectFile &Obj,
970
                             const MachOObjectFile::LoadCommandInfo &Load,
971
                             uint32_t LoadCommandIndex, const char *CmdName,
972
                             size_t SizeOfCmd, const char *CmdStructName,
973
9
                             uint32_t PathOffset, const char *PathFieldName) {
974
9
  if (PathOffset < SizeOfCmd)
975
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
976
1
                          CmdName + " " + PathFieldName + ".offset field too "
977
1
                          "small, not past the end of the " + CmdStructName);
978
8
  if (PathOffset >= Load.C.cmdsize)
979
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
980
1
                          CmdName + " " + PathFieldName + ".offset field "
981
1
                          "extends past the end of the load command");
982
7
  // Make sure there is a null between the starting offset of the path and
983
7
  // the end of the load command.
984
7
  uint32_t i;
985
7
  const char *P = (const char *)Load.Ptr;
986
32
  for (i = PathOffset; i < Load.C.cmdsize; 
i++25
)
987
31
    if (P[i] == '\0')
988
6
      break;
989
7
  if (i >= Load.C.cmdsize)
990
1
    return malformedError("load command " + Twine(LoadCommandIndex) + " " +
991
1
                          CmdName + " " + PathFieldName + " name extends past "
992
1
                          "the end of the load command");
993
6
  return Error::success();
994
6
}
995
996
static Error checkThreadCommand(const MachOObjectFile &Obj,
997
                                const MachOObjectFile::LoadCommandInfo &Load,
998
                                uint32_t LoadCommandIndex,
999
21
                                const char *CmdName) {
1000
21
  if (Load.C.cmdsize < sizeof(MachO::thread_command))
1001
0
    return malformedError("load command " + Twine(LoadCommandIndex) +
1002
0
                          CmdName + " cmdsize too small");
1003
21
  auto ThreadCommandOrErr =
1004
21
    getStructOrErr<MachO::thread_command>(Obj, Load.Ptr);
1005
21
  if (!ThreadCommandOrErr)
1006
0
    return ThreadCommandOrErr.takeError();
1007
21
  MachO::thread_command T = ThreadCommandOrErr.get();
1008
21
  const char *state = Load.Ptr + sizeof(MachO::thread_command);
1009
21
  const char *end = Load.Ptr + T.cmdsize;
1010
21
  uint32_t nflavor = 0;
1011
21
  uint32_t cputype = getCPUType(Obj);
1012
37
  while (state < end) {
1013
21
    if(state + sizeof(uint32_t) > end)
1014
0
      return malformedError("load command " + Twine(LoadCommandIndex) +
1015
0
                            "flavor in " + CmdName + " extends past end of "
1016
0
                            "command");
1017
21
    uint32_t flavor;
1018
21
    memcpy(&flavor, state, sizeof(uint32_t));
1019
21
    if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1020
1
      sys::swapByteOrder(flavor);
1021
21
    state += sizeof(uint32_t);
1022
21
1023
21
    if(state + sizeof(uint32_t) > end)
1024
1
      return malformedError("load command " + Twine(LoadCommandIndex) +
1025
1
                            " count in " + CmdName + " extends past end of "
1026
1
                            "command");
1027
20
    uint32_t count;
1028
20
    memcpy(&count, state, sizeof(uint32_t));
1029
20
    if (Obj.isLittleEndian() != sys::IsLittleEndianHost)
1030
1
      sys::swapByteOrder(count);
1031
20
    state += sizeof(uint32_t);
1032
20
1033
20
    if (cputype == MachO::CPU_TYPE_I386) {
1034
1
      if (flavor == MachO::x86_THREAD_STATE32) {
1035
1
        if (count != MachO::x86_THREAD_STATE32_COUNT)
1036
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1037
0
                                " count not x86_THREAD_STATE32_COUNT for "
1038
0
                                "flavor number " + Twine(nflavor) + " which is "
1039
0
                                "a x86_THREAD_STATE32 flavor in " + CmdName +
1040
0
                                " command");
1041
1
        if (state + sizeof(MachO::x86_thread_state32_t) > end)
1042
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1043
0
                                " x86_THREAD_STATE32 extends past end of "
1044
0
                                "command in " + CmdName + " command");
1045
1
        state += sizeof(MachO::x86_thread_state32_t);
1046
1
      } else {
1047
0
        return malformedError("load command " + Twine(LoadCommandIndex) +
1048
0
                              " unknown flavor (" + Twine(flavor) + ") for "
1049
0
                              "flavor number " + Twine(nflavor) + " in " +
1050
0
                              CmdName + " command");
1051
0
      }
1052
19
    } else if (cputype == MachO::CPU_TYPE_X86_64) {
1053
10
      if (flavor == MachO::x86_THREAD_STATE) {
1054
0
        if (count != MachO::x86_THREAD_STATE_COUNT)
1055
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1056
0
                                " count not x86_THREAD_STATE_COUNT for "
1057
0
                                "flavor number " + Twine(nflavor) + " which is "
1058
0
                                "a x86_THREAD_STATE flavor in " + CmdName +
1059
0
                                " command");
1060
0
        if (state + sizeof(MachO::x86_thread_state_t) > end)
1061
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1062
0
                                " x86_THREAD_STATE extends past end of "
1063
0
                                "command in " + CmdName + " command");
1064
0
        state += sizeof(MachO::x86_thread_state_t);
1065
10
      } else if (flavor == MachO::x86_FLOAT_STATE) {
1066
0
        if (count != MachO::x86_FLOAT_STATE_COUNT)
1067
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1068
0
                                " count not x86_FLOAT_STATE_COUNT for "
1069
0
                                "flavor number " + Twine(nflavor) + " which is "
1070
0
                                "a x86_FLOAT_STATE flavor in " + CmdName +
1071
0
                                " command");
1072
0
        if (state + sizeof(MachO::x86_float_state_t) > end)
1073
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1074
0
                                " x86_FLOAT_STATE extends past end of "
1075
0
                                "command in " + CmdName + " command");
1076
0
        state += sizeof(MachO::x86_float_state_t);
1077
10
      } else if (flavor == MachO::x86_EXCEPTION_STATE) {
1078
0
        if (count != MachO::x86_EXCEPTION_STATE_COUNT)
1079
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1080
0
                                " count not x86_EXCEPTION_STATE_COUNT for "
1081
0
                                "flavor number " + Twine(nflavor) + " which is "
1082
0
                                "a x86_EXCEPTION_STATE flavor in " + CmdName +
1083
0
                                " command");
1084
0
        if (state + sizeof(MachO::x86_exception_state_t) > end)
1085
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1086
0
                                " x86_EXCEPTION_STATE extends past end of "
1087
0
                                "command in " + CmdName + " command");
1088
0
        state += sizeof(MachO::x86_exception_state_t);
1089
10
      } else if (flavor == MachO::x86_THREAD_STATE64) {
1090
9
        if (count != MachO::x86_THREAD_STATE64_COUNT)
1091
1
          return malformedError("load command " + Twine(LoadCommandIndex) +
1092
1
                                " count not x86_THREAD_STATE64_COUNT for "
1093
1
                                "flavor number " + Twine(nflavor) + " which is "
1094
1
                                "a x86_THREAD_STATE64 flavor in " + CmdName +
1095
1
                                " command");
1096
8
        if (state + sizeof(MachO::x86_thread_state64_t) > end)
1097
1
          return malformedError("load command " + Twine(LoadCommandIndex) +
1098
1
                                " x86_THREAD_STATE64 extends past end of "
1099
1
                                "command in " + CmdName + " command");
1100
7
        state += sizeof(MachO::x86_thread_state64_t);
1101
7
      } else 
if (1
flavor == MachO::x86_EXCEPTION_STATE641
) {
1102
0
        if (count != MachO::x86_EXCEPTION_STATE64_COUNT)
1103
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1104
0
                                " count not x86_EXCEPTION_STATE64_COUNT for "
1105
0
                                "flavor number " + Twine(nflavor) + " which is "
1106
0
                                "a x86_EXCEPTION_STATE64 flavor in " + CmdName +
1107
0
                                " command");
1108
0
        if (state + sizeof(MachO::x86_exception_state64_t) > end)
1109
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1110
0
                                " x86_EXCEPTION_STATE64 extends past end of "
1111
0
                                "command in " + CmdName + " command");
1112
0
        state += sizeof(MachO::x86_exception_state64_t);
1113
1
      } else {
1114
1
        return malformedError("load command " + Twine(LoadCommandIndex) +
1115
1
                              " unknown flavor (" + Twine(flavor) + ") for "
1116
1
                              "flavor number " + Twine(nflavor) + " in " +
1117
1
                              CmdName + " command");
1118
1
      }
1119
9
    } else if (cputype == MachO::CPU_TYPE_ARM) {
1120
5
      if (flavor == MachO::ARM_THREAD_STATE) {
1121
5
        if (count != MachO::ARM_THREAD_STATE_COUNT)
1122
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1123
0
                                " count not ARM_THREAD_STATE_COUNT for "
1124
0
                                "flavor number " + Twine(nflavor) + " which is "
1125
0
                                "a ARM_THREAD_STATE flavor in " + CmdName +
1126
0
                                " command");
1127
5
        if (state + sizeof(MachO::arm_thread_state32_t) > end)
1128
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1129
0
                                " ARM_THREAD_STATE extends past end of "
1130
0
                                "command in " + CmdName + " command");
1131
5
        state += sizeof(MachO::arm_thread_state32_t);
1132
5
      } else {
1133
0
        return malformedError("load command " + Twine(LoadCommandIndex) +
1134
0
                              " unknown flavor (" + Twine(flavor) + ") for "
1135
0
                              "flavor number " + Twine(nflavor) + " in " +
1136
0
                              CmdName + " command");
1137
0
      }
1138
4
    } else if (cputype == MachO::CPU_TYPE_ARM64 ||
1139
4
               
cputype == MachO::CPU_TYPE_ARM64_323
) {
1140
2
      if (flavor == MachO::ARM_THREAD_STATE64) {
1141
2
        if (count != MachO::ARM_THREAD_STATE64_COUNT)
1142
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1143
0
                                " count not ARM_THREAD_STATE64_COUNT for "
1144
0
                                "flavor number " + Twine(nflavor) + " which is "
1145
0
                                "a ARM_THREAD_STATE64 flavor in " + CmdName +
1146
0
                                " command");
1147
2
        if (state + sizeof(MachO::arm_thread_state64_t) > end)
1148
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1149
0
                                " ARM_THREAD_STATE64 extends past end of "
1150
0
                                "command in " + CmdName + " command");
1151
2
        state += sizeof(MachO::arm_thread_state64_t);
1152
2
      } else {
1153
0
        return malformedError("load command " + Twine(LoadCommandIndex) +
1154
0
                              " unknown flavor (" + Twine(flavor) + ") for "
1155
0
                              "flavor number " + Twine(nflavor) + " in " +
1156
0
                              CmdName + " command");
1157
0
      }
1158
2
    } else if (cputype == MachO::CPU_TYPE_POWERPC) {
1159
1
      if (flavor == MachO::PPC_THREAD_STATE) {
1160
1
        if (count != MachO::PPC_THREAD_STATE_COUNT)
1161
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1162
0
                                " count not PPC_THREAD_STATE_COUNT for "
1163
0
                                "flavor number " + Twine(nflavor) + " which is "
1164
0
                                "a PPC_THREAD_STATE flavor in " + CmdName +
1165
0
                                " command");
1166
1
        if (state + sizeof(MachO::ppc_thread_state32_t) > end)
1167
0
          return malformedError("load command " + Twine(LoadCommandIndex) +
1168
0
                                " PPC_THREAD_STATE extends past end of "
1169
0
                                "command in " + CmdName + " command");
1170
1
        state += sizeof(MachO::ppc_thread_state32_t);
1171
1
      } else {
1172
0
        return malformedError("load command " + Twine(LoadCommandIndex) +
1173
0
                              " unknown flavor (" + Twine(flavor) + ") for "
1174
0
                              "flavor number " + Twine(nflavor) + " in " +
1175
0
                              CmdName + " command");
1176
0
      }
1177
1
    } else {
1178
1
      return malformedError("unknown cputype (" + Twine(cputype) + ") load "
1179
1
                            "command " + Twine(LoadCommandIndex) + " for " +
1180
1
                            CmdName + " command can't be checked");
1181
1
    }
1182
16
    nflavor++;
1183
16
  }
1184
21
  
return Error::success()16
;
1185
21
}
1186
1187
static Error checkTwoLevelHintsCommand(const MachOObjectFile &Obj,
1188
                                       const MachOObjectFile::LoadCommandInfo
1189
                                         &Load,
1190
                                       uint32_t LoadCommandIndex,
1191
                                       const char **LoadCmd,
1192
8
                                       std::list<MachOElement> &Elements) {
1193
8
  if (Load.C.cmdsize != sizeof(MachO::twolevel_hints_command))
1194
1
    return malformedError("load command " + Twine(LoadCommandIndex) +
1195
1
                          " LC_TWOLEVEL_HINTS has incorrect cmdsize");
1196
7
  if (*LoadCmd != nullptr)
1197
1
    return malformedError("more than one LC_TWOLEVEL_HINTS command");
1198
6
  auto HintsOrErr = getStructOrErr<MachO::twolevel_hints_command>(Obj, Load.Ptr);
1199
6
  if(!HintsOrErr)
1200
0
    return HintsOrErr.takeError();
1201
6
  MachO::twolevel_hints_command Hints = HintsOrErr.get();
1202
6
  uint64_t FileSize = Obj.getData().size();
1203
6
  if (Hints.offset > FileSize)
1204
1
    return malformedError("offset field of LC_TWOLEVEL_HINTS command " +
1205
1
                          Twine(LoadCommandIndex) + " extends past the end of "
1206
1
                          "the file");
1207
5
  uint64_t BigSize = Hints.nhints;
1208
5
  BigSize *= sizeof(MachO::twolevel_hint);
1209
5
  BigSize += Hints.offset;
1210
5
  if (BigSize > FileSize)
1211
1
    return malformedError("offset field plus nhints times sizeof(struct "
1212
1
                          "twolevel_hint) field of LC_TWOLEVEL_HINTS command " +
1213
1
                          Twine(LoadCommandIndex) + " extends past the end of "
1214
1
                          "the file");
1215
4
  if (Error Err = checkOverlappingElement(Elements, Hints.offset, Hints.nhints *
1216
1
                                          sizeof(MachO::twolevel_hint),
1217
1
                                          "two level hints"))
1218
1
    return Err;
1219
3
  *LoadCmd = Load.Ptr;
1220
3
  return Error::success();
1221
3
}
1222
1223
// Returns true if the libObject code does not support the load command and its
1224
// contents.  The cmd value it is treated as an unknown load command but with
1225
// an error message that says the cmd value is obsolete.
1226
10
static bool isLoadCommandObsolete(uint32_t cmd) {
1227
10
  if (cmd == MachO::LC_SYMSEG ||
1228
10
      
cmd == MachO::LC_LOADFVMLIB9
||
1229
10
      
cmd == MachO::LC_IDFVMLIB8
||
1230
10
      
cmd == MachO::LC_IDENT7
||
1231
10
      
cmd == MachO::LC_FVMFILE6
||
1232
10
      
cmd == MachO::LC_PREPAGE5
||
1233
10
      
cmd == MachO::LC_PREBOUND_DYLIB4
||
1234
10
      
cmd == MachO::LC_TWOLEVEL_HINTS3
||
1235
10
      
cmd == MachO::LC_PREBIND_CKSUM3
)
1236
8
    return true;
1237
2
  return false;
1238
2
}
1239
1240
Expected<std::unique_ptr<MachOObjectFile>>
1241
MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
1242
                        bool Is64Bits, uint32_t UniversalCputype,
1243
2.72k
                        uint32_t UniversalIndex) {
1244
2.72k
  Error Err = Error::success();
1245
2.72k
  std::unique_ptr<MachOObjectFile> Obj(
1246
2.72k
      new MachOObjectFile(std::move(Object), IsLittleEndian,
1247
2.72k
                          Is64Bits, Err, UniversalCputype,
1248
2.72k
                          UniversalIndex));
1249
2.72k
  if (Err)
1250
153
    return std::move(Err);
1251
2.57k
  return std::move(Obj);
1252
2.57k
}
1253
1254
MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
1255
                                 bool Is64bits, Error &Err,
1256
                                 uint32_t UniversalCputype,
1257
                                 uint32_t UniversalIndex)
1258
2.72k
    : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object) {
1259
2.72k
  ErrorAsOutParameter ErrAsOutParam(&Err);
1260
2.72k
  uint64_t SizeOfHeaders;
1261
2.72k
  uint32_t cputype;
1262
2.72k
  if (is64Bit()) {
1263
2.17k
    parseHeader(*this, Header64, Err);
1264
2.17k
    SizeOfHeaders = sizeof(MachO::mach_header_64);
1265
2.17k
    cputype = Header64.cputype;
1266
2.17k
  } else {
1267
550
    parseHeader(*this, Header, Err);
1268
550
    SizeOfHeaders = sizeof(MachO::mach_header);
1269
550
    cputype = Header.cputype;
1270
550
  }
1271
2.72k
  if (Err)
1272
0
    return;
1273
2.72k
  SizeOfHeaders += getHeader().sizeofcmds;
1274
2.72k
  if (getData().data() + SizeOfHeaders > getData().end()) {
1275
6
    Err = malformedError("load commands extend past the end of the file");
1276
6
    return;
1277
6
  }
1278
2.71k
  if (UniversalCputype != 0 && 
cputype != UniversalCputype75
) {
1279
1
    Err = malformedError("universal header architecture: " +
1280
1
                         Twine(UniversalIndex) + "'s cputype does not match "
1281
1
                         "object file's mach header");
1282
1
    return;
1283
1
  }
1284
2.71k
  std::list<MachOElement> Elements;
1285
2.71k
  Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
1286
2.71k
1287
2.71k
  uint32_t LoadCommandCount = getHeader().ncmds;
1288
2.71k
  LoadCommandInfo Load;
1289
2.71k
  if (LoadCommandCount != 0) {
1290
2.68k
    if (auto LoadOrErr = getFirstLoadCommandInfo(*this))
1291
2.68k
      Load = *LoadOrErr;
1292
2
    else {
1293
2
      Err = LoadOrErr.takeError();
1294
2
      return;
1295
2
    }
1296
2.71k
  }
1297
2.71k
1298
2.71k
  const char *DyldIdLoadCmd = nullptr;
1299
2.71k
  const char *FuncStartsLoadCmd = nullptr;
1300
2.71k
  const char *SplitInfoLoadCmd = nullptr;
1301
2.71k
  const char *CodeSignDrsLoadCmd = nullptr;
1302
2.71k
  const char *CodeSignLoadCmd = nullptr;
1303
2.71k
  const char *VersLoadCmd = nullptr;
1304
2.71k
  const char *SourceLoadCmd = nullptr;
1305
2.71k
  const char *EntryPointLoadCmd = nullptr;
1306
2.71k
  const char *EncryptLoadCmd = nullptr;
1307
2.71k
  const char *RoutinesLoadCmd = nullptr;
1308
2.71k
  const char *UnixThreadLoadCmd = nullptr;
1309
2.71k
  const char *TwoLevelHintsLoadCmd = nullptr;
1310
16.7k
  for (unsigned I = 0; I < LoadCommandCount; 
++I14.0k
) {
1311
14.1k
    if (is64Bit()) {
1312
12.0k
      if (Load.C.cmdsize % 8 != 0) {
1313
1
        // We have a hack here to allow 64-bit Mach-O core files to have
1314
1
        // LC_THREAD commands that are only a multiple of 4 and not 8 to be
1315
1
        // allowed since the macOS kernel produces them.
1316
1
        if (getHeader().filetype != MachO::MH_CORE ||
1317
1
            
Load.C.cmd != MachO::LC_THREAD0
||
Load.C.cmdsize % 40
) {
1318
1
          Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1319
1
                               "multiple of 8");
1320
1
          return;
1321
1
        }
1322
2.17k
      }
1323
2.17k
    } else {
1324
2.17k
      if (Load.C.cmdsize % 4 != 0) {
1325
1
        Err = malformedError("load command " + Twine(I) + " cmdsize not a "
1326
1
                             "multiple of 4");
1327
1
        return;
1328
1
      }
1329
14.1k
    }
1330
14.1k
    LoadCommands.push_back(Load);
1331
14.1k
    if (Load.C.cmd == MachO::LC_SYMTAB) {
1332
2.34k
      if ((Err = checkSymtabCommand(*this, Load, I, &SymtabLoadCmd, Elements)))
1333
10
        return;
1334
11.8k
    } else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
1335
2.20k
      if ((Err = checkDysymtabCommand(*this, Load, I, &DysymtabLoadCmd,
1336
2.20k
                                      Elements)))
1337
21
        return;
1338
9.62k
    } else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
1339
451
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &DataInCodeLoadCmd,
1340
451
                                          "LC_DATA_IN_CODE", Elements,
1341
451
                                          "data in code info")))
1342
3
        return;
1343
9.17k
    } else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
1344
4
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &LinkOptHintsLoadCmd,
1345
4
                                          "LC_LINKER_OPTIMIZATION_HINT",
1346
4
                                          Elements, "linker optimization "
1347
4
                                          "hints")))
1348
2
        return;
1349
9.17k
    } else if (Load.C.cmd == MachO::LC_FUNCTION_STARTS) {
1350
414
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &FuncStartsLoadCmd,
1351
414
                                          "LC_FUNCTION_STARTS", Elements,
1352
414
                                          "function starts data")))
1353
1
        return;
1354
8.75k
    } else if (Load.C.cmd == MachO::LC_SEGMENT_SPLIT_INFO) {
1355
9
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &SplitInfoLoadCmd,
1356
9
                                          "LC_SEGMENT_SPLIT_INFO", Elements,
1357
9
                                          "split info data")))
1358
1
        return;
1359
8.74k
    } else if (Load.C.cmd == MachO::LC_DYLIB_CODE_SIGN_DRS) {
1360
185
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignDrsLoadCmd,
1361
185
                                          "LC_DYLIB_CODE_SIGN_DRS", Elements,
1362
185
                                          "code signing RDs data")))
1363
1
        return;
1364
8.56k
    } else if (Load.C.cmd == MachO::LC_CODE_SIGNATURE) {
1365
6
      if ((Err = checkLinkeditDataCommand(*this, Load, I, &CodeSignLoadCmd,
1366
6
                                          "LC_CODE_SIGNATURE", Elements,
1367
6
                                          "code signature data")))
1368
2
        return;
1369
8.55k
    } else if (Load.C.cmd == MachO::LC_DYLD_INFO) {
1370
13
      if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1371
13
                                      "LC_DYLD_INFO", Elements)))
1372
12
        return;
1373
8.54k
    } else if (Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
1374
428
      if ((Err = checkDyldInfoCommand(*this, Load, I, &DyldInfoLoadCmd,
1375
428
                                      "LC_DYLD_INFO_ONLY", Elements)))
1376
6
        return;
1377
8.11k
    } else if (Load.C.cmd == MachO::LC_UUID) {
1378
448
      if (Load.C.cmdsize != sizeof(MachO::uuid_command)) {
1379
1
        Err = malformedError("LC_UUID command " + Twine(I) + " has incorrect "
1380
1
                             "cmdsize");
1381
1
        return;
1382
1
      }
1383
447
      if (UuidLoadCmd) {
1384
1
        Err = malformedError("more than one LC_UUID command");
1385
1
        return;
1386
1
      }
1387
446
      UuidLoadCmd = Load.Ptr;
1388
7.66k
    } else if (Load.C.cmd == MachO::LC_SEGMENT_64) {
1389
3.48k
      if ((Err = parseSegmentLoadCommand<MachO::segment_command_64,
1390
3.48k
                                         MachO::section_64>(
1391
3.48k
                   *this, Load, Sections, HasPageZeroSegment, I,
1392
3.48k
                   "LC_SEGMENT_64", SizeOfHeaders, Elements)))
1393
7
        return;
1394
4.18k
    } else if (Load.C.cmd == MachO::LC_SEGMENT) {
1395
586
      if ((Err = parseSegmentLoadCommand<MachO::segment_command,
1396
586
                                         MachO::section>(
1397
586
                   *this, Load, Sections, HasPageZeroSegment, I,
1398
586
                   "LC_SEGMENT", SizeOfHeaders, Elements)))
1399
16
        return;
1400
3.59k
    } else if (Load.C.cmd == MachO::LC_ID_DYLIB) {
1401
124
      if ((Err = checkDylibIdCommand(*this, Load, I, &DyldIdLoadCmd)))
1402
2
        return;
1403
3.47k
    } else if (Load.C.cmd == MachO::LC_LOAD_DYLIB) {
1404
535
      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_DYLIB")))
1405
1
        return;
1406
534
      Libraries.push_back(Load.Ptr);
1407
2.93k
    } else if (Load.C.cmd == MachO::LC_LOAD_WEAK_DYLIB) {
1408
5
      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_WEAK_DYLIB")))
1409
1
        return;
1410
4
      Libraries.push_back(Load.Ptr);
1411
2.93k
    } else if (Load.C.cmd == MachO::LC_LAZY_LOAD_DYLIB) {
1412
5
      if ((Err = checkDylibCommand(*this, Load, I, "LC_LAZY_LOAD_DYLIB")))
1413
1
        return;
1414
4
      Libraries.push_back(Load.Ptr);
1415
2.92k
    } else if (Load.C.cmd == MachO::LC_REEXPORT_DYLIB) {
1416
4
      if ((Err = checkDylibCommand(*this, Load, I, "LC_REEXPORT_DYLIB")))
1417
0
        return;
1418
4
      Libraries.push_back(Load.Ptr);
1419
2.92k
    } else if (Load.C.cmd == MachO::LC_LOAD_UPWARD_DYLIB) {
1420
2
      if ((Err = checkDylibCommand(*this, Load, I, "LC_LOAD_UPWARD_DYLIB")))
1421
1
        return;
1422
1
      Libraries.push_back(Load.Ptr);
1423
2.92k
    } else if (Load.C.cmd == MachO::LC_ID_DYLINKER) {
1424
3
      if ((Err = checkDyldCommand(*this, Load, I, "LC_ID_DYLINKER")))
1425
1
        return;
1426
2.92k
    } else if (Load.C.cmd == MachO::LC_LOAD_DYLINKER) {
1427
300
      if ((Err = checkDyldCommand(*this, Load, I, "LC_LOAD_DYLINKER")))
1428
1
        return;
1429
2.62k
    } else if (Load.C.cmd == MachO::LC_DYLD_ENVIRONMENT) {
1430
1
      if ((Err = checkDyldCommand(*this, Load, I, "LC_DYLD_ENVIRONMENT")))
1431
1
        return;
1432
2.61k
    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_MACOSX) {
1433
1.55k
      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1434
1.55k
                                  "LC_VERSION_MIN_MACOSX")))
1435
1
        return;
1436
1.06k
    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_IPHONEOS) {
1437
111
      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1438
111
                                  "LC_VERSION_MIN_IPHONEOS")))
1439
0
        return;
1440
953
    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_TVOS) {
1441
2
      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1442
2
                                  "LC_VERSION_MIN_TVOS")))
1443
0
        return;
1444
951
    } else if (Load.C.cmd == MachO::LC_VERSION_MIN_WATCHOS) {
1445
4
      if ((Err = checkVersCommand(*this, Load, I, &VersLoadCmd,
1446
4
                                  "LC_VERSION_MIN_WATCHOS")))
1447
1
        return;
1448
947
    } else if (Load.C.cmd == MachO::LC_NOTE) {
1449
2
      if ((Err = checkNoteCommand(*this, Load, I, Elements)))
1450
1
        return;
1451
945
    } else if (Load.C.cmd == MachO::LC_BUILD_VERSION) {
1452
46
      if ((Err = parseBuildVersionCommand(*this, Load, BuildTools, I)))
1453
1
        return;
1454
899
    } else if (Load.C.cmd == MachO::LC_RPATH) {
1455
12
      if ((Err = checkRpathCommand(*this, Load, I)))
1456
3
        return;
1457
887
    } else if (Load.C.cmd == MachO::LC_SOURCE_VERSION) {
1458
405
      if (Load.C.cmdsize != sizeof(MachO::source_version_command)) {
1459
1
        Err = malformedError("LC_SOURCE_VERSION command " + Twine(I) +
1460
1
                             " has incorrect cmdsize");
1461
1
        return;
1462
1
      }
1463
404
      if (SourceLoadCmd) {
1464
1
        Err = malformedError("more than one LC_SOURCE_VERSION command");
1465
1
        return;
1466
1
      }
1467
403
      SourceLoadCmd = Load.Ptr;
1468
482
    } else if (Load.C.cmd == MachO::LC_MAIN) {
1469
295
      if (Load.C.cmdsize != sizeof(MachO::entry_point_command)) {
1470
1
        Err = malformedError("LC_MAIN command " + Twine(I) +
1471
1
                             " has incorrect cmdsize");
1472
1
        return;
1473
1
      }
1474
294
      if (EntryPointLoadCmd) {
1475
1
        Err = malformedError("more than one LC_MAIN command");
1476
1
        return;
1477
1
      }
1478
293
      EntryPointLoadCmd = Load.Ptr;
1479
293
    } else 
if (187
Load.C.cmd == MachO::LC_ENCRYPTION_INFO187
) {
1480
5
      if (Load.C.cmdsize != sizeof(MachO::encryption_info_command)) {
1481
1
        Err = malformedError("LC_ENCRYPTION_INFO command " + Twine(I) +
1482
1
                             " has incorrect cmdsize");
1483
1
        return;
1484
1
      }
1485
4
      MachO::encryption_info_command E =
1486
4
        getStruct<MachO::encryption_info_command>(*this, Load.Ptr);
1487
4
      if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1488
4
                                     &EncryptLoadCmd, "LC_ENCRYPTION_INFO")))
1489
1
        return;
1490
182
    } else if (Load.C.cmd == MachO::LC_ENCRYPTION_INFO_64) {
1491
18
      if (Load.C.cmdsize != sizeof(MachO::encryption_info_command_64)) {
1492
1
        Err = malformedError("LC_ENCRYPTION_INFO_64 command " + Twine(I) +
1493
1
                             " has incorrect cmdsize");
1494
1
        return;
1495
1
      }
1496
17
      MachO::encryption_info_command_64 E =
1497
17
        getStruct<MachO::encryption_info_command_64>(*this, Load.Ptr);
1498
17
      if ((Err = checkEncryptCommand(*this, Load, I, E.cryptoff, E.cryptsize,
1499
17
                                     &EncryptLoadCmd, "LC_ENCRYPTION_INFO_64")))
1500
2
        return;
1501
164
    } else if (Load.C.cmd == MachO::LC_LINKER_OPTION) {
1502
109
      if ((Err = checkLinkerOptCommand(*this, Load, I)))
1503
3
        return;
1504
55
    } else if (Load.C.cmd == MachO::LC_SUB_FRAMEWORK) {
1505
4
      if (Load.C.cmdsize < sizeof(MachO::sub_framework_command)) {
1506
1
        Err =  malformedError("load command " + Twine(I) +
1507
1
                              " LC_SUB_FRAMEWORK cmdsize too small");
1508
1
        return;
1509
1
      }
1510
3
      MachO::sub_framework_command S =
1511
3
        getStruct<MachO::sub_framework_command>(*this, Load.Ptr);
1512
3
      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_FRAMEWORK",
1513
3
                                 sizeof(MachO::sub_framework_command),
1514
3
                                 "sub_framework_command", S.umbrella,
1515
3
                                 "umbrella")))
1516
0
        return;
1517
51
    } else if (Load.C.cmd == MachO::LC_SUB_UMBRELLA) {
1518
2
      if (Load.C.cmdsize < sizeof(MachO::sub_umbrella_command)) {
1519
0
        Err =  malformedError("load command " + Twine(I) +
1520
0
                              " LC_SUB_UMBRELLA cmdsize too small");
1521
0
        return;
1522
0
      }
1523
2
      MachO::sub_umbrella_command S =
1524
2
        getStruct<MachO::sub_umbrella_command>(*this, Load.Ptr);
1525
2
      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_UMBRELLA",
1526
2
                                 sizeof(MachO::sub_umbrella_command),
1527
2
                                 "sub_umbrella_command", S.sub_umbrella,
1528
2
                                 "sub_umbrella")))
1529
1
        return;
1530
49
    } else if (Load.C.cmd == MachO::LC_SUB_LIBRARY) {
1531
2
      if (Load.C.cmdsize < sizeof(MachO::sub_library_command)) {
1532
0
        Err =  malformedError("load command " + Twine(I) +
1533
0
                              " LC_SUB_LIBRARY cmdsize too small");
1534
0
        return;
1535
0
      }
1536
2
      MachO::sub_library_command S =
1537
2
        getStruct<MachO::sub_library_command>(*this, Load.Ptr);
1538
2
      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_LIBRARY",
1539
2
                                 sizeof(MachO::sub_library_command),
1540
2
                                 "sub_library_command", S.sub_library,
1541
2
                                 "sub_library")))
1542
1
        return;
1543
47
    } else if (Load.C.cmd == MachO::LC_SUB_CLIENT) {
1544
2
      if (Load.C.cmdsize < sizeof(MachO::sub_client_command)) {
1545
0
        Err =  malformedError("load command " + Twine(I) +
1546
0
                              " LC_SUB_CLIENT cmdsize too small");
1547
0
        return;
1548
0
      }
1549
2
      MachO::sub_client_command S =
1550
2
        getStruct<MachO::sub_client_command>(*this, Load.Ptr);
1551
2
      if ((Err = checkSubCommand(*this, Load, I, "LC_SUB_CLIENT",
1552
2
                                 sizeof(MachO::sub_client_command),
1553
2
                                 "sub_client_command", S.client, "client")))
1554
1
        return;
1555
45
    } else if (Load.C.cmd == MachO::LC_ROUTINES) {
1556
2
      if (Load.C.cmdsize != sizeof(MachO::routines_command)) {
1557
1
        Err = malformedError("LC_ROUTINES command " + Twine(I) +
1558
1
                             " has incorrect cmdsize");
1559
1
        return;
1560
1
      }
1561
1
      if (RoutinesLoadCmd) {
1562
0
        Err = malformedError("more than one LC_ROUTINES and or LC_ROUTINES_64 "
1563
0
                             "command");
1564
0
        return;
1565
0
      }
1566
1
      RoutinesLoadCmd = Load.Ptr;
1567
43
    } else if (Load.C.cmd == MachO::LC_ROUTINES_64) {
1568
4
      if (Load.C.cmdsize != sizeof(MachO::routines_command_64)) {
1569
0
        Err = malformedError("LC_ROUTINES_64 command " + Twine(I) +
1570
0
                             " has incorrect cmdsize");
1571
0
        return;
1572
0
      }
1573
4
      if (RoutinesLoadCmd) {
1574
1
        Err = malformedError("more than one LC_ROUTINES_64 and or LC_ROUTINES "
1575
1
                             "command");
1576
1
        return;
1577
1
      }
1578
3
      RoutinesLoadCmd = Load.Ptr;
1579
39
    } else if (Load.C.cmd == MachO::LC_UNIXTHREAD) {
1580
16
      if ((Err = checkThreadCommand(*this, Load, I, "LC_UNIXTHREAD")))
1581
1
        return;
1582
15
      if (UnixThreadLoadCmd) {
1583
1
        Err = malformedError("more than one LC_UNIXTHREAD command");
1584
1
        return;
1585
1
      }
1586
14
      UnixThreadLoadCmd = Load.Ptr;
1587
23
    } else if (Load.C.cmd == MachO::LC_THREAD) {
1588
5
      if ((Err = checkThreadCommand(*this, Load, I, "LC_THREAD")))
1589
4
        return;
1590
18
    // Note: LC_TWOLEVEL_HINTS is really obsolete and is not supported.
1591
18
    } else if (Load.C.cmd == MachO::LC_TWOLEVEL_HINTS) {
1592
8
       if ((Err = checkTwoLevelHintsCommand(*this, Load, I,
1593
8
                                            &TwoLevelHintsLoadCmd, Elements)))
1594
5
         return;
1595
10
    } else if (isLoadCommandObsolete(Load.C.cmd)) {
1596
8
      Err = malformedError("load command " + Twine(I) + " for cmd value of: " +
1597
8
                           Twine(Load.C.cmd) + " is obsolete and not "
1598
8
                           "supported");
1599
8
      return;
1600
8
    }
1601
14.0k
    // TODO: generate a error for unknown load commands by default.  But still
1602
14.0k
    // need work out an approach to allow or not allow unknown values like this
1603
14.0k
    // as an option for some uses like lldb.
1604
14.0k
    if (I < LoadCommandCount - 1) {
1605
11.5k
      if (auto LoadOrErr = getNextLoadCommandInfo(*this, I, Load))
1606
11.4k
        Load = *LoadOrErr;
1607
2
      else {
1608
2
        Err = LoadOrErr.takeError();
1609
2
        return;
1610
2
      }
1611
11.5k
    }
1612
14.0k
  }
1613
2.71k
  
if (2.57k
!SymtabLoadCmd2.57k
) {
1614
242
    if (DysymtabLoadCmd) {
1615
0
      Err = malformedError("contains LC_DYSYMTAB load command without a "
1616
0
                           "LC_SYMTAB load command");
1617
0
      return;
1618
0
    }
1619
2.33k
  } else if (DysymtabLoadCmd) {
1620
2.18k
    MachO::symtab_command Symtab =
1621
2.18k
      getStruct<MachO::symtab_command>(*this, SymtabLoadCmd);
1622
2.18k
    MachO::dysymtab_command Dysymtab =
1623
2.18k
      getStruct<MachO::dysymtab_command>(*this, DysymtabLoadCmd);
1624
2.18k
    if (Dysymtab.nlocalsym != 0 && 
Dysymtab.ilocalsym > Symtab.nsyms957
) {
1625
0
      Err = malformedError("ilocalsym in LC_DYSYMTAB load command "
1626
0
                           "extends past the end of the symbol table");
1627
0
      return;
1628
0
    }
1629
2.18k
    uint64_t BigSize = Dysymtab.ilocalsym;
1630
2.18k
    BigSize += Dysymtab.nlocalsym;
1631
2.18k
    if (Dysymtab.nlocalsym != 0 && 
BigSize > Symtab.nsyms957
) {
1632
1
      Err = malformedError("ilocalsym plus nlocalsym in LC_DYSYMTAB load "
1633
1
                           "command extends past the end of the symbol table");
1634
1
      return;
1635
1
    }
1636
2.18k
    if (Dysymtab.nextdefsym != 0 && 
Dysymtab.iextdefsym > Symtab.nsyms1.85k
) {
1637
1
      Err = malformedError("iextdefsym in LC_DYSYMTAB load command "
1638
1
                           "extends past the end of the symbol table");
1639
1
      return;
1640
1
    }
1641
2.18k
    BigSize = Dysymtab.iextdefsym;
1642
2.18k
    BigSize += Dysymtab.nextdefsym;
1643
2.18k
    if (Dysymtab.nextdefsym != 0 && 
BigSize > Symtab.nsyms1.85k
) {
1644
0
      Err = malformedError("iextdefsym plus nextdefsym in LC_DYSYMTAB "
1645
0
                           "load command extends past the end of the symbol "
1646
0
                           "table");
1647
0
      return;
1648
0
    }
1649
2.18k
    if (Dysymtab.nundefsym != 0 && 
Dysymtab.iundefsym > Symtab.nsyms1.24k
) {
1650
0
      Err = malformedError("iundefsym in LC_DYSYMTAB load command "
1651
0
                           "extends past the end of the symbol table");
1652
0
      return;
1653
0
    }
1654
2.18k
    BigSize = Dysymtab.iundefsym;
1655
2.18k
    BigSize += Dysymtab.nundefsym;
1656
2.18k
    if (Dysymtab.nundefsym != 0 && 
BigSize > Symtab.nsyms1.24k
) {
1657
0
      Err = malformedError("iundefsym plus nundefsym in LC_DYSYMTAB load "
1658
0
                           " command extends past the end of the symbol table");
1659
0
      return;
1660
0
    }
1661
2.57k
  }
1662
2.57k
  if ((getHeader().filetype == MachO::MH_DYLIB ||
1663
2.57k
       
getHeader().filetype == MachO::MH_DYLIB_STUB2.45k
) &&
1664
2.57k
       
DyldIdLoadCmd == nullptr122
) {
1665
1
    Err = malformedError("no LC_ID_DYLIB load command in dynamic library "
1666
1
                         "filetype");
1667
1
    return;
1668
1
  }
1669
2.57k
  assert(LoadCommands.size() == LoadCommandCount);
1670
2.57k
1671
2.57k
  Err = Error::success();
1672
2.57k
}
1673
1674
107
Error MachOObjectFile::checkSymbolTable() const {
1675
107
  uint32_t Flags = 0;
1676
107
  if (is64Bit()) {
1677
64
    MachO::mach_header_64 H_64 = MachOObjectFile::getHeader64();
1678
64
    Flags = H_64.flags;
1679
64
  } else {
1680
43
    MachO::mach_header H = MachOObjectFile::getHeader();
1681
43
    Flags = H.flags;
1682
43
  }
1683
107
  uint8_t NType = 0;
1684
107
  uint8_t NSect = 0;
1685
107
  uint16_t NDesc = 0;
1686
107
  uint32_t NStrx = 0;
1687
107
  uint64_t NValue = 0;
1688
107
  uint32_t SymbolIndex = 0;
1689
107
  MachO::symtab_command S = getSymtabLoadCommand();
1690
465
  for (const SymbolRef &Symbol : symbols()) {
1691
465
    DataRefImpl SymDRI = Symbol.getRawDataRefImpl();
1692
465
    if (is64Bit()) {
1693
370
      MachO::nlist_64 STE_64 = getSymbol64TableEntry(SymDRI);
1694
370
      NType = STE_64.n_type;
1695
370
      NSect = STE_64.n_sect;
1696
370
      NDesc = STE_64.n_desc;
1697
370
      NStrx = STE_64.n_strx;
1698
370
      NValue = STE_64.n_value;
1699
370
    } else {
1700
95
      MachO::nlist STE = getSymbolTableEntry(SymDRI);
1701
95
      NType = STE.n_type;
1702
95
      NSect = STE.n_sect;
1703
95
      NDesc = STE.n_desc;
1704
95
      NStrx = STE.n_strx;
1705
95
      NValue = STE.n_value;
1706
95
    }
1707
465
    if ((NType & MachO::N_STAB) == 0) {
1708
403
      if ((NType & MachO::N_TYPE) == MachO::N_SECT) {
1709
266
        if (NSect == 0 || NSect > Sections.size())
1710
2
          return malformedError("bad section index: " + Twine((int)NSect) +
1711
2
                                " for symbol at index " + Twine(SymbolIndex));
1712
401
      }
1713
401
      if ((NType & MachO::N_TYPE) == MachO::N_INDR) {
1714
2
        if (NValue >= S.strsize)
1715
2
          return malformedError("bad n_value: " + Twine((int)NValue) + " past "
1716
2
                                "the end of string table, for N_INDR symbol at "
1717
2
                                "index " + Twine(SymbolIndex));
1718
399
      }
1719
399
      if ((Flags & MachO::MH_TWOLEVEL) == MachO::MH_TWOLEVEL &&
1720
399
          
(223
(223
(NType & MachO::N_TYPE) == MachO::N_UNDF223
&&
NValue == 0104
) ||
1721
223
           
(NType & MachO::N_TYPE) == MachO::N_PBUD119
)) {
1722
104
            uint32_t LibraryOrdinal = MachO::GET_LIBRARY_ORDINAL(NDesc);
1723
104
            if (LibraryOrdinal != 0 &&
1724
104
                LibraryOrdinal != MachO::EXECUTABLE_ORDINAL &&
1725
104
                LibraryOrdinal != MachO::DYNAMIC_LOOKUP_ORDINAL &&
1726
104
                
LibraryOrdinal - 1 >= Libraries.size()102
) {
1727
1
              return malformedError("bad library ordinal: " + Twine(LibraryOrdinal) +
1728
1
                                    " for symbol at index " + Twine(SymbolIndex));
1729
1
            }
1730
460
          }
1731
399
    }
1732
460
    if (NStrx >= S.strsize)
1733
2
      return malformedError("bad string table index: " + Twine((int)NStrx) +
1734
2
                            " past the end of string table, for symbol at "
1735
2
                            "index " + Twine(SymbolIndex));
1736
458
    SymbolIndex++;
1737
458
  }
1738
107
  
return Error::success()100
;
1739
107
}
1740
1741
13.4k
void MachOObjectFile::moveSymbolNext(DataRefImpl &Symb) const {
1742
13.4k
  unsigned SymbolTableEntrySize = is64Bit() ?
1743
12.1k
    sizeof(MachO::nlist_64) :
1744
13.4k
    
sizeof(MachO::nlist)1.27k
;
1745
13.4k
  Symb.p += SymbolTableEntrySize;
1746
13.4k
}
1747
1748
5.36k
Expected<StringRef> MachOObjectFile::getSymbolName(DataRefImpl Symb) const {
1749
5.36k
  StringRef StringTable = getStringTableData();
1750
5.36k
  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1751
5.36k
  if (Entry.n_strx == 0)
1752
2
    // A n_strx value of 0 indicates that no name is associated with a
1753
2
    // particular symbol table entry.
1754
2
    return StringRef();
1755
5.36k
  const char *Start = &StringTable.data()[Entry.n_strx];
1756
5.36k
  if (Start < getData().begin() || 
Start >= getData().end()5.36k
) {
1757
7
    return malformedError("bad string index: " + Twine(Entry.n_strx) +
1758
7
                          " for symbol at index " + Twine(getSymbolIndex(Symb)));
1759
7
  }
1760
5.35k
  return StringRef(Start);
1761
5.35k
}
1762
1763
842
unsigned MachOObjectFile::getSectionType(SectionRef Sec) const {
1764
842
  DataRefImpl DRI = Sec.getRawDataRefImpl();
1765
842
  uint32_t Flags = getSectionFlags(*this, DRI);
1766
842
  return Flags & MachO::SECTION_TYPE;
1767
842
}
1768
1769
5.95k
uint64_t MachOObjectFile::getNValue(DataRefImpl Sym) const {
1770
5.95k
  if (is64Bit()) {
1771
5.33k
    MachO::nlist_64 Entry = getSymbol64TableEntry(Sym);
1772
5.33k
    return Entry.n_value;
1773
5.33k
  }
1774
616
  MachO::nlist Entry = getSymbolTableEntry(Sym);
1775
616
  return Entry.n_value;
1776
616
}
1777
1778
// getIndirectName() returns the name of the alias'ed symbol who's string table
1779
// index is in the n_value field.
1780
std::error_code MachOObjectFile::getIndirectName(DataRefImpl Symb,
1781
1
                                                 StringRef &Res) const {
1782
1
  StringRef StringTable = getStringTableData();
1783
1
  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1784
1
  if ((Entry.n_type & MachO::N_TYPE) != MachO::N_INDR)
1785
0
    return object_error::parse_failed;
1786
1
  uint64_t NValue = getNValue(Symb);
1787
1
  if (NValue >= StringTable.size())
1788
0
    return object_error::parse_failed;
1789
1
  const char *Start = &StringTable.data()[NValue];
1790
1
  Res = StringRef(Start);
1791
1
  return std::error_code();
1792
1
}
1793
1794
3.54k
uint64_t MachOObjectFile::getSymbolValueImpl(DataRefImpl Sym) const {
1795
3.54k
  return getNValue(Sym);
1796
3.54k
}
1797
1798
1.54k
Expected<uint64_t> MachOObjectFile::getSymbolAddress(DataRefImpl Sym) const {
1799
1.54k
  return getSymbolValue(Sym);
1800
1.54k
}
1801
1802
129
uint32_t MachOObjectFile::getSymbolAlignment(DataRefImpl DRI) const {
1803
129
  uint32_t flags = getSymbolFlags(DRI);
1804
129
  if (flags & SymbolRef::SF_Common) {
1805
82
    MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1806
82
    return 1 << MachO::GET_COMM_ALIGN(Entry.n_desc);
1807
82
  }
1808
47
  return 0;
1809
47
}
1810
1811
148
uint64_t MachOObjectFile::getCommonSymbolSizeImpl(DataRefImpl DRI) const {
1812
148
  return getNValue(DRI);
1813
148
}
1814
1815
Expected<SymbolRef::Type>
1816
6.62k
MachOObjectFile::getSymbolType(DataRefImpl Symb) const {
1817
6.62k
  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1818
6.62k
  uint8_t n_type = Entry.n_type;
1819
6.62k
1820
6.62k
  // If this is a STAB debugging symbol, we can do nothing more.
1821
6.62k
  if (n_type & MachO::N_STAB)
1822
2.15k
    return SymbolRef::ST_Debug;
1823
4.46k
1824
4.46k
  switch (n_type & MachO::N_TYPE) {
1825
4.46k
    case MachO::N_UNDF :
1826
1.06k
      return SymbolRef::ST_Unknown;
1827
4.46k
    case MachO::N_SECT :
1828
3.40k
      Expected<section_iterator> SecOrError = getSymbolSection(Symb);
1829
3.40k
      if (!SecOrError)
1830
1
        return SecOrError.takeError();
1831
3.40k
      section_iterator Sec = *SecOrError;
1832
3.40k
      if (Sec->isData() || 
Sec->isBSS()2.85k
)
1833
821
        return SymbolRef::ST_Data;
1834
2.57k
      return SymbolRef::ST_Function;
1835
5
  }
1836
5
  return SymbolRef::ST_Other;
1837
5
}
1838
1839
12.3k
uint32_t MachOObjectFile::getSymbolFlags(DataRefImpl DRI) const {
1840
12.3k
  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, DRI);
1841
12.3k
1842
12.3k
  uint8_t MachOType = Entry.n_type;
1843
12.3k
  uint16_t MachOFlags = Entry.n_desc;
1844
12.3k
1845
12.3k
  uint32_t Result = SymbolRef::SF_None;
1846
12.3k
1847
12.3k
  if ((MachOType & MachO::N_TYPE) == MachO::N_INDR)
1848
4
    Result |= SymbolRef::SF_Indirect;
1849
12.3k
1850
12.3k
  if (MachOType & MachO::N_STAB)
1851
534
    Result |= SymbolRef::SF_FormatSpecific;
1852
12.3k
1853
12.3k
  if (MachOType & MachO::N_EXT) {
1854
9.33k
    Result |= SymbolRef::SF_Global;
1855
9.33k
    if ((MachOType & MachO::N_TYPE) == MachO::N_UNDF) {
1856
2.25k
      if (getNValue(DRI))
1857
591
        Result |= SymbolRef::SF_Common;
1858
1.66k
      else
1859
1.66k
        Result |= SymbolRef::SF_Undefined;
1860
2.25k
    }
1861
9.33k
1862
9.33k
    if (!(MachOType & MachO::N_PEXT))
1863
9.20k
      Result |= SymbolRef::SF_Exported;
1864
9.33k
  }
1865
12.3k
1866
12.3k
  if (MachOFlags & (MachO::N_WEAK_REF | MachO::N_WEAK_DEF))
1867
204
    Result |= SymbolRef::SF_Weak;
1868
12.3k
1869
12.3k
  if (MachOFlags & (MachO::N_ARM_THUMB_DEF))
1870
223
    Result |= SymbolRef::SF_Thumb;
1871
12.3k
1872
12.3k
  if ((MachOType & MachO::N_TYPE) == MachO::N_ABS)
1873
13
    Result |= SymbolRef::SF_Absolute;
1874
12.3k
1875
12.3k
  return Result;
1876
12.3k
}
1877
1878
Expected<section_iterator>
1879
6.20k
MachOObjectFile::getSymbolSection(DataRefImpl Symb) const {
1880
6.20k
  MachO::nlist_base Entry = getSymbolTableEntryBase(*this, Symb);
1881
6.20k
  uint8_t index = Entry.n_sect;
1882
6.20k
1883
6.20k
  if (index == 0)
1884
313
    return section_end();
1885
5.88k
  DataRefImpl DRI;
1886
5.88k
  DRI.d.a = index - 1;
1887
5.88k
  if (DRI.d.a >= Sections.size()){
1888
5
    return malformedError("bad section index: " + Twine((int)index) +
1889
5
                          " for symbol at index " + Twine(getSymbolIndex(Symb)));
1890
5
  }
1891
5.88k
  return section_iterator(SectionRef(DRI, this));
1892
5.88k
}
1893
1894
107
unsigned MachOObjectFile::getSymbolSectionID(SymbolRef Sym) const {
1895
107
  MachO::nlist_base Entry =
1896
107
      getSymbolTableEntryBase(*this, Sym.getRawDataRefImpl());
1897
107
  return Entry.n_sect - 1;
1898
107
}
1899
1900
20.0k
void MachOObjectFile::moveSectionNext(DataRefImpl &Sec) const {
1901
20.0k
  Sec.d.a++;
1902
20.0k
}
1903
1904
36.8k
Expected<StringRef> MachOObjectFile::getSectionName(DataRefImpl Sec) const {
1905
36.8k
  ArrayRef<char> Raw = getSectionRawName(Sec);
1906
36.8k
  return parseSegmentOrSectionName(Raw.data());
1907
36.8k
}
1908
1909
8.11k
uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
1910
8.11k
  if (is64Bit())
1911
3.19k
    return getSection64(Sec).addr;
1912
4.92k
  return getSection(Sec).addr;
1913
4.92k
}
1914
1915
895
uint64_t MachOObjectFile::getSectionIndex(DataRefImpl Sec) const {
1916
895
  return Sec.d.a;
1917
895
}
1918
1919
9.01k
uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
1920
9.01k
  // In the case if a malformed Mach-O file where the section offset is past
1921
9.01k
  // the end of the file or some part of the section size is past the end of
1922
9.01k
  // the file return a size of zero or a size that covers the rest of the file
1923
9.01k
  // but does not extend past the end of the file.
1924
9.01k
  uint32_t SectOffset, SectType;
1925
9.01k
  uint64_t SectSize;
1926
9.01k
1927
9.01k
  if (is64Bit()) {
1928
4.23k
    MachO::section_64 Sect = getSection64(Sec);
1929
4.23k
    SectOffset = Sect.offset;
1930
4.23k
    SectSize = Sect.size;
1931
4.23k
    SectType = Sect.flags & MachO::SECTION_TYPE;
1932
4.77k
  } else {
1933
4.77k
    MachO::section Sect = getSection(Sec);
1934
4.77k
    SectOffset = Sect.offset;
1935
4.77k
    SectSize = Sect.size;
1936
4.77k
    SectType = Sect.flags & MachO::SECTION_TYPE;
1937
4.77k
  }
1938
9.01k
  if (SectType == MachO::S_ZEROFILL || 
SectType == MachO::S_GB_ZEROFILL8.97k
)
1939
34
    return SectSize;
1940
8.97k
  uint64_t FileSize = getData().size();
1941
8.97k
  if (SectOffset > FileSize)
1942
0
    return 0;
1943
8.97k
  if (FileSize - SectOffset < SectSize)
1944
0
    return FileSize - SectOffset;
1945
8.97k
  return SectSize;
1946
8.97k
}
1947
1948
Expected<ArrayRef<uint8_t>>
1949
10.5k
MachOObjectFile::getSectionContents(DataRefImpl Sec) const {
1950
10.5k
  uint32_t Offset;
1951
10.5k
  uint64_t Size;
1952
10.5k
1953
10.5k
  if (is64Bit()) {
1954
9.15k
    MachO::section_64 Sect = getSection64(Sec);
1955
9.15k
    Offset = Sect.offset;
1956
9.15k
    Size = Sect.size;
1957
9.15k
  } else {
1958
1.36k
    MachO::section Sect = getSection(Sec);
1959
1.36k
    Offset = Sect.offset;
1960
1.36k
    Size = Sect.size;
1961
1.36k
  }
1962
10.5k
1963
10.5k
  return arrayRefFromStringRef(getData().substr(Offset, Size));
1964
10.5k
}
1965
1966
1.82k
uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
1967
1.82k
  uint32_t Align;
1968
1.82k
  if (is64Bit()) {
1969
1.81k
    MachO::section_64 Sect = getSection64(Sec);
1970
1.81k
    Align = Sect.align;
1971
1.81k
  } else {
1972
14
    MachO::section Sect = getSection(Sec);
1973
14
    Align = Sect.align;
1974
14
  }
1975
1.82k
1976
1.82k
  return uint64_t(1) << Align;
1977
1.82k
}
1978
1979
23
Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
1980
23
  if (SectionIndex < 1 || SectionIndex > Sections.size())
1981
0
    return malformedError("bad section index: " + Twine((int)SectionIndex));
1982
23
1983
23
  DataRefImpl DRI;
1984
23
  DRI.d.a = SectionIndex - 1;
1985
23
  return SectionRef(DRI, this);
1986
23
}
1987
1988
0
Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
1989
0
  StringRef SecName;
1990
0
  for (const SectionRef &Section : sections()) {
1991
0
    if (std::error_code E = Section.getName(SecName))
1992
0
      return errorCodeToError(E);
1993
0
    if (SecName == SectionName) {
1994
0
      return Section;
1995
0
    }
1996
0
  }
1997
0
  return errorCodeToError(object_error::parse_failed);
1998
0
}
1999
2000
8.32k
bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
2001
8.32k
  return false;
2002
8.32k
}
2003
2004
2.09k
bool MachOObjectFile::isSectionText(DataRefImpl Sec) const {
2005
2.09k
  uint32_t Flags = getSectionFlags(*this, Sec);
2006
2.09k
  return Flags & MachO::S_ATTR_PURE_INSTRUCTIONS;
2007
2.09k
}
2008
2009
3.44k
bool MachOObjectFile::isSectionData(DataRefImpl Sec) const {
2010
3.44k
  uint32_t Flags = getSectionFlags(*this, Sec);
2011
3.44k
  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2012
3.44k
  return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2013
3.44k
         
!(855
SectionType == MachO::S_ZEROFILL855
||
2014
855
           
SectionType == MachO::S_GB_ZEROFILL576
);
2015
3.44k
}
2016
2017
12.1k
bool MachOObjectFile::isSectionBSS(DataRefImpl Sec) const {
2018
12.1k
  uint32_t Flags = getSectionFlags(*this, Sec);
2019
12.1k
  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2020
12.1k
  return !(Flags & MachO::S_ATTR_PURE_INSTRUCTIONS) &&
2021
12.1k
         
(8.72k
SectionType == MachO::S_ZEROFILL8.72k
||
2022
8.72k
          
SectionType == MachO::S_GB_ZEROFILL8.25k
);
2023
12.1k
}
2024
2025
158
unsigned MachOObjectFile::getSectionID(SectionRef Sec) const {
2026
158
  return Sec.getRawDataRefImpl().d.a;
2027
158
}
2028
2029
9.75k
bool MachOObjectFile::isSectionVirtual(DataRefImpl Sec) const {
2030
9.75k
  uint32_t Flags = getSectionFlags(*this, Sec);
2031
9.75k
  unsigned SectionType = Flags & MachO::SECTION_TYPE;
2032
9.75k
  return SectionType == MachO::S_ZEROFILL ||
2033
9.75k
         
SectionType == MachO::S_GB_ZEROFILL9.73k
;
2034
9.75k
}
2035
2036
221
bool MachOObjectFile::isSectionBitcode(DataRefImpl Sec) const {
2037
221
  StringRef SegmentName = getSectionFinalSegmentName(Sec);
2038
221
  if (Expected<StringRef> NameOrErr = getSectionName(Sec))
2039
221
    return (SegmentName == "__LLVM" && 
*NameOrErr == "__bitcode"4
);
2040
0
  return false;
2041
0
}
2042
2043
8.75k
bool MachOObjectFile::isSectionStripped(DataRefImpl Sec) const {
2044
8.75k
  if (is64Bit())
2045
8.10k
    return getSection64(Sec).offset == 0;
2046
650
  return getSection(Sec).offset == 0;
2047
650
}
2048
2049
2.78k
relocation_iterator MachOObjectFile::section_rel_begin(DataRefImpl Sec) const {
2050
2.78k
  DataRefImpl Ret;
2051
2.78k
  Ret.d.a = Sec.d.a;
2052
2.78k
  Ret.d.b = 0;
2053
2.78k
  return relocation_iterator(RelocationRef(Ret, this));
2054
2.78k
}
2055
2056
relocation_iterator
2057
2.78k
MachOObjectFile::section_rel_end(DataRefImpl Sec) const {
2058
2.78k
  uint32_t Num;
2059
2.78k
  if (is64Bit()) {
2060
2.43k
    MachO::section_64 Sect = getSection64(Sec);
2061
2.43k
    Num = Sect.nreloc;
2062
2.43k
  } else {
2063
350
    MachO::section Sect = getSection(Sec);
2064
350
    Num = Sect.nreloc;
2065
350
  }
2066
2.78k
2067
2.78k
  DataRefImpl Ret;
2068
2.78k
  Ret.d.a = Sec.d.a;
2069
2.78k
  Ret.d.b = Num;
2070
2.78k
  return relocation_iterator(RelocationRef(Ret, this));
2071
2.78k
}
2072
2073
798
relocation_iterator MachOObjectFile::extrel_begin() const {
2074
798
  DataRefImpl Ret;
2075
798
  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2076
798
  Ret.d.a = 0; // Would normally be a section index.
2077
798
  Ret.d.b = 0; // Index into the external relocations
2078
798
  return relocation_iterator(RelocationRef(Ret, this));
2079
798
}
2080
2081
798
relocation_iterator MachOObjectFile::extrel_end() const {
2082
798
  MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2083
798
  DataRefImpl Ret;
2084
798
  // for DYSYMTAB symbols, Ret.d.a == 0 for external relocations
2085
798
  Ret.d.a = 0; // Would normally be a section index.
2086
798
  Ret.d.b = DysymtabLoadCmd.nextrel; // Index into the external relocations
2087
798
  return relocation_iterator(RelocationRef(Ret, this));
2088
798
}
2089
2090
1
relocation_iterator MachOObjectFile::locrel_begin() const {
2091
1
  DataRefImpl Ret;
2092
1
  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2093
1
  Ret.d.a = 1; // Would normally be a section index.
2094
1
  Ret.d.b = 0; // Index into the local relocations
2095
1
  return relocation_iterator(RelocationRef(Ret, this));
2096
1
}
2097
2098
1
relocation_iterator MachOObjectFile::locrel_end() const {
2099
1
  MachO::dysymtab_command DysymtabLoadCmd = getDysymtabLoadCommand();
2100
1
  DataRefImpl Ret;
2101
1
  // for DYSYMTAB symbols, Ret.d.a == 1 for local relocations
2102
1
  Ret.d.a = 1; // Would normally be a section index.
2103
1
  Ret.d.b = DysymtabLoadCmd.nlocrel; // Index into the local relocations
2104
1
  return relocation_iterator(RelocationRef(Ret, this));
2105
1
}
2106
2107
5.42k
void MachOObjectFile::moveRelocationNext(DataRefImpl &Rel) const {
2108
5.42k
  ++Rel.d.b;
2109
5.42k
}
2110
2111
4.62k
uint64_t MachOObjectFile::getRelocationOffset(DataRefImpl Rel) const {
2112
4.62k
  assert((getHeader().filetype == MachO::MH_OBJECT ||
2113
4.62k
          getHeader().filetype == MachO::MH_KEXT_BUNDLE) &&
2114
4.62k
         "Only implemented for MH_OBJECT && MH_KEXT_BUNDLE");
2115
4.62k
  MachO::any_relocation_info RE = getRelocation(Rel);
2116
4.62k
  return getAnyRelocationAddress(RE);
2117
4.62k
}
2118
2119
symbol_iterator
2120
1.79k
MachOObjectFile::getRelocationSymbol(DataRefImpl Rel) const {
2121
1.79k
  MachO::any_relocation_info RE = getRelocation(Rel);
2122
1.79k
  if (isRelocationScattered(RE))
2123
1
    return symbol_end();
2124
1.79k
2125
1.79k
  uint32_t SymbolIdx = getPlainRelocationSymbolNum(RE);
2126
1.79k
  bool isExtern = getPlainRelocationExternal(RE);
2127
1.79k
  if (!isExtern)
2128
966
    return symbol_end();
2129
828
2130
828
  MachO::symtab_command S = getSymtabLoadCommand();
2131
828
  unsigned SymbolTableEntrySize = is64Bit() ?
2132
748
    sizeof(MachO::nlist_64) :
2133
828
    
sizeof(MachO::nlist)80
;
2134
828
  uint64_t Offset = S.symoff + SymbolIdx * SymbolTableEntrySize;
2135
828
  DataRefImpl Sym;
2136
828
  Sym.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2137
828
  return symbol_iterator(SymbolRef(Sym, this));
2138
828
}
2139
2140
section_iterator
2141
107
MachOObjectFile::getRelocationSection(DataRefImpl Rel) const {
2142
107
  return section_iterator(getAnyRelocationSection(getRelocation(Rel)));
2143
107
}
2144
2145
528
uint64_t MachOObjectFile::getRelocationType(DataRefImpl Rel) const {
2146
528
  MachO::any_relocation_info RE = getRelocation(Rel);
2147
528
  return getAnyRelocationType(RE);
2148
528
}
2149
2150
void MachOObjectFile::getRelocationTypeName(
2151
454
    DataRefImpl Rel, SmallVectorImpl<char> &Result) const {
2152
454
  StringRef res;
2153
454
  uint64_t RType = getRelocationType(Rel);
2154
454
2155
454
  unsigned Arch = this->getArch();
2156
454
2157
454
  switch (Arch) {
2158
454
    case Triple::x86: {
2159
80
      static const char *const Table[] =  {
2160
80
        "GENERIC_RELOC_VANILLA",
2161
80
        "GENERIC_RELOC_PAIR",
2162
80
        "GENERIC_RELOC_SECTDIFF",
2163
80
        "GENERIC_RELOC_PB_LA_PTR",
2164
80
        "GENERIC_RELOC_LOCAL_SECTDIFF",
2165
80
        "GENERIC_RELOC_TLV" };
2166
80
2167
80
      if (RType > 5)
2168
0
        res = "Unknown";
2169
80
      else
2170
80
        res = Table[RType];
2171
80
      break;
2172
454
    }
2173
454
    case Triple::x86_64: {
2174
174
      static const char *const Table[] =  {
2175
174
        "X86_64_RELOC_UNSIGNED",
2176
174
        "X86_64_RELOC_SIGNED",
2177
174
        "X86_64_RELOC_BRANCH",
2178
174
        "X86_64_RELOC_GOT_LOAD",
2179
174
        "X86_64_RELOC_GOT",
2180
174
        "X86_64_RELOC_SUBTRACTOR",
2181
174
        "X86_64_RELOC_SIGNED_1",
2182
174
        "X86_64_RELOC_SIGNED_2",
2183
174
        "X86_64_RELOC_SIGNED_4",
2184
174
        "X86_64_RELOC_TLV" };
2185
174
2186
174
      if (RType > 9)
2187
0
        res = "Unknown";
2188
174
      else
2189
174
        res = Table[RType];
2190
174
      break;
2191
454
    }
2192
454
    case Triple::arm: {
2193
94
      static const char *const Table[] =  {
2194
94
        "ARM_RELOC_VANILLA",
2195
94
        "ARM_RELOC_PAIR",
2196
94
        "ARM_RELOC_SECTDIFF",
2197
94
        "ARM_RELOC_LOCAL_SECTDIFF",
2198
94
        "ARM_RELOC_PB_LA_PTR",
2199
94
        "ARM_RELOC_BR24",
2200
94
        "ARM_THUMB_RELOC_BR22",
2201
94
        "ARM_THUMB_32BIT_BRANCH",
2202
94
        "ARM_RELOC_HALF",
2203
94
        "ARM_RELOC_HALF_SECTDIFF" };
2204
94
2205
94
      if (RType > 9)
2206
0
        res = "Unknown";
2207
94
      else
2208
94
        res = Table[RType];
2209
94
      break;
2210
454
    }
2211
454
    case Triple::aarch64:
2212
56
    case Triple::aarch64_32: {
2213
56
      static const char *const Table[] = {
2214
56
        "ARM64_RELOC_UNSIGNED",           "ARM64_RELOC_SUBTRACTOR",
2215
56
        "ARM64_RELOC_BRANCH26",           "ARM64_RELOC_PAGE21",
2216
56
        "ARM64_RELOC_PAGEOFF12",          "ARM64_RELOC_GOT_LOAD_PAGE21",
2217
56
        "ARM64_RELOC_GOT_LOAD_PAGEOFF12", "ARM64_RELOC_POINTER_TO_GOT",
2218
56
        "ARM64_RELOC_TLVP_LOAD_PAGE21",   "ARM64_RELOC_TLVP_LOAD_PAGEOFF12",
2219
56
        "ARM64_RELOC_ADDEND"
2220
56
      };
2221
56
2222
56
      if (RType >= array_lengthof(Table))
2223
0
        res = "Unknown";
2224
56
      else
2225
56
        res = Table[RType];
2226
56
      break;
2227
56
    }
2228
56
    case Triple::ppc: {
2229
30
      static const char *const Table[] =  {
2230
30
        "PPC_RELOC_VANILLA",
2231
30
        "PPC_RELOC_PAIR",
2232
30
        "PPC_RELOC_BR14",
2233
30
        "PPC_RELOC_BR24",
2234
30
        "PPC_RELOC_HI16",
2235
30
        "PPC_RELOC_LO16",
2236
30
        "PPC_RELOC_HA16",
2237
30
        "PPC_RELOC_LO14",
2238
30
        "PPC_RELOC_SECTDIFF",
2239
30
        "PPC_RELOC_PB_LA_PTR",
2240
30
        "PPC_RELOC_HI16_SECTDIFF",
2241
30
        "PPC_RELOC_LO16_SECTDIFF",
2242
30
        "PPC_RELOC_HA16_SECTDIFF",
2243
30
        "PPC_RELOC_JBSR",
2244
30
        "PPC_RELOC_LO14_SECTDIFF",
2245
30
        "PPC_RELOC_LOCAL_SECTDIFF" };
2246
30
2247
30
      if (RType > 15)
2248
0
        res = "Unknown";
2249
30
      else
2250
30
        res = Table[RType];
2251
30
      break;
2252
56
    }
2253
56
    case Triple::UnknownArch:
2254
0
      res = "Unknown";
2255
0
      break;
2256
454
  }
2257
454
  Result.append(res.begin(), res.end());
2258
454
}
2259
2260
0
uint8_t MachOObjectFile::getRelocationLength(DataRefImpl Rel) const {
2261
0
  MachO::any_relocation_info RE = getRelocation(Rel);
2262
0
  return getAnyRelocationLength(RE);
2263
0
}
2264
2265
//
2266
// guessLibraryShortName() is passed a name of a dynamic library and returns a
2267
// guess on what the short name is.  Then name is returned as a substring of the
2268
// StringRef Name passed in.  The name of the dynamic library is recognized as
2269
// a framework if it has one of the two following forms:
2270
//      Foo.framework/Versions/A/Foo
2271
//      Foo.framework/Foo
2272
// Where A and Foo can be any string.  And may contain a trailing suffix
2273
// starting with an underbar.  If the Name is recognized as a framework then
2274
// isFramework is set to true else it is set to false.  If the Name has a
2275
// suffix then Suffix is set to the substring in Name that contains the suffix
2276
// else it is set to a NULL StringRef.
2277
//
2278
// The Name of the dynamic library is recognized as a library name if it has
2279
// one of the two following forms:
2280
//      libFoo.A.dylib
2281
//      libFoo.dylib
2282
//
2283
// The library may have a suffix trailing the name Foo of the form:
2284
//      libFoo_profile.A.dylib
2285
//      libFoo_profile.dylib
2286
// These dyld image suffixes are separated from the short name by a '_'
2287
// character. Because the '_' character is commonly used to separate words in
2288
// filenames guessLibraryShortName() cannot reliably separate a dylib's short
2289
// name from an arbitrary image suffix; imagine if both the short name and the
2290
// suffix contains an '_' character! To better deal with this ambiguity,
2291
// guessLibraryShortName() will recognize only "_debug" and "_profile" as valid
2292
// Suffix values. Calling code needs to be tolerant of guessLibraryShortName()
2293
// guessing incorrectly.
2294
//
2295
// The Name of the dynamic library is also recognized as a library name if it
2296
// has the following form:
2297
//      Foo.qtx
2298
//
2299
// If the Name of the dynamic library is none of the forms above then a NULL
2300
// StringRef is returned.
2301
StringRef MachOObjectFile::guessLibraryShortName(StringRef Name,
2302
                                                 bool &isFramework,
2303
90
                                                 StringRef &Suffix) {
2304
90
  StringRef Foo, F, DotFramework, V, Dylib, Lib, Dot, Qtx;
2305
90
  size_t a, b, c, d, Idx;
2306
90
2307
90
  isFramework = false;
2308
90
  Suffix = StringRef();
2309
90
2310
90
  // Pull off the last component and make Foo point to it
2311
90
  a = Name.rfind('/');
2312
90
  if (a == Name.npos || 
a == 075
)
2313
15
    goto guess_library;
2314
75
  Foo = Name.slice(a+1, Name.npos);
2315
75
2316
75
  // Look for a suffix starting with a '_'
2317
75
  Idx = Foo.rfind('_');
2318
75
  if (Idx != Foo.npos && 
Foo.size() >= 26
) {
2319
6
    Suffix = Foo.slice(Idx, Foo.npos);
2320
6
    if (Suffix != "_debug" && 
Suffix != "_profile"5
)
2321
4
      Suffix = StringRef();
2322
2
    else
2323
2
      Foo = Foo.slice(0, Idx);
2324
6
  }
2325
75
2326
75
  // First look for the form Foo.framework/Foo
2327
75
  b = Name.rfind('/', a);
2328
75
  if (b == Name.npos)
2329
2
    Idx = 0;
2330
73
  else
2331
73
    Idx = b+1;
2332
75
  F = Name.slice(Idx, Idx + Foo.size());
2333
75
  DotFramework = Name.slice(Idx + Foo.size(),
2334
75
                            Idx + Foo.size() + sizeof(".framework/")-1);
2335
75
  if (F == Foo && 
DotFramework == ".framework/"4
) {
2336
4
    isFramework = true;
2337
4
    return Foo;
2338
4
  }
2339
71
2340
71
  // Next look for the form Foo.framework/Versions/A/Foo
2341
71
  if (b == Name.npos)
2342
0
    goto guess_library;
2343
71
  c =  Name.rfind('/', b);
2344
71
  if (c == Name.npos || 
c == 068
)
2345
68
    goto guess_library;
2346
3
  V = Name.slice(c+1, Name.npos);
2347
3
  if (!V.startswith("Versions/"))
2348
1
    goto guess_library;
2349
2
  d =  Name.rfind('/', c);
2350
2
  if (d == Name.npos)
2351
1
    Idx = 0;
2352
1
  else
2353
1
    Idx = d+1;
2354
2
  F = Name.slice(Idx, Idx + Foo.size());
2355
2
  DotFramework = Name.slice(Idx + Foo.size(),
2356
2
                            Idx + Foo.size() + sizeof(".framework/")-1);
2357
2
  if (F == Foo && DotFramework == ".framework/") {
2358
2
    isFramework = true;
2359
2
    return Foo;
2360
2
  }
2361
84
2362
84
guess_library:
2363
84
  // pull off the suffix after the "." and make a point to it
2364
84
  a = Name.rfind('.');
2365
84
  if (a == Name.npos || a == 0)
2366
0
    return StringRef();
2367
84
  Dylib = Name.slice(a, Name.npos);
2368
84
  if (Dylib != ".dylib")
2369
2
    goto guess_qtx;
2370
82
2371
82
  // First pull off the version letter for the form Foo.A.dylib if any.
2372
82
  if (a >= 3) {
2373
82
    Dot = Name.slice(a-2, a-1);
2374
82
    if (Dot == ".")
2375
54
      a = a - 2;
2376
82
  }
2377
82
2378
82
  b = Name.rfind('/', a);
2379
82
  if (b == Name.npos)
2380
14
    b = 0;
2381
68
  else
2382
68
    b = b+1;
2383
82
  // ignore any suffix after an underbar like Foo_profile.A.dylib
2384
82
  Idx = Name.rfind('_');
2385
82
  if (Idx != Name.npos && 
Idx != b6
) {
2386
6
    Lib = Name.slice(b, Idx);
2387
6
    Suffix = Name.slice(Idx, a);
2388
6
    if (Suffix != "_debug" && 
Suffix != "_profile"5
) {
2389
1
      Suffix = StringRef();
2390
1
      Lib = Name.slice(b, a);
2391
1
    }
2392
6
  }
2393
76
  else
2394
76
    Lib = Name.slice(b, a);
2395
82
  // There are incorrect library names of the form:
2396
82
  // libATS.A_profile.dylib so check for these.
2397
82
  if (Lib.size() >= 3) {
2398
82
    Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2399
82
    if (Dot == ".")
2400
2
      Lib = Lib.slice(0, Lib.size()-2);
2401
82
  }
2402
82
  return Lib;
2403
2
2404
2
guess_qtx:
2405
2
  Qtx = Name.slice(a, Name.npos);
2406
2
  if (Qtx != ".qtx")
2407
0
    return StringRef();
2408
2
  b = Name.rfind('/', a);
2409
2
  if (b == Name.npos)
2410
1
    Lib = Name.slice(0, a);
2411
1
  else
2412
1
    Lib = Name.slice(b+1, a);
2413
2
  // There are library names of the form: QT.A.qtx so check for these.
2414
2
  if (Lib.size() >= 3) {
2415
2
    Dot = Lib.slice(Lib.size()-2, Lib.size()-1);
2416
2
    if (Dot == ".")
2417
1
      Lib = Lib.slice(0, Lib.size()-2);
2418
2
  }
2419
2
  return Lib;
2420
2
}
2421
2422
// getLibraryShortNameByIndex() is used to get the short name of the library
2423
// for an undefined symbol in a linked Mach-O binary that was linked with the
2424
// normal two-level namespace default (that is MH_TWOLEVEL in the header).
2425
// It is passed the index (0 - based) of the library as translated from
2426
// GET_LIBRARY_ORDINAL (1 - based).
2427
std::error_code MachOObjectFile::getLibraryShortNameByIndex(unsigned Index,
2428
97
                                                         StringRef &Res) const {
2429
97
  if (Index >= Libraries.size())
2430
0
    return object_error::parse_failed;
2431
97
2432
97
  // If the cache of LibrariesShortNames is not built up do that first for
2433
97
  // all the Libraries.
2434
97
  if (LibrariesShortNames.size() == 0) {
2435
137
    for (unsigned i = 0; i < Libraries.size(); 
i++90
) {
2436
90
      auto CommandOrErr =
2437
90
        getStructOrErr<MachO::dylib_command>(*this, Libraries[i]);
2438
90
      if (!CommandOrErr)
2439
0
        return object_error::parse_failed;
2440
90
      MachO::dylib_command D = CommandOrErr.get();
2441
90
      if (D.dylib.name >= D.cmdsize)
2442
0
        return object_error::parse_failed;
2443
90
      const char *P = (const char *)(Libraries[i]) + D.dylib.name;
2444
90
      StringRef Name = StringRef(P);
2445
90
      if (D.dylib.name+Name.size() >= D.cmdsize)
2446
0
        return object_error::parse_failed;
2447
90
      StringRef Suffix;
2448
90
      bool isFramework;
2449
90
      StringRef shortName = guessLibraryShortName(Name, isFramework, Suffix);
2450
90
      if (shortName.empty())
2451
0
        LibrariesShortNames.push_back(Name);
2452
90
      else
2453
90
        LibrariesShortNames.push_back(shortName);
2454
90
    }
2455
47
  }
2456
97
2457
97
  Res = LibrariesShortNames[Index];
2458
97
  return std::error_code();
2459
97
}
2460
2461
66
uint32_t MachOObjectFile::getLibraryCount() const {
2462
66
  return Libraries.size();
2463
66
}
2464
2465
section_iterator
2466
8
MachOObjectFile::getRelocationRelocatedSection(relocation_iterator Rel) const {
2467
8
  DataRefImpl Sec;
2468
8
  Sec.d.a = Rel->getRawDataRefImpl().d.a;
2469
8
  return section_iterator(SectionRef(Sec, this));
2470
8
}
2471
2472
1.94k
basic_symbol_iterator MachOObjectFile::symbol_begin() const {
2473
1.94k
  DataRefImpl DRI;
2474
1.94k
  MachO::symtab_command Symtab = getSymtabLoadCommand();
2475
1.94k
  if (!SymtabLoadCmd || 
Symtab.nsyms == 01.87k
)
2476
69
    return basic_symbol_iterator(SymbolRef(DRI, this));
2477
1.87k
2478
1.87k
  return getSymbolByIndex(0);
2479
1.87k
}
2480
2481
4.81k
basic_symbol_iterator MachOObjectFile::symbol_end() const {
2482
4.81k
  DataRefImpl DRI;
2483
4.81k
  MachO::symtab_command Symtab = getSymtabLoadCommand();
2484
4.81k
  if (!SymtabLoadCmd || 
Symtab.nsyms == 04.74k
)
2485
69
    return basic_symbol_iterator(SymbolRef(DRI, this));
2486
4.74k
2487
4.74k
  unsigned SymbolTableEntrySize = is64Bit() ?
2488
4.28k
    sizeof(MachO::nlist_64) :
2489
4.74k
    
sizeof(MachO::nlist)459
;
2490
4.74k
  unsigned Offset = Symtab.symoff +
2491
4.74k
    Symtab.nsyms * SymbolTableEntrySize;
2492
4.74k
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2493
4.74k
  return basic_symbol_iterator(SymbolRef(DRI, this));
2494
4.74k
}
2495
2496
2.00k
symbol_iterator MachOObjectFile::getSymbolByIndex(unsigned Index) const {
2497
2.00k
  MachO::symtab_command Symtab = getSymtabLoadCommand();
2498
2.00k
  if (!SymtabLoadCmd || Index >= Symtab.nsyms)
2499
0
    report_fatal_error("Requested symbol index is out of range.");
2500
2.00k
  unsigned SymbolTableEntrySize =
2501
2.00k
    is64Bit() ? 
sizeof(MachO::nlist_64)1.73k
:
sizeof(MachO::nlist)267
;
2502
2.00k
  DataRefImpl DRI;
2503
2.00k
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2504
2.00k
  DRI.p += Index * SymbolTableEntrySize;
2505
2.00k
  return basic_symbol_iterator(SymbolRef(DRI, this));
2506
2.00k
}
2507
2508
12
uint64_t MachOObjectFile::getSymbolIndex(DataRefImpl Symb) const {
2509
12
  MachO::symtab_command Symtab = getSymtabLoadCommand();
2510
12
  if (!SymtabLoadCmd)
2511
0
    report_fatal_error("getSymbolIndex() called with no symbol table symbol");
2512
12
  unsigned SymbolTableEntrySize =
2513
12
    is64Bit() ? 
sizeof(MachO::nlist_64)11
:
sizeof(MachO::nlist)1
;
2514
12
  DataRefImpl DRIstart;
2515
12
  DRIstart.p = reinterpret_cast<uintptr_t>(getPtr(*this, Symtab.symoff));
2516
12
  uint64_t Index = (Symb.p - DRIstart.p) / SymbolTableEntrySize;
2517
12
  return Index;
2518
12
}
2519
2520
3.54k
section_iterator MachOObjectFile::section_begin() const {
2521
3.54k
  DataRefImpl DRI;
2522
3.54k
  return section_iterator(SectionRef(DRI, this));
2523
3.54k
}
2524
2525
15.5k
section_iterator MachOObjectFile::section_end() const {
2526
15.5k
  DataRefImpl DRI;
2527
15.5k
  DRI.d.a = Sections.size();
2528
15.5k
  return section_iterator(SectionRef(DRI, this));
2529
15.5k
}
2530
2531
1.08k
uint8_t MachOObjectFile::getBytesInAddress() const {
2532
1.08k
  return is64Bit() ? 
8854
:
4230
;
2533
1.08k
}
2534
2535
786
StringRef MachOObjectFile::getFileFormatName() const {
2536
786
  unsigned CPUType = getCPUType(*this);
2537
786
  if (!is64Bit()) {
2538
188
    switch (CPUType) {
2539
188
    case MachO::CPU_TYPE_I386:
2540
93
      return "Mach-O 32-bit i386";
2541
188
    case MachO::CPU_TYPE_ARM:
2542
89
      return "Mach-O arm";
2543
188
    case MachO::CPU_TYPE_ARM64_32:
2544
0
      return "Mach-O arm64 (ILP32)";
2545
188
    case MachO::CPU_TYPE_POWERPC:
2546
6
      return "Mach-O 32-bit ppc";
2547
188
    default:
2548
0
      return "Mach-O 32-bit unknown";
2549
598
    }
2550
598
  }
2551
598
2552
598
  switch (CPUType) {
2553
598
  case MachO::CPU_TYPE_X86_64:
2554
544
    return "Mach-O 64-bit x86-64";
2555
598
  case MachO::CPU_TYPE_ARM64:
2556
50
    return "Mach-O arm64";
2557
598
  case MachO::CPU_TYPE_POWERPC64:
2558
4
    return "Mach-O 64-bit ppc64";
2559
598
  default:
2560
0
    return "Mach-O 64-bit unknown";
2561
598
  }
2562
598
}
2563
2564
7.05k
Triple::ArchType MachOObjectFile::getArch(uint32_t CPUType) {
2565
7.05k
  switch (CPUType) {
2566
7.05k
  case MachO::CPU_TYPE_I386:
2567
379
    return Triple::x86;
2568
7.05k
  case MachO::CPU_TYPE_X86_64:
2569
5.59k
    return Triple::x86_64;
2570
7.05k
  case MachO::CPU_TYPE_ARM:
2571
594
    return Triple::arm;
2572
7.05k
  case MachO::CPU_TYPE_ARM64:
2573
419
    return Triple::aarch64;
2574
7.05k
  case MachO::CPU_TYPE_ARM64_32:
2575
6
    return Triple::aarch64_32;
2576
7.05k
  case MachO::CPU_TYPE_POWERPC:
2577
36
    return Triple::ppc;
2578
7.05k
  case MachO::CPU_TYPE_POWERPC64:
2579
24
    return Triple::ppc64;
2580
7.05k
  default:
2581
0
    return Triple::UnknownArch;
2582
7.05k
  }
2583
7.05k
}
2584
2585
Triple MachOObjectFile::getArchTriple(uint32_t CPUType, uint32_t CPUSubType,
2586
                                      const char **McpuDefault,
2587
1.01k
                                      const char **ArchFlag) {
2588
1.01k
  if (McpuDefault)
2589
228
    *McpuDefault = nullptr;
2590
1.01k
  if (ArchFlag)
2591
166
    *ArchFlag = nullptr;
2592
1.01k
2593
1.01k
  switch (CPUType) {
2594
1.01k
  case MachO::CPU_TYPE_I386:
2595
104
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2596
104
    case MachO::CPU_SUBTYPE_I386_ALL:
2597
104
      if (ArchFlag)
2598
56
        *ArchFlag = "i386";
2599
104
      return Triple("i386-apple-darwin");
2600
104
    default:
2601
0
      return Triple();
2602
0
    }
2603
730
  case MachO::CPU_TYPE_X86_64:
2604
730
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2605
730
    case MachO::CPU_SUBTYPE_X86_64_ALL:
2606
702
      if (ArchFlag)
2607
72
        *ArchFlag = "x86_64";
2608
702
      return Triple("x86_64-apple-darwin");
2609
730
    case MachO::CPU_SUBTYPE_X86_64_H:
2610
28
      if (ArchFlag)
2611
11
        *ArchFlag = "x86_64h";
2612
28
      return Triple("x86_64h-apple-darwin");
2613
730
    default:
2614
0
      return Triple();
2615
0
    }
2616
106
  case MachO::CPU_TYPE_ARM:
2617
106
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2618
106
    case MachO::CPU_SUBTYPE_ARM_V4T:
2619
0
      if (ArchFlag)
2620
0
        *ArchFlag = "armv4t";
2621
0
      return Triple("armv4t-apple-darwin");
2622
106
    case MachO::CPU_SUBTYPE_ARM_V5TEJ:
2623
0
      if (ArchFlag)
2624
0
        *ArchFlag = "armv5e";
2625
0
      return Triple("armv5e-apple-darwin");
2626
106
    case MachO::CPU_SUBTYPE_ARM_XSCALE:
2627
0
      if (ArchFlag)
2628
0
        *ArchFlag = "xscale";
2629
0
      return Triple("xscale-apple-darwin");
2630
106
    case MachO::CPU_SUBTYPE_ARM_V6:
2631
0
      if (ArchFlag)
2632
0
        *ArchFlag = "armv6";
2633
0
      return Triple("armv6-apple-darwin");
2634
106
    case MachO::CPU_SUBTYPE_ARM_V6M:
2635
0
      if (McpuDefault)
2636
0
        *McpuDefault = "cortex-m0";
2637
0
      if (ArchFlag)
2638
0
        *ArchFlag = "armv6m";
2639
0
      return Triple("armv6m-apple-darwin");
2640
106
    case MachO::CPU_SUBTYPE_ARM_V7:
2641
51
      if (ArchFlag)
2642
7
        *ArchFlag = "armv7";
2643
51
      return Triple("armv7-apple-darwin");
2644
106
    case MachO::CPU_SUBTYPE_ARM_V7EM:
2645
3
      if (McpuDefault)
2646
3
        *McpuDefault = "cortex-m4";
2647
3
      if (ArchFlag)
2648
2
        *ArchFlag = "armv7em";
2649
3
      return Triple("thumbv7em-apple-darwin");
2650
106
    case MachO::CPU_SUBTYPE_ARM_V7K:
2651
1
      if (McpuDefault)
2652
0
        *McpuDefault = "cortex-a7";
2653
1
      if (ArchFlag)
2654
0
        *ArchFlag = "armv7k";
2655
1
      return Triple("armv7k-apple-darwin");
2656
106
    case MachO::CPU_SUBTYPE_ARM_V7M:
2657
18
      if (McpuDefault)
2658
8
        *McpuDefault = "cortex-m3";
2659
18
      if (ArchFlag)
2660
5
        *ArchFlag = "armv7m";
2661
18
      return Triple("thumbv7m-apple-darwin");
2662
106
    case MachO::CPU_SUBTYPE_ARM_V7S:
2663
32
      if (McpuDefault)
2664
5
        *McpuDefault = "cortex-a7";
2665
32
      if (ArchFlag)
2666
2
        *ArchFlag = "armv7s";
2667
32
      return Triple("armv7s-apple-darwin");
2668
106
    default:
2669
1
      return Triple();
2670
0
    }
2671
68
  case MachO::CPU_TYPE_ARM64:
2672
68
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2673
68
    case MachO::CPU_SUBTYPE_ARM64_ALL:
2674
68
      if (McpuDefault)
2675
16
        *McpuDefault = "cyclone";
2676
68
      if (ArchFlag)
2677
6
        *ArchFlag = "arm64";
2678
68
      return Triple("arm64-apple-darwin");
2679
68
    default:
2680
0
      return Triple();
2681
0
    }
2682
5
  case MachO::CPU_TYPE_ARM64_32:
2683
5
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2684
5
    case MachO::CPU_SUBTYPE_ARM64_32_V8:
2685
5
      if (McpuDefault)
2686
5
        *McpuDefault = "cyclone";
2687
5
      if (ArchFlag)
2688
4
        *ArchFlag = "arm64_32";
2689
5
      return Triple("arm64_32-apple-darwin");
2690
5
    default:
2691
0
      return Triple();
2692
0
    }
2693
0
  case MachO::CPU_TYPE_POWERPC:
2694
0
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2695
0
    case MachO::CPU_SUBTYPE_POWERPC_ALL:
2696
0
      if (ArchFlag)
2697
0
        *ArchFlag = "ppc";
2698
0
      return Triple("ppc-apple-darwin");
2699
0
    default:
2700
0
      return Triple();
2701
0
    }
2702
0
  case MachO::CPU_TYPE_POWERPC64:
2703
0
    switch (CPUSubType & ~MachO::CPU_SUBTYPE_MASK) {
2704
0
    case MachO::CPU_SUBTYPE_POWERPC_ALL:
2705
0
      if (ArchFlag)
2706
0
        *ArchFlag = "ppc64";
2707
0
      return Triple("ppc64-apple-darwin");
2708
0
    default:
2709
0
      return Triple();
2710
0
    }
2711
2
  default:
2712
2
    return Triple();
2713
1.01k
  }
2714
1.01k
}
2715
2716
10
Triple MachOObjectFile::getHostArch() {
2717
10
  return Triple(sys::getDefaultTargetTriple());
2718
10
}
2719
2720
49
bool MachOObjectFile::isValidArch(StringRef ArchFlag) {
2721
49
  auto validArchs = getValidArchs();
2722
49
  return llvm::find(validArchs, ArchFlag) != validArchs.end();
2723
49
}
2724
2725
55
ArrayRef<StringRef> MachOObjectFile::getValidArchs() {
2726
55
  static const std::array<StringRef, 17> validArchs = {
2727
55
      "i386",   "x86_64", "x86_64h",  "armv4t",  "arm",    "armv5e",
2728
55
      "armv6",  "armv6m", "armv7",    "armv7em", "armv7k", "armv7m",
2729
55
      "armv7s", "arm64",  "arm64_32", "ppc",     "ppc64",
2730
55
  };
2731
55
2732
55
  return validArchs;
2733
55
}
2734
2735
7.05k
Triple::ArchType MachOObjectFile::getArch() const {
2736
7.05k
  return getArch(getCPUType(*this));
2737
7.05k
}
2738
2739
849
Triple MachOObjectFile::getArchTriple(const char **McpuDefault) const {
2740
849
  return getArchTriple(Header.cputype, Header.cpusubtype, McpuDefault);
2741
849
}
2742
2743
0
relocation_iterator MachOObjectFile::section_rel_begin(unsigned Index) const {
2744
0
  DataRefImpl DRI;
2745
0
  DRI.d.a = Index;
2746
0
  return section_rel_begin(DRI);
2747
0
}
2748
2749
0
relocation_iterator MachOObjectFile::section_rel_end(unsigned Index) const {
2750
0
  DataRefImpl DRI;
2751
0
  DRI.d.a = Index;
2752
0
  return section_rel_end(DRI);
2753
0
}
2754
2755
72
dice_iterator MachOObjectFile::begin_dices() const {
2756
72
  DataRefImpl DRI;
2757
72
  if (!DataInCodeLoadCmd)
2758
39
    return dice_iterator(DiceRef(DRI, this));
2759
33
2760
33
  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2761
33
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, DicLC.dataoff));
2762
33
  return dice_iterator(DiceRef(DRI, this));
2763
33
}
2764
2765
72
dice_iterator MachOObjectFile::end_dices() const {
2766
72
  DataRefImpl DRI;
2767
72
  if (!DataInCodeLoadCmd)
2768
39
    return dice_iterator(DiceRef(DRI, this));
2769
33
2770
33
  MachO::linkedit_data_command DicLC = getDataInCodeLoadCommand();
2771
33
  unsigned Offset = DicLC.dataoff + DicLC.datasize;
2772
33
  DRI.p = reinterpret_cast<uintptr_t>(getPtr(*this, Offset));
2773
33
  return dice_iterator(DiceRef(DRI, this));
2774
33
}
2775
2776
ExportEntry::ExportEntry(Error *E, const MachOObjectFile *O,
2777
50
                         ArrayRef<uint8_t> T) : E(E), O(O), Trie(T) {}
2778
2779
24
void ExportEntry::moveToFirst() {
2780
24
  ErrorAsOutParameter ErrAsOutParam(E);
2781
24
  pushNode(0);
2782
24
  if (*E)
2783
0
    return;
2784
24
  pushDownUntilBottom();
2785
24
}
2786
2787
38
void ExportEntry::moveToEnd() {
2788
38
  Stack.clear();
2789
38
  Done = true;
2790
38
}
2791
2792
97
bool ExportEntry::operator==(const ExportEntry &Other) const {
2793
97
  // Common case, one at end, other iterating from begin.
2794
97
  if (Done || 
Other.Done72
)
2795
97
    return (Done == Other.Done);
2796
0
  // Not equal if different stack sizes.
2797
0
  if (Stack.size() != Other.Stack.size())
2798
0
    return false;
2799
0
  // Not equal if different cumulative strings.
2800
0
  if (!CumulativeString.equals(Other.CumulativeString))
2801
0
    return false;
2802
0
  // Equal if all nodes in both stacks match.
2803
0
  for (unsigned i=0; i < Stack.size(); ++i) {
2804
0
    if (Stack[i].Start != Other.Stack[i].Start)
2805
0
      return false;
2806
0
  }
2807
0
  return true;
2808
0
}
2809
2810
415
uint64_t ExportEntry::readULEB128(const uint8_t *&Ptr, const char **error) {
2811
415
  unsigned Count;
2812
415
  uint64_t Result = decodeULEB128(Ptr, &Count, Trie.end(), error);
2813
415
  Ptr += Count;
2814
415
  if (Ptr > Trie.end())
2815
0
    Ptr = Trie.end();
2816
415
  return Result;
2817
415
}
2818
2819
90
StringRef ExportEntry::name() const {
2820
90
  return CumulativeString;
2821
90
}
2822
2823
75
uint64_t ExportEntry::flags() const {
2824
75
  return Stack.back().Flags;
2825
75
}
2826
2827
70
uint64_t ExportEntry::address() const {
2828
70
  return Stack.back().Address;
2829
70
}
2830
2831
24
uint64_t ExportEntry::other() const {
2832
24
  return Stack.back().Other;
2833
24
}
2834
2835
28
StringRef ExportEntry::otherName() const {
2836
28
  const char* ImportName = Stack.back().ImportName;
2837
28
  if (ImportName)
2838
24
    return StringRef(ImportName);
2839
4
  return StringRef();
2840
4
}
2841
2842
0
uint32_t ExportEntry::nodeOffset() const {
2843
0
  return Stack.back().Start - Trie.begin();
2844
0
}
2845
2846
ExportEntry::NodeState::NodeState(const uint8_t *Ptr)
2847
140
    : Start(Ptr), Current(Ptr) {}
2848
2849
140
void ExportEntry::pushNode(uint64_t offset) {
2850
140
  ErrorAsOutParameter ErrAsOutParam(E);
2851
140
  const uint8_t *Ptr = Trie.begin() + offset;
2852
140
  NodeState State(Ptr);
2853
140
  const char *error;
2854
140
  uint64_t ExportInfoSize = readULEB128(State.Current, &error);
2855
140
  if (error) {
2856
2
    *E = malformedError("export info size " + Twine(error) +
2857
2
                        " in export trie data at node: 0x" +
2858
2
                        Twine::utohexstr(offset));
2859
2
    moveToEnd();
2860
2
    return;
2861
2
  }
2862
138
  State.IsExportNode = (ExportInfoSize != 0);
2863
138
  const uint8_t* Children = State.Current + ExportInfoSize;
2864
138
  if (Children > Trie.end()) {
2865
1
    *E = malformedError(
2866
1
        "export info size: 0x" + Twine::utohexstr(ExportInfoSize) +
2867
1
        " in export trie data at node: 0x" + Twine::utohexstr(offset) +
2868
1
        " too big and extends past end of trie data");
2869
1
    moveToEnd();
2870
1
    return;
2871
1
  }
2872
137
  if (State.IsExportNode) {
2873
77
    const uint8_t *ExportStart = State.Current;
2874
77
    State.Flags = readULEB128(State.Current, &error);
2875
77
    if (error) {
2876
0
      *E = malformedError("flags " + Twine(error) +
2877
0
                          " in export trie data at node: 0x" +
2878
0
                          Twine::utohexstr(offset));
2879
0
      moveToEnd();
2880
0
      return;
2881
0
    }
2882
77
    uint64_t Kind = State.Flags & MachO::EXPORT_SYMBOL_FLAGS_KIND_MASK;
2883
77
    if (State.Flags != 0 &&
2884
77
        
(40
Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_REGULAR40
&&
2885
40
         
Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE3
&&
2886
40
         
Kind != MachO::EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL2
)) {
2887
1
      *E = malformedError(
2888
1
          "unsupported exported symbol kind: " + Twine((int)Kind) +
2889
1
          " in flags: 0x" + Twine::utohexstr(State.Flags) +
2890
1
          " in export trie data at node: 0x" + Twine::utohexstr(offset));
2891
1
      moveToEnd();
2892
1
      return;
2893
1
    }
2894
76
    if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_REEXPORT) {
2895
19
      State.Address = 0;
2896
19
      State.Other = readULEB128(State.Current, &error); // dylib ordinal
2897
19
      if (error) {
2898
0
        *E = malformedError("dylib ordinal of re-export " + Twine(error) +
2899
0
                            " in export trie data at node: 0x" +
2900
0
                            Twine::utohexstr(offset));
2901
0
        moveToEnd();
2902
0
        return;
2903
0
      }
2904
19
      if (O != nullptr) {
2905
19
        if (State.Other > O->getLibraryCount()) {
2906
1
          *E = malformedError(
2907
1
              "bad library ordinal: " + Twine((int)State.Other) + " (max " +
2908
1
              Twine((int)O->getLibraryCount()) +
2909
1
              ") in export trie data at node: 0x" + Twine::utohexstr(offset));
2910
1
          moveToEnd();
2911
1
          return;
2912
1
        }
2913
18
      }
2914
18
      State.ImportName = reinterpret_cast<const char*>(State.Current);
2915
18
      if (*State.ImportName == '\0') {
2916
8
        State.Current++;
2917
10
      } else {
2918
10
        const uint8_t *End = State.Current + 1;
2919
10
        if (End >= Trie.end()) {
2920
1
          *E = malformedError("import name of re-export in export trie data at "
2921
1
                              "node: 0x" +
2922
1
                              Twine::utohexstr(offset) +
2923
1
                              " starts past end of trie data");
2924
1
          moveToEnd();
2925
1
          return;
2926
1
        }
2927
42
        
while(9
*End != '\0' &&
End < Trie.end()34
)
2928
33
          End++;
2929
9
        if (*End != '\0') {
2930
1
          *E = malformedError("import name of re-export in export trie data at "
2931
1
                              "node: 0x" +
2932
1
                              Twine::utohexstr(offset) +
2933
1
                              " extends past end of trie data");
2934
1
          moveToEnd();
2935
1
          return;
2936
1
        }
2937
8
        State.Current = End + 1;
2938
8
      }
2939
57
    } else {
2940
57
      State.Address = readULEB128(State.Current, &error);
2941
57
      if (error) {
2942
0
        *E = malformedError("address " + Twine(error) +
2943
0
                            " in export trie data at node: 0x" +
2944
0
                            Twine::utohexstr(offset));
2945
0
        moveToEnd();
2946
0
        return;
2947
0
      }
2948
57
      if (State.Flags & MachO::EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER) {
2949
5
        State.Other = readULEB128(State.Current, &error);
2950
5
        if (error) {
2951
0
          *E = malformedError("resolver of stub and resolver " + Twine(error) +
2952
0
                              " in export trie data at node: 0x" +
2953
0
                              Twine::utohexstr(offset));
2954
0
          moveToEnd();
2955
0
          return;
2956
0
        }
2957
73
      }
2958
57
    }
2959
73
    if(ExportStart + ExportInfoSize != State.Current) {
2960
1
      *E = malformedError(
2961
1
          "inconsistant export info size: 0x" +
2962
1
          Twine::utohexstr(ExportInfoSize) + " where actual size was: 0x" +
2963
1
          Twine::utohexstr(State.Current - ExportStart) +
2964
1
          " in export trie data at node: 0x" + Twine::utohexstr(offset));
2965
1
      moveToEnd();
2966
1
      return;
2967
1
    }
2968
132
  }
2969
132
  State.ChildCount = *Children;
2970
132
  if (State.ChildCount != 0 && 
Children + 1 >= Trie.end()59
) {
2971
1
    *E = malformedError("byte for count of childern in export trie data at "
2972
1
                        "node: 0x" +
2973
1
                        Twine::utohexstr(offset) +
2974
1
                        " extends past end of trie data");
2975
1
    moveToEnd();
2976
1
    return;
2977
1
  }
2978
131
  State.Current = Children + 1;
2979
131
  State.NextChildIndex = 0;
2980
131
  State.ParentStringLength = CumulativeString.size();
2981
131
  Stack.push_back(State);
2982
131
}
2983
2984
84
void ExportEntry::pushDownUntilBottom() {
2985
84
  ErrorAsOutParameter ErrAsOutParam(E);
2986
84
  const char *error;
2987
191
  while (Stack.back().NextChildIndex < Stack.back().ChildCount) {
2988
118
    NodeState &Top = Stack.back();
2989
118
    CumulativeString.resize(Top.ParentStringLength);
2990
735
    for (;*Top.Current != 0 && 
Top.Current < Trie.end()618
;
Top.Current++617
) {
2991
617
      char C = *Top.Current;
2992
617
      CumulativeString.push_back(C);
2993
617
    }
2994
118
    if (Top.Current >= Trie.end()) {
2995
1
      *E = malformedError("edge sub-string in export trie data at node: 0x" +
2996
1
                          Twine::utohexstr(Top.Start - Trie.begin()) +
2997
1
                          " for child #" + Twine((int)Top.NextChildIndex) +
2998
1
                          " extends past end of trie data");
2999
1
      moveToEnd();
3000
1
      return;
3001
1
    }
3002
117
    Top.Current += 1;
3003
117
    uint64_t childNodeIndex = readULEB128(Top.Current, &error);
3004
117
    if (error) {
3005
0
      *E = malformedError("child node offset " + Twine(error) +
3006
0
                          " in export trie data at node: 0x" +
3007
0
                          Twine::utohexstr(Top.Start - Trie.begin()));
3008
0
      moveToEnd();
3009
0
      return;
3010
0
    }
3011
248
    
for (const NodeState &node : nodes())117
{
3012
248
      if (node.Start == Trie.begin() + childNodeIndex){
3013
1
        *E = malformedError("loop in childern in export trie data at node: 0x" +
3014
1
                            Twine::utohexstr(Top.Start - Trie.begin()) +
3015
1
                            " back to node: 0x" +
3016
1
                            Twine::utohexstr(childNodeIndex));
3017
1
        moveToEnd();
3018
1
        return;
3019
1
      }
3020
248
    }
3021
117
    Top.NextChildIndex += 1;
3022
116
    pushNode(childNodeIndex);
3023
116
    if (*E)
3024
9
      return;
3025
116
  }
3026
84
  
if (73
!Stack.back().IsExportNode73
) {
3027
1
    *E = malformedError("node is not an export node in export trie data at "
3028
1
                        "node: 0x" +
3029
1
                        Twine::utohexstr(Stack.back().Start - Trie.begin()));
3030
1
    moveToEnd();
3031
1
    return;
3032
1
  }
3033
73
}
3034
3035
// We have a trie data structure and need a way to walk it that is compatible
3036
// with the C++ iterator model. The solution is a non-recursive depth first
3037
// traversal where the iterator contains a stack of parent nodes along with a
3038
// string that is the accumulation of all edge strings along the parent chain
3039
// to this point.
3040
//
3041
// There is one "export" node for each exported symbol.  But because some
3042
// symbols may be a prefix of another symbol (e.g. _dup and _dup2), an export
3043
// node may have child nodes too.
3044
//
3045
// The algorithm for moveNext() is to keep moving down the leftmost unvisited
3046
// child until hitting a node with no children (which is an export node or
3047
// else the trie is malformed). On the way down, each node is pushed on the
3048
// stack ivar.  If there is no more ways down, it pops up one and tries to go
3049
// down a sibling path until a childless node is reached.
3050
72
void ExportEntry::moveNext() {
3051
72
  assert(!Stack.empty() && "ExportEntry::moveNext() with empty node stack");
3052
72
  if (!Stack.back().IsExportNode) {
3053
0
    *E = malformedError("node is not an export node in export trie data at "
3054
0
                        "node: 0x" +
3055
0
                        Twine::utohexstr(Stack.back().Start - Trie.begin()));
3056
0
    moveToEnd();
3057
0
    return;
3058
0
  }
3059
72
3060
72
  Stack.pop_back();
3061
100
  while (!Stack.empty()) {
3062
88
    NodeState &Top = Stack.back();
3063
88
    if (Top.NextChildIndex < Top.ChildCount) {
3064
60
      pushDownUntilBottom();
3065
60
      // Now at the next export node.
3066
60
      return;
3067
60
    } else {
3068
28
      if (Top.IsExportNode) {
3069
0
        // This node has no children but is itself an export node.
3070
0
        CumulativeString.resize(Top.ParentStringLength);
3071
0
        return;
3072
0
      }
3073
28
      Stack.pop_back();
3074
28
    }
3075
88
  }
3076
72
  Done = true;
3077
12
}
3078
3079
iterator_range<export_iterator>
3080
MachOObjectFile::exports(Error &E, ArrayRef<uint8_t> Trie,
3081
25
                         const MachOObjectFile *O) {
3082
25
  ExportEntry Start(&E, O, Trie);
3083
25
  if (Trie.empty())
3084
1
    Start.moveToEnd();
3085
24
  else
3086
24
    Start.moveToFirst();
3087
25
3088
25
  ExportEntry Finish(&E, O, Trie);
3089
25
  Finish.moveToEnd();
3090
25
3091
25
  return make_range(export_iterator(Start), export_iterator(Finish));
3092
25
}
3093
3094
21
iterator_range<export_iterator> MachOObjectFile::exports(Error &Err) const {
3095
21
  return exports(Err, getDyldInfoExportsTrie(), this);
3096
21
}
3097
3098
MachORebaseEntry::MachORebaseEntry(Error *E, const MachOObjectFile *O,
3099
                                   ArrayRef<uint8_t> Bytes, bool is64Bit)
3100
    : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3101
24
      PointerSize(is64Bit ? 8 : 4) {}
3102
3103
12
void MachORebaseEntry::moveToFirst() {
3104
12
  Ptr = Opcodes.begin();
3105
12
  moveNext();
3106
12
}
3107
3108
24
void MachORebaseEntry::moveToEnd() {
3109
24
  Ptr = Opcodes.end();
3110
24
  RemainingLoopCount = 0;
3111
24
  Done = true;
3112
24
}
3113
3114
24
void MachORebaseEntry::moveNext() {
3115
24
  ErrorAsOutParameter ErrAsOutParam(E);
3116
24
  // If in the middle of some loop, move to next rebasing in loop.
3117
24
  SegmentOffset += AdvanceAmount;
3118
24
  if (RemainingLoopCount) {
3119
5
    --RemainingLoopCount;
3120
5
    return;
3121
5
  }
3122
19
  // REBASE_OPCODE_DONE is only used for padding if we are not aligned to
3123
19
  // pointer size. Therefore it is possible to reach the end without ever having
3124
19
  // seen REBASE_OPCODE_DONE.
3125
19
  if (Ptr == Opcodes.end()) {
3126
0
    Done = true;
3127
0
    return;
3128
0
  }
3129
19
  bool More = true;
3130
40
  while (More) {
3131
39
    // Parse next opcode and set up next loop.
3132
39
    const uint8_t *OpcodeStart = Ptr;
3133
39
    uint8_t Byte = *Ptr++;
3134
39
    uint8_t ImmValue = Byte & MachO::REBASE_IMMEDIATE_MASK;
3135
39
    uint8_t Opcode = Byte & MachO::REBASE_OPCODE_MASK;
3136
39
    uint32_t Count, Skip;
3137
39
    const char *error = nullptr;
3138
39
    switch (Opcode) {
3139
39
    case MachO::REBASE_OPCODE_DONE:
3140
1
      More = false;
3141
1
      Done = true;
3142
1
      moveToEnd();
3143
1
      DEBUG_WITH_TYPE("mach-o-rebase", dbgs() << "REBASE_OPCODE_DONE\n");
3144
1
      break;
3145
39
    case MachO::REBASE_OPCODE_SET_TYPE_IMM:
3146
12
      RebaseType = ImmValue;
3147
12
      if (RebaseType > MachO::REBASE_TYPE_TEXT_PCREL32) {
3148
1
        *E = malformedError("for REBASE_OPCODE_SET_TYPE_IMM bad bind type: " +
3149
1
                            Twine((int)RebaseType) + " for opcode at: 0x" +
3150
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3151
1
        moveToEnd();
3152
1
        return;
3153
1
      }
3154
11
      DEBUG_WITH_TYPE(
3155
11
          "mach-o-rebase",
3156
11
          dbgs() << "REBASE_OPCODE_SET_TYPE_IMM: "
3157
11
                 << "RebaseType=" << (int) RebaseType << "\n");
3158
11
      break;
3159
11
    case MachO::REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3160
11
      SegmentIndex = ImmValue;
3161
11
      SegmentOffset = readULEB128(&error);
3162
11
      if (error) {
3163
1
        *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3164
1
                            Twine(error) + " for opcode at: 0x" +
3165
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3166
1
        moveToEnd();
3167
1
        return;
3168
1
      }
3169
10
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3170
10
                                               PointerSize);
3171
10
      if (error) {
3172
2
        *E = malformedError("for REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3173
2
                            Twine(error) + " for opcode at: 0x" +
3174
2
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3175
2
        moveToEnd();
3176
2
        return;
3177
2
      }
3178
8
      DEBUG_WITH_TYPE(
3179
8
          "mach-o-rebase",
3180
8
          dbgs() << "REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3181
8
                 << "SegmentIndex=" << SegmentIndex << ", "
3182
8
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3183
8
                 << "\n");
3184
8
      break;
3185
8
    case MachO::REBASE_OPCODE_ADD_ADDR_ULEB:
3186
2
      SegmentOffset += readULEB128(&error);
3187
2
      if (error) {
3188
0
        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3189
0
                            " for opcode at: 0x" +
3190
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3191
0
        moveToEnd();
3192
0
        return;
3193
0
      }
3194
2
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3195
2
                                               PointerSize);
3196
2
      if (error) {
3197
1
        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3198
1
                            " for opcode at: 0x" +
3199
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3200
1
        moveToEnd();
3201
1
        return;
3202
1
      }
3203
1
      DEBUG_WITH_TYPE("mach-o-rebase",
3204
1
                      dbgs() << "REBASE_OPCODE_ADD_ADDR_ULEB: "
3205
1
                             << format("SegmentOffset=0x%06X",
3206
1
                                       SegmentOffset) << "\n");
3207
1
      break;
3208
1
    case MachO::REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
3209
1
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3210
1
                                               PointerSize);
3211
1
      if (error) {
3212
0
        *E = malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED " +
3213
0
                            Twine(error) + " for opcode at: 0x" +
3214
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3215
0
        moveToEnd();
3216
0
        return;
3217
0
      }
3218
1
      SegmentOffset += ImmValue * PointerSize;
3219
1
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3220
1
                                               PointerSize);
3221
1
      if (error) {
3222
1
        *E =
3223
1
            malformedError("for REBASE_OPCODE_ADD_ADDR_IMM_SCALED "
3224
1
                           " (after adding immediate times the pointer size) " +
3225
1
                           Twine(error) + " for opcode at: 0x" +
3226
1
                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3227
1
        moveToEnd();
3228
1
        return;
3229
1
      }
3230
0
      DEBUG_WITH_TYPE("mach-o-rebase",
3231
0
                      dbgs() << "REBASE_OPCODE_ADD_ADDR_IMM_SCALED: "
3232
0
                             << format("SegmentOffset=0x%06X",
3233
0
                                       SegmentOffset) << "\n");
3234
0
      break;
3235
5
    case MachO::REBASE_OPCODE_DO_REBASE_IMM_TIMES:
3236
5
      AdvanceAmount = PointerSize;
3237
5
      Skip = 0;
3238
5
      Count = ImmValue;
3239
5
      if (ImmValue != 0)
3240
5
        RemainingLoopCount = ImmValue - 1;
3241
0
      else
3242
0
        RemainingLoopCount = 0;
3243
5
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3244
5
                                               PointerSize, Count, Skip);
3245
5
      if (error) {
3246
2
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_IMM_TIMES " +
3247
2
                            Twine(error) + " for opcode at: 0x" +
3248
2
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3249
2
        moveToEnd();
3250
2
        return;
3251
2
      }
3252
3
      DEBUG_WITH_TYPE(
3253
3
          "mach-o-rebase",
3254
3
          dbgs() << "REBASE_OPCODE_DO_REBASE_IMM_TIMES: "
3255
3
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3256
3
                 << ", AdvanceAmount=" << AdvanceAmount
3257
3
                 << ", RemainingLoopCount=" << RemainingLoopCount
3258
3
                 << "\n");
3259
3
      return;
3260
3
    case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
3261
1
      AdvanceAmount = PointerSize;
3262
1
      Skip = 0;
3263
1
      Count = readULEB128(&error);
3264
1
      if (error) {
3265
0
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3266
0
                            Twine(error) + " for opcode at: 0x" +
3267
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3268
0
        moveToEnd();
3269
0
        return;
3270
0
      }
3271
1
      if (Count != 0)
3272
1
        RemainingLoopCount = Count - 1;
3273
0
      else
3274
0
        RemainingLoopCount = 0;
3275
1
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3276
1
                                               PointerSize, Count, Skip);
3277
1
      if (error) {
3278
1
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES " +
3279
1
                            Twine(error) + " for opcode at: 0x" +
3280
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3281
1
        moveToEnd();
3282
1
        return;
3283
1
      }
3284
0
      DEBUG_WITH_TYPE(
3285
0
          "mach-o-rebase",
3286
0
          dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES: "
3287
0
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3288
0
                 << ", AdvanceAmount=" << AdvanceAmount
3289
0
                 << ", RemainingLoopCount=" << RemainingLoopCount
3290
0
                 << "\n");
3291
0
      return;
3292
3
    case MachO::REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
3293
3
      Skip = readULEB128(&error);
3294
3
      if (error) {
3295
0
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3296
0
                            Twine(error) + " for opcode at: 0x" +
3297
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3298
0
        moveToEnd();
3299
0
        return;
3300
0
      }
3301
3
      AdvanceAmount = Skip + PointerSize;
3302
3
      Count = 1;
3303
3
      RemainingLoopCount = 0;
3304
3
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3305
3
                                               PointerSize, Count, Skip);
3306
3
      if (error) {
3307
0
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB " +
3308
0
                            Twine(error) + " for opcode at: 0x" +
3309
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3310
0
        moveToEnd();
3311
0
        return;
3312
0
      }
3313
3
      DEBUG_WITH_TYPE(
3314
3
          "mach-o-rebase",
3315
3
          dbgs() << "REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB: "
3316
3
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3317
3
                 << ", AdvanceAmount=" << AdvanceAmount
3318
3
                 << ", RemainingLoopCount=" << RemainingLoopCount
3319
3
                 << "\n");
3320
3
      return;
3321
3
    case MachO::REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
3322
2
      Count = readULEB128(&error);
3323
2
      if (error) {
3324
0
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3325
0
                            "ULEB " +
3326
0
                            Twine(error) + " for opcode at: 0x" +
3327
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3328
0
        moveToEnd();
3329
0
        return;
3330
0
      }
3331
2
      if (Count != 0)
3332
2
        RemainingLoopCount = Count - 1;
3333
0
      else
3334
0
        RemainingLoopCount = 0;
3335
2
      Skip = readULEB128(&error);
3336
2
      if (error) {
3337
0
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3338
0
                            "ULEB " +
3339
0
                            Twine(error) + " for opcode at: 0x" +
3340
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3341
0
        moveToEnd();
3342
0
        return;
3343
0
      }
3344
2
      AdvanceAmount = Skip + PointerSize;
3345
2
3346
2
      error = O->RebaseEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3347
2
                                               PointerSize, Count, Skip);
3348
2
      if (error) {
3349
1
        *E = malformedError("for REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_"
3350
1
                            "ULEB " +
3351
1
                            Twine(error) + " for opcode at: 0x" +
3352
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3353
1
        moveToEnd();
3354
1
        return;
3355
1
      }
3356
1
      DEBUG_WITH_TYPE(
3357
1
          "mach-o-rebase",
3358
1
          dbgs() << "REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB: "
3359
1
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3360
1
                 << ", AdvanceAmount=" << AdvanceAmount
3361
1
                 << ", RemainingLoopCount=" << RemainingLoopCount
3362
1
                 << "\n");
3363
1
      return;
3364
1
    default:
3365
1
      *E = malformedError("bad rebase info (bad opcode value 0x" +
3366
1
                          Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3367
1
                          Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3368
1
      moveToEnd();
3369
1
      return;
3370
39
    }
3371
39
  }
3372
19
}
3373
3374
21
uint64_t MachORebaseEntry::readULEB128(const char **error) {
3375
21
  unsigned Count;
3376
21
  uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3377
21
  Ptr += Count;
3378
21
  if (Ptr > Opcodes.end())
3379
0
    Ptr = Opcodes.end();
3380
21
  return Result;
3381
21
}
3382
3383
0
int32_t MachORebaseEntry::segmentIndex() const { return SegmentIndex; }
3384
3385
0
uint64_t MachORebaseEntry::segmentOffset() const { return SegmentOffset; }
3386
3387
12
StringRef MachORebaseEntry::typeName() const {
3388
12
  switch (RebaseType) {
3389
12
  case MachO::REBASE_TYPE_POINTER:
3390
12
    return "pointer";
3391
12
  case MachO::REBASE_TYPE_TEXT_ABSOLUTE32:
3392
0
    return "text abs32";
3393
12
  case MachO::REBASE_TYPE_TEXT_PCREL32:
3394
0
    return "text rel32";
3395
0
  }
3396
0
  return "unknown";
3397
0
}
3398
3399
// For use with the SegIndex of a checked Mach-O Rebase entry
3400
// to get the segment name.
3401
12
StringRef MachORebaseEntry::segmentName() const {
3402
12
  return O->BindRebaseSegmentName(SegmentIndex);
3403
12
}
3404
3405
// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3406
// to get the section name.
3407
12
StringRef MachORebaseEntry::sectionName() const {
3408
12
  return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3409
12
}
3410
3411
// For use with a SegIndex,SegOffset pair from a checked Mach-O Rebase entry
3412
// to get the address.
3413
12
uint64_t MachORebaseEntry::address() const {
3414
12
  return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3415
12
}
3416
3417
24
bool MachORebaseEntry::operator==(const MachORebaseEntry &Other) const {
3418
#ifdef EXPENSIVE_CHECKS
3419
  assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3420
#else
3421
  assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3422
24
#endif
3423
24
  return (Ptr == Other.Ptr) &&
3424
24
         
(RemainingLoopCount == Other.RemainingLoopCount)12
&&
3425
24
         
(Done == Other.Done)12
;
3426
24
}
3427
3428
iterator_range<rebase_iterator>
3429
MachOObjectFile::rebaseTable(Error &Err, MachOObjectFile *O,
3430
12
                             ArrayRef<uint8_t> Opcodes, bool is64) {
3431
12
  if (O->BindRebaseSectionTable == nullptr)
3432
12
    O->BindRebaseSectionTable = llvm::make_unique<BindRebaseSegInfo>(O);
3433
12
  MachORebaseEntry Start(&Err, O, Opcodes, is64);
3434
12
  Start.moveToFirst();
3435
12
3436
12
  MachORebaseEntry Finish(&Err, O, Opcodes, is64);
3437
12
  Finish.moveToEnd();
3438
12
3439
12
  return make_range(rebase_iterator(Start), rebase_iterator(Finish));
3440
12
}
3441
3442
12
iterator_range<rebase_iterator> MachOObjectFile::rebaseTable(Error &Err) {
3443
12
  return rebaseTable(Err, this, getDyldInfoRebaseOpcodes(), is64Bit());
3444
12
}
3445
3446
MachOBindEntry::MachOBindEntry(Error *E, const MachOObjectFile *O,
3447
                               ArrayRef<uint8_t> Bytes, bool is64Bit, Kind BK)
3448
    : E(E), O(O), Opcodes(Bytes), Ptr(Bytes.begin()),
3449
96
      PointerSize(is64Bit ? 8 : 4), TableKind(BK) {}
3450
3451
48
void MachOBindEntry::moveToFirst() {
3452
48
  Ptr = Opcodes.begin();
3453
48
  moveNext();
3454
48
}
3455
3456
87
void MachOBindEntry::moveToEnd() {
3457
87
  Ptr = Opcodes.end();
3458
87
  RemainingLoopCount = 0;
3459
87
  Done = true;
3460
87
}
3461
3462
107
void MachOBindEntry::moveNext() {
3463
107
  ErrorAsOutParameter ErrAsOutParam(E);
3464
107
  // If in the middle of some loop, move to next binding in loop.
3465
107
  SegmentOffset += AdvanceAmount;
3466
107
  if (RemainingLoopCount) {
3467
2
    --RemainingLoopCount;
3468
2
    return;
3469
2
  }
3470
105
  // BIND_OPCODE_DONE is only used for padding if we are not aligned to
3471
105
  // pointer size. Therefore it is possible to reach the end without ever having
3472
105
  // seen BIND_OPCODE_DONE.
3473
105
  if (Ptr == Opcodes.end()) {
3474
9
    Done = true;
3475
9
    return;
3476
9
  }
3477
96
  bool More = true;
3478
290
  while (More) {
3479
276
    // Parse next opcode and set up next loop.
3480
276
    const uint8_t *OpcodeStart = Ptr;
3481
276
    uint8_t Byte = *Ptr++;
3482
276
    uint8_t ImmValue = Byte & MachO::BIND_IMMEDIATE_MASK;
3483
276
    uint8_t Opcode = Byte & MachO::BIND_OPCODE_MASK;
3484
276
    int8_t SignExtended;
3485
276
    const uint8_t *SymStart;
3486
276
    uint32_t Count, Skip;
3487
276
    const char *error = nullptr;
3488
276
    switch (Opcode) {
3489
276
    case MachO::BIND_OPCODE_DONE:
3490
18
      if (TableKind == Kind::Lazy) {
3491
8
        // Lazying bindings have a DONE opcode between entries.  Need to ignore
3492
8
        // it to advance to next entry.  But need not if this is last entry.
3493
8
        bool NotLastEntry = false;
3494
117
        for (const uint8_t *P = Ptr; P < Opcodes.end(); 
++P109
) {
3495
109
          if (*P) {
3496
60
            NotLastEntry = true;
3497
60
          }
3498
109
        }
3499
8
        if (NotLastEntry)
3500
4
          break;
3501
14
      }
3502
14
      More = false;
3503
14
      moveToEnd();
3504
14
      DEBUG_WITH_TYPE("mach-o-bind", dbgs() << "BIND_OPCODE_DONE\n");
3505
14
      break;
3506
30
    case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
3507
30
      if (TableKind == Kind::Weak) {
3508
1
        *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_IMM not allowed in "
3509
1
                            "weak bind table for opcode at: 0x" +
3510
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3511
1
        moveToEnd();
3512
1
        return;
3513
1
      }
3514
29
      Ordinal = ImmValue;
3515
29
      LibraryOrdinalSet = true;
3516
29
      if (ImmValue > O->getLibraryCount()) {
3517
1
        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3518
1
                            "library ordinal: " +
3519
1
                            Twine((int)ImmValue) + " (max " +
3520
1
                            Twine((int)O->getLibraryCount()) +
3521
1
                            ") for opcode at: 0x" +
3522
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3523
1
        moveToEnd();
3524
1
        return;
3525
1
      }
3526
28
      DEBUG_WITH_TYPE(
3527
28
          "mach-o-bind",
3528
28
          dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_IMM: "
3529
28
                 << "Ordinal=" << Ordinal << "\n");
3530
28
      break;
3531
28
    case MachO::BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
3532
17
      if (TableKind == Kind::Weak) {
3533
1
        *E = malformedError("BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB not allowed in "
3534
1
                            "weak bind table for opcode at: 0x" +
3535
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3536
1
        moveToEnd();
3537
1
        return;
3538
1
      }
3539
16
      Ordinal = readULEB128(&error);
3540
16
      LibraryOrdinalSet = true;
3541
16
      if (error) {
3542
2
        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB " +
3543
2
                            Twine(error) + " for opcode at: 0x" +
3544
2
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3545
2
        moveToEnd();
3546
2
        return;
3547
2
      }
3548
14
      if (Ordinal > (int)O->getLibraryCount()) {
3549
2
        *E = malformedError("for BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB bad "
3550
2
                            "library ordinal: " +
3551
2
                            Twine((int)Ordinal) + " (max " +
3552
2
                            Twine((int)O->getLibraryCount()) +
3553
2
                            ") for opcode at: 0x" +
3554
2
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3555
2
        moveToEnd();
3556
2
        return;
3557
2
      }
3558
12
      DEBUG_WITH_TYPE(
3559
12
          "mach-o-bind",
3560
12
          dbgs() << "BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB: "
3561
12
                 << "Ordinal=" << Ordinal << "\n");
3562
12
      break;
3563
12
    case MachO::BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
3564
5
      if (TableKind == Kind::Weak) {
3565
1
        *E = malformedError("BIND_OPCODE_SET_DYLIB_SPECIAL_IMM not allowed in "
3566
1
                            "weak bind table for opcode at: 0x" +
3567
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3568
1
        moveToEnd();
3569
1
        return;
3570
1
      }
3571
4
      if (ImmValue) {
3572
3
        SignExtended = MachO::BIND_OPCODE_MASK | ImmValue;
3573
3
        Ordinal = SignExtended;
3574
3
        if (Ordinal < MachO::BIND_SPECIAL_DYLIB_FLAT_LOOKUP) {
3575
1
          *E = malformedError("for BIND_OPCODE_SET_DYLIB_SPECIAL_IMM unknown "
3576
1
                              "special ordinal: " +
3577
1
                              Twine((int)Ordinal) + " for opcode at: 0x" +
3578
1
                              Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3579
1
          moveToEnd();
3580
1
          return;
3581
1
        }
3582
1
      } else
3583
1
        Ordinal = 0;
3584
4
      LibraryOrdinalSet = true;
3585
3
      DEBUG_WITH_TYPE(
3586
3
          "mach-o-bind",
3587
3
          dbgs() << "BIND_OPCODE_SET_DYLIB_SPECIAL_IMM: "
3588
3
                 << "Ordinal=" << Ordinal << "\n");
3589
3
      break;
3590
61
    case MachO::BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
3591
61
      Flags = ImmValue;
3592
61
      SymStart = Ptr;
3593
887
      while (*Ptr && 
(Ptr < Opcodes.end())827
) {
3594
826
        ++Ptr;
3595
826
      }
3596
61
      if (Ptr == Opcodes.end()) {
3597
1
        *E = malformedError(
3598
1
            "for BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM "
3599
1
            "symbol name extends past opcodes for opcode at: 0x" +
3600
1
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3601
1
        moveToEnd();
3602
1
        return;
3603
1
      }
3604
60
      SymbolName = StringRef(reinterpret_cast<const char*>(SymStart),
3605
60
                             Ptr-SymStart);
3606
60
      ++Ptr;
3607
60
      DEBUG_WITH_TYPE(
3608
60
          "mach-o-bind",
3609
60
          dbgs() << "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: "
3610
60
                 << "SymbolName=" << SymbolName << "\n");
3611
60
      if (TableKind == Kind::Weak) {
3612
4
        if (ImmValue & MachO::BIND_SYMBOL_FLAGS_NON_WEAK_DEFINITION)
3613
2
          return;
3614
58
      }
3615
58
      break;
3616
58
    case MachO::BIND_OPCODE_SET_TYPE_IMM:
3617
21
      BindType = ImmValue;
3618
21
      if (ImmValue > MachO::BIND_TYPE_TEXT_PCREL32) {
3619
1
        *E = malformedError("for BIND_OPCODE_SET_TYPE_IMM bad bind type: " +
3620
1
                            Twine((int)ImmValue) + " for opcode at: 0x" +
3621
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3622
1
        moveToEnd();
3623
1
        return;
3624
1
      }
3625
20
      DEBUG_WITH_TYPE(
3626
20
          "mach-o-bind",
3627
20
          dbgs() << "BIND_OPCODE_SET_TYPE_IMM: "
3628
20
                 << "BindType=" << (int)BindType << "\n");
3629
20
      break;
3630
20
    case MachO::BIND_OPCODE_SET_ADDEND_SLEB:
3631
1
      Addend = readSLEB128(&error);
3632
1
      if (error) {
3633
1
        *E = malformedError("for BIND_OPCODE_SET_ADDEND_SLEB " + Twine(error) +
3634
1
                            " for opcode at: 0x" +
3635
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3636
1
        moveToEnd();
3637
1
        return;
3638
1
      }
3639
0
      DEBUG_WITH_TYPE(
3640
0
          "mach-o-bind",
3641
0
          dbgs() << "BIND_OPCODE_SET_ADDEND_SLEB: "
3642
0
                 << "Addend=" << Addend << "\n");
3643
0
      break;
3644
40
    case MachO::BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
3645
40
      SegmentIndex = ImmValue;
3646
40
      SegmentOffset = readULEB128(&error);
3647
40
      if (error) {
3648
0
        *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3649
0
                            Twine(error) + " for opcode at: 0x" +
3650
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3651
0
        moveToEnd();
3652
0
        return;
3653
0
      }
3654
40
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3655
40
                                             PointerSize);
3656
40
      if (error) {
3657
2
        *E = malformedError("for BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB " +
3658
2
                            Twine(error) + " for opcode at: 0x" +
3659
2
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3660
2
        moveToEnd();
3661
2
        return;
3662
2
      }
3663
38
      DEBUG_WITH_TYPE(
3664
38
          "mach-o-bind",
3665
38
          dbgs() << "BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB: "
3666
38
                 << "SegmentIndex=" << SegmentIndex << ", "
3667
38
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3668
38
                 << "\n");
3669
38
      break;
3670
38
    case MachO::BIND_OPCODE_ADD_ADDR_ULEB:
3671
18
      SegmentOffset += readULEB128(&error);
3672
18
      if (error) {
3673
0
        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3674
0
                            " for opcode at: 0x" +
3675
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3676
0
        moveToEnd();
3677
0
        return;
3678
0
      }
3679
18
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3680
18
                                             PointerSize);
3681
18
      if (error) {
3682
1
        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB " + Twine(error) +
3683
1
                            " for opcode at: 0x" +
3684
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3685
1
        moveToEnd();
3686
1
        return;
3687
1
      }
3688
17
      DEBUG_WITH_TYPE("mach-o-bind",
3689
17
                      dbgs() << "BIND_OPCODE_ADD_ADDR_ULEB: "
3690
17
                             << format("SegmentOffset=0x%06X",
3691
17
                                       SegmentOffset) << "\n");
3692
17
      break;
3693
51
    case MachO::BIND_OPCODE_DO_BIND:
3694
51
      AdvanceAmount = PointerSize;
3695
51
      RemainingLoopCount = 0;
3696
51
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3697
51
                                             PointerSize);
3698
51
      if (error) {
3699
1
        *E = malformedError("for BIND_OPCODE_DO_BIND " + Twine(error) +
3700
1
                            " for opcode at: 0x" +
3701
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3702
1
        moveToEnd();
3703
1
        return;
3704
1
      }
3705
50
      if (SymbolName == StringRef()) {
3706
0
        *E = malformedError(
3707
0
            "for BIND_OPCODE_DO_BIND missing preceding "
3708
0
            "BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode at: 0x" +
3709
0
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3710
0
        moveToEnd();
3711
0
        return;
3712
0
      }
3713
50
      if (!LibraryOrdinalSet && 
TableKind != Kind::Weak4
) {
3714
0
        *E =
3715
0
            malformedError("for BIND_OPCODE_DO_BIND missing preceding "
3716
0
                           "BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3717
0
                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3718
0
        moveToEnd();
3719
0
        return;
3720
0
      }
3721
50
      DEBUG_WITH_TYPE("mach-o-bind",
3722
50
                      dbgs() << "BIND_OPCODE_DO_BIND: "
3723
50
                             << format("SegmentOffset=0x%06X",
3724
50
                                       SegmentOffset) << "\n");
3725
50
      return;
3726
50
     case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
3727
5
      if (TableKind == Kind::Lazy) {
3728
1
        *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB not allowed in "
3729
1
                            "lazy bind table for opcode at: 0x" +
3730
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3731
1
        moveToEnd();
3732
1
        return;
3733
1
      }
3734
4
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3735
4
                                             PointerSize);
3736
4
      if (error) {
3737
0
        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3738
0
                            Twine(error) + " for opcode at: 0x" +
3739
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3740
0
        moveToEnd();
3741
0
        return;
3742
0
      }
3743
4
      if (SymbolName == StringRef()) {
3744
1
        *E = malformedError(
3745
1
            "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3746
1
            "preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for opcode "
3747
1
            "at: 0x" +
3748
1
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3749
1
        moveToEnd();
3750
1
        return;
3751
1
      }
3752
3
      if (!LibraryOrdinalSet && 
TableKind != Kind::Weak1
) {
3753
1
        *E = malformedError(
3754
1
            "for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB missing "
3755
1
            "preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode at: 0x" +
3756
1
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3757
1
        moveToEnd();
3758
1
        return;
3759
1
      }
3760
2
      AdvanceAmount = readULEB128(&error) + PointerSize;
3761
2
      if (error) {
3762
0
        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB " +
3763
0
                            Twine(error) + " for opcode at: 0x" +
3764
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3765
0
        moveToEnd();
3766
0
        return;
3767
0
      }
3768
2
      // Note, this is not really an error until the next bind but make no sense
3769
2
      // for a BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB to not be followed by another
3770
2
      // bind operation.
3771
2
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3772
2
                                            AdvanceAmount, PointerSize);
3773
2
      if (error) {
3774
1
        *E = malformedError("for BIND_OPCODE_ADD_ADDR_ULEB (after adding "
3775
1
                            "ULEB) " +
3776
1
                            Twine(error) + " for opcode at: 0x" +
3777
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3778
1
        moveToEnd();
3779
1
        return;
3780
1
      }
3781
1
      RemainingLoopCount = 0;
3782
1
      DEBUG_WITH_TYPE(
3783
1
          "mach-o-bind",
3784
1
          dbgs() << "BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB: "
3785
1
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3786
1
                 << ", AdvanceAmount=" << AdvanceAmount
3787
1
                 << ", RemainingLoopCount=" << RemainingLoopCount
3788
1
                 << "\n");
3789
1
      return;
3790
5
    case MachO::BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
3791
5
      if (TableKind == Kind::Lazy) {
3792
1
        *E = malformedError("BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED not "
3793
1
                            "allowed in lazy bind table for opcode at: 0x" +
3794
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3795
1
        moveToEnd();
3796
1
        return;
3797
1
      }
3798
4
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3799
4
                                             PointerSize);
3800
4
      if (error) {
3801
0
        *E = malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED " +
3802
0
                            Twine(error) + " for opcode at: 0x" +
3803
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3804
0
        moveToEnd();
3805
0
        return;
3806
0
      }
3807
4
      if (SymbolName == StringRef()) {
3808
0
        *E = malformedError(
3809
0
            "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3810
0
            "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3811
0
            "opcode at: 0x" +
3812
0
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3813
0
        moveToEnd();
3814
0
        return;
3815
0
      }
3816
4
      if (!LibraryOrdinalSet && 
TableKind != Kind::Weak0
) {
3817
0
        *E = malformedError(
3818
0
            "for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3819
0
            "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3820
0
            "at: 0x" +
3821
0
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3822
0
        moveToEnd();
3823
0
        return;
3824
0
      }
3825
4
      AdvanceAmount = ImmValue * PointerSize + PointerSize;
3826
4
      RemainingLoopCount = 0;
3827
4
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset +
3828
4
                                             AdvanceAmount, PointerSize);
3829
4
      if (error) {
3830
1
        *E =
3831
1
            malformedError("for BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED "
3832
1
                           " (after adding immediate times the pointer size) " +
3833
1
                           Twine(error) + " for opcode at: 0x" +
3834
1
                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3835
1
        moveToEnd();
3836
1
        return;
3837
1
      }
3838
3
      DEBUG_WITH_TYPE("mach-o-bind",
3839
3
                      dbgs()
3840
3
                      << "BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED: "
3841
3
                      << format("SegmentOffset=0x%06X", SegmentOffset) << "\n");
3842
3
      return;
3843
3
    case MachO::BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
3844
3
      if (TableKind == Kind::Lazy) {
3845
1
        *E = malformedError("BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB not "
3846
1
                            "allowed in lazy bind table for opcode at: 0x" +
3847
1
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3848
1
        moveToEnd();
3849
1
        return;
3850
1
      }
3851
2
      Count = readULEB128(&error);
3852
2
      if (Count != 0)
3853
2
        RemainingLoopCount = Count - 1;
3854
0
      else
3855
0
        RemainingLoopCount = 0;
3856
2
      if (error) {
3857
0
        *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3858
0
                            " (count value) " +
3859
0
                            Twine(error) + " for opcode at: 0x" +
3860
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3861
0
        moveToEnd();
3862
0
        return;
3863
0
      }
3864
2
      Skip = readULEB128(&error);
3865
2
      AdvanceAmount = Skip + PointerSize;
3866
2
      if (error) {
3867
0
        *E = malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3868
0
                            " (skip value) " +
3869
0
                            Twine(error) + " for opcode at: 0x" +
3870
0
                            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3871
0
        moveToEnd();
3872
0
        return;
3873
0
      }
3874
2
      if (SymbolName == StringRef()) {
3875
0
        *E = malformedError(
3876
0
            "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3877
0
            "missing preceding BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM for "
3878
0
            "opcode at: 0x" +
3879
0
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3880
0
        moveToEnd();
3881
0
        return;
3882
0
      }
3883
2
      if (!LibraryOrdinalSet && 
TableKind != Kind::Weak0
) {
3884
0
        *E = malformedError(
3885
0
            "for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB "
3886
0
            "missing preceding BIND_OPCODE_SET_DYLIB_ORDINAL_* for opcode "
3887
0
            "at: 0x" +
3888
0
            Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3889
0
        moveToEnd();
3890
0
        return;
3891
0
      }
3892
2
      error = O->BindEntryCheckSegAndOffsets(SegmentIndex, SegmentOffset,
3893
2
                                             PointerSize, Count, Skip);
3894
2
      if (error) {
3895
1
        *E =
3896
1
            malformedError("for BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB " +
3897
1
                           Twine(error) + " for opcode at: 0x" +
3898
1
                           Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3899
1
        moveToEnd();
3900
1
        return;
3901
1
      }
3902
1
      DEBUG_WITH_TYPE(
3903
1
          "mach-o-bind",
3904
1
          dbgs() << "BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB: "
3905
1
                 << format("SegmentOffset=0x%06X", SegmentOffset)
3906
1
                 << ", AdvanceAmount=" << AdvanceAmount
3907
1
                 << ", RemainingLoopCount=" << RemainingLoopCount
3908
1
                 << "\n");
3909
1
      return;
3910
1
    default:
3911
1
      *E = malformedError("bad bind info (bad opcode value 0x" +
3912
1
                          Twine::utohexstr(Opcode) + " for opcode at: 0x" +
3913
1
                          Twine::utohexstr(OpcodeStart - Opcodes.begin()));
3914
1
      moveToEnd();
3915
1
      return;
3916
276
    }
3917
276
  }
3918
96
}
3919
3920
80
uint64_t MachOBindEntry::readULEB128(const char **error) {
3921
80
  unsigned Count;
3922
80
  uint64_t Result = decodeULEB128(Ptr, &Count, Opcodes.end(), error);
3923
80
  Ptr += Count;
3924
80
  if (Ptr > Opcodes.end())
3925
0
    Ptr = Opcodes.end();
3926
80
  return Result;
3927
80
}
3928
3929
1
int64_t MachOBindEntry::readSLEB128(const char **error) {
3930
1
  unsigned Count;
3931
1
  int64_t Result = decodeSLEB128(Ptr, &Count, Opcodes.end(), error);
3932
1
  Ptr += Count;
3933
1
  if (Ptr > Opcodes.end())
3934
0
    Ptr = Opcodes.end();
3935
1
  return Result;
3936
1
}
3937
3938
0
int32_t MachOBindEntry::segmentIndex() const { return SegmentIndex; }
3939
3940
0
uint64_t MachOBindEntry::segmentOffset() const { return SegmentOffset; }
3941
3942
21
StringRef MachOBindEntry::typeName() const {
3943
21
  switch (BindType) {
3944
21
  case MachO::BIND_TYPE_POINTER:
3945
21
    return "pointer";
3946
21
  case MachO::BIND_TYPE_TEXT_ABSOLUTE32:
3947
0
    return "text abs32";
3948
21
  case MachO::BIND_TYPE_TEXT_PCREL32:
3949
0
    return "text rel32";
3950
0
  }
3951
0
  return "unknown";
3952
0
}
3953
3954
79
StringRef MachOBindEntry::symbolName() const { return SymbolName; }
3955
3956
21
int64_t MachOBindEntry::addend() const { return Addend; }
3957
3958
23
uint32_t MachOBindEntry::flags() const { return Flags; }
3959
3960
27
int MachOBindEntry::ordinal() const { return Ordinal; }
3961
3962
// For use with the SegIndex of a checked Mach-O Bind entry
3963
// to get the segment name.
3964
27
StringRef MachOBindEntry::segmentName() const {
3965
27
  return O->BindRebaseSegmentName(SegmentIndex);
3966
27
}
3967
3968
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3969
// to get the section name.
3970
27
StringRef MachOBindEntry::sectionName() const {
3971
27
  return O->BindRebaseSectionName(SegmentIndex, SegmentOffset);
3972
27
}
3973
3974
// For use with a SegIndex,SegOffset pair from a checked Mach-O Bind entry
3975
// to get the address.
3976
53
uint64_t MachOBindEntry::address() const {
3977
53
  return O->BindRebaseAddress(SegmentIndex, SegmentOffset);
3978
53
}
3979
3980
107
bool MachOBindEntry::operator==(const MachOBindEntry &Other) const {
3981
#ifdef EXPENSIVE_CHECKS
3982
  assert(Opcodes == Other.Opcodes && "compare iterators of different files");
3983
#else
3984
  assert(Opcodes.data() == Other.Opcodes.data() && "compare iterators of different files");
3985
107
#endif
3986
107
  return (Ptr == Other.Ptr) &&
3987
107
         
(RemainingLoopCount == Other.RemainingLoopCount)48
&&
3988
107
         
(Done == Other.Done)48
;
3989
107
}
3990
3991
// Build table of sections so SegIndex/SegOffset pairs can be translated.
3992
52
BindRebaseSegInfo::BindRebaseSegInfo(const object::MachOObjectFile *Obj) {
3993
52
  uint32_t CurSegIndex = Obj->hasPageZeroSegment() ? 
144
:
08
;
3994
52
  StringRef CurSegName;
3995
52
  uint64_t CurSegAddress;
3996
407
  for (const SectionRef &Section : Obj->sections()) {
3997
407
    SectionInfo Info;
3998
407
    Section.getName(Info.SectionName);
3999
407
    Info.Address = Section.getAddress();
4000
407
    Info.Size = Section.getSize();
4001
407
    Info.SegmentName =
4002
407
        Obj->getSectionFinalSegmentName(Section.getRawDataRefImpl());
4003
407
    if (!Info.SegmentName.equals(CurSegName)) {
4004
110
      ++CurSegIndex;
4005
110
      CurSegName = Info.SegmentName;
4006
110
      CurSegAddress = Info.Address;
4007
110
    }
4008
407
    Info.SegmentIndex = CurSegIndex - 1;
4009
407
    Info.OffsetInSegment = Info.Address - CurSegAddress;
4010
407
    Info.SegmentStartAddress = CurSegAddress;
4011
407
    Sections.push_back(Info);
4012
407
  }
4013
52
  MaxSegIndex = CurSegIndex;
4014
52
}
4015
4016
// For use with a SegIndex, SegOffset, and PointerSize triple in
4017
// MachOBindEntry::moveNext() to validate a MachOBindEntry or MachORebaseEntry.
4018
//
4019
// Given a SegIndex, SegOffset, and PointerSize, verify a valid section exists
4020
// that fully contains a pointer at that location. Multiple fixups in a bind
4021
// (such as with the BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB opcode) can
4022
// be tested via the Count and Skip parameters.
4023
const char * BindRebaseSegInfo::checkSegAndOffsets(int32_t SegIndex,
4024
                                                   uint64_t SegOffset,
4025
                                                   uint8_t PointerSize,
4026
                                                   uint32_t Count,
4027
150
                                                   uint32_t Skip) {
4028
150
  if (SegIndex == -1)
4029
1
    return "missing preceding *_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB";
4030
149
  if (SegIndex >= MaxSegIndex)
4031
2
    return "bad segIndex (too large)";
4032
293
  
for (uint32_t i = 0; 147
i < Count;
++i146
) {
4033
158
    uint32_t Start = SegOffset + i * (PointerSize + Skip);
4034
158
    uint32_t End = Start + PointerSize;
4035
158
    bool Found = false;
4036
1.24k
    for (const SectionInfo &SI : Sections) {
4037
1.24k
      if (SI.SegmentIndex != SegIndex)
4038
836
        continue;
4039
410
      if ((SI.OffsetInSegment<=Start) && (Start<(SI.OffsetInSegment+SI.Size))) {
4040
146
        if (End <= SI.OffsetInSegment + SI.Size) {
4041
146
          Found = true;
4042
146
          break;
4043
146
        }
<