Skip to content

Commit 6703b45

Browse files
authored
Fix oat_hook for recent Android versions (#387)
We used to hook functions `OatHeader::GetKeyValueStore` and `OatHeader::GetKeyValueStoreSize` to clean the `dex2oat` trace introduced by LSPosed. However, in recent versions of Android, these two functions are no longer exported. Moreover, the `OatHeader` structure has changed, which now sets certain entries to have fixed length by padding zeros. To address these two changes, we hook `OatHeader::ComputeChecksum` as an entrypoint (fallback), and then employ the header file of `OatHeader` copied from AOSP to precisely locate its fields. Using this strategy, we modify `key_value_store` in memory, depending on whether the entry `dex2oat-cmdline` is padded.
1 parent e75b600 commit 6703b45

File tree

9 files changed

+513
-57
lines changed

9 files changed

+513
-57
lines changed

dex2oat/src/main/cpp/CMakeLists.txt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
cmake_minimum_required(VERSION 3.10)
22
project(dex2oat)
33

4-
add_executable(dex2oat dex2oat.c)
5-
add_library(oat_hook SHARED oat_hook.cpp)
4+
add_executable(dex2oat dex2oat.cpp)
5+
add_library(oat_hook SHARED oat_hook.cpp oat.cpp)
66

77
OPTION(LSPLT_BUILD_SHARED OFF)
88
add_subdirectory(${EXTERNAL_ROOT}/lsplt/lsplt/src/main/jni external)
99

10+
target_include_directories(oat_hook PUBLIC include)
11+
target_include_directories(dex2oat PUBLIC include)
1012
target_link_libraries(dex2oat log)
1113
target_link_libraries(oat_hook log lsplt_static)
1214

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
/*
2+
* Copyright (C) 2015 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
#include <stddef.h> // for size_t
20+
#include <unistd.h> // for TEMP_FAILURE_RETRY
21+
22+
#include <utility>
23+
24+
// bionic and glibc both have TEMP_FAILURE_RETRY, but eg Mac OS' libc doesn't.
25+
#ifndef TEMP_FAILURE_RETRY
26+
#define TEMP_FAILURE_RETRY(exp) \
27+
({ \
28+
decltype(exp) _rc; \
29+
do { \
30+
_rc = (exp); \
31+
} while (_rc == -1 && errno == EINTR); \
32+
_rc; \
33+
})
34+
#endif
35+
36+
// A macro to disallow the copy constructor and operator= functions
37+
// This must be placed in the private: declarations for a class.
38+
//
39+
// For disallowing only assign or copy, delete the relevant operator or
40+
// constructor, for example:
41+
// void operator=(const TypeName&) = delete;
42+
// Note, that most uses of DISALLOW_ASSIGN and DISALLOW_COPY are broken
43+
// semantically, one should either use disallow both or neither. Try to
44+
// avoid these in new code.
45+
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
46+
TypeName(const TypeName &) = delete; \
47+
void operator=(const TypeName &) = delete
48+
49+
// A macro to disallow all the implicit constructors, namely the
50+
// default constructor, copy constructor and operator= functions.
51+
//
52+
// This should be used in the private: declarations for a class
53+
// that wants to prevent anyone from instantiating it. This is
54+
// especially useful for classes containing only static methods.
55+
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
56+
TypeName() = delete; \
57+
DISALLOW_COPY_AND_ASSIGN(TypeName)
58+
59+
// The arraysize(arr) macro returns the # of elements in an array arr.
60+
// The expression is a compile-time constant, and therefore can be
61+
// used in defining new arrays, for example. If you use arraysize on
62+
// a pointer by mistake, you will get a compile-time error.
63+
//
64+
// One caveat is that arraysize() doesn't accept any array of an
65+
// anonymous type or a type defined inside a function. In these rare
66+
// cases, you have to use the unsafe ARRAYSIZE_UNSAFE() macro below. This is
67+
// due to a limitation in C++'s template system. The limitation might
68+
// eventually be removed, but it hasn't happened yet.
69+
70+
// This template function declaration is used in defining arraysize.
71+
// Note that the function doesn't need an implementation, as we only
72+
// use its type.
73+
template <typename T, size_t N>
74+
char (&ArraySizeHelper(T (&array)[N]))[N]; // NOLINT(readability/casting)
75+
76+
#define arraysize(array) (sizeof(ArraySizeHelper(array)))
77+
78+
#define SIZEOF_MEMBER(t, f) sizeof(std::declval<t>().f)
79+
80+
// Changing this definition will cause you a lot of pain. A majority of
81+
// vendor code defines LIKELY and UNLIKELY this way, and includes
82+
// this header through an indirect path.
83+
#define LIKELY(exp) (__builtin_expect((exp) != 0, true))
84+
#define UNLIKELY(exp) (__builtin_expect((exp) != 0, false))
85+
86+
#define WARN_UNUSED __attribute__((warn_unused_result))
87+
88+
// A deprecated function to call to create a false use of the parameter, for
89+
// example:
90+
// int foo(int x) { UNUSED(x); return 10; }
91+
// to avoid compiler warnings. Going forward we prefer ATTRIBUTE_UNUSED.
92+
template <typename... T>
93+
void UNUSED(const T &...) {}
94+
95+
// An attribute to place on a parameter to a function, for example:
96+
// int foo(int x ATTRIBUTE_UNUSED) { return 10; }
97+
// to avoid compiler warnings.
98+
#define ATTRIBUTE_UNUSED __attribute__((__unused__))
99+
100+
// The FALLTHROUGH_INTENDED macro can be used to annotate implicit fall-through
101+
// between switch labels:
102+
// switch (x) {
103+
// case 40:
104+
// case 41:
105+
// if (truth_is_out_there) {
106+
// ++x;
107+
// FALLTHROUGH_INTENDED; // Use instead of/along with annotations in
108+
// // comments.
109+
// } else {
110+
// return x;
111+
// }
112+
// case 42:
113+
// ...
114+
//
115+
// As shown in the example above, the FALLTHROUGH_INTENDED macro should be
116+
// followed by a semicolon. It is designed to mimic control-flow statements
117+
// like 'break;', so it can be placed in most places where 'break;' can, but
118+
// only if there are no statements on the execution path between it and the
119+
// next switch label.
120+
//
121+
// When compiled with clang, the FALLTHROUGH_INTENDED macro is expanded to
122+
// [[clang::fallthrough]] attribute, which is analysed when performing switch
123+
// labels fall-through diagnostic ('-Wimplicit-fallthrough'). See clang
124+
// documentation on language extensions for details:
125+
// http://clang.llvm.org/docs/LanguageExtensions.html#clang__fallthrough
126+
//
127+
// When used with unsupported compilers, the FALLTHROUGH_INTENDED macro has no
128+
// effect on diagnostics.
129+
//
130+
// In either case this macro has no effect on runtime behavior and performance
131+
// of code.
132+
#ifndef FALLTHROUGH_INTENDED
133+
#define FALLTHROUGH_INTENDED [[fallthrough]] // NOLINT
134+
#endif
135+
136+
// Current ABI string
137+
#if defined(__arm__)
138+
#define ABI_STRING "arm"
139+
#elif defined(__aarch64__)
140+
#define ABI_STRING "arm64"
141+
#elif defined(__i386__)
142+
#define ABI_STRING "x86"
143+
#elif defined(__riscv)
144+
#define ABI_STRING "riscv64"
145+
#elif defined(__x86_64__)
146+
#define ABI_STRING "x86_64"
147+
#endif
Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
/*
2+
* Copyright (C) 2010 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef ART_LIBARTBASE_BASE_MACROS_H_
18+
#define ART_LIBARTBASE_BASE_MACROS_H_
19+
20+
#include <stddef.h> // for size_t
21+
#include <unistd.h> // for TEMP_FAILURE_RETRY
22+
23+
// Declare a friend relationship in a class with a test. Used rather that FRIEND_TEST to avoid
24+
// globally importing gtest/gtest.h into the main ART header files.
25+
#define ART_FRIEND_TEST(test_set_name, individual_test) \
26+
friend class test_set_name##_##individual_test##_Test
27+
28+
// Declare a friend relationship in a class with a typed test.
29+
#define ART_FRIEND_TYPED_TEST(test_set_name, individual_test) \
30+
template <typename T> \
31+
ART_FRIEND_TEST(test_set_name, individual_test)
32+
33+
// Shorthand for formatting with compile time checking of the format string
34+
#define ART_FORMAT(str, ...) ::fmt::format(FMT_STRING(str), __VA_ARGS__)
35+
36+
// A macro to disallow new and delete operators for a class. It goes in the private: declarations.
37+
// NOTE: Providing placement new (and matching delete) for constructing container elements.
38+
#define DISALLOW_ALLOCATION() \
39+
public: \
40+
NO_RETURN ALWAYS_INLINE void operator delete(void*, size_t) { UNREACHABLE(); } \
41+
ALWAYS_INLINE void* operator new(size_t, void* ptr) noexcept { return ptr; } \
42+
ALWAYS_INLINE void operator delete(void*, void*) noexcept {} \
43+
\
44+
private: \
45+
void* operator new(size_t) = delete // NOLINT
46+
47+
// offsetof is not defined by the spec on types with non-standard layout,
48+
// however it is implemented by compilers in practice.
49+
// (note that reinterpret_cast is not valid constexpr)
50+
//
51+
// Alternative approach would be something like:
52+
// #define OFFSETOF_HELPER(t, f) \
53+
// (reinterpret_cast<uintptr_t>(&reinterpret_cast<t*>(16)->f) - static_cast<uintptr_t>(16u))
54+
// #define OFFSETOF_MEMBER(t, f) \
55+
// (__builtin_constant_p(OFFSETOF_HELPER(t,f)) ? OFFSETOF_HELPER(t,f) : OFFSETOF_HELPER(t,f))
56+
#define OFFSETOF_MEMBER(t, f) offsetof(t, f)
57+
58+
#define OFFSETOF_MEMBERPTR(t, f) \
59+
(reinterpret_cast<uintptr_t>(&(reinterpret_cast<t*>(16)->*f)) - \
60+
static_cast<uintptr_t>(16)) // NOLINT
61+
62+
#define ALIGNED(x) __attribute__((__aligned__(x)))
63+
#define PACKED(x) __attribute__((__aligned__(x), __packed__))
64+
65+
// Stringify the argument.
66+
#define QUOTE(x) #x
67+
#define STRINGIFY(x) QUOTE(x)
68+
69+
// Append tokens after evaluating.
70+
#define APPEND_TOKENS_AFTER_EVAL_2(a, b) a##b
71+
#define APPEND_TOKENS_AFTER_EVAL(a, b) APPEND_TOKENS_AFTER_EVAL_2(a, b)
72+
73+
#ifndef NDEBUG
74+
#define ALWAYS_INLINE
75+
#define FLATTEN
76+
#else
77+
#define ALWAYS_INLINE __attribute__((always_inline))
78+
#define FLATTEN __attribute__((flatten))
79+
#endif
80+
81+
#define NO_STACK_PROTECTOR __attribute__((no_stack_protector))
82+
83+
// clang doesn't like attributes on lambda functions. It would be nice to say:
84+
// #define ALWAYS_INLINE_LAMBDA ALWAYS_INLINE
85+
#define ALWAYS_INLINE_LAMBDA
86+
87+
#define NO_INLINE __attribute__((noinline))
88+
89+
#if defined(__APPLE__)
90+
#define HOT_ATTR
91+
#define COLD_ATTR
92+
#else
93+
#define HOT_ATTR __attribute__((hot))
94+
#define COLD_ATTR __attribute__((cold))
95+
#endif
96+
97+
#define PURE __attribute__((__pure__))
98+
99+
// Define that a position within code is unreachable, for example:
100+
// int foo () { LOG(FATAL) << "Don't call me"; UNREACHABLE(); }
101+
// without the UNREACHABLE a return statement would be necessary.
102+
#define UNREACHABLE __builtin_unreachable
103+
104+
// Add the C++11 noreturn attribute.
105+
#define NO_RETURN [[noreturn]] // NOLINT[whitespace/braces] [5]
106+
107+
// Annotalysis thread-safety analysis support. Things that are not in base.
108+
109+
#define LOCKABLE CAPABILITY("mutex")
110+
#define SHARED_LOCKABLE SHARED_CAPABILITY("mutex")
111+
112+
// Some of the libs (e.g. libarttest(d)) require more public symbols when built
113+
// in debug configuration.
114+
// Using symbol visibility only for release builds allows to reduce the list of
115+
// exported symbols and eliminates the need to check debug build configurations
116+
// when changing the exported symbols.
117+
#ifdef NDEBUG
118+
#define HIDDEN __attribute__((visibility("hidden")))
119+
#define PROTECTED __attribute__((visibility("protected")))
120+
#define EXPORT __attribute__((visibility("default")))
121+
#else
122+
#define HIDDEN
123+
#define PROTECTED
124+
#define EXPORT
125+
#endif
126+
127+
// Protected symbols must be declared with "protected" visibility attribute when
128+
// building the library and "default" visibility when referred to from external
129+
// libraries/binaries. Otherwise, the external code will expect the symbol to be
130+
// defined locally and fail to link.
131+
#ifdef BUILDING_LIBART
132+
#define LIBART_PROTECTED PROTECTED
133+
#else
134+
#define LIBART_PROTECTED EXPORT
135+
#endif
136+
137+
// Some global variables shouldn't be visible outside libraries declaring them.
138+
// The attribute allows hiding them, so preventing direct access.
139+
#define ALWAYS_HIDDEN __attribute__((visibility("hidden")))
140+
141+
#endif // ART_LIBARTBASE_BASE_MACROS_H_

0 commit comments

Comments
 (0)