summaryrefslogtreecommitdiffstats
path: root/chromium/base/android/library_loader/anchor_functions.cc
blob: 4997c1b5790f7d2ac0d1efa9d54a437aa0703b55 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/android/library_loader/anchor_functions.h"

#include "build/build_config.h"

#if BUILDFLAG(SUPPORTS_CODE_ORDERING)

// These functions are here to delimit the start and end of the ordered part of
// .text. They require a suitably constructed orderfile, with these functions at
// the beginning and end.
//
// These functions are weird: this is due to ICF (Identical Code Folding).
// The linker merges functions that have the same code, which would be the case
// if these functions were empty, or simple.
// Gold's flag --icf=safe will *not* alias functions when their address is used
// in code, but as of November 2017, we use the default setting that
// deduplicates function in this case as well.
//
// Thus these functions are made to be unique, using inline .word in assembly,
// or the equivalent directive depending on the architecture.
//
// Note that code |CheckOrderingSanity()| below will make sure that these
// functions are not aliased, in case the toolchain becomes really clever.
extern "C" {

// The assembler has a different syntax depending on the architecture.
#if defined(ARCH_CPU_ARMEL) || defined(ARCH_CPU_ARM64)

// These functions have a well-defined ordering in this file, see the comment
// in |IsOrderingSane()|.
void dummy_function_end_of_ordered_text() {
  asm(".word 0x21bad44d");
  asm(".word 0xb815c5b0");
}

void dummy_function_start_of_ordered_text() {
  asm(".word 0xe4a07375");
  asm(".word 0x66dda6dc");
}

#elif defined(ARCH_CPU_X86_FAMILY)

void dummy_function_end_of_ordered_text() {
  asm(".4byte 0x21bad44d");
  asm(".4byte 0xb815c5b0");
}

void dummy_function_start_of_ordered_text() {
  asm(".4byte 0xe4a07375");
  asm(".4byte 0x66dda6dc");
}

#endif

// These two symbols are defined by anchor_functions.lds and delimit the start
// and end of .text.
void linker_script_start_of_text();
void linker_script_end_of_text();

}  // extern "C"

namespace base {
namespace android {

const size_t kStartOfText =
    reinterpret_cast<size_t>(linker_script_start_of_text);
const size_t kEndOfText = reinterpret_cast<size_t>(linker_script_end_of_text);
const size_t kStartOfOrderedText =
    reinterpret_cast<size_t>(dummy_function_start_of_ordered_text);
const size_t kEndOfOrderedText =
    reinterpret_cast<size_t>(dummy_function_end_of_ordered_text);

bool AreAnchorsSane() {
  size_t here = reinterpret_cast<size_t>(&IsOrderingSane);
  return kStartOfText < here && here < kEndOfText;
}

bool IsOrderingSane() {
  // The symbols linker_script_start_of_text and linker_script_end_of_text
  // should cover all of .text, and dummy_function_start_of_ordered_text and
  // dummy_function_end_of_ordered_text should cover the ordered part of it.
  // This check is intended to catch the lack of ordering.
  //
  // Ordered text can start at the start of text, but should not cover the
  // entire range. Most addresses are distinct nonetheless as the symbols are
  // different, but linker-defined symbols have zero size and therefore the
  // start address could be the same as the address of
  // dummy_function_start_of_ordered_text.
  return AreAnchorsSane() && kStartOfOrderedText < kEndOfOrderedText &&
         kStartOfText <= kStartOfOrderedText && kEndOfOrderedText < kEndOfText;
}

}  // namespace android
}  // namespace base

#endif  // BUILDFLAG(SUPPORTS_CODE_ORDERING)